From 970c43b16310414f31866a1edaac472b69e42a02 Mon Sep 17 00:00:00 2001
From: Apertis CI <devel@lists.apertis.org>
Date: Wed, 26 Feb 2025 11:34:38 +0000
Subject: [PATCH 1/4] Import Upstream version 5.79

---
 .checkpatch.conf                              |    15 -
 .gitignore                                    |   189 -
 .gitlint                                      |    48 -
 .mailmap                                      |    11 -
 AUTHORS                                       |     4 +-
 ChangeLog                                     |    92 +
 HACKING                                       |   151 -
 LICENSES/dual/Apache-2.0                      |   187 -
 LICENSES/preferred/BSD-2-Clause               |    32 -
 LICENSES/preferred/GPL-2.0                    |   355 -
 LICENSES/preferred/LGPL-2.1                   |   503 -
 LICENSES/preferred/MIT                        |    30 -
 Makefile.am                                   |   237 +-
 Makefile.in                                   | 14022 +++++++++++
 Makefile.mesh                                 |    10 +-
 Makefile.obexd                                |    29 +-
 Makefile.plugins                              |    37 +-
 Makefile.tools                                |    61 +-
 README                                        |    13 +
 acinclude.m4                                  |     2 +
 aclocal.m4                                    | 10619 +++++++++
 android/Makefile.am                           |     3 +
 android/avctp.c                               |     6 +-
 android/avdtp.c                               |     4 +-
 android/gatt.c                                |     4 +
 android/hal-audio-sbc.c                       |     2 +-
 android/hal-audio.c                           |     1 +
 android/hal-bluetooth.c                       |     1 +
 android/hal-sco.c                             |     1 +
 android/handsfree.c                           |    14 +-
 android/hidhost.c                             |     5 +-
 android/ipc-tester.c                          |     1 +
 android/sco-ipc-api.txt                       |    37 -
 android/socket-api.txt                        |    61 -
 android/system-emulator.c                     |     1 +
 android/tester-main.c                         |     1 +
 attrib/gatt.c                                 |     8 +-
 attrib/gattrib.c                              |    52 +-
 attrib/gattrib.h                              |     2 +
 attrib/gatttool.c                             |    16 +-
 attrib/interactive.c                          |     2 +-
 bootstrap                                     |     7 -
 bootstrap-configure                           |    37 -
 btio/btio.c                                   |   198 +-
 btio/btio.h                                   |     9 +
 client/adv_monitor.c                          |     8 +-
 client/advertising.c                          |    48 +-
 client/advertising.h                          |     1 +
 client/agent.c                                |    99 +-
 client/assistant.c                            |   415 +
 client/assistant.h                            |    13 +
 client/bluetoothctl-admin.1                   |    61 +
 client/bluetoothctl-admin.rst                 |    41 +
 client/bluetoothctl-advertise.1               |   278 +
 client/bluetoothctl-advertise.rst             |   239 +
 client/bluetoothctl-assistant.1               |    88 +
 client/bluetoothctl-assistant.rst             |    67 +
 client/bluetoothctl-endpoint.1                |   224 +
 client/bluetoothctl-endpoint.rst              |   171 +
 client/bluetoothctl-gatt.1                    |   215 +
 client/bluetoothctl-gatt.rst                  |   180 +
 client/bluetoothctl-mgmt.1                    |   645 +
 client/bluetoothctl-mgmt.rst                  |   559 +
 client/bluetoothctl-monitor.1                 |   111 +
 client/bluetoothctl-monitor.rst               |    89 +
 client/bluetoothctl-player.1                  |   199 +
 client/bluetoothctl-player.rst                |   165 +
 client/bluetoothctl-scan.1                    |   172 +
 client/bluetoothctl-scan.rst                  |   140 +
 client/bluetoothctl-transport.1               |   140 +
 client/bluetoothctl-transport.rst             |   116 +
 client/bluetoothctl.1                         |   401 +
 client/bluetoothctl.rst                       |   363 +
 client/gatt.c                                 |   353 +-
 client/gatt.h                                 |     4 +
 client/main.c                                 |   514 +-
 client/mgmt.c                                 |  6053 +++++
 client/mgmt.h                                 |    13 +
 client/player.c                               |  4329 +++-
 client/print.c                                |   238 +
 client/print.h                                |    15 +
 compile                                       |   348 +
 config.guess                                  |  1754 ++
 config.h.in                                   |   145 +
 config.sub                                    |  1890 ++
 configure                                     | 19902 ++++++++++++++++
 configure.ac                                  |   170 +-
 depcomp                                       |   791 +
 doc/adapter-api.txt                           |   361 -
 doc/admin-policy-api.txt                      |    65 -
 doc/advertisement-monitor-api.txt             |   187 -
 doc/advertising-api.txt                       |   277 -
 doc/agent-api.txt                             |   185 -
 doc/battery-api.txt                           |    69 -
 doc/ci.config                                 |   122 -
 doc/coding-style.txt                          |   279 -
 doc/device-api.txt                            |   283 -
 doc/errors.txt                                |   233 -
 doc/gatt-api.txt                              |   509 -
 doc/hci.7                                     |   225 +
 doc/hci.rst                                   |   152 +
 doc/input-api.txt                             |    32 -
 doc/intel-variants.txt                        |   159 -
 doc/l2cap.7                                   |   578 +
 doc/l2cap.rst                                 |   258 +
 doc/maintainer-guidelines.txt                 |   114 -
 doc/media-api.txt                             |   779 -
 doc/mesh-api.txt                              |  1247 -
 doc/mgmt-api.txt                              |     9 +-
 doc/network-api.txt                           |    76 -
 doc/obex-agent-api.txt                        |    61 -
 doc/obex-api.txt                              |   894 -
 doc/org.bluez.Adapter.5                       |   486 +
 doc/org.bluez.Adapter.rst                     |   425 +
 doc/org.bluez.AdminPolicySet.5                |    79 +
 doc/org.bluez.AdminPolicySet.rst              |    52 +
 doc/org.bluez.AdminPolicyStatus.5             |    77 +
 doc/org.bluez.AdminPolicyStatus.rst           |    49 +
 doc/org.bluez.AdvertisementMonitor.5          |   189 +
 doc/org.bluez.AdvertisementMonitor.rst        |   153 +
 doc/org.bluez.AdvertisementMonitorManager.5   |   119 +
 doc/org.bluez.AdvertisementMonitorManager.rst |    90 +
 doc/org.bluez.Agent.5                         |   201 +
 doc/org.bluez.Agent.rst                       |   149 +
 doc/org.bluez.AgentManager.5                  |   122 +
 doc/org.bluez.AgentManager.rst                |    83 +
 doc/org.bluez.Battery.5                       |    66 +
 doc/org.bluez.Battery.rst                     |    39 +
 doc/org.bluez.BatteryProvider.5               |    58 +
 doc/org.bluez.BatteryProvider.rst             |    32 +
 doc/org.bluez.BatteryProviderManager.5        |    75 +
 doc/org.bluez.BatteryProviderManager.rst      |    50 +
 doc/org.bluez.Device.5                        |   445 +
 doc/org.bluez.Device.rst                      |   348 +
 doc/org.bluez.DeviceSet.5                     |   107 +
 doc/org.bluez.DeviceSet.rst                   |    71 +
 doc/org.bluez.GattCharacteristic.5            |   478 +
 doc/org.bluez.GattCharacteristic.rst          |   385 +
 doc/org.bluez.GattDescriptor.5                |   226 +
 doc/org.bluez.GattDescriptor.rst              |   168 +
 doc/org.bluez.GattManager.5                   |   149 +
 doc/org.bluez.GattManager.rst                 |   114 +
 doc/org.bluez.GattProfile.5                   |    69 +
 doc/org.bluez.GattProfile.rst                 |    46 +
 doc/org.bluez.GattService.5                   |   111 +
 doc/org.bluez.GattService.rst                 |    79 +
 doc/org.bluez.Input.5                         |    75 +
 doc/org.bluez.Input.rst                       |    51 +
 doc/org.bluez.LEAdvertisement.5               |   244 +
 doc/org.bluez.LEAdvertisement.rst             |   195 +
 doc/org.bluez.LEAdvertisingManager.5          |   189 +
 doc/org.bluez.LEAdvertisingManager.rst        |   144 +
 doc/org.bluez.Media.5                         |   175 +
 doc/org.bluez.Media.rst                       |   133 +
 doc/org.bluez.MediaAssistant.5                |   120 +
 doc/org.bluez.MediaAssistant.rst              |    74 +
 doc/org.bluez.MediaControl.5                  |   111 +
 doc/org.bluez.MediaControl.rst                |    80 +
 doc/org.bluez.MediaEndpoint.5                 |   282 +
 doc/org.bluez.MediaEndpoint.rst               |   240 +
 doc/org.bluez.MediaFolder.5                   |   156 +
 doc/org.bluez.MediaFolder.rst                 |   117 +
 doc/org.bluez.MediaItem.5                     |   163 +
 doc/org.bluez.MediaItem.rst                   |   131 +
 doc/org.bluez.MediaPlayer.5                   |   431 +
 doc/org.bluez.MediaPlayer.rst                 |   326 +
 doc/org.bluez.MediaTransport.5                |   369 +
 doc/org.bluez.MediaTransport.rst              |   327 +
 doc/org.bluez.Network.5                       |   118 +
 doc/org.bluez.Network.rst                     |    83 +
 doc/org.bluez.NetworkServer.5                 |   100 +
 doc/org.bluez.NetworkServer.rst               |    68 +
 doc/org.bluez.Profile.5                       |    81 +
 doc/org.bluez.Profile.rst                     |    51 +
 doc/org.bluez.ProfileManager.5                |   164 +
 doc/org.bluez.ProfileManager.rst              |   141 +
 doc/org.bluez.obex.Agent.5                    |    78 +
 doc/org.bluez.obex.Agent.rst                  |    54 +
 doc/org.bluez.obex.AgentManager.5             |    76 +
 doc/org.bluez.obex.AgentManager.rst           |    45 +
 doc/org.bluez.obex.Client.5                   |   112 +
 doc/org.bluez.obex.Client.rst                 |    74 +
 doc/org.bluez.obex.FileTransfer.5             |   203 +
 doc/org.bluez.obex.FileTransfer.rst           |   155 +
 doc/org.bluez.obex.Image.5                    |   165 +
 doc/org.bluez.obex.Image.rst                  |   118 +
 doc/org.bluez.obex.Message.5                  |   191 +
 doc/org.bluez.obex.Message.rst                |   139 +
 doc/org.bluez.obex.MessageAccess.5            |   279 +
 doc/org.bluez.obex.MessageAccess.rst          |   201 +
 doc/org.bluez.obex.ObjectPush.5               |   121 +
 doc/org.bluez.obex.ObjectPush.rst             |    84 +
 doc/org.bluez.obex.PhonebookAccess.5          |   515 +
 doc/org.bluez.obex.PhonebookAccess.rst        |   386 +
 doc/org.bluez.obex.Session.5                  |    99 +
 doc/org.bluez.obex.Session.rst                |    66 +
 doc/org.bluez.obex.Synchronization.5          |   118 +
 doc/org.bluez.obex.Synchronization.rst        |    82 +
 doc/org.bluez.obex.Transfer.5                 |   171 +
 doc/org.bluez.obex.Transfer.rst               |   123 +
 doc/profile-api.txt                           |   170 -
 doc/rfcomm.7                                  |   452 +
 doc/rfcomm.rst                                |   225 +
 doc/security-bugs.txt                         |    88 -
 doc/test-runner.rst                           |   178 +
 doc/test-runner.txt                           |    82 -
 doc/tester.config                             |    56 -
 doc/thermometer-api.txt                       |   134 -
 ell/asn1-private.h                            |   193 +
 ell/base64.c                                  |   163 +
 ell/base64.h                                  |    23 +
 ell/cert-crypto.c                             |   787 +
 ell/cert-private.h                            |    42 +
 ell/cert.c                                    |  1954 ++
 ell/cert.h                                    |    71 +
 ell/checksum.c                                |   445 +
 ell/checksum.h                                |    60 +
 ell/cipher.c                                  |  1102 +
 ell/cipher.h                                  |    80 +
 ell/cleanup.h                                 |    15 +
 ell/dbus-client.c                             |   722 +
 ell/dbus-client.h                             |    83 +
 ell/dbus-filter.c                             |   414 +
 ell/dbus-message.c                            |  1974 ++
 ell/dbus-name-cache.c                         |   298 +
 ell/dbus-private.h                            |   297 +
 ell/dbus-service.c                            |  2159 ++
 ell/dbus-service.h                            |    79 +
 ell/dbus-util.c                               |  1299 +
 ell/dbus.c                                    |  1932 ++
 ell/dbus.h                                    |   266 +
 ell/ecc-external.c                            |  1023 +
 ell/ecc-private.h                             |   128 +
 ell/ecc.c                                     |  1073 +
 ell/ecc.h                                     |   113 +
 ell/ecdh.c                                    |    99 +
 ell/ecdh.h                                    |    38 +
 ell/ell.h                                     |    38 +
 ell/gvariant-private.h                        |    54 +
 ell/gvariant-util.c                           |  1364 ++
 ell/hashmap.c                                 |   718 +
 ell/hashmap.h                                 |    66 +
 ell/idle.c                                    |   153 +
 ell/idle.h                                    |    34 +
 ell/internal                                  |     0
 ell/io.c                                      |   399 +
 ell/io.h                                      |    47 +
 ell/key.c                                     |   799 +
 ell/key.h                                     |   118 +
 ell/log.c                                     |   442 +
 ell/log.h                                     |    96 +
 ell/main-private.h                            |    23 +
 ell/main.c                                    |   651 +
 ell/main.h                                    |    36 +
 ell/missing.h                                 |    64 +
 ell/pem-private.h                             |    36 +
 ell/pem.c                                     |   819 +
 ell/pem.h                                     |    42 +
 ell/private.h                                 |    10 +
 ell/queue.c                                   |   573 +
 ell/queue.h                                   |    67 +
 ell/random.c                                  |    90 +
 ell/random.h                                  |    28 +
 ell/settings.c                                |  1542 ++
 ell/settings.h                                |   136 +
 ell/signal.c                                  |   253 +
 ell/signal.h                                  |    30 +
 ell/siphash-private.h                         |    12 +
 ell/siphash.c                                 |   123 +
 ell/string.c                                  |   496 +
 ell/string.h                                  |    46 +
 ell/strv.c                                    |   366 +
 ell/strv.h                                    |    42 +
 ell/tester.c                                  |   765 +
 ell/tester.h                                  |    82 +
 ell/time-private.h                            |    15 +
 ell/time.c                                    |   141 +
 ell/time.h                                    |    66 +
 ell/timeout.c                                 |   329 +
 ell/timeout.h                                 |    43 +
 ell/tls-extensions.c                          |  1037 +
 ell/tls-private.h                             |   373 +
 ell/tls-record.c                              |   629 +
 ell/tls-suites.c                              |  1458 ++
 ell/tls.c                                     |  3987 ++++
 ell/tls.h                                     |   141 +
 ell/useful.h                                  |    89 +
 ell/utf8.c                                    |   547 +
 ell/utf8.h                                    |   125 +
 ell/util.c                                    |   832 +
 ell/util.h                                    |   524 +
 ell/uuid.c                                    |   246 +
 ell/uuid.h                                    |    47 +
 emulator/amp.c                                |     3 +-
 emulator/btdev.c                              |   487 +-
 emulator/bthost.c                             |   410 +-
 emulator/bthost.h                             |    22 +-
 emulator/hciemu.c                             |    72 +-
 emulator/hciemu.h                             |     5 +
 emulator/serial.c                             |     1 +
 emulator/vhci.c                               |    86 +-
 emulator/vhci.h                               |     3 +
 gdbus/client.c                                |   115 +
 gdbus/gdbus.h                                 |    36 +
 gdbus/object.c                                |   175 +-
 gdbus/watch.c                                 |    46 +-
 gobex/gobex-header.c                          |    41 +-
 gobex/gobex.c                                 |    20 +-
 install-sh                                    |   541 +
 lib/bluetooth.h                               |    61 +-
 lib/hci.c                                     |    44 +-
 lib/hci_lib.h                                 |     4 +-
 lib/l2cap.h                                   |     2 +
 lib/mgmt.h                                    |   121 +-
 lib/sdp.c                                     |    82 +-
 lib/sdp_lib.h                                 |    21 +-
 lib/uuid.c                                    |     9 +
 lib/uuid.h                                    |    60 +
 ltmain.sh                                     | 11436 +++++++++
 mesh/README                                   |    95 -
 mesh/agent.c                                  |     4 +-
 mesh/bluetooth-mesh.service.in                |     2 +-
 mesh/bluetooth-meshd.rst.in                   |    11 +-
 mesh/cfgmod-server.c                          |     6 +-
 mesh/crypto.c                                 |    13 +-
 mesh/crypto.h                                 |     2 +-
 mesh/keyring.c                                |    28 +-
 mesh/keyring.h                                |     1 +
 mesh/main.c                                   |    40 +-
 mesh/manager.c                                |   535 +-
 mesh/mesh-config-json.c                       |   433 +-
 mesh/mesh-config.h                            |    12 +-
 mesh/mesh-io-api.h                            |     7 +
 mesh/mesh-io-generic.c                        |    73 +-
 mesh/mesh-io-mgmt.c                           |   126 +-
 mesh/mesh-io-unit.c                           |    30 -
 mesh/mesh-io.c                                |   112 +-
 mesh/mesh-io.h                                |     2 -
 mesh/mesh-mgmt.c                              |     5 +
 mesh/mesh-mgmt.h                              |     1 +
 mesh/model.c                                  |    37 +-
 mesh/net-keys.c                               |   506 +-
 mesh/net-keys.h                               |    11 +-
 mesh/net.c                                    |   188 +-
 mesh/net.h                                    |     6 +-
 mesh/node.c                                   |   332 +-
 mesh/node.h                                   |     5 +
 mesh/pb-adv.c                                 |     6 +-
 mesh/pb-adv.h                                 |     2 +-
 mesh/prov-acceptor.c                          |    87 +-
 mesh/prov-initiator.c                         |   278 +-
 mesh/prov.h                                   |     4 +-
 mesh/provision.h                              |    23 +-
 mesh/prv-beacon.h                             |    36 +
 mesh/prvbeac-server.c                         |   128 +
 mesh/remprv-server.c                          |   919 +
 mesh/remprv.h                                 |    78 +
 mesh/rpl.c                                    |     4 +-
 mesh/util.c                                   |    10 +
 mesh/util.h                                   |     5 +
 missing                                       |   215 +
 monitor/a2dp.c                                |    48 +
 monitor/analyze.c                             |   514 +-
 monitor/att.c                                 |  2645 +-
 monitor/avctp.c                               |     5 +-
 monitor/broadcom.c                            |     3 +-
 monitor/bt.h                                  |    74 +-
 monitor/btmon.1                               |   258 +
 monitor/btmon.rst                             |     4 +-
 monitor/display.h                             |     2 +-
 monitor/hwdb.c                                |     2 +-
 monitor/intel.c                               |   238 +-
 monitor/jlink.c                               |     3 +-
 monitor/keys.c                                |    26 +
 monitor/keys.h                                |     2 +
 monitor/l2cap.c                               |    50 +-
 monitor/l2cap.h                               |     2 +
 monitor/ll.c                                  |    62 +-
 monitor/main.c                                |    12 +-
 monitor/msft.c                                |     3 +-
 monitor/packet.c                              |  1148 +-
 monitor/packet.h                              |    34 +-
 monitor/rfcomm.c                              |     2 +-
 monitor/sdp.c                                 |    10 +-
 monitor/vendor.h                              |     3 +-
 obexd/client/bip-common.c                     |   800 +
 obexd/client/bip-common.h                     |    24 +
 obexd/client/bip.c                            |   440 +
 obexd/client/bip.h                            |    12 +
 obexd/client/manager.c                        |    22 +-
 obexd/client/map.c                            |     4 +-
 obexd/client/mns.c                            |     8 +-
 obexd/client/pbap.c                           |     5 +-
 obexd/client/session.c                        |    27 +-
 obexd/client/session.h                        |     1 +
 obexd/client/transfer.c                       |    19 +
 obexd/client/transfer.h                       |     2 +
 obexd/plugins/bluetooth.c                     |     6 +-
 obexd/plugins/filesystem.c                    |    23 +-
 obexd/plugins/ftp.c                           |     7 +-
 obexd/plugins/irmc.c                          |     4 +-
 obexd/plugins/mas.c                           |    18 +-
 obexd/plugins/messages-dummy.c                |    12 +-
 obexd/plugins/messages-tracker.c              |   332 -
 obexd/plugins/opp.c                           |     7 +-
 obexd/plugins/pbap.c                          |     8 +-
 obexd/plugins/pcsuite.c                       |     5 +-
 obexd/plugins/phonebook-ebook.c               |     2 +-
 obexd/plugins/syncevolution.c                 |   470 -
 obexd/src/genbuiltin                          |     4 +-
 obexd/src/main.c                              |     2 +-
 obexd/src/manager.c                           |    26 +-
 obexd/src/mimetype.c                          |    29 +-
 obexd/src/mimetype.h                          |    14 +-
 obexd/src/obex-priv.h                         |     4 +-
 obexd/src/obex.c                              |    21 +-
 obexd/src/obex.service.in                     |     2 +-
 obexd/src/obexd.h                             |     2 +-
 ...obex.service => org.bluez.obex.service.in} |     2 +-
 obexd/src/plugin.c                            |    95 +-
 obexd/src/plugin.h                            |     8 +-
 obexd/src/server.c                            |    10 +-
 obexd/src/server.h                            |     2 +-
 obexd/src/service.c                           |    20 +-
 obexd/src/service.h                           |     6 +-
 obexd/src/transport.c                         |    17 +-
 obexd/src/transport.h                         |     7 +-
 peripheral/efivars.c                          |     1 +
 plugins/admin.c                               |     8 +-
 plugins/external-dummy.c                      |    28 -
 plugins/hostname.c                            |    63 +-
 plugins/policy.c                              |     4 +-
 plugins/sixaxis.c                             |     5 +
 profiles/audio/a2dp-codecs.h                  |    17 +
 profiles/audio/a2dp.c                         |    74 +-
 profiles/audio/asha.c                         |   525 +
 profiles/audio/asha.h                         |    38 +
 profiles/audio/avctp.c                        |     2 +-
 profiles/audio/avdtp.c                        |   166 +-
 profiles/audio/avdtp.h                        |     1 +
 profiles/audio/avrcp.c                        |   207 +-
 profiles/audio/avrcp.h                        |     4 +-
 profiles/audio/bap.c                          |  2888 ++-
 profiles/audio/bap.h                          |    11 +
 profiles/audio/bass.c                         |  1241 +
 profiles/audio/bass.h                         |    24 +
 profiles/audio/ccp.c                          |   233 +
 profiles/audio/csip.c                         |   479 +
 profiles/audio/mcp.c                          |    37 +-
 profiles/audio/media.c                        |   611 +-
 profiles/audio/media.h                        |     6 +-
 profiles/audio/micp.c                         |   340 +
 profiles/audio/player.c                       |    46 +-
 profiles/audio/player.h                       |     2 +
 profiles/audio/sink.c                         |     7 +-
 profiles/audio/source.c                       |     7 +-
 profiles/audio/transport.c                    |  1503 +-
 profiles/audio/transport.h                    |     4 +-
 profiles/audio/vcp.c                          |    18 +-
 profiles/gap/gas.c                            |   119 +-
 profiles/health/hdp_util.c                    |    15 +-
 profiles/health/mcap.c                        |    11 +
 profiles/iap/main.c                           |     2 +-
 profiles/input/device.c                       |   432 +-
 profiles/input/device.h                       |     9 +-
 profiles/input/hog-lib.c                      |   289 +-
 profiles/input/hog-lib.h                      |     6 +-
 profiles/input/hog.c                          |    11 +-
 profiles/input/input.conf                     |    15 +-
 profiles/input/manager.c                      |    14 +-
 profiles/input/suspend-dummy.c                |   149 -
 profiles/midi/midi.c                          |    27 +-
 src/adapter.c                                 |   555 +-
 src/adapter.h                                 |    27 +-
 src/adv_monitor.c                             |    17 +-
 src/advertising.c                             |   159 +-
 src/battery.c                                 |    23 +-
 src/bluetooth.service.in                      |     2 +-
 src/bluetooth.ver                             |     8 +
 src/bluetoothd.8                              |   120 +
 src/bluetoothd.rst                            |    93 +
 src/bluetoothd.rst.in                         |     9 +-
 src/btd.h                                     |    40 +-
 src/device.c                                  |   696 +-
 src/device.h                                  |    34 +-
 src/eir.c                                     |    25 +
 src/eir.h                                     |     4 +
 src/error.c                                   |     4 +
 src/error.h                                   |     2 +
 src/gatt-client.c                             |    44 +-
 src/gatt-database.c                           |   274 +-
 src/genbuiltin                                |     4 +-
 src/log.c                                     |     2 +-
 src/main.c                                    |   832 +-
 src/main.conf                                 |    62 +-
 src/oui.c                                     |     2 +-
 src/plugin.c                                  |   140 +-
 src/plugin.h                                  |    12 +-
 src/profile.c                                 |    12 +
 src/profile.h                                 |    10 +
 src/rfkill.c                                  |     3 +-
 src/set.c                                     |   393 +
 src/set.h                                     |    21 +
 src/settings.c                                |    35 +-
 src/shared/ad.c                               |   592 +-
 src/shared/ad.h                               |    17 +-
 src/shared/asha.c                             |   359 +
 src/shared/asha.h                             |    63 +
 src/shared/att-types.h                        |     4 +-
 src/shared/att.c                              |    54 +-
 src/shared/att.h                              |     3 +-
 src/shared/bap-debug.c                        |   543 +
 src/shared/bap-debug.h                        |    14 +
 src/shared/bap-defs.h                         |    97 +
 src/shared/bap.c                              |  7586 +++---
 src/shared/bap.h                              |   117 +-
 src/shared/bass.c                             |  1875 ++
 src/shared/bass.h                             |   136 +
 src/shared/btsnoop.c                          |    18 +-
 src/shared/ccp.c                              |  1226 +
 src/shared/ccp.h                              |    45 +
 src/shared/crypto.c                           |   247 +-
 src/shared/crypto.h                           |     7 +
 src/shared/csip.c                             |   845 +
 src/shared/csip.h                             |    64 +
 src/shared/ecc.c                              |     2 +
 src/shared/gatt-client.c                      |   289 +-
 src/shared/gatt-client.h                      |    11 +
 src/shared/gatt-db.c                          |   213 +-
 src/shared/gatt-db.h                          |     8 +
 src/shared/gatt-server.c                      |   117 +-
 src/shared/lc3.h                              |  1151 +-
 src/shared/log.c                              |     2 +-
 src/shared/mainloop-notify.c                  |     3 +-
 src/shared/mcp.c                              |    82 +-
 src/shared/mcp.h                              |     2 +
 src/shared/micp.c                             |   894 +
 src/shared/micp.h                             |    83 +
 src/shared/ringbuf.c                          |     2 +-
 src/shared/shell.c                            |   392 +-
 src/shared/shell.h                            |    22 +-
 src/shared/tester.c                           |    55 +
 src/shared/tester.h                           |     5 +
 src/shared/uhid.c                             |   414 +-
 src/shared/uhid.h                             |    39 +
 src/shared/util.c                             |   598 +-
 src/shared/util.h                             |    88 +-
 src/shared/vcp.c                              |  1702 +-
 src/storage.c                                 |     1 +
 src/textfile.c                                |     9 +-
 test-driver                                   |   153 +
 test/agent.py                                 |     2 +-
 test/example-adv-monitor                      |   403 -
 test/example-advertisement                    |     2 +-
 test/example-battery-provider                 |   232 -
 test/example-endpoint                         |   187 -
 test/example-gatt-client                      |     7 +-
 test/example-gatt-server                      |    11 +-
 test/example-player                           |   204 -
 test/exchange-business-cards                  |    20 -
 test/ftp-client                               |     2 +-
 test/get-managed-objects                      |    30 -
 test/get-obex-capabilities                    |    20 -
 test/list-devices                             |     2 +-
 test/list-folders                             |    40 -
 test/map-client                               |     2 +-
 test/monitor-bluetooth                        |     2 +-
 test/opp-client                               |     2 +-
 test/pbap-client                              |     2 +-
 test/sap_client.py                            |    68 +-
 test/simple-agent                             |     2 +-
 test/simple-endpoint                          |     2 +-
 test/simple-obex-agent                        |    88 -
 test/simple-player                            |     8 +-
 test/test-adapter                             |     2 +-
 test/test-device                              |     2 +-
 test/test-discovery                           |     2 +-
 test/test-gatt-profile                        |     2 +-
 test/test-health                              |     2 +-
 test/test-health-sink                         |     2 +-
 test/test-hfp                                 |     2 +-
 test/test-join                                |   436 -
 test/test-manager                             |     2 +-
 test/test-nap                                 |     2 +-
 test/test-network                             |     2 +-
 test/test-profile                             |     2 +-
 test/test-sap-server                          |     2 +-
 tools/advtest.c                               |    80 +-
 tools/avtest.c                                |    23 +-
 tools/bdaddr.1                                |    94 +
 tools/bdaddr.c                                |     1 +
 tools/bluemoon.c                              |     1 +
 tools/bluetooth-logger.service.in             |     2 +-
 tools/bluetooth-player.c                      |     9 +-
 tools/btattach.1                              |   123 +
 tools/btgatt-client.c                         |   251 +-
 tools/btiotest.c                              |    17 +-
 tools/btmgmt.1                                |   114 +
 tools/btmgmt.c                                |  6042 +----
 tools/btmgmt.rst                              |    79 +
 tools/btpclientctl.c                          |     2 +-
 tools/btsnoop.c                               |    10 +-
 tools/ciptool.1                               |    89 +
 tools/example.psr                             |    12 -
 tools/hciattach.1                             |   258 +
 tools/hciattach.c                             |     1 +
 tools/hciattach_ath3k.c                       |     1 +
 tools/hciattach_intel.c                       |     1 +
 tools/hciattach_st.c                          |     1 +
 tools/hciattach_ti.c                          |     1 +
 tools/hciconfig.1                             |   334 +
 tools/hcidump.1                               |   131 +
 tools/hcidump.c                               |     2 +-
 tools/hcitool.1                               |   229 +
 tools/hex2hcd.c                               |     1 +
 tools/hid2hci.1                               |    70 +
 tools/iso-tester.c                            |  2514 +-
 tools/isotest.1                               |   329 +
 tools/isotest.c                               |   646 +-
 tools/isotest.rst                             |    23 +
 tools/l2cap-tester.c                          |   858 +-
 tools/l2ping.1                                |    92 +
 tools/l2test.c                                |    31 +-
 tools/mesh-cfgclient.c                        |   500 +-
 tools/mesh-cfgtest.c                          |   188 +-
 tools/mesh-gatt/README                        |    43 -
 tools/mesh-gatt/local_node.json               |    61 -
 tools/mesh-gatt/prov_db.json                  |    37 -
 tools/mesh-gatt/util.c                        |     4 +-
 tools/mesh/README                             |    54 -
 tools/mesh/cfgcli.c                           |   114 +-
 tools/mesh/cfgcli.h                           |     2 +
 tools/mesh/mesh-db.c                          |    64 +-
 tools/mesh/mesh-db.h                          |     1 +
 tools/mesh/remote.c                           |   131 +
 tools/mesh/remote.h                           |     9 +
 tools/mesh/util.c                             |     9 +-
 tools/meshctl.c                               |    10 +-
 tools/mgmt-tester.c                           |   502 +-
 tools/missing.h                               |    21 +
 tools/mpris-proxy.service.in                  |    13 +
 tools/obexctl.c                               |    32 +-
 tools/parse_companies.pl                      |    66 -
 tools/parser/avrcp.c                          |     3 +
 tools/rctest.1                                |   126 +
 tools/rctest.c                                |    40 +-
 tools/rfcomm-tester.c                         |     5 +-
 tools/rfcomm.1                                |   128 +
 tools/rfcomm.c                                |     8 +-
 tools/sco-tester.c                            |   197 +-
 tools/sdptool.1                               |   122 +
 tools/test-runner.c                           |   240 +-
 tools/tester.h                                |   166 +
 tools/update_compids.sh                       |    43 -
 tools/valgrind.supp                           |    34 -
 unit/test-bap.c                               |  7380 ++++++
 unit/test-bass.c                              |   823 +
 unit/test-crypto.c                            |    74 +
 unit/test-eir.c                               |    51 +
 unit/test-gatt.c                              |    74 +-
 unit/test-hog.c                               |     2 +-
 unit/test-mesh-crypto.c                       |   182 +-
 unit/test-micp.c                              |   838 +
 unit/test-midi.c                              |    74 +-
 unit/test-uhid.c                              |   113 +-
 unit/test-vcp.c                               |  2761 +++
 666 files changed, 191278 insertions(+), 27580 deletions(-)
 delete mode 100644 .checkpatch.conf
 delete mode 100644 .gitignore
 delete mode 100644 .gitlint
 delete mode 100644 .mailmap
 delete mode 100644 HACKING
 delete mode 100644 LICENSES/dual/Apache-2.0
 delete mode 100644 LICENSES/preferred/BSD-2-Clause
 delete mode 100644 LICENSES/preferred/GPL-2.0
 delete mode 100644 LICENSES/preferred/LGPL-2.1
 delete mode 100644 LICENSES/preferred/MIT
 create mode 100644 Makefile.in
 create mode 100644 aclocal.m4
 delete mode 100644 android/sco-ipc-api.txt
 delete mode 100644 android/socket-api.txt
 delete mode 100755 bootstrap
 delete mode 100755 bootstrap-configure
 create mode 100644 client/assistant.c
 create mode 100644 client/assistant.h
 create mode 100644 client/bluetoothctl-admin.1
 create mode 100644 client/bluetoothctl-admin.rst
 create mode 100644 client/bluetoothctl-advertise.1
 create mode 100644 client/bluetoothctl-advertise.rst
 create mode 100644 client/bluetoothctl-assistant.1
 create mode 100644 client/bluetoothctl-assistant.rst
 create mode 100644 client/bluetoothctl-endpoint.1
 create mode 100644 client/bluetoothctl-endpoint.rst
 create mode 100644 client/bluetoothctl-gatt.1
 create mode 100644 client/bluetoothctl-gatt.rst
 create mode 100644 client/bluetoothctl-mgmt.1
 create mode 100644 client/bluetoothctl-mgmt.rst
 create mode 100644 client/bluetoothctl-monitor.1
 create mode 100644 client/bluetoothctl-monitor.rst
 create mode 100644 client/bluetoothctl-player.1
 create mode 100644 client/bluetoothctl-player.rst
 create mode 100644 client/bluetoothctl-scan.1
 create mode 100644 client/bluetoothctl-scan.rst
 create mode 100644 client/bluetoothctl-transport.1
 create mode 100644 client/bluetoothctl-transport.rst
 create mode 100644 client/bluetoothctl.1
 create mode 100644 client/bluetoothctl.rst
 create mode 100644 client/mgmt.c
 create mode 100644 client/mgmt.h
 create mode 100644 client/print.c
 create mode 100644 client/print.h
 create mode 100755 compile
 create mode 100755 config.guess
 create mode 100644 config.h.in
 create mode 100755 config.sub
 create mode 100755 configure
 create mode 100755 depcomp
 delete mode 100644 doc/adapter-api.txt
 delete mode 100644 doc/admin-policy-api.txt
 delete mode 100644 doc/advertisement-monitor-api.txt
 delete mode 100644 doc/advertising-api.txt
 delete mode 100644 doc/agent-api.txt
 delete mode 100644 doc/battery-api.txt
 delete mode 100644 doc/ci.config
 delete mode 100644 doc/coding-style.txt
 delete mode 100644 doc/device-api.txt
 delete mode 100644 doc/errors.txt
 delete mode 100644 doc/gatt-api.txt
 create mode 100644 doc/hci.7
 create mode 100644 doc/hci.rst
 delete mode 100644 doc/input-api.txt
 delete mode 100644 doc/intel-variants.txt
 create mode 100644 doc/l2cap.7
 create mode 100644 doc/l2cap.rst
 delete mode 100644 doc/maintainer-guidelines.txt
 delete mode 100644 doc/media-api.txt
 delete mode 100644 doc/mesh-api.txt
 delete mode 100644 doc/network-api.txt
 delete mode 100644 doc/obex-agent-api.txt
 delete mode 100644 doc/obex-api.txt
 create mode 100644 doc/org.bluez.Adapter.5
 create mode 100644 doc/org.bluez.Adapter.rst
 create mode 100644 doc/org.bluez.AdminPolicySet.5
 create mode 100644 doc/org.bluez.AdminPolicySet.rst
 create mode 100644 doc/org.bluez.AdminPolicyStatus.5
 create mode 100644 doc/org.bluez.AdminPolicyStatus.rst
 create mode 100644 doc/org.bluez.AdvertisementMonitor.5
 create mode 100644 doc/org.bluez.AdvertisementMonitor.rst
 create mode 100644 doc/org.bluez.AdvertisementMonitorManager.5
 create mode 100644 doc/org.bluez.AdvertisementMonitorManager.rst
 create mode 100644 doc/org.bluez.Agent.5
 create mode 100644 doc/org.bluez.Agent.rst
 create mode 100644 doc/org.bluez.AgentManager.5
 create mode 100644 doc/org.bluez.AgentManager.rst
 create mode 100644 doc/org.bluez.Battery.5
 create mode 100644 doc/org.bluez.Battery.rst
 create mode 100644 doc/org.bluez.BatteryProvider.5
 create mode 100644 doc/org.bluez.BatteryProvider.rst
 create mode 100644 doc/org.bluez.BatteryProviderManager.5
 create mode 100644 doc/org.bluez.BatteryProviderManager.rst
 create mode 100644 doc/org.bluez.Device.5
 create mode 100644 doc/org.bluez.Device.rst
 create mode 100644 doc/org.bluez.DeviceSet.5
 create mode 100644 doc/org.bluez.DeviceSet.rst
 create mode 100644 doc/org.bluez.GattCharacteristic.5
 create mode 100644 doc/org.bluez.GattCharacteristic.rst
 create mode 100644 doc/org.bluez.GattDescriptor.5
 create mode 100644 doc/org.bluez.GattDescriptor.rst
 create mode 100644 doc/org.bluez.GattManager.5
 create mode 100644 doc/org.bluez.GattManager.rst
 create mode 100644 doc/org.bluez.GattProfile.5
 create mode 100644 doc/org.bluez.GattProfile.rst
 create mode 100644 doc/org.bluez.GattService.5
 create mode 100644 doc/org.bluez.GattService.rst
 create mode 100644 doc/org.bluez.Input.5
 create mode 100644 doc/org.bluez.Input.rst
 create mode 100644 doc/org.bluez.LEAdvertisement.5
 create mode 100644 doc/org.bluez.LEAdvertisement.rst
 create mode 100644 doc/org.bluez.LEAdvertisingManager.5
 create mode 100644 doc/org.bluez.LEAdvertisingManager.rst
 create mode 100644 doc/org.bluez.Media.5
 create mode 100644 doc/org.bluez.Media.rst
 create mode 100644 doc/org.bluez.MediaAssistant.5
 create mode 100644 doc/org.bluez.MediaAssistant.rst
 create mode 100644 doc/org.bluez.MediaControl.5
 create mode 100644 doc/org.bluez.MediaControl.rst
 create mode 100644 doc/org.bluez.MediaEndpoint.5
 create mode 100644 doc/org.bluez.MediaEndpoint.rst
 create mode 100644 doc/org.bluez.MediaFolder.5
 create mode 100644 doc/org.bluez.MediaFolder.rst
 create mode 100644 doc/org.bluez.MediaItem.5
 create mode 100644 doc/org.bluez.MediaItem.rst
 create mode 100644 doc/org.bluez.MediaPlayer.5
 create mode 100644 doc/org.bluez.MediaPlayer.rst
 create mode 100644 doc/org.bluez.MediaTransport.5
 create mode 100644 doc/org.bluez.MediaTransport.rst
 create mode 100644 doc/org.bluez.Network.5
 create mode 100644 doc/org.bluez.Network.rst
 create mode 100644 doc/org.bluez.NetworkServer.5
 create mode 100644 doc/org.bluez.NetworkServer.rst
 create mode 100644 doc/org.bluez.Profile.5
 create mode 100644 doc/org.bluez.Profile.rst
 create mode 100644 doc/org.bluez.ProfileManager.5
 create mode 100644 doc/org.bluez.ProfileManager.rst
 create mode 100644 doc/org.bluez.obex.Agent.5
 create mode 100644 doc/org.bluez.obex.Agent.rst
 create mode 100644 doc/org.bluez.obex.AgentManager.5
 create mode 100644 doc/org.bluez.obex.AgentManager.rst
 create mode 100644 doc/org.bluez.obex.Client.5
 create mode 100644 doc/org.bluez.obex.Client.rst
 create mode 100644 doc/org.bluez.obex.FileTransfer.5
 create mode 100644 doc/org.bluez.obex.FileTransfer.rst
 create mode 100644 doc/org.bluez.obex.Image.5
 create mode 100644 doc/org.bluez.obex.Image.rst
 create mode 100644 doc/org.bluez.obex.Message.5
 create mode 100644 doc/org.bluez.obex.Message.rst
 create mode 100644 doc/org.bluez.obex.MessageAccess.5
 create mode 100644 doc/org.bluez.obex.MessageAccess.rst
 create mode 100644 doc/org.bluez.obex.ObjectPush.5
 create mode 100644 doc/org.bluez.obex.ObjectPush.rst
 create mode 100644 doc/org.bluez.obex.PhonebookAccess.5
 create mode 100644 doc/org.bluez.obex.PhonebookAccess.rst
 create mode 100644 doc/org.bluez.obex.Session.5
 create mode 100644 doc/org.bluez.obex.Session.rst
 create mode 100644 doc/org.bluez.obex.Synchronization.5
 create mode 100644 doc/org.bluez.obex.Synchronization.rst
 create mode 100644 doc/org.bluez.obex.Transfer.5
 create mode 100644 doc/org.bluez.obex.Transfer.rst
 delete mode 100644 doc/profile-api.txt
 create mode 100644 doc/rfcomm.7
 create mode 100644 doc/rfcomm.rst
 delete mode 100644 doc/security-bugs.txt
 create mode 100644 doc/test-runner.rst
 delete mode 100644 doc/test-runner.txt
 delete mode 100644 doc/tester.config
 delete mode 100644 doc/thermometer-api.txt
 create mode 100644 ell/asn1-private.h
 create mode 100644 ell/base64.c
 create mode 100644 ell/base64.h
 create mode 100644 ell/cert-crypto.c
 create mode 100644 ell/cert-private.h
 create mode 100644 ell/cert.c
 create mode 100644 ell/cert.h
 create mode 100644 ell/checksum.c
 create mode 100644 ell/checksum.h
 create mode 100644 ell/cipher.c
 create mode 100644 ell/cipher.h
 create mode 100644 ell/cleanup.h
 create mode 100644 ell/dbus-client.c
 create mode 100644 ell/dbus-client.h
 create mode 100644 ell/dbus-filter.c
 create mode 100644 ell/dbus-message.c
 create mode 100644 ell/dbus-name-cache.c
 create mode 100644 ell/dbus-private.h
 create mode 100644 ell/dbus-service.c
 create mode 100644 ell/dbus-service.h
 create mode 100644 ell/dbus-util.c
 create mode 100644 ell/dbus.c
 create mode 100644 ell/dbus.h
 create mode 100644 ell/ecc-external.c
 create mode 100644 ell/ecc-private.h
 create mode 100644 ell/ecc.c
 create mode 100644 ell/ecc.h
 create mode 100644 ell/ecdh.c
 create mode 100644 ell/ecdh.h
 create mode 100644 ell/ell.h
 create mode 100644 ell/gvariant-private.h
 create mode 100644 ell/gvariant-util.c
 create mode 100644 ell/hashmap.c
 create mode 100644 ell/hashmap.h
 create mode 100644 ell/idle.c
 create mode 100644 ell/idle.h
 create mode 100644 ell/internal
 create mode 100644 ell/io.c
 create mode 100644 ell/io.h
 create mode 100644 ell/key.c
 create mode 100644 ell/key.h
 create mode 100644 ell/log.c
 create mode 100644 ell/log.h
 create mode 100644 ell/main-private.h
 create mode 100644 ell/main.c
 create mode 100644 ell/main.h
 create mode 100644 ell/missing.h
 create mode 100644 ell/pem-private.h
 create mode 100644 ell/pem.c
 create mode 100644 ell/pem.h
 create mode 100644 ell/private.h
 create mode 100644 ell/queue.c
 create mode 100644 ell/queue.h
 create mode 100644 ell/random.c
 create mode 100644 ell/random.h
 create mode 100644 ell/settings.c
 create mode 100644 ell/settings.h
 create mode 100644 ell/signal.c
 create mode 100644 ell/signal.h
 create mode 100644 ell/siphash-private.h
 create mode 100644 ell/siphash.c
 create mode 100644 ell/string.c
 create mode 100644 ell/string.h
 create mode 100644 ell/strv.c
 create mode 100644 ell/strv.h
 create mode 100644 ell/tester.c
 create mode 100644 ell/tester.h
 create mode 100644 ell/time-private.h
 create mode 100644 ell/time.c
 create mode 100644 ell/time.h
 create mode 100644 ell/timeout.c
 create mode 100644 ell/timeout.h
 create mode 100644 ell/tls-extensions.c
 create mode 100644 ell/tls-private.h
 create mode 100644 ell/tls-record.c
 create mode 100644 ell/tls-suites.c
 create mode 100644 ell/tls.c
 create mode 100644 ell/tls.h
 create mode 100644 ell/useful.h
 create mode 100644 ell/utf8.c
 create mode 100644 ell/utf8.h
 create mode 100644 ell/util.c
 create mode 100644 ell/util.h
 create mode 100644 ell/uuid.c
 create mode 100644 ell/uuid.h
 create mode 100755 install-sh
 create mode 100755 ltmain.sh
 delete mode 100644 mesh/README
 create mode 100644 mesh/prv-beacon.h
 create mode 100644 mesh/prvbeac-server.c
 create mode 100644 mesh/remprv-server.c
 create mode 100644 mesh/remprv.h
 create mode 100755 missing
 create mode 100644 monitor/btmon.1
 create mode 100644 obexd/client/bip-common.c
 create mode 100644 obexd/client/bip-common.h
 create mode 100644 obexd/client/bip.c
 create mode 100644 obexd/client/bip.h
 delete mode 100644 obexd/plugins/messages-tracker.c
 delete mode 100644 obexd/plugins/syncevolution.c
 rename obexd/src/{org.bluez.obex.service => org.bluez.obex.service.in} (74%)
 delete mode 100644 plugins/external-dummy.c
 create mode 100644 profiles/audio/asha.c
 create mode 100644 profiles/audio/asha.h
 create mode 100644 profiles/audio/bap.h
 create mode 100644 profiles/audio/bass.c
 create mode 100644 profiles/audio/bass.h
 create mode 100644 profiles/audio/ccp.c
 create mode 100644 profiles/audio/csip.c
 create mode 100644 profiles/audio/micp.c
 delete mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 src/bluetoothd.8
 create mode 100644 src/bluetoothd.rst
 create mode 100644 src/set.c
 create mode 100644 src/set.h
 create mode 100644 src/shared/asha.c
 create mode 100644 src/shared/asha.h
 create mode 100644 src/shared/bap-debug.c
 create mode 100644 src/shared/bap-debug.h
 create mode 100644 src/shared/bap-defs.h
 create mode 100644 src/shared/bass.c
 create mode 100644 src/shared/bass.h
 create mode 100644 src/shared/ccp.c
 create mode 100644 src/shared/ccp.h
 create mode 100644 src/shared/csip.c
 create mode 100644 src/shared/csip.h
 create mode 100644 src/shared/micp.c
 create mode 100644 src/shared/micp.h
 create mode 100755 test-driver
 delete mode 100644 test/example-adv-monitor
 delete mode 100755 test/example-battery-provider
 delete mode 100644 test/example-endpoint
 delete mode 100644 test/example-player
 delete mode 100755 test/exchange-business-cards
 delete mode 100755 test/get-managed-objects
 delete mode 100755 test/get-obex-capabilities
 delete mode 100755 test/list-folders
 delete mode 100755 test/simple-obex-agent
 delete mode 100644 test/test-join
 create mode 100644 tools/bdaddr.1
 create mode 100644 tools/btattach.1
 create mode 100644 tools/btmgmt.1
 create mode 100644 tools/btmgmt.rst
 create mode 100644 tools/ciptool.1
 delete mode 100644 tools/example.psr
 create mode 100644 tools/hciattach.1
 create mode 100644 tools/hciconfig.1
 create mode 100644 tools/hcidump.1
 create mode 100644 tools/hcitool.1
 create mode 100644 tools/hid2hci.1
 create mode 100644 tools/isotest.1
 create mode 100644 tools/l2ping.1
 delete mode 100644 tools/mesh-gatt/README
 delete mode 100644 tools/mesh-gatt/local_node.json
 delete mode 100644 tools/mesh-gatt/prov_db.json
 delete mode 100644 tools/mesh/README
 create mode 100644 tools/missing.h
 create mode 100644 tools/mpris-proxy.service.in
 delete mode 100755 tools/parse_companies.pl
 create mode 100644 tools/rctest.1
 create mode 100644 tools/rfcomm.1
 create mode 100644 tools/sdptool.1
 create mode 100644 tools/tester.h
 delete mode 100755 tools/update_compids.sh
 delete mode 100644 tools/valgrind.supp
 create mode 100644 unit/test-bap.c
 create mode 100644 unit/test-bass.c
 create mode 100644 unit/test-micp.c
 create mode 100644 unit/test-vcp.c

diff --git a/.checkpatch.conf b/.checkpatch.conf
deleted file mode 100644
index 72c3529..0000000
--- a/.checkpatch.conf
+++ /dev/null
@@ -1,15 +0,0 @@
---no-tree
---no-signoff
---summary-file
---show-types
---max-line-length=80
-
---ignore COMPLEX_MACRO
---ignore SPLIT_STRING
---ignore CONST_STRUCT
---ignore FILE_PATH_CHANGES
---ignore MISSING_SIGN_OFF
---ignore PREFER_PACKED
---ignore COMMIT_MESSAGE
---ignore SSCANF_TO_KSTRTO
---ignore SPDX_LICENSE_TAG
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 9f57aa1..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,189 +0,0 @@
-*.o
-*.a
-*.lo
-*.la
-*.so
-*.gcno
-*.gcda
-.deps
-.libs
-.dirstamp
-Makefile
-Makefile.in
-aclocal.m4
-config.guess
-config.h
-config.h.in
-config.h.in~
-config.log
-config.status
-config.sub
-configure
-depcomp
-compile
-install-sh
-libtool
-ltmain.sh
-missing
-stamp-h1
-autom4te.cache
-test-driver
-test-suite.log
-coverage.info
-coverage
-ell
-
-lib/bluez.pc
-lib/bluetooth
-src/builtin.h
-src/bluetoothd
-tools/97-hid2hci.rules
-
-profiles/cups/bluetooth
-profiles/iap/iapd
-
-attrib/gatttool
-tools/avinfo
-tools/bccmd
-tools/hwdb
-tools/ciptool
-tools/ciptool.1
-tools/hciattach
-tools/hciattach.1
-tools/hciconfig
-tools/hciconfig.1
-tools/hcieventmask
-tools/hcisecfilter
-tools/hcitool
-tools/hcitool.1
-tools/hcidump
-tools/hcidump.1
-tools/hid2hci
-tools/hid2hci.1
-tools/rfcomm
-tools/rfcomm.1
-tools/l2ping
-tools/l2ping.1
-tools/l2test
-tools/cltest
-tools/rctest
-tools/rctest.1
-tools/scotest
-tools/amptest
-tools/oobtest
-tools/advtest
-tools/sdptool
-tools/sdptool.1
-tools/avtest
-tools/bdaddr
-tools/bluemoon
-tools/seq2bseq
-tools/hex2hcd
-tools/bcmfw
-tools/nokfw
-tools/rtlfw
-tools/btiotest
-tools/mpris-proxy
-tools/bluetooth-player
-tools/l2cap-tester
-tools/sco-tester
-tools/hci-tester
-tools/eddystone
-tools/ibeacon
-tools/btproxy
-tools/btinfo
-tools/3dsp
-tools/obexctl
-tools/gatt-service
-tools/btgatt-client
-tools/btgatt-server
-tools/create-image
-tools/test-runner
-tools/check-selftest
-tools/mcaptest
-tools/bneptest
-test/sap_client.pyc
-test/bluezutils.pyc
-unit/test-ringbuf
-unit/test-queue
-unit/test-eir
-unit/test-uuid
-unit/test-crc
-unit/test-textfile
-unit/test-gdbus-client
-unit/test-sdp
-unit/test-lib
-unit/test-mgmt
-unit/test-uhid
-unit/test-hfp
-unit/test-crypto
-unit/test-ecc
-unit/test-hog
-tools/mgmt-tester
-tools/smp-tester
-tools/gap-tester
-tools/rfcomm-tester
-tools/bnep-tester
-tools/userchan-tester
-tools/btattach
-tools/btattach.1
-tools/btconfig
-tools/btmgmt
-tools/btsnoop
-tools/btpclient
-tools/btpclientctl
-tools/btmon-logger
-tools/bluetooth-logger.service
-peripheral/btsensor
-monitor/btmon
-monitor/btmon.1
-emulator/btvirt
-emulator/b1ee
-emulator/hfp
-client/bluetoothctl
-tools/meshctl
-tools/mesh-cfgclient
-tools/mesh-cfgtest
-mesh/bluetooth-meshd
-mesh/bluetooth-meshd.8
-mesh/bluetooth-meshd.rst
-
-src/bluetoothd.8
-src/bluetoothd.rst
-src/bluetooth.service
-mesh/bluetooth-mesh.service
-
-obexd/src/builtin.h
-obexd/src/obexd
-obexd/src/obex.service
-tools/obex-client-tool
-tools/obex-server-tool
-unit/test-gobex
-unit/test-gobex-apparam
-unit/test-gobex-header
-unit/test-gobex-packet
-unit/test-gobex-transfer
-unit/test-avdtp
-unit/test-avctp
-unit/test-avrcp
-unit/test-gatt
-unit/test-midi
-unit/test-gattrib
-unit/test-mesh-crypto
-unit/test-*.log
-unit/test-*.trs
-
-android/system-emulator
-android/bluetoothd
-android/avdtptest
-android/haltest
-android/android-tester
-android/ipc-tester
-android/bluetoothd-snoop
-android/test-ipc
-android/test-*.log
-android/test-*.trs
-
-cscope.in.out
-cscope.out
-cscope.po.out
diff --git a/.gitlint b/.gitlint
deleted file mode 100644
index 59ed7d6..0000000
--- a/.gitlint
+++ /dev/null
@@ -1,48 +0,0 @@
-# All these sections are optional, edit this file as you like.
-# [general]
-# ignore=title-trailing-punctuation, T3
-# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this
-# verbosity = 2
-# By default gitlint will ignore merge commits. Set to 'false' to disable.
-# ignore-merge-commits=true
-# Enable debug mode (prints more output). Disabled by default.
-# debug=true
-
-# Set the extra-path where gitlint will search for user defined rules
-# See http://jorisroovers.github.io/gitlint/user_defined_rules for details
-# extra-path=examples/
-
-[title-max-length]
-line-length=72
-
-# [title-must-not-contain-word]
-# Comma-separated list of words that should not occur in the title. Matching is case
-# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING"
-# will not cause a violation, but "WIP: my title" will.
-# words=wip
-
-# [title-match-regex]
-# python like regex (https://docs.python.org/2/library/re.html) that the
-# commit-msg title must be matched to.
-# Note that the regex can contradict with other rules if not used correctly
-# (e.g. title-must-not-contain-word).
-# regex=^US[0-9]*
-
-# [B1]
-# B1 = body-max-line-length
-# line-length=120
-
-[body-min-length]
-min-length=1
-
-# [body-is-missing]
-# Whether to ignore this rule on merge commits (which typically only have a title)
-# default = True
-# ignore-merge-commits=false
-
-# [body-changed-file-mention]
-# List of files that need to be explicitly mentioned in the body when they are changed
-# This is useful for when developers often erroneously edit certain files or git submodules.
-# By specifying this rule, developers can only change the file when they explicitly reference
-# it in the commit message.
-# files=gitlint/rules.py,README.md
diff --git a/.mailmap b/.mailmap
deleted file mode 100644
index a7e36e3..0000000
--- a/.mailmap
+++ /dev/null
@@ -1,11 +0,0 @@
-Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>	<luiz.dentz-von@nokia.com>
-Vinicius Costa Gomes <vinicius.gomes@openbossa.org>	<vinicius.gomes@openbossa.org>
-Elvis Pfützenreuter <epx@signove.com>			<epx@signove.com>
-Santiago Carot-Nemesio <scarot@libresoft.es>		<scarot@libresoft.es>
-José Antonio Santos Cadenas <santoscadenas@gmail.com>	<santoscadenas@gmail.com>
-Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>	<Waldemar.Rymarkiewicz@tieto.com>
-Alok Barsode <alokbarsode@gmail.com>			<alok@greatbear.(none)>
-André Dieb Martins <andre.dieb@signove.com>		<andre.dieb@signove.com>
-Tedd Ho-Jeong An <tedd.an@intel.com>			<tedd.an@intel.com>
-Martin Xu <martin.xu@linux.intel.com>			<martin.xu@linux.intel.com>
-Marie Janssen <jamuraa@chromium.org>			<jamuraa@chromium.org>
diff --git a/AUTHORS b/AUTHORS
index 291d9b0..879f97f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -53,7 +53,7 @@ Daniel Orstadius <daniel.orstadius@gmail.com>
 Anderson Briglia <anderson.briglia@openbossa.org>
 Anderson Lizardo <anderson.lizardo@openbossa.org>
 Bruna Moreira <bruna.moreira@openbossa.org>
-Brian Gix <brian.gix@intel.com>
+Brian Gix <brian.gix@gmail.com>
 Andre Guedes <andre.guedes@openbossa.org>
 Sheldon Demario <sheldon.demario@openbossa.org>
 Lucas De Marchi <lucas.demarchi@profusion.mobi>
@@ -84,7 +84,7 @@ Petri Gynther <pgynther@google.com>
 Scott James Remnant <scott@netsplit.com>
 Jakub Tyszkowski <jakub.tyszkowski@tieto.com>
 Grzegorz Kołodziejczyk <grzegorz.kolodziejczyk@codecoup.pl>
-Marcin KrÄ…glak <marcin.kraglak@tieto.com>
+Marcin KrÄ…glak <marcin.kraglak@telink-semi.com>
 Łukasz Rymanowski <lukasz.rymanowski@codecoup.pl>
 Jerzy Kasenberg <jerzy.kasenberg@tieto.com>
 Arman Uguray <armansito@chromium.org>
diff --git a/ChangeLog b/ChangeLog
index ad0e679..766f0a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,95 @@
+ver 5.79:
+	Fix issue with handling address type while pairing.
+	Add support for allowing to set A2DP transport delay.
+	Add support for persistent userspace HID operation.
+	Add support for handling syncing to multiple BISes.
+
+ver 5.78:
+	Fix issue with handling notification of scanned BISes to BASS
+	Fix issue with handling checking BIS caps against peer caps.
+	Fix issue with handling MGMT Set Device Flags overwrites.
+	Fix issue with handling ASE notification order.
+	Fix issue with handling BIG Info report events.
+	Fix issue with handling PACS Server role.
+	Fix issue with registering UHID_START multiple times.
+	Fix issue with pairing method not setting auto-connect.
+
+ver 5.77:
+	Fix issue with storing and handling connection parameters.
+	Fix issue with handling device that are marked as temporary.
+	Fix issue with HID and special handling for non-keyboards.
+	Fix issue with BR/EDR not support when discoverable is off.
+	Add support for initial implementation of ASHA profile.
+
+ver 5.76:
+	Fix issue with broadcast channel location and stream capabilities.
+	Fix issue with handling BIS management and synchronization.
+	Fix issue with handling Extended Advertising.
+	Fix issue with UserspaceHID and replay structures.
+	Add support for providing PPCP characteristic.
+
+ver 5.75:
+	Fix issue with build system and header inclusion.
+
+ver 5.74:
+	Fix issue with not enabling Wideband Speech when available.
+	Fix issue with UserspaceHID and Bluetooth Classic devices.
+	Fix issue with checking for services being connected.
+	Fix issue with GATT client connection creation.
+	Fix issue with OBEX and small file transfers.
+	Fix issue with handling pairing with Apple AirPods.
+
+ver 5.73:
+	Fix issue with BAP and setting up broadcast source.
+	Fix issue with BAP and register all endpoints.
+	Fix issue with BAP and missing metadata property.
+	Fix issue with BAP and not handling out of order responses.
+	Fix issue with BAP and attempting to set device as connectable.
+	Add support for CCP plugin for call control profile.
+
+ver 5.72:
+	Fix issue with BAP and handling stream IO linking.
+	Fix issue with BAP and setup of multiple streams per endpoint.
+	Fix issue with AVDTP and potential incorrect transaction label.
+	Fix issue with A2DP and handling crash on suspend.
+	Fix issue with GATT database and an invalid pointer.
+	Add support for AICS service.
+
+ver 5.71:
+	Fix issue with not registering CSIS service.
+	Fix issue with registering pairing callbacks.
+	Fix issue with corruption during discovery filter parsing.
+
+ver 5.70:
+	Fix issue with not sending GATT confirmations.
+	Fix issue with not handling initiator properly.
+	Fix issue with not checking PBAP counter length.
+	Add support for MICP profile and MICS service.
+
+ver 5.69:
+	Fix issue with BAP enabling state correctly when resuming.
+	Fix issue with detaching source ASEs only after Stop Ready.
+	Fix issue with handling VCP audio location and descriptor.
+	Fix issue with generating IRK for adapter with privacy enabled.
+	Add support for BAP broadcast sink.
+
+ver 5.68:
+	Fix issue with A2DP and handling of Transport.Acquire.
+
+ver 5.67:
+	Fix issue with BAP and initiating QoS and Enable procedures.
+	Fix issue with BAP and detaching streams when PAC is removed.
+	Fix issue with BAP and reading all instances of PAC.
+	Fix issue with BAP and not being able to reconfigure.
+	Fix issue with BAP and transport configuration changes.
+	Fix issue with BAP and handling unexpected disconnect.
+	Fix issue with GATT and not removing pending services.
+	Fix issue with GATT and client ready handling.
+	Fix issue with handling fallback to transient hostname.
+	Add support for SecureConnections configuration option.
+	Add support for Mesh Remove Provisioning.
+	Add support for Mesh Private Beacons.
+
 ver 5.66:
 	Fix issue with A2DP and transport connection collisions.
 	Fix issue with allowing application specific error codes.
diff --git a/HACKING b/HACKING
deleted file mode 100644
index 29b136b..0000000
--- a/HACKING
+++ /dev/null
@@ -1,151 +0,0 @@
-Hacking on BlueZ
-****************
-
-Build tools requirements
-========================
-
-When building and testing directly from the repository it is important to
-have at least automake version 1.10 or later installed.
-
-
-Working with the source code repository
-=======================================
-
-The repository contains two extra scripts that accomplish the bootstrap
-process. One is called "bootstrap" which is the basic scripts that uses the
-autotools scripts to create the needed files for building and installing.
-It makes sure to call the right programs depending on the usage of shared or
-static libraries or translations etc.
-
-The second program is called "bootstrap-configure". This program will make
-sure to properly clean the repository, call the "bootstrap" script and then
-call configure with proper settings for development. It will use the best
-options and pass them over to configure. These options normally include
-the enabling the maintainer mode and the debugging features.
-
-So while in a normal source project the call "./configure ..." is used to
-configure the project with its settings like prefix and extra options. In
-case of bare repositories call "./bootstrap-configure" and it will bootstrap
-the repository and calls configure with all the correct options to make
-development easier.
-
-In case of preparing for a release with "make distcheck", don't use
-bootstrap-configure since it could export development specific settings.
-
-So the normal steps to checkout, build and install such a repository is
-like this:
-
-  Checkout repository
-    # git clone git://git.kernel.org/pub/scm/bluetooth/bluez.git
-    # cd bluez
-
-  Configure and build
-    # ./bootstrap-configure
-    # make
-
-  Configure and build with cgcc (Sparse)
-    # ./bootstrap-configure CC=cgcc
-    # make
-
-  Run unit tests
-    # make check
-
-  Check installation
-    # make install DESTDIR=$PWD/x
-    # find x
-    # rm -rf x
-
-  Check distribution
-    # make distcheck
-
-  Final installation
-    # sudo make install
-
-  Remove autogenerated files
-    # make maintainer-clean
-
-
-Running from within the source code repository
-==============================================
-
-When using "./configure --enable-maintainer-mode" the automake scripts will
-use the plugins directly from within the repository. This removes the need
-to use "make install" when testing "bluetoothd". The "bootstrap-configure"
-automatically includes this option.
-
-  Copy configuration file which specifies the required security policies
-    # sudo cp ./src/bluetooth.conf /etc/dbus-1/system.d/
-
-  Disable SELinux
-    # sudo setenforce 0
-
-  Run daemon in foreground with debugging
-    # sudo ./src/bluetoothd -n -d -f ./src/main.conf
-
-  Run daemon with valgrind
-   # sudo valgrind --trace-children=yes --track-origins=yes --track-fds=yes \
-   --show-possibly-lost=no --leak-check=full --suppressions=./tools/valgrind.supp \
-   ./src/bluetoothd -n -d -f ./src/main.conf
-
-For production installations or distribution packaging it is important that
-the "--enable-maintainer-mode" option is NOT used.
-
-Note multiple arguments to -d can be specified, colon, comma or space
-separated. The arguments are relative source code filenames for which
-debugging output should be enabled; output shell-style globs are
-accepted (e.g.: 'plugins/*:src/main.c').
-
-Submitting patches
-==================
-
-If you fixed a bug or you want to add support for something, patches are
-welcome! In order to ease the inclusion of your patch, it's important to follow
-some rules, otherwise it will likely be rejected by maintainers.
-
-Make sure the author name and email are set properly:
-
-  # git config --global user.name <name>
-  # git config --global user.email <email>
-
-The preferred way to send patches is by email, using git send-email:
-
-  # git config --global sendemail.smtpencryption <tls>
-  # git config --global sendemail.smtpserver <smtp.gmail.com>
-  # git config --global sendemail.smtpuser <yourname@gmail.com>
-  # git config --global sendemail.smtpserverport <587>
-  # git config sendemail.to linux-bluetooth@vger.kernel.org
-
-BlueZ rules for submitting patches follow most of the rules used by Linux kernel
-(https://www.kernel.org/doc/Documentation/SubmittingPatches) with some remarks:
-
-1) Do *not* add "Signed-off-by" lines in your commit messages. BlueZ does not
-use them, so including them is actually an error.
-
-2) Be sure to follow the coding style rules of BlueZ. They are listed in
-doc/coding-style.txt.
-
-3) Split your patch according to the top-level directories. E.g.: if you added
-a feature that touches files under 'include/', 'src/' and 'drivers/'
-directories, split in three separated patches, taking care not to
-break compilation.
-
-4) Bug fixes should be sent first as they take priority over new features.
-
-5) The commit message should follow 50/72 formatting which means the header
-should be limited to 50 characters and the description should be wrapped at 72
-characters except if it contains quoted information from debug tools like
-backtraces, compiler errors, etc.
-
-6) Prefix the email subject with [PATCH BlueZ]:
-
-  # git config format.subjectprefix "PATCH BlueZ"
-
-7) Add a cover letter when introducing a new feature explaning what problem
-you're trying to solve:
-
-  # git format-patch --cover-letter -M origin/master -o outgoing/
-  # edit outgoing/0000-*
-
-8) Submit:
-
-  # git send-email outgoing/*
diff --git a/LICENSES/dual/Apache-2.0 b/LICENSES/dual/Apache-2.0
deleted file mode 100644
index 6e89dde..0000000
--- a/LICENSES/dual/Apache-2.0
+++ /dev/null
@@ -1,187 +0,0 @@
-Valid-License-Identifier: Apache-2.0
-SPDX-URL: https://spdx.org/licenses/Apache-2.0.html
-Usage-Guide:
-  Do NOT use. The Apache-2.0 is not GPL2 compatible. It may only be used
-  for dual-licensed files where the other license is GPL2 compatible.
-  If you end up using this it MUST be used together with a GPL2 compatible
-  license using "OR".
-  To use the Apache License version 2.0 put the following SPDX tag/value
-  pair into a comment according to the placement guidelines in the
-  licensing rules documentation:
-    SPDX-License-Identifier: Apache-2.0
-License-Text:
-
-Apache License
-
-Version 2.0, January 2004
-
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the
-copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other
-entities that control, are controlled by, or are under common control with
-that entity. For the purposes of this definition, "control" means (i) the
-power, direct or indirect, to cause the direction or management of such
-entity, whether by contract or otherwise, or (ii) ownership of fifty
-percent (50%) or more of the outstanding shares, or (iii) beneficial
-ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications,
-including but not limited to software source code, documentation source,
-and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation
-or translation of a Source form, including but not limited to compiled
-object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form,
-made available under the License, as indicated by a copyright notice that
-is included in or attached to the work (an example is provided in the
-Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form,
-that is based on (or derived from) the Work and for which the editorial
-revisions, annotations, elaborations, or other modifications represent, as
-a whole, an original work of authorship. For the purposes of this License,
-Derivative Works shall not include works that remain separable from, or
-merely link (or bind by name) to the interfaces of, the Work and Derivative
-Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original
-version of the Work and any modifications or additions to that Work or
-Derivative Works thereof, that is intentionally submitted to Licensor for
-inclusion in the Work by the copyright owner or by an individual or Legal
-Entity authorized to submit on behalf of the copyright owner. For the
-purposes of this definition, "submitted" means any form of electronic,
-verbal, or written communication sent to the Licensor or its
-representatives, including but not limited to communication on electronic
-mailing lists, source code control systems, and issue tracking systems that
-are managed by, or on behalf of, the Licensor for the purpose of discussing
-and improving the Work, but excluding communication that is conspicuously
-marked or otherwise designated in writing by the copyright owner as "Not a
-Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on
-behalf of whom a Contribution has been received by Licensor and
-subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this
-   License, each Contributor hereby grants to You a perpetual, worldwide,
-   non-exclusive, no-charge, royalty-free, irrevocable copyright license to
-   reproduce, prepare Derivative Works of, publicly display, publicly
-   perform, sublicense, and distribute the Work and such Derivative Works
-   in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this
-   License, each Contributor hereby grants to You a perpetual, worldwide,
-   non-exclusive, no-charge, royalty-free, irrevocable (except as stated in
-   this section) patent license to make, have made, use, offer to sell,
-   sell, import, and otherwise transfer the Work, where such license
-   applies only to those patent claims licensable by such Contributor that
-   are necessarily infringed by their Contribution(s) alone or by
-   combination of their Contribution(s) with the Work to which such
-   Contribution(s) was submitted. If You institute patent litigation
-   against any entity (including a cross-claim or counterclaim in a
-   lawsuit) alleging that the Work or a Contribution incorporated within
-   the Work constitutes direct or contributory patent infringement, then
-   any patent licenses granted to You under this License for that Work
-   shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or
-   Derivative Works thereof in any medium, with or without modifications,
-   and in Source or Object form, provided that You meet the following
-   conditions:
-
-   a. You must give any other recipients of the Work or Derivative Works a
-      copy of this License; and
-
-   b. You must cause any modified files to carry prominent notices stating
-      that You changed the files; and
-
-   c. You must retain, in the Source form of any Derivative Works that You
-      distribute, all copyright, patent, trademark, and attribution notices
-      from the Source form of the Work, excluding those notices that do not
-      pertain to any part of the Derivative Works; and
-
-   d. If the Work includes a "NOTICE" text file as part of its
-      distribution, then any Derivative Works that You distribute must
-      include a readable copy of the attribution notices contained within
-      such NOTICE file, excluding those notices that do not pertain to any
-      part of the Derivative Works, in at least one of the following
-      places: within a NOTICE text file distributed as part of the
-      Derivative Works; within the Source form or documentation, if
-      provided along with the Derivative Works; or, within a display
-      generated by the Derivative Works, if and wherever such third-party
-      notices normally appear. The contents of the NOTICE file are for
-      informational purposes only and do not modify the License. You may
-      add Your own attribution notices within Derivative Works that You
-      distribute, alongside or as an addendum to the NOTICE text from the
-      Work, provided that such additional attribution notices cannot be
-      construed as modifying the License.
-
-    You may add Your own copyright statement to Your modifications and may
-    provide additional or different license terms and conditions for use,
-    reproduction, or distribution of Your modifications, or for any such
-    Derivative Works as a whole, provided Your use, reproduction, and
-    distribution of the Work otherwise complies with the conditions stated
-    in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any
-   Contribution intentionally submitted for inclusion in the Work by You to
-   the Licensor shall be under the terms and conditions of this License,
-   without any additional terms or conditions. Notwithstanding the above,
-   nothing herein shall supersede or modify the terms of any separate
-   license agreement you may have executed with Licensor regarding such
-   Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to
-   in writing, Licensor provides the Work (and each Contributor provides
-   its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
-   OF ANY KIND, either express or implied, including, without limitation,
-   any warranties or conditions of TITLE, NON-INFRINGEMENT,
-   MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely
-   responsible for determining the appropriateness of using or
-   redistributing the Work and assume any risks associated with Your
-   exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether
-   in tort (including negligence), contract, or otherwise, unless required
-   by applicable law (such as deliberate and grossly negligent acts) or
-   agreed to in writing, shall any Contributor be liable to You for
-   damages, including any direct, indirect, special, incidental, or
-   consequential damages of any character arising as a result of this
-   License or out of the use or inability to use the Work (including but
-   not limited to damages for loss of goodwill, work stoppage, computer
-   failure or malfunction, or any and all other commercial damages or
-   losses), even if such Contributor has been advised of the possibility of
-   such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the
-   Work or Derivative Works thereof, You may choose to offer, and charge a
-   fee for, acceptance of support, warranty, indemnity, or other liability
-   obligations and/or rights consistent with this License. However, in
-   accepting such obligations, You may act only on Your own behalf and on
-   Your sole responsibility, not on behalf of any other Contributor, and
-   only if You agree to indemnify, defend, and hold each Contributor
-   harmless for any liability incurred by, or claims asserted against, such
-   Contributor by reason of your accepting any such warranty or additional
-   liability.
-
-END OF TERMS AND CONDITIONS
diff --git a/LICENSES/preferred/BSD-2-Clause b/LICENSES/preferred/BSD-2-Clause
deleted file mode 100644
index da366e2..0000000
--- a/LICENSES/preferred/BSD-2-Clause
+++ /dev/null
@@ -1,32 +0,0 @@
-Valid-License-Identifier: BSD-2-Clause
-SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
-Usage-Guide:
-  To use the BSD 2-clause "Simplified" License put the following SPDX
-  tag/value pair into a comment according to the placement guidelines in
-  the licensing rules documentation:
-    SPDX-License-Identifier: BSD-2-Clause
-License-Text:
-
-Copyright (c) <year> <owner> . All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-   this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-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.
diff --git a/LICENSES/preferred/GPL-2.0 b/LICENSES/preferred/GPL-2.0
deleted file mode 100644
index 9d6c26e..0000000
--- a/LICENSES/preferred/GPL-2.0
+++ /dev/null
@@ -1,355 +0,0 @@
-Valid-License-Identifier: GPL-2.0
-Valid-License-Identifier: GPL-2.0-only
-Valid-License-Identifier: GPL-2.0-or-later
-SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
-Usage-Guide:
-  To use this license in source code, put one of the following SPDX
-  tag/value pairs into a comment according to the placement
-  guidelines in the licensing rules documentation.
-  For 'GNU General Public License (GPL) version 2 only' use:
-    SPDX-License-Identifier: GPL-2.0-only
-  For 'GNU General Public License (GPL) version 2 or any later version' use:
-    SPDX-License-Identifier: GPL-2.0-or-later
-License-Text:
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-1:w
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/LICENSES/preferred/LGPL-2.1 b/LICENSES/preferred/LGPL-2.1
deleted file mode 100644
index 8e08d6e..0000000
--- a/LICENSES/preferred/LGPL-2.1
+++ /dev/null
@@ -1,503 +0,0 @@
-Valid-License-Identifier: LGPL-2.1
-Valid-License-Identifier: LGPL-2.1-or-later
-SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
-Usage-Guide:
-  To use this license in source code, put one of the following SPDX
-  tag/value pairs into a comment according to the placement
-  guidelines in the licensing rules documentation.
-  For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
-    SPDX-License-Identifier: LGPL-2.1
-  For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
-  version' use:
-    SPDX-License-Identifier: LGPL-2.1-or-later
-License-Text:
-
-GNU LESSER GENERAL PUBLIC LICENSE
-Version 2.1, February 1999
-
-Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Everyone is permitted to copy and distribute verbatim copies of this
-license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts as
-the successor of the GNU Library Public License, version 2, hence the
-version number 2.1.]
-
-Preamble
-
-The licenses for most software are designed to take away your freedom to
-share and change it. By contrast, the GNU General Public Licenses are
-intended to guarantee your freedom to share and change free software--to
-make sure the software is free for all its users.
-
-This license, the Lesser General Public License, applies to some specially
-designated software packages--typically libraries--of the Free Software
-Foundation and other authors who decide to use it. You can use it too, but
-we suggest you first think carefully about whether this license or the
-ordinary General Public License is the better strategy to use in any
-particular case, based on the explanations below.
-
-When we speak of free software, we are referring to freedom of use, not
-price. Our General Public Licenses are designed to make sure that you have
-the freedom to distribute copies of free software (and charge for this
-service if you wish); that you receive source code or can get it if you
-want it; that you can change the software and use pieces of it in new free
-programs; and that you are informed that you can do these things.
-
-To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for you if
-you distribute copies of the library or if you modify it.
-
-For example, if you distribute copies of the library, whether gratis or for
-a fee, you must give the recipients all the rights that we gave you. You
-must make sure that they, too, receive or can get the source code. If you
-link other code with the library, you must provide complete object files to
-the recipients, so that they can relink them with the library after making
-changes to the library and recompiling it. And you must show them these
-terms so they know their rights.
-
-We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-To protect each distributor, we want to make it very clear that there is no
-warranty for the free library. Also, if the library is modified by someone
-else and passed on, the recipients should know that what they have is not
-the original version, so that the original author's reputation will not be
-affected by problems that might be introduced by others.
-
-Finally, software patents pose a constant threat to the existence of any
-free program. We wish to make sure that a company cannot effectively
-restrict the users of a free program by obtaining a restrictive license
-from a patent holder. Therefore, we insist that any patent license obtained
-for a version of the library must be consistent with the full freedom of
-use specified in this license.
-
-Most GNU software, including some libraries, is covered by the ordinary GNU
-General Public License. This license, the GNU Lesser General Public
-License, applies to certain designated libraries, and is quite different
-from the ordinary General Public License. We use this license for certain
-libraries in order to permit linking those libraries into non-free
-programs.
-
-When a program is linked with a library, whether statically or using a
-shared library, the combination of the two is legally speaking a combined
-work, a derivative of the original library. The ordinary General Public
-License therefore permits such linking only if the entire combination fits
-its criteria of freedom. The Lesser General Public License permits more lax
-criteria for linking other code with the library.
-
-We call this license the "Lesser" General Public License because it does
-Less to protect the user's freedom than the ordinary General Public
-License. It also provides other free software developers Less of an
-advantage over competing non-free programs. These disadvantages are the
-reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
-For example, on rare occasions, there may be a special need to encourage
-the widest possible use of a certain library, so that it becomes a de-facto
-standard. To achieve this, non-free programs must be allowed to use the
-library. A more frequent case is that a free library does the same job as
-widely used non-free libraries. In this case, there is little to gain by
-limiting the free library to free software only, so we use the Lesser
-General Public License.
-
-In other cases, permission to use a particular library in non-free programs
-enables a greater number of people to use a large body of free
-software. For example, permission to use the GNU C Library in non-free
-programs enables many more people to use the whole GNU operating system, as
-well as its variant, the GNU/Linux operating system.
-
-Although the Lesser General Public License is Less protective of the users'
-freedom, it does ensure that the user of a program that is linked with the
-Library has the freedom and the wherewithal to run that program using a
-modified version of the Library.
-
-The precise terms and conditions for copying, distribution and modification
-follow. Pay close attention to the difference between a "work based on the
-library" and a "work that uses the library". The former contains code
-derived from the library, whereas the latter must be combined with the
-library in order to run.
-
-TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-0. This License Agreement applies to any software library or other program
-   which contains a notice placed by the copyright holder or other
-   authorized party saying it may be distributed under the terms of this
-   Lesser General Public License (also called "this License"). Each
-   licensee is addressed as "you".
-
-   A "library" means a collection of software functions and/or data
-   prepared so as to be conveniently linked with application programs
-   (which use some of those functions and data) to form executables.
-
-   The "Library", below, refers to any such software library or work which
-   has been distributed under these terms. A "work based on the Library"
-   means either the Library or any derivative work under copyright law:
-   that is to say, a work containing the Library or a portion of it, either
-   verbatim or with modifications and/or translated straightforwardly into
-   another language. (Hereinafter, translation is included without
-   limitation in the term "modification".)
-
-   "Source code" for a work means the preferred form of the work for making
-   modifications to it. For a library, complete source code means all the
-   source code for all modules it contains, plus any associated interface
-   definition files, plus the scripts used to control compilation and
-   installation of the library.
-
-    Activities other than copying, distribution and modification are not
-    covered by this License; they are outside its scope. The act of running
-    a program using the Library is not restricted, and output from such a
-    program is covered only if its contents constitute a work based on the
-    Library (independent of the use of the Library in a tool for writing
-    it). Whether that is true depends on what the Library does and what the
-    program that uses the Library does.
-
-1. You may copy and distribute verbatim copies of the Library's complete
-   source code as you receive it, in any medium, provided that you
-   conspicuously and appropriately publish on each copy an appropriate
-   copyright notice and disclaimer of warranty; keep intact all the notices
-   that refer to this License and to the absence of any warranty; and
-   distribute a copy of this License along with the Library.
-
-   You may charge a fee for the physical act of transferring a copy, and
-   you may at your option offer warranty protection in exchange for a fee.
-
-2. You may modify your copy or copies of the Library or any portion of it,
-   thus forming a work based on the Library, and copy and distribute such
-   modifications or work under the terms of Section 1 above, provided that
-   you also meet all of these conditions:
-
-   a) The modified work must itself be a software library.
-
-   b) You must cause the files modified to carry prominent notices stating
-      that you changed the files and the date of any change.
-
-   c) You must cause the whole of the work to be licensed at no charge to
-      all third parties under the terms of this License.
-
-   d) If a facility in the modified Library refers to a function or a table
-      of data to be supplied by an application program that uses the
-      facility, other than as an argument passed when the facility is
-      invoked, then you must make a good faith effort to ensure that, in
-      the event an application does not supply such function or table, the
-      facility still operates, and performs whatever part of its purpose
-      remains meaningful.
-
-   (For example, a function in a library to compute square roots has a
-    purpose that is entirely well-defined independent of the
-    application. Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must be
-    optional: if the application does not supply it, the square root
-    function must still compute square roots.)
-
-   These requirements apply to the modified work as a whole. If
-   identifiable sections of that work are not derived from the Library, and
-   can be reasonably considered independent and separate works in
-   themselves, then this License, and its terms, do not apply to those
-   sections when you distribute them as separate works. But when you
-   distribute the same sections as part of a whole which is a work based on
-   the Library, the distribution of the whole must be on the terms of this
-   License, whose permissions for other licensees extend to the entire
-   whole, and thus to each and every part regardless of who wrote it.
-
-   Thus, it is not the intent of this section to claim rights or contest
-   your rights to work written entirely by you; rather, the intent is to
-   exercise the right to control the distribution of derivative or
-   collective works based on the Library.
-
-   In addition, mere aggregation of another work not based on the Library
-   with the Library (or with a work based on the Library) on a volume of a
-   storage or distribution medium does not bring the other work under the
-   scope of this License.
-
-3. You may opt to apply the terms of the ordinary GNU General Public
-   License instead of this License to a given copy of the Library. To do
-   this, you must alter all the notices that refer to this License, so that
-   they refer to the ordinary GNU General Public License, version 2,
-   instead of to this License. (If a newer version than version 2 of the
-   ordinary GNU General Public License has appeared, then you can specify
-   that version instead if you wish.) Do not make any other change in these
-   notices.
-
-   Once this change is made in a given copy, it is irreversible for that
-   copy, so the ordinary GNU General Public License applies to all
-   subsequent copies and derivative works made from that copy.
-
-   This option is useful when you wish to copy part of the code of the
-   Library into a program that is not a library.
-
-4. You may copy and distribute the Library (or a portion or derivative of
-   it, under Section 2) in object code or executable form under the terms
-   of Sections 1 and 2 above provided that you accompany it with the
-   complete corresponding machine-readable source code, which must be
-   distributed under the terms of Sections 1 and 2 above on a medium
-   customarily used for software interchange.
-
-   If distribution of object code is made by offering access to copy from a
-   designated place, then offering equivalent access to copy the source
-   code from the same place satisfies the requirement to distribute the
-   source code, even though third parties are not compelled to copy the
-   source along with the object code.
-
-5. A program that contains no derivative of any portion of the Library, but
-   is designed to work with the Library by being compiled or linked with
-   it, is called a "work that uses the Library". Such a work, in isolation,
-   is not a derivative work of the Library, and therefore falls outside the
-   scope of this License.
-
-   However, linking a "work that uses the Library" with the Library creates
-   an executable that is a derivative of the Library (because it contains
-   portions of the Library), rather than a "work that uses the
-   library". The executable is therefore covered by this License. Section 6
-   states terms for distribution of such executables.
-
-   When a "work that uses the Library" uses material from a header file
-   that is part of the Library, the object code for the work may be a
-   derivative work of the Library even though the source code is
-   not. Whether this is true is especially significant if the work can be
-   linked without the Library, or if the work is itself a library. The
-   threshold for this to be true is not precisely defined by law.
-
-   If such an object file uses only numerical parameters, data structure
-   layouts and accessors, and small macros and small inline functions (ten
-   lines or less in length), then the use of the object file is
-   unrestricted, regardless of whether it is legally a derivative
-   work. (Executables containing this object code plus portions of the
-   Library will still fall under Section 6.)
-
-   Otherwise, if the work is a derivative of the Library, you may
-   distribute the object code for the work under the terms of Section
-   6. Any executables containing that work also fall under Section 6,
-   whether or not they are linked directly with the Library itself.
-
-6. As an exception to the Sections above, you may also combine or link a
-   "work that uses the Library" with the Library to produce a work
-   containing portions of the Library, and distribute that work under terms
-   of your choice, provided that the terms permit modification of the work
-   for the customer's own use and reverse engineering for debugging such
-   modifications.
-
-   You must give prominent notice with each copy of the work that the
-   Library is used in it and that the Library and its use are covered by
-   this License. You must supply a copy of this License. If the work during
-   execution displays copyright notices, you must include the copyright
-   notice for the Library among them, as well as a reference directing the
-   user to the copy of this License. Also, you must do one of these things:
-
-   a) Accompany the work with the complete corresponding machine-readable
-      source code for the Library including whatever changes were used in
-      the work (which must be distributed under Sections 1 and 2 above);
-      and, if the work is an executable linked with the Library, with the
-      complete machine-readable "work that uses the Library", as object
-      code and/or source code, so that the user can modify the Library and
-      then relink to produce a modified executable containing the modified
-      Library. (It is understood that the user who changes the contents of
-      definitions files in the Library will not necessarily be able to
-      recompile the application to use the modified definitions.)
-
-   b) Use a suitable shared library mechanism for linking with the
-      Library. A suitable mechanism is one that (1) uses at run time a copy
-      of the library already present on the user's computer system, rather
-      than copying library functions into the executable, and (2) will
-      operate properly with a modified version of the library, if the user
-      installs one, as long as the modified version is interface-compatible
-      with the version that the work was made with.
-
-   c) Accompany the work with a written offer, valid for at least three
-      years, to give the same user the materials specified in Subsection
-      6a, above, for a charge no more than the cost of performing this
-      distribution.
-
-   d) If distribution of the work is made by offering access to copy from a
-      designated place, offer equivalent access to copy the above specified
-      materials from the same place.
-
-   e) Verify that the user has already received a copy of these materials
-      or that you have already sent this user a copy.
-
-   For an executable, the required form of the "work that uses the Library"
-   must include any data and utility programs needed for reproducing the
-   executable from it. However, as a special exception, the materials to be
-   distributed need not include anything that is normally distributed (in
-   either source or binary form) with the major components (compiler,
-   kernel, and so on) of the operating system on which the executable runs,
-   unless that component itself accompanies the executable.
-
-   It may happen that this requirement contradicts the license restrictions
-   of other proprietary libraries that do not normally accompany the
-   operating system. Such a contradiction means you cannot use both them
-   and the Library together in an executable that you distribute.
-
-7. You may place library facilities that are a work based on the Library
-   side-by-side in a single library together with other library facilities
-   not covered by this License, and distribute such a combined library,
-   provided that the separate distribution of the work based on the Library
-   and of the other library facilities is otherwise permitted, and provided
-   that you do these two things:
-
-   a) Accompany the combined library with a copy of the same work based on
-      the Library, uncombined with any other library facilities. This must
-      be distributed under the terms of the Sections above.
-
-   b) Give prominent notice with the combined library of the fact that part
-      of it is a work based on the Library, and explaining where to find
-      the accompanying uncombined form of the same work.
-
-8. You may not copy, modify, sublicense, link with, or distribute the
-   Library except as expressly provided under this License. Any attempt
-   otherwise to copy, modify, sublicense, link with, or distribute the
-   Library is void, and will automatically terminate your rights under this
-   License. However, parties who have received copies, or rights, from you
-   under this License will not have their licenses terminated so long as
-   such parties remain in full compliance.
-
-9. You are not required to accept this License, since you have not signed
-   it. However, nothing else grants you permission to modify or distribute
-   the Library or its derivative works. These actions are prohibited by law
-   if you do not accept this License. Therefore, by modifying or
-   distributing the Library (or any work based on the Library), you
-   indicate your acceptance of this License to do so, and all its terms and
-   conditions for copying, distributing or modifying the Library or works
-   based on it.
-
-10. Each time you redistribute the Library (or any work based on the
-    Library), the recipient automatically receives a license from the
-    original licensor to copy, distribute, link with or modify the Library
-    subject to these terms and conditions. You may not impose any further
-    restrictions on the recipients' exercise of the rights granted
-    herein. You are not responsible for enforcing compliance by third
-    parties with this License.
-
-11. If, as a consequence of a court judgment or allegation of patent
-    infringement or for any other reason (not limited to patent issues),
-    conditions are imposed on you (whether by court order, agreement or
-    otherwise) that contradict the conditions of this License, they do not
-    excuse you from the conditions of this License. If you cannot
-    distribute so as to satisfy simultaneously your obligations under this
-    License and any other pertinent obligations, then as a consequence you
-    may not distribute the Library at all. For example, if a patent license
-    would not permit royalty-free redistribution of the Library by all
-    those who receive copies directly or indirectly through you, then the
-    only way you could satisfy both it and this License would be to refrain
-    entirely from distribution of the Library.
-
-    If any portion of this section is held invalid or unenforceable under
-    any particular circumstance, the balance of the section is intended to
-    apply, and the section as a whole is intended to apply in other
-    circumstances.
-
-    It is not the purpose of this section to induce you to infringe any
-    patents or other property right claims or to contest validity of any
-    such claims; this section has the sole purpose of protecting the
-    integrity of the free software distribution system which is implemented
-    by public license practices. Many people have made generous
-    contributions to the wide range of software distributed through that
-    system in reliance on consistent application of that system; it is up
-    to the author/donor to decide if he or she is willing to distribute
-    software through any other system and a licensee cannot impose that
-    choice.
-
-    This section is intended to make thoroughly clear what is believed to
-    be a consequence of the rest of this License.
-
-12. If the distribution and/or use of the Library is restricted in certain
-    countries either by patents or by copyrighted interfaces, the original
-    copyright holder who places the Library under this License may add an
-    explicit geographical distribution limitation excluding those
-    countries, so that distribution is permitted only in or among countries
-    not thus excluded. In such case, this License incorporates the
-    limitation as if written in the body of this License.
-
-13. The Free Software Foundation may publish revised and/or new versions of
-    the Lesser General Public License from time to time. Such new versions
-    will be similar in spirit to the present version, but may differ in
-    detail to address new problems or concerns.
-
-    Each version is given a distinguishing version number. If the Library
-    specifies a version number of this License which applies to it and "any
-    later version", you have the option of following the terms and
-    conditions either of that version or of any later version published by
-    the Free Software Foundation. If the Library does not specify a license
-    version number, you may choose any version ever published by the Free
-    Software Foundation.
-
-14. If you wish to incorporate parts of the Library into other free
-    programs whose distribution conditions are incompatible with these,
-    write to the author to ask for permission. For software which is
-    copyrighted by the Free Software Foundation, write to the Free Software
-    Foundation; we sometimes make exceptions for this. Our decision will be
-    guided by the two goals of preserving the free status of all
-    derivatives of our free software and of promoting the sharing and reuse
-    of software generally.
-
-NO WARRANTY
-
-15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-    FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-    PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
-    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
-    YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
-    NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-    REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
-    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
-    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
-    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
-    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
-    THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
-    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Libraries
-
-If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-one line to give the library's name and an idea of what it does.
-Copyright (C) year name of author
-
-This library is free software; you can redistribute it and/or modify it
-under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or (at
-your option) any later version.
-
-This library is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
-information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
-Yoyodyne, Inc., hereby disclaims all copyright interest in
-the library `Frob' (a library for tweaking knobs) written
-by James Random Hacker.
-
-signature of Ty Coon, 1 April 1990
-Ty Coon, President of Vice
-That's all there is to it!
diff --git a/LICENSES/preferred/MIT b/LICENSES/preferred/MIT
deleted file mode 100644
index f33a68c..0000000
--- a/LICENSES/preferred/MIT
+++ /dev/null
@@ -1,30 +0,0 @@
-Valid-License-Identifier: MIT
-SPDX-URL: https://spdx.org/licenses/MIT.html
-Usage-Guide:
-  To use the MIT License put the following SPDX tag/value pair into a
-  comment according to the placement guidelines in the licensing rules
-  documentation:
-    SPDX-License-Identifier: MIT
-License-Text:
-
-MIT License
-
-Copyright (c) <year> <copyright holders>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/Makefile.am b/Makefile.am
index 7041f8e..f639f7f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@ CLEANFILES =
 
 EXTRA_DIST =
 
-pkglibexecdir = $(libexecdir)/bluetooth
+pkglibexecdir = @PKGLIBEXECDIR@
 
 pkglibexec_PROGRAMS =
 
@@ -31,11 +31,17 @@ AM_LDFLAGS = $(MISC_LDFLAGS)
 confdir = $(sysconfdir)/bluetooth
 statedir = $(localstatedir)/lib/bluetooth
 
+bluetoothd-fix-permissions:
+	install -dm555 $(DESTDIR)$(confdir)
+	install -dm700 $(DESTDIR)$(statedir)
+
 if DATAFILES
 dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d
 dbus_DATA = src/bluetooth.conf
 
-conf_DATA =
+conf_DATA = src/main.conf
+conf_DATA += profiles/input/input.conf
+conf_DATA += profiles/network/network.conf
 state_DATA =
 endif
 
@@ -43,19 +49,18 @@ if SYSTEMD
 systemdsystemunitdir = $(SYSTEMD_SYSTEMUNITDIR)
 systemdsystemunit_DATA = src/bluetooth.service
 
+systemduserunitdir = $(SYSTEMD_USERUNITDIR)
+systemduserunit_DATA =
+
 dbussystembusdir = $(DBUS_SYSTEMBUSDIR)
 dbussystembus_DATA = src/org.bluez.service
 endif
 
-EXTRA_DIST += src/bluetooth.service.in src/org.bluez.service
+EXTRA_DIST += src/org.bluez.service
 
 plugindir = $(libdir)/bluetooth/plugins
 
-if MAINTAINER_MODE
-build_plugindir = $(abs_top_srcdir)/plugins/.libs
-else
 build_plugindir = $(plugindir)
-endif
 
 if MANPAGES
 man_MANS =
@@ -82,8 +87,7 @@ pkginclude_HEADERS += $(lib_headers)
 lib_LTLIBRARIES += lib/libbluetooth.la
 
 lib_libbluetooth_la_SOURCES = $(lib_headers) $(lib_sources)
-lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 22:8:19
-lib_libbluetooth_la_DEPENDENCIES = $(local_headers)
+lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 22:15:19
 endif
 
 noinst_LTLIBRARIES += lib/libbluetooth-internal.la
@@ -100,12 +104,10 @@ gdbus_libgdbus_internal_la_SOURCES = gdbus/gdbus.h \
 if EXTERNAL_ELL
 ell_cflags = @ELL_CFLAGS@
 ell_ldadd = @ELL_LIBS@
-ell_dependencies =
 ell_built_sources = ell/shared
 else
 ell_cflags =
 ell_ldadd = ell/libell-internal.la
-ell_dependencies = $(ell_ldadd)
 ell_built_sources = ell/shared ell/internal ell/ell.h
 
 noinst_LTLIBRARIES += ell/libell-internal.la
@@ -231,9 +233,16 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
 			src/shared/gap.h src/shared/gap.c \
 			src/shared/log.h src/shared/log.c \
 			src/shared/bap.h src/shared/bap.c src/shared/ascs.h \
+			src/shared/bap-debug.h src/shared/bap-debug.c \
 			src/shared/mcs.h src/shared/mcp.h src/shared/mcp.c \
 			src/shared/vcp.c src/shared/vcp.h \
-			src/shared/lc3.h src/shared/tty.h
+			src/shared/micp.c src/shared/micp.h \
+			src/shared/csip.c src/shared/csip.h \
+			src/shared/bass.h src/shared/bass.c \
+			src/shared/ccp.h src/shared/ccp.c \
+			src/shared/lc3.h src/shared/tty.h \
+			src/shared/bap-defs.h \
+			src/shared/asha.h src/shared/asha.c
 
 if READLINE
 shared_sources += src/shared/shell.c src/shared/shell.h
@@ -284,24 +293,14 @@ gobex_sources = gobex/gobex.h gobex/gobex.c \
 builtin_modules =
 builtin_sources =
 builtin_cppflags =
-builtin_nodist =
 builtin_ldadd =
 
 include Makefile.plugins
 
-if MAINTAINER_MODE
-plugin_LTLIBRARIES += plugins/external-dummy.la
-plugins_external_dummy_la_SOURCES = plugins/external-dummy.c
-plugins_external_dummy_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
-				    -no-undefined
-plugins_external_dummy_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
-endif
-
 pkglibexec_PROGRAMS += src/bluetoothd
 
 src_bluetoothd_SOURCES = $(builtin_sources) \
 			$(attrib_sources) $(btio_sources) \
-			src/bluetooth.ver \
 			src/main.c src/log.h src/log.c \
 			src/backtrace.h src/backtrace.c \
 			src/rfkill.c src/btd.h src/sdpd.h \
@@ -326,35 +325,99 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/eir.h src/eir.c \
 			src/adv_monitor.h src/adv_monitor.c \
 			src/battery.h src/battery.c \
-			src/settings.h src/settings.c
+			src/settings.h src/settings.c \
+			src/set.h src/set.c
 src_bluetoothd_LDADD = lib/libbluetooth-internal.la \
 			gdbus/libgdbus-internal.la \
 			src/libshared-glib.la \
 			$(BACKTRACE_LIBS) $(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt \
 			$(builtin_ldadd)
+
+if EXTERNAL_PLUGINS
+src_bluetoothd_SOURCES += src/bluetooth.ver
 src_bluetoothd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic \
 				-Wl,--version-script=$(srcdir)/src/bluetooth.ver
-
-src_bluetoothd_DEPENDENCIES = lib/libbluetooth-internal.la \
-				gdbus/libgdbus-internal.la \
-				src/libshared-glib.la \
-				src/bluetooth.service
+endif
 
 src_bluetoothd_CPPFLAGS = $(AM_CPPFLAGS) -DBLUETOOTH_PLUGIN_BUILTIN \
 					-DPLUGINDIR=\""$(build_plugindir)"\" \
 					$(BACKTRACE_CFLAGS) $(builtin_cppflags)
 src_bluetoothd_SHORTNAME = bluetoothd
 
-builtin_files = src/builtin.h $(builtin_nodist)
+builtin_files = src/builtin.h
 
 nodist_src_bluetoothd_SOURCES = $(builtin_files)
 
-CLEANFILES += $(builtin_files) src/bluetooth.service
+CLEANFILES += $(builtin_files)
 
 if MANPAGES
 man_MANS += src/bluetoothd.8
+man_MANS += doc/hci.7 doc/l2cap.7 doc/rfcomm.7
+man_MANS += doc/org.bluez.Adapter.5 doc/org.bluez.Device.5 \
+		doc/org.bluez.DeviceSet.5 doc/org.bluez.AgentManager.5 \
+		doc/org.bluez.Agent.5 doc/org.bluez.ProfileManager.5 \
+		doc/org.bluez.Profile.5 doc/org.bluez.NetworkServer.5 \
+		doc/org.bluez.Network.5 doc/org.bluez.Input.5 \
+		doc/org.bluez.BatteryProviderManager.5 \
+		doc/org.bluez.BatteryProvider.5 doc/org.bluez.Battery.5 \
+		doc/org.bluez.AdminPolicySet.5 \
+		doc/org.bluez.AdminPolicyStatus.5
+man_MANS += doc/org.bluez.Media.5 doc/org.bluez.MediaControl.5 \
+		doc/org.bluez.MediaPlayer.5 doc/org.bluez.MediaFolder.5 \
+		doc/org.bluez.MediaItem.5 doc/org.bluez.MediaEndpoint.5 \
+		doc/org.bluez.MediaTransport.5 doc/org.bluez.MediaAssistant.5
+man_MANS += doc/org.bluez.GattManager.5 doc/org.bluez.GattProfile.5 \
+		doc/org.bluez.GattService.5 \
+		doc/org.bluez.GattCharacteristic.5 \
+		doc/org.bluez.GattDescriptor.5 \
+		doc/org.bluez.LEAdvertisingManager.5 \
+		doc/org.bluez.LEAdvertisement.5 \
+		doc/org.bluez.AdvertisementMonitorManager.5 \
+		doc/org.bluez.AdvertisementMonitor.5
+man_MANS += doc/org.bluez.obex.Client.5 doc/org.bluez.obex.Session.5 \
+		doc/org.bluez.obex.Transfer.5 \
+		doc/org.bluez.obex.ObjectPush.5 \
+		doc/org.bluez.obex.FileTransfer.5 \
+		doc/org.bluez.obex.Synchronization.5 \
+		doc/org.bluez.obex.PhonebookAccess.5 \
+		doc/org.bluez.obex.MessageAccess.5 \
+		doc/org.bluez.obex.Message.5 \
+		doc/org.bluez.obex.AgentManager.5 doc/org.bluez.obex.Agent.5 \
+		doc/org.bluez.obex.Image.5
 endif
 manual_pages += src/bluetoothd.8
+manual_pages += doc/hci.7 doc/l2cap.7 doc/rfcomm.7
+manual_pages += doc/org.bluez.Adapter.5 doc/org.bluez.Device.5 \
+		doc/org.bluez.DeviceSet.5 doc/org.bluez.AgentManager.5 \
+		doc/org.bluez.Agent.5 doc/org.bluez.ProfileManager.5 \
+		doc/org.bluez.Profile.5 doc/org.bluez.NetworkServer.5 \
+		doc/org.bluez.Network.5 doc/org.bluez.Input.5\
+		doc/org.bluez.BatteryProviderManager.5 \
+		doc/org.bluez.BatteryProvider.5 doc/org.bluez.Battery.5 \
+		doc/org.bluez.AdminPolicySet.5 \
+		doc/org.bluez.AdminPolicyStatus.5
+manual_pages += doc/org.bluez.Media.5 doc/org.bluez.MediaControl.5 \
+		doc/org.bluez.MediaPlayer.5 doc/org.bluez.MediaFolder.5 \
+		doc/org.bluez.MediaItem.5 doc/org.bluez.MediaEndpoint.5 \
+		doc/org.bluez.MediaTransport.5 doc/org.bluez.MediaAssistant.5
+manual_pages += doc/org.bluez.GattManager.5 doc/org.bluez.GattProfile.5 \
+		doc/org.bluez.GattService.5 \
+		doc/org.bluez.GattCharacteristic.5 \
+		doc/org.bluez.GattDescriptor.5 \
+		doc/org.bluez.LEAdvertisingManager.5 \
+		doc/org.bluez.LEAdvertisement.5 \
+		doc/org.bluez.AdvertisementMonitorManager.5 \
+		doc/org.bluez.AdvertisementMonitor.5
+manual_pages += doc/org.bluez.obex.Client.5 doc/org.bluez.obex.Session.5 \
+		doc/org.bluez.obex.Transfer.5 \
+		doc/org.bluez.obex.ObjectPush.5 \
+		doc/org.bluez.obex.FileTransfer.5 \
+		doc/org.bluez.obex.Synchronization.5 \
+		doc/org.bluez.obex.PhonebookAccess.5 \
+		doc/org.bluez.obex.MessageAccess.5 \
+		doc/org.bluez.obex.Message.5 \
+		doc/org.bluez.obex.AgentManager.5 doc/org.bluez.obex.Agent.5 \
+		doc/org.bluez.obex.Image.5
 
 EXTRA_DIST += src/genbuiltin src/bluetooth.conf \
 			src/main.conf profiles/network/network.conf \
@@ -368,6 +431,14 @@ include Makefile.obexd
 include android/Makefile.am
 include Makefile.mesh
 
+if SYSTEMD
+install-data-hook: obexd-add-service-symlink
+else
+install-data-hook: bluetoothd-fix-permissions obexd-add-service-symlink
+endif
+
+uninstall-hook: obexd-remove-service-symlink
+
 if HID2HCI
 rulesdir = $(UDEV_DIR)/rules.d
 
@@ -387,19 +458,49 @@ EXTRA_DIST += $(test_scripts)
 
 EXTRA_DIST += doc/assigned-numbers.txt doc/supported-features.txt \
 				doc/test-coverage.txt \
-				doc/test-runner.txt \
+				doc/test-runner.rst \
 				doc/settings-storage.txt
 
 EXTRA_DIST += doc/mgmt-api.txt \
-		doc/adapter-api.txt doc/device-api.txt \
-		doc/agent-api.txt doc/profile-api.txt \
-		doc/network-api.txt doc/media-api.txt \
-		doc/health-api.txt doc/sap-api.txt \
-		doc/input-api.txt
-
-EXTRA_DIST += doc/gatt-api.txt doc/advertising-api.txt
-
-EXTRA_DIST += doc/obex-api.txt doc/obex-agent-api.txt
+		doc/health-api.txt \
+		doc/sap-api.txt
+
+EXTRA_DIST += doc/hci.rst doc/l2cap.rst doc/rfcomm.rst
+
+EXTRA_DIST += doc/org.bluez.Adapter.rst doc/org.bluez.Device.rst \
+		doc/org.bluez.DeviceSet.rst doc/org.bluez.AgentManager.rst \
+		doc/org.bluez.Agent.rst doc/org.bluez.ProfileManager.rst \
+		doc/org.bluez.Profile.rst doc/org.bluez.NetworkServer.rst \
+		doc/org.bluez.Network.rst doc/org.bluez.Input.rst \
+		doc/org.bluez.BatteryProviderManager.rst \
+		doc/org.bluez.BatteryProvider.rst doc/org.bluez.Battery.rst \
+		doc/org.bluez.AdminPolicySet.rst \
+		doc/org.bluez.AdminPolicyStatus.rst
+
+EXTRA_DIST += doc/org.bluez.Media.rst doc/org.bluez.MediaControl.rst \
+		doc/org.bluez.MediaPlayer.rst doc/org.bluez.MediaFolder.rst \
+		doc/org.bluez.MediaItem.rst doc/org.bluez.MediaEndpoint.rst \
+		doc/org.bluez.MediaTransport.rst doc/org.bluez.MediaAssistant.rst
+
+EXTRA_DIST += doc/org.bluez.GattManager.rst doc/org.bluez.GattProfile.rst\
+		doc/org.bluez.GattService.rst \
+		doc/org.bluez.GattCharacteristic.rst \
+		doc/org.bluez.GattDescriptor.rst \
+		doc/org.bluez.LEAdvertisingManager.rst \
+		doc/org.bluez.LEAdvertisement.rst \
+		doc/org.bluez.AdvertisementMonitorManager.rst \
+		doc/org.bluez.AdvertisementMonitor.rst
+
+EXTRA_DIST += doc/org.bluez.obex.Client.rst doc/org.bluez.obex.Session.rst \
+		doc/org.bluez.obex.Transfer.rst \
+		doc/org.bluez.obex.ObjectPush.rst \
+		doc/org.bluez.obex.FileTransfer.rst \
+		doc/org.bluez.obex.Synchronization.rst \
+		doc/org.bluez.obex.PhonebookAccess.rst \
+		doc/org.bluez.obex.MessageAccess.rst \
+		doc/org.bluez.obex.Message.rst \
+		doc/org.bluez.obex.AgentManager.rst doc/org.bluez.obex.Agent.rst \
+		doc/org.bluez.obex.Image.rst
 
 EXTRA_DIST += doc/pics-opp.txt doc/pixit-opp.txt \
 		doc/pts-opp.txt
@@ -565,9 +666,33 @@ unit_tests += unit/test-gattrib
 
 unit_test_gattrib_SOURCES = unit/test-gattrib.c attrib/gattrib.c \
 					$(btio_sources) src/log.h src/log.c
-unit_test_gattrib_LDADD = lib/libbluetooth-internal.la \
-			src/libshared-glib.la \
-			$(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt
+unit_test_gattrib_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la \
+				$(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt
+
+unit_tests += unit/test-bap
+
+unit_test_bap_SOURCES = unit/test-bap.c
+unit_test_bap_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_tests += unit/test-micp
+
+unit_test_micp_SOURCES = unit/test-micp.c
+unit_test_micp_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_tests += unit/test-bass
+
+unit_test_bass_SOURCES = unit/test-bass.c $(btio_sources)
+unit_test_bass_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_tests += unit/test-vcp
+
+unit_test_vcp_SOURCES = unit/test-vcp.c $(btio_sources)
+unit_test_vcp_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
 
 if MIDI
 unit_tests += unit/test-midi
@@ -629,13 +754,6 @@ MAINTAINERCLEANFILES = Makefile.in \
 	aclocal.m4 configure config.h.in config.sub config.guess \
 	ltmain.sh depcomp compile missing install-sh mkinstalldirs test-driver
 
-SED_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
-		$(SED) -e 's,@pkglibexecdir\@,$(pkglibexecdir),g' \
-		       -e 's,@libexecdir\@,$(libexecdir),g' \
-		       -e 's,@statedir\@,$(statedir),g' \
-		       -e 's,@confdir\@,$(confdir),g' \
-		< $< > $@
-
 if RUN_RST2MAN
 RST2MAN_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
 			$(RST2MAN) --strict --no-raw \
@@ -645,12 +763,15 @@ RST2MAN_PROCESS = $(AM_V_GEN)test -f $@ || \
 		{ echo "Generated manual page $@ does not exist"; false; }
 endif
 
-%.service: %.service.in Makefile
-	$(SED_PROCESS)
-
 %.1: %.rst Makefile
 	$(RST2MAN_PROCESS)
 
+%.5: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
+%.7: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
 %.8: %.rst Makefile
 	$(RST2MAN_PROCESS)
 
@@ -692,8 +813,8 @@ ell/ell.h: Makefile
 maintainer-clean-local:
 	-rm -rf ell
 
-if COVERAGE
 clean-coverage:
+if COVERAGE
 	@lcov --directory $(top_builddir) --zerocounters
 	$(RM) -r coverage $(top_builddir)/coverage.info
 
@@ -702,15 +823,9 @@ coverage: check
 				--output-file $(top_builddir)/coverage.info
 	$(AM_V_at)$(MKDIR_P) coverage
 	@genhtml -o coverage/ $(top_builddir)/coverage.info
+endif
 
 clean-local: clean-coverage
 	-find $(top_builddir) -name "*.gcno" -delete
 	-find $(top_builddir) -name "*.gcda" -delete
 	$(RM) -r lib/bluetooth
-
-else
-clean-local:
-	-find $(top_builddir) -name "*.gcno" -delete
-	-find $(top_builddir) -name "*.gcda" -delete
-	$(RM) -r lib/bluetooth
-endif
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..fc54e01
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,14022 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6)
+noinst_PROGRAMS = $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \
+	$(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \
+	$(am__EXEEXT_18)
+pkglibexec_PROGRAMS = src/bluetoothd$(EXEEXT) $(am__EXEEXT_19) \
+	$(am__EXEEXT_20) $(am__EXEEXT_21)
+@LIBRARY_TRUE@am__append_1 = $(lib_headers)
+@LIBRARY_TRUE@am__append_2 = lib/libbluetooth.la
+@EXTERNAL_ELL_FALSE@am__append_3 = ell/libell-internal.la
+@LIBSHARED_ELL_TRUE@am__append_4 = src/libshared-ell.la
+@READLINE_TRUE@am__append_5 = src/shared/shell.c src/shared/shell.h
+@ADMIN_TRUE@am__append_6 = admin
+@ADMIN_TRUE@am__append_7 = plugins/admin.c
+@NFC_TRUE@am__append_8 = neard
+@NFC_TRUE@am__append_9 = plugins/neard.c
+@SAP_TRUE@am__append_10 = sap
+@SAP_TRUE@am__append_11 = profiles/sap/main.c profiles/sap/manager.h \
+@SAP_TRUE@			profiles/sap/manager.c profiles/sap/server.h \
+@SAP_TRUE@			profiles/sap/server.c profiles/sap/sap.h \
+@SAP_TRUE@			profiles/sap/sap-dummy.c
+
+@A2DP_TRUE@am__append_12 = a2dp
+@A2DP_TRUE@am__append_13 = profiles/audio/source.h profiles/audio/source.c \
+@A2DP_TRUE@			profiles/audio/sink.h profiles/audio/sink.c \
+@A2DP_TRUE@			profiles/audio/a2dp.h profiles/audio/a2dp.c \
+@A2DP_TRUE@			profiles/audio/avdtp.h profiles/audio/avdtp.c \
+@A2DP_TRUE@			profiles/audio/media.h profiles/audio/media.c \
+@A2DP_TRUE@			profiles/audio/transport.h profiles/audio/transport.c \
+@A2DP_TRUE@			profiles/audio/a2dp-codecs.h
+
+@AVRCP_TRUE@am__append_14 = avrcp
+@AVRCP_TRUE@am__append_15 = profiles/audio/control.h profiles/audio/control.c \
+@AVRCP_TRUE@			profiles/audio/avctp.h profiles/audio/avctp.c \
+@AVRCP_TRUE@			profiles/audio/avrcp.h profiles/audio/avrcp.c \
+@AVRCP_TRUE@			profiles/audio/player.h profiles/audio/player.c
+
+@NETWORK_TRUE@am__append_16 = network
+@NETWORK_TRUE@am__append_17 = profiles/network/manager.c \
+@NETWORK_TRUE@			profiles/network/bnep.h profiles/network/bnep.c \
+@NETWORK_TRUE@			profiles/network/server.h profiles/network/server.c \
+@NETWORK_TRUE@			profiles/network/connection.h \
+@NETWORK_TRUE@			profiles/network/connection.c
+
+@HID_TRUE@am__append_18 = input
+@HID_TRUE@am__append_19 = profiles/input/manager.c \
+@HID_TRUE@			profiles/input/server.h profiles/input/server.c \
+@HID_TRUE@			profiles/input/device.h profiles/input/device.c \
+@HID_TRUE@			profiles/input/hidp_defs.h profiles/input/sixaxis.h
+
+@HOG_TRUE@am__append_20 = hog
+@HOG_TRUE@am__append_21 = profiles/input/hog.c \
+@HOG_TRUE@			profiles/input/hog-lib.c profiles/input/hog-lib.h \
+@HOG_TRUE@			profiles/deviceinfo/dis.c profiles/deviceinfo/dis.h \
+@HOG_TRUE@			profiles/battery/bas.c profiles/battery/bas.h \
+@HOG_TRUE@			profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
+@HOG_TRUE@			profiles/input/suspend.h profiles/input/suspend-none.c
+
+@HEALTH_TRUE@am__append_22 = health
+@HEALTH_TRUE@am__append_23 = profiles/health/mcap.h profiles/health/mcap.c \
+@HEALTH_TRUE@			profiles/health/hdp_main.c profiles/health/hdp_types.h \
+@HEALTH_TRUE@			profiles/health/hdp_manager.h \
+@HEALTH_TRUE@			profiles/health/hdp_manager.c \
+@HEALTH_TRUE@			profiles/health/hdp.h profiles/health/hdp.c \
+@HEALTH_TRUE@			profiles/health/hdp_util.h profiles/health/hdp_util.c
+
+@MIDI_TRUE@am__append_24 = midi
+@MIDI_TRUE@am__append_25 = profiles/midi/midi.c \
+@MIDI_TRUE@			profiles/midi/libmidi.h \
+@MIDI_TRUE@			profiles/midi/libmidi.c
+
+@MIDI_TRUE@am__append_26 = $(ALSA_CFLAGS)
+@MIDI_TRUE@am__append_27 = $(ALSA_LIBS)
+@SIXAXIS_TRUE@am__append_28 = sixaxis
+@SIXAXIS_TRUE@am__append_29 = plugins/sixaxis.c
+@SIXAXIS_TRUE@am__append_30 = $(UDEV_LIBS)
+@BAP_TRUE@am__append_31 = bap
+@BAP_TRUE@am__append_32 = profiles/audio/bap.h profiles/audio/bap.c
+@BASS_TRUE@am__append_33 = bass
+@BASS_TRUE@am__append_34 = profiles/audio/bass.h profiles/audio/bass.c
+@MCP_TRUE@am__append_35 = mcp
+@MCP_TRUE@am__append_36 = profiles/audio/mcp.c
+@VCP_TRUE@am__append_37 = vcp
+@VCP_TRUE@am__append_38 = profiles/audio/vcp.c
+@MICP_TRUE@am__append_39 = micp
+@MICP_TRUE@am__append_40 = profiles/audio/micp.c
+@CCP_TRUE@am__append_41 = ccp
+@CCP_TRUE@am__append_42 = profiles/audio/ccp.c
+@CSIP_TRUE@am__append_43 = csip
+@CSIP_TRUE@am__append_44 = profiles/audio/csip.c
+@ASHA_TRUE@am__append_45 = asha
+@ASHA_TRUE@am__append_46 = profiles/audio/asha.h profiles/audio/asha.c
+@EXTERNAL_PLUGINS_TRUE@am__append_47 = src/bluetooth.ver
+
+# SPDX-License-Identifier: GPL-2.0
+@CLIENT_TRUE@am__append_48 = client/bluetoothctl
+@MONITOR_TRUE@am__append_49 = monitor/btmon
+@MANPAGES_TRUE@@MONITOR_TRUE@am__append_50 = monitor/btmon.1
+@LOGGER_TRUE@am__append_51 = tools/btmon-logger
+@LOGGER_TRUE@@SYSTEMD_TRUE@am__append_52 = tools/bluetooth-logger.service
+@TESTING_TRUE@am__append_53 = emulator/btvirt emulator/b1ee emulator/hfp \
+@TESTING_TRUE@					peripheral/btsensor tools/3dsp \
+@TESTING_TRUE@					tools/mgmt-tester tools/gap-tester \
+@TESTING_TRUE@					tools/l2cap-tester tools/sco-tester \
+@TESTING_TRUE@					tools/smp-tester tools/hci-tester \
+@TESTING_TRUE@					tools/rfcomm-tester tools/bnep-tester \
+@TESTING_TRUE@					tools/userchan-tester tools/iso-tester \
+@TESTING_TRUE@					tools/mesh-tester tools/ioctl-tester
+
+@TOOLS_TRUE@am__append_54 = tools/rctest tools/l2test tools/l2ping tools/bluemoon \
+@TOOLS_TRUE@		tools/hex2hcd tools/mpris-proxy tools/btattach tools/isotest
+
+@TOOLS_TRUE@am__append_55 = tools/bdaddr tools/avinfo tools/avtest \
+@TOOLS_TRUE@			tools/scotest tools/amptest tools/hwdb \
+@TOOLS_TRUE@			tools/hcieventmask tools/hcisecfilter \
+@TOOLS_TRUE@			tools/btinfo tools/btconfig \
+@TOOLS_TRUE@			tools/btsnoop tools/btproxy \
+@TOOLS_TRUE@			tools/btiotest tools/bneptest tools/mcaptest \
+@TOOLS_TRUE@			tools/cltest tools/oobtest tools/advtest \
+@TOOLS_TRUE@			tools/seq2bseq tools/nokfw tools/rtlfw \
+@TOOLS_TRUE@			tools/bcmfw tools/create-image \
+@TOOLS_TRUE@			tools/eddystone tools/ibeacon \
+@TOOLS_TRUE@			tools/btgatt-client tools/btgatt-server \
+@TOOLS_TRUE@			tools/test-runner tools/check-selftest \
+@TOOLS_TRUE@			tools/gatt-service profiles/iap/iapd
+
+@SYSTEMD_TRUE@@TOOLS_TRUE@am__append_56 = tools/mpris-proxy.service
+@MANPAGES_TRUE@@TOOLS_TRUE@am__append_57 = tools/rctest.1 tools/l2ping.1 tools/btattach.1 tools/isotest.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		tools/btmgmt.1 client/bluetoothctl.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-mgmt.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-monitor.1 client/bluetoothctl-admin.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-advertise.1 client/bluetoothctl-endpoint.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-gatt.1 client/bluetoothctl-player.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-scan.1 client/bluetoothctl-transport.1 \
+@MANPAGES_TRUE@@TOOLS_TRUE@		client/bluetoothctl-assistant.1
+
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@am__append_58 = tools/meshctl
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@am__append_59 = tools/mesh-gatt/local_node.json tools/mesh-gatt/prov_db.json
+@MESH_TRUE@@TOOLS_TRUE@am__append_60 = tools/mesh-cfgclient \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-cfgtest
+@DEPRECATED_TRUE@@TOOLS_TRUE@am__append_61 = tools/hciattach tools/hciconfig tools/hcitool tools/hcidump \
+@DEPRECATED_TRUE@@TOOLS_TRUE@			tools/rfcomm tools/sdptool tools/ciptool
+
+@DEPRECATED_TRUE@@MANPAGES_TRUE@@TOOLS_TRUE@am__append_62 = tools/hciattach.1 tools/hciconfig.1 \
+@DEPRECATED_TRUE@@MANPAGES_TRUE@@TOOLS_TRUE@			tools/hcitool.1 tools/hcidump.1 \
+@DEPRECATED_TRUE@@MANPAGES_TRUE@@TOOLS_TRUE@			tools/rfcomm.1 tools/sdptool.1 tools/ciptool.1
+
+@HID2HCI_TRUE@udev_PROGRAMS = tools/hid2hci$(EXEEXT)
+@HID2HCI_TRUE@@MANPAGES_TRUE@am__append_63 = tools/hid2hci.1
+@READLINE_TRUE@am__append_64 = tools/btmgmt tools/obex-client-tool tools/obex-server-tool \
+@READLINE_TRUE@			tools/bluetooth-player tools/obexctl
+
+@DEPRECATED_TRUE@@READLINE_TRUE@am__append_65 = attrib/gatttool
+@CUPS_TRUE@cups_PROGRAMS = profiles/cups/bluetooth$(EXEEXT)
+@BTPCLIENT_TRUE@am__append_66 = tools/btpclient tools/btpclientctl
+
+# SPDX-License-Identifier: GPL-2.0
+@OBEX_TRUE@@SYSTEMD_TRUE@am__append_67 = obexd/src/obex.service
+@EXPERIMENTAL_TRUE@@OBEX_TRUE@am__append_68 = pcsuite
+@EXPERIMENTAL_TRUE@@OBEX_TRUE@am__append_69 = obexd/plugins/pcsuite.c
+@OBEX_TRUE@am__append_70 = obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c \
+@OBEX_TRUE@				obexd/plugins/phonebook-tracker.c
+
+@OBEX_TRUE@am__append_71 = obexd/src/obexd
+@ANDROID_TRUE@am__append_72 = -DANDROID_VERSION=0x050100
+@ANDROID_TRUE@am__append_73 = android/system-emulator \
+@ANDROID_TRUE@	android/bluetoothd-snoop android/bluetoothd \
+@ANDROID_TRUE@	android/avdtptest android/haltest \
+@ANDROID_TRUE@	android/android-tester android/ipc-tester
+@ANDROID_TRUE@am__append_74 = android/bluetooth.default.la \
+@ANDROID_TRUE@	android/audio.a2dp.default.la \
+@ANDROID_TRUE@	android/audio.sco.default.la
+@ANDROID_TRUE@am__append_75 = android/test-ipc
+
+# SPDX-License-Identifier: GPL-2.0
+@DATAFILES_TRUE@@MESH_TRUE@am__append_76 = mesh/bluetooth-mesh.conf
+@DATAFILES_TRUE@@MESH_TRUE@am__append_77 = mesh/mesh-main.conf
+@MESH_TRUE@@SYSTEMD_TRUE@am__append_78 = mesh/bluetooth-mesh.service
+@MESH_TRUE@@SYSTEMD_TRUE@am__append_79 = mesh/org.bluez.mesh.service
+@MESH_TRUE@am__append_80 = mesh/bluetooth-meshd
+@MANPAGES_TRUE@@MESH_TRUE@am__append_81 = mesh/bluetooth-meshd.8
+@MESH_TRUE@am__append_82 = mesh/bluetooth-meshd.8
+@HID2HCI_TRUE@am__append_83 = $(rules_DATA)
+@OBEX_TRUE@am__append_84 = unit/test-gobex-header unit/test-gobex-packet unit/test-gobex \
+@OBEX_TRUE@			unit/test-gobex-transfer unit/test-gobex-apparam
+
+@MIDI_TRUE@am__append_85 = unit/test-midi
+@MESH_TRUE@am__append_86 = unit/test-mesh-crypto
+@MAINTAINER_MODE_TRUE@am__append_87 = $(unit_tests)
+TESTS = $(am__EXEEXT_17)
+@DBUS_RUN_SESSION_TRUE@am__append_88 = dbus-run-session --
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+	$(am__configure_deps) $(am__dist_zshcompletion_DATA_DIST) \
+	$(am__pkginclude_HEADERS_DIST) $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = lib/bluez.pc mesh/bluetooth-meshd.rst \
+	mesh/bluetooth-mesh.service obexd/src/obex.service \
+	obexd/src/org.bluez.obex.service src/bluetoothd.rst \
+	src/bluetooth.service tools/bluetooth-logger.service \
+	tools/mpris-proxy.service
+CONFIG_CLEAN_VPATH_FILES =
+@CLIENT_TRUE@am__EXEEXT_1 = client/bluetoothctl$(EXEEXT)
+@MONITOR_TRUE@am__EXEEXT_2 = monitor/btmon$(EXEEXT)
+@TOOLS_TRUE@am__EXEEXT_3 = tools/rctest$(EXEEXT) tools/l2test$(EXEEXT) \
+@TOOLS_TRUE@	tools/l2ping$(EXEEXT) tools/bluemoon$(EXEEXT) \
+@TOOLS_TRUE@	tools/hex2hcd$(EXEEXT) tools/mpris-proxy$(EXEEXT) \
+@TOOLS_TRUE@	tools/btattach$(EXEEXT) tools/isotest$(EXEEXT)
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@am__EXEEXT_4 = tools/meshctl$(EXEEXT)
+@MESH_TRUE@@TOOLS_TRUE@am__EXEEXT_5 = tools/mesh-cfgclient$(EXEEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-cfgtest$(EXEEXT)
+@DEPRECATED_TRUE@@TOOLS_TRUE@am__EXEEXT_6 = tools/hciattach$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciconfig$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hcitool$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hcidump$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/rfcomm$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/sdptool$(EXEEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/ciptool$(EXEEXT)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cupsdir)" \
+	"$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(udevdir)" \
+	"$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \
+	"$(DESTDIR)$(testdir)" "$(DESTDIR)$(man1dir)" \
+	"$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man7dir)" \
+	"$(DESTDIR)$(man8dir)" "$(DESTDIR)$(confdir)" \
+	"$(DESTDIR)$(dbusdir)" "$(DESTDIR)$(dbussessionbusdir)" \
+	"$(DESTDIR)$(dbussystembusdir)" \
+	"$(DESTDIR)$(zshcompletiondir)" "$(DESTDIR)$(pkgconfigdir)" \
+	"$(DESTDIR)$(rulesdir)" "$(DESTDIR)$(statedir)" \
+	"$(DESTDIR)$(systemdsystemunitdir)" \
+	"$(DESTDIR)$(systemduserunitdir)" "$(DESTDIR)$(pkgincludedir)"
+@TESTING_TRUE@am__EXEEXT_7 = emulator/btvirt$(EXEEXT) \
+@TESTING_TRUE@	emulator/b1ee$(EXEEXT) emulator/hfp$(EXEEXT) \
+@TESTING_TRUE@	peripheral/btsensor$(EXEEXT) tools/3dsp$(EXEEXT) \
+@TESTING_TRUE@	tools/mgmt-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/gap-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/l2cap-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/sco-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/smp-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/hci-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/rfcomm-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/bnep-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/userchan-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/iso-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/mesh-tester$(EXEEXT) \
+@TESTING_TRUE@	tools/ioctl-tester$(EXEEXT)
+@TOOLS_TRUE@am__EXEEXT_8 = tools/bdaddr$(EXEEXT) tools/avinfo$(EXEEXT) \
+@TOOLS_TRUE@	tools/avtest$(EXEEXT) tools/scotest$(EXEEXT) \
+@TOOLS_TRUE@	tools/amptest$(EXEEXT) tools/hwdb$(EXEEXT) \
+@TOOLS_TRUE@	tools/hcieventmask$(EXEEXT) \
+@TOOLS_TRUE@	tools/hcisecfilter$(EXEEXT) tools/btinfo$(EXEEXT) \
+@TOOLS_TRUE@	tools/btconfig$(EXEEXT) tools/btsnoop$(EXEEXT) \
+@TOOLS_TRUE@	tools/btproxy$(EXEEXT) tools/btiotest$(EXEEXT) \
+@TOOLS_TRUE@	tools/bneptest$(EXEEXT) tools/mcaptest$(EXEEXT) \
+@TOOLS_TRUE@	tools/cltest$(EXEEXT) tools/oobtest$(EXEEXT) \
+@TOOLS_TRUE@	tools/advtest$(EXEEXT) tools/seq2bseq$(EXEEXT) \
+@TOOLS_TRUE@	tools/nokfw$(EXEEXT) tools/rtlfw$(EXEEXT) \
+@TOOLS_TRUE@	tools/bcmfw$(EXEEXT) tools/create-image$(EXEEXT) \
+@TOOLS_TRUE@	tools/eddystone$(EXEEXT) tools/ibeacon$(EXEEXT) \
+@TOOLS_TRUE@	tools/btgatt-client$(EXEEXT) \
+@TOOLS_TRUE@	tools/btgatt-server$(EXEEXT) \
+@TOOLS_TRUE@	tools/test-runner$(EXEEXT) \
+@TOOLS_TRUE@	tools/check-selftest$(EXEEXT) \
+@TOOLS_TRUE@	tools/gatt-service$(EXEEXT) \
+@TOOLS_TRUE@	profiles/iap/iapd$(EXEEXT)
+@READLINE_TRUE@am__EXEEXT_9 = tools/btmgmt$(EXEEXT) \
+@READLINE_TRUE@	tools/obex-client-tool$(EXEEXT) \
+@READLINE_TRUE@	tools/obex-server-tool$(EXEEXT) \
+@READLINE_TRUE@	tools/bluetooth-player$(EXEEXT) \
+@READLINE_TRUE@	tools/obexctl$(EXEEXT)
+@DEPRECATED_TRUE@@READLINE_TRUE@am__EXEEXT_10 =  \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/gatttool$(EXEEXT)
+@BTPCLIENT_TRUE@am__EXEEXT_11 = tools/btpclient$(EXEEXT) \
+@BTPCLIENT_TRUE@	tools/btpclientctl$(EXEEXT)
+@ANDROID_TRUE@am__EXEEXT_12 = android/system-emulator$(EXEEXT) \
+@ANDROID_TRUE@	android/bluetoothd-snoop$(EXEEXT) \
+@ANDROID_TRUE@	android/bluetoothd$(EXEEXT) \
+@ANDROID_TRUE@	android/avdtptest$(EXEEXT) \
+@ANDROID_TRUE@	android/haltest$(EXEEXT) \
+@ANDROID_TRUE@	android/android-tester$(EXEEXT) \
+@ANDROID_TRUE@	android/ipc-tester$(EXEEXT)
+@ANDROID_TRUE@am__EXEEXT_13 = android/test-ipc$(EXEEXT)
+@OBEX_TRUE@am__EXEEXT_14 = unit/test-gobex-header$(EXEEXT) \
+@OBEX_TRUE@	unit/test-gobex-packet$(EXEEXT) \
+@OBEX_TRUE@	unit/test-gobex$(EXEEXT) \
+@OBEX_TRUE@	unit/test-gobex-transfer$(EXEEXT) \
+@OBEX_TRUE@	unit/test-gobex-apparam$(EXEEXT)
+@MIDI_TRUE@am__EXEEXT_15 = unit/test-midi$(EXEEXT)
+@MESH_TRUE@am__EXEEXT_16 = unit/test-mesh-crypto$(EXEEXT)
+am__EXEEXT_17 = $(am__EXEEXT_13) unit/test-tester$(EXEEXT) \
+	unit/test-eir$(EXEEXT) unit/test-uuid$(EXEEXT) \
+	unit/test-textfile$(EXEEXT) unit/test-crc$(EXEEXT) \
+	unit/test-crypto$(EXEEXT) unit/test-ecc$(EXEEXT) \
+	unit/test-ringbuf$(EXEEXT) unit/test-queue$(EXEEXT) \
+	unit/test-mgmt$(EXEEXT) unit/test-uhid$(EXEEXT) \
+	unit/test-sdp$(EXEEXT) unit/test-avdtp$(EXEEXT) \
+	unit/test-avctp$(EXEEXT) unit/test-avrcp$(EXEEXT) \
+	unit/test-hfp$(EXEEXT) unit/test-gdbus-client$(EXEEXT) \
+	$(am__EXEEXT_14) unit/test-lib$(EXEEXT) \
+	unit/test-gatt$(EXEEXT) unit/test-hog$(EXEEXT) \
+	unit/test-gattrib$(EXEEXT) unit/test-bap$(EXEEXT) \
+	unit/test-micp$(EXEEXT) unit/test-bass$(EXEEXT) \
+	unit/test-vcp$(EXEEXT) $(am__EXEEXT_15) $(am__EXEEXT_16)
+@MAINTAINER_MODE_TRUE@am__EXEEXT_18 = $(am__EXEEXT_17)
+@LOGGER_TRUE@am__EXEEXT_19 = tools/btmon-logger$(EXEEXT)
+@OBEX_TRUE@am__EXEEXT_20 = obexd/src/obexd$(EXEEXT)
+@MESH_TRUE@am__EXEEXT_21 = mesh/bluetooth-meshd$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS) $(cups_PROGRAMS) $(noinst_PROGRAMS) \
+	$(pkglibexec_PROGRAMS) $(udev_PROGRAMS)
+LIBRARIES = $(noinst_LIBRARIES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \
+	$(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@ANDROID_TRUE@android_audio_a2dp_default_la_DEPENDENCIES =  \
+@ANDROID_TRUE@	$(am__DEPENDENCIES_1)
+am__android_audio_a2dp_default_la_SOURCES_DIST = android/audio-msg.h \
+	android/hal-msg.h android/hal-audio.h android/hal-audio.c \
+	android/hal-audio-sbc.c android/hal-audio-aptx.c \
+	android/hardware/audio.h android/hardware/audio_effect.h \
+	android/hardware/hardware.h android/system/audio.h
+am__dirstamp = $(am__leading_dot)dirstamp
+@ANDROID_TRUE@am_android_audio_a2dp_default_la_OBJECTS =  \
+@ANDROID_TRUE@	android/audio_a2dp_default_la-hal-audio.lo \
+@ANDROID_TRUE@	android/audio_a2dp_default_la-hal-audio-sbc.lo \
+@ANDROID_TRUE@	android/audio_a2dp_default_la-hal-audio-aptx.lo
+android_audio_a2dp_default_la_OBJECTS =  \
+	$(am_android_audio_a2dp_default_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+android_audio_a2dp_default_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) \
+	$(android_audio_a2dp_default_la_LDFLAGS) $(LDFLAGS) -o $@
+@ANDROID_TRUE@am_android_audio_a2dp_default_la_rpath = -rpath \
+@ANDROID_TRUE@	$(plugindir)
+@ANDROID_TRUE@android_audio_sco_default_la_DEPENDENCIES =  \
+@ANDROID_TRUE@	$(am__DEPENDENCIES_1)
+am__android_audio_sco_default_la_SOURCES_DIST = android/hal-log.h \
+	android/sco-msg.h android/hal-sco.c android/hardware/audio.h \
+	android/hardware/audio_effect.h android/hardware/hardware.h \
+	android/audio_utils/resampler.c \
+	android/audio_utils/resampler.h android/system/audio.h
+@ANDROID_TRUE@am_android_audio_sco_default_la_OBJECTS =  \
+@ANDROID_TRUE@	android/audio_sco_default_la-hal-sco.lo \
+@ANDROID_TRUE@	android/audio_utils/audio_sco_default_la-resampler.lo
+android_audio_sco_default_la_OBJECTS =  \
+	$(am_android_audio_sco_default_la_OBJECTS)
+android_audio_sco_default_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(android_audio_sco_default_la_CFLAGS) $(CFLAGS) \
+	$(android_audio_sco_default_la_LDFLAGS) $(LDFLAGS) -o $@
+@ANDROID_TRUE@am_android_audio_sco_default_la_rpath = -rpath \
+@ANDROID_TRUE@	$(plugindir)
+android_bluetooth_default_la_LIBADD =
+am__android_bluetooth_default_la_SOURCES_DIST = android/hal.h \
+	android/hal-bluetooth.c android/hal-socket.c \
+	android/hal-hidhost.c android/hal-health.c android/hal-pan.c \
+	android/hal-a2dp.c android/hal-a2dp-sink.c android/hal-avrcp.c \
+	android/hal-avrcp-ctrl.c android/hal-handsfree.c \
+	android/hal-handsfree-client.c android/hal-gatt.c \
+	android/hal-map-client.c android/hardware/bluetooth.h \
+	android/hardware/bt_av.h android/hardware/bt_gatt.h \
+	android/hardware/bt_gatt_client.h \
+	android/hardware/bt_gatt_server.h \
+	android/hardware/bt_gatt_types.h android/hardware/bt_hf.h \
+	android/hardware/bt_hh.h android/hardware/bt_hl.h \
+	android/hardware/bt_pan.h android/hardware/bt_rc.h \
+	android/hardware/bt_sock.h android/hardware/bt_hf_client.h \
+	android/hardware/bt_mce.h android/hardware/hardware.h \
+	android/cutils/properties.h android/ipc-common.h \
+	android/hal-log.h android/hal-ipc.h android/hal-ipc.c \
+	android/hal-utils.h android/hal-utils.c
+@ANDROID_TRUE@am_android_bluetooth_default_la_OBJECTS =  \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-bluetooth.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-socket.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-hidhost.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-health.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-pan.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-a2dp.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-a2dp-sink.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-avrcp.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-avrcp-ctrl.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-handsfree.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-handsfree-client.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-gatt.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-map-client.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-ipc.lo \
+@ANDROID_TRUE@	android/bluetooth_default_la-hal-utils.lo
+android_bluetooth_default_la_OBJECTS =  \
+	$(am_android_bluetooth_default_la_OBJECTS)
+android_bluetooth_default_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(android_bluetooth_default_la_CFLAGS) $(CFLAGS) \
+	$(android_bluetooth_default_la_LDFLAGS) $(LDFLAGS) -o $@
+@ANDROID_TRUE@am_android_bluetooth_default_la_rpath = -rpath \
+@ANDROID_TRUE@	$(plugindir)
+ell_libell_internal_la_LIBADD =
+am__ell_libell_internal_la_SOURCES_DIST = ell/util.h ell/log.h \
+	ell/queue.h ell/hashmap.h ell/random.h ell/signal.h ell/time.h \
+	ell/time-private.h ell/timeout.h ell/cipher.h ell/checksum.h \
+	ell/io.h ell/idle.h ell/main.h ell/settings.h ell/strv.h \
+	ell/string.h ell/utf8.h ell/dbus.h ell/dbus-service.h \
+	ell/dbus-client.h ell/key.h ell/cert.h ell/pem.h ell/base64.h \
+	ell/asn1-private.h ell/cert-private.h ell/pem-private.h \
+	ell/uuid.h ell/useful.h ell/main-private.h ell/tester.h \
+	ell/tls.h ell/tls-private.h ell/ecc.h ell/ecc-private.h \
+	ell/cleanup.h ell/ecdh.h ell/private.h ell/missing.h \
+	ell/util.c ell/log.c ell/queue.c ell/hashmap.c ell/random.c \
+	ell/signal.c ell/time.c ell/timeout.c ell/io.c ell/idle.c \
+	ell/main.c ell/settings.c ell/strv.c ell/string.c ell/cipher.c \
+	ell/checksum.c ell/pem.c ell/cert.c ell/cert-crypto.c \
+	ell/key.c ell/base64.c ell/utf8.c ell/dbus-private.h \
+	ell/dbus.c ell/dbus-message.c ell/dbus-util.c \
+	ell/dbus-service.c ell/dbus-client.c ell/dbus-name-cache.c \
+	ell/dbus-filter.c ell/gvariant-private.h ell/gvariant-util.c \
+	ell/siphash-private.h ell/siphash.c ell/uuid.c ell/tester.c \
+	ell/tls.c ell/tls-extensions.c ell/tls-suites.c \
+	ell/tls-record.c ell/ecc.c ell/ecc-external.c ell/ecdh.c
+am__objects_1 =
+@EXTERNAL_ELL_FALSE@am__objects_2 = ell/util.lo ell/log.lo \
+@EXTERNAL_ELL_FALSE@	ell/queue.lo ell/hashmap.lo ell/random.lo \
+@EXTERNAL_ELL_FALSE@	ell/signal.lo ell/time.lo ell/timeout.lo \
+@EXTERNAL_ELL_FALSE@	ell/io.lo ell/idle.lo ell/main.lo \
+@EXTERNAL_ELL_FALSE@	ell/settings.lo ell/strv.lo ell/string.lo \
+@EXTERNAL_ELL_FALSE@	ell/cipher.lo ell/checksum.lo ell/pem.lo \
+@EXTERNAL_ELL_FALSE@	ell/cert.lo ell/cert-crypto.lo ell/key.lo \
+@EXTERNAL_ELL_FALSE@	ell/base64.lo ell/utf8.lo ell/dbus.lo \
+@EXTERNAL_ELL_FALSE@	ell/dbus-message.lo ell/dbus-util.lo \
+@EXTERNAL_ELL_FALSE@	ell/dbus-service.lo ell/dbus-client.lo \
+@EXTERNAL_ELL_FALSE@	ell/dbus-name-cache.lo ell/dbus-filter.lo \
+@EXTERNAL_ELL_FALSE@	ell/gvariant-util.lo ell/siphash.lo \
+@EXTERNAL_ELL_FALSE@	ell/uuid.lo ell/tester.lo ell/tls.lo \
+@EXTERNAL_ELL_FALSE@	ell/tls-extensions.lo ell/tls-suites.lo \
+@EXTERNAL_ELL_FALSE@	ell/tls-record.lo ell/ecc.lo \
+@EXTERNAL_ELL_FALSE@	ell/ecc-external.lo ell/ecdh.lo
+@EXTERNAL_ELL_FALSE@am_ell_libell_internal_la_OBJECTS =  \
+@EXTERNAL_ELL_FALSE@	$(am__objects_1) $(am__objects_2) \
+@EXTERNAL_ELL_FALSE@	$(am__objects_1)
+ell_libell_internal_la_OBJECTS = $(am_ell_libell_internal_la_OBJECTS)
+@EXTERNAL_ELL_FALSE@am_ell_libell_internal_la_rpath =
+gdbus_libgdbus_internal_la_LIBADD =
+am_gdbus_libgdbus_internal_la_OBJECTS = gdbus/mainloop.lo \
+	gdbus/watch.lo gdbus/object.lo gdbus/client.lo gdbus/polkit.lo
+gdbus_libgdbus_internal_la_OBJECTS =  \
+	$(am_gdbus_libgdbus_internal_la_OBJECTS)
+lib_libbluetooth_internal_la_LIBADD =
+am__objects_3 = lib/bluetooth.lo lib/hci.lo lib/sdp.lo
+am__objects_4 = lib/uuid.lo
+am_lib_libbluetooth_internal_la_OBJECTS = $(am__objects_1) \
+	$(am__objects_3) $(am__objects_1) $(am__objects_4)
+lib_libbluetooth_internal_la_OBJECTS =  \
+	$(am_lib_libbluetooth_internal_la_OBJECTS)
+lib_libbluetooth_la_LIBADD =
+am__lib_libbluetooth_la_SOURCES_DIST = lib/bluetooth.h lib/hci.h \
+	lib/hci_lib.h lib/sco.h lib/l2cap.h lib/sdp.h lib/sdp_lib.h \
+	lib/rfcomm.h lib/bnep.h lib/cmtp.h lib/hidp.h lib/bluetooth.c \
+	lib/hci.c lib/sdp.c
+@LIBRARY_TRUE@am_lib_libbluetooth_la_OBJECTS = $(am__objects_1) \
+@LIBRARY_TRUE@	$(am__objects_3)
+lib_libbluetooth_la_OBJECTS = $(am_lib_libbluetooth_la_OBJECTS)
+lib_libbluetooth_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(lib_libbluetooth_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+@LIBRARY_TRUE@am_lib_libbluetooth_la_rpath = -rpath $(libdir)
+src_libshared_ell_la_LIBADD =
+am__src_libshared_ell_la_SOURCES_DIST = src/shared/io.h \
+	src/shared/timeout.h src/shared/queue.h src/shared/queue.c \
+	src/shared/util.h src/shared/util.c src/shared/mgmt.h \
+	src/shared/mgmt.c src/shared/crypto.h src/shared/crypto.c \
+	src/shared/ecc.h src/shared/ecc.c src/shared/ringbuf.h \
+	src/shared/ringbuf.c src/shared/tester.h src/shared/hci.h \
+	src/shared/hci.c src/shared/hci-crypto.h \
+	src/shared/hci-crypto.c src/shared/hfp.h src/shared/hfp.c \
+	src/shared/uhid.h src/shared/uhid.c src/shared/pcap.h \
+	src/shared/pcap.c src/shared/btsnoop.h src/shared/btsnoop.c \
+	src/shared/ad.h src/shared/ad.c src/shared/att-types.h \
+	src/shared/att.h src/shared/att.c src/shared/gatt-helpers.h \
+	src/shared/gatt-helpers.c src/shared/gatt-client.h \
+	src/shared/gatt-client.c src/shared/gatt-server.h \
+	src/shared/gatt-server.c src/shared/gatt-db.h \
+	src/shared/gatt-db.c src/shared/gap.h src/shared/gap.c \
+	src/shared/log.h src/shared/log.c src/shared/bap.h \
+	src/shared/bap.c src/shared/ascs.h src/shared/bap-debug.h \
+	src/shared/bap-debug.c src/shared/mcs.h src/shared/mcp.h \
+	src/shared/mcp.c src/shared/vcp.c src/shared/vcp.h \
+	src/shared/micp.c src/shared/micp.h src/shared/csip.c \
+	src/shared/csip.h src/shared/bass.h src/shared/bass.c \
+	src/shared/ccp.h src/shared/ccp.c src/shared/lc3.h \
+	src/shared/tty.h src/shared/bap-defs.h src/shared/asha.h \
+	src/shared/asha.c src/shared/shell.c src/shared/shell.h \
+	src/shared/io-ell.c src/shared/timeout-ell.c \
+	src/shared/mainloop.h src/shared/mainloop-ell.c
+@READLINE_TRUE@am__objects_5 = src/shared/libshared_ell_la-shell.lo
+am__objects_6 = src/shared/libshared_ell_la-queue.lo \
+	src/shared/libshared_ell_la-util.lo \
+	src/shared/libshared_ell_la-mgmt.lo \
+	src/shared/libshared_ell_la-crypto.lo \
+	src/shared/libshared_ell_la-ecc.lo \
+	src/shared/libshared_ell_la-ringbuf.lo \
+	src/shared/libshared_ell_la-hci.lo \
+	src/shared/libshared_ell_la-hci-crypto.lo \
+	src/shared/libshared_ell_la-hfp.lo \
+	src/shared/libshared_ell_la-uhid.lo \
+	src/shared/libshared_ell_la-pcap.lo \
+	src/shared/libshared_ell_la-btsnoop.lo \
+	src/shared/libshared_ell_la-ad.lo \
+	src/shared/libshared_ell_la-att.lo \
+	src/shared/libshared_ell_la-gatt-helpers.lo \
+	src/shared/libshared_ell_la-gatt-client.lo \
+	src/shared/libshared_ell_la-gatt-server.lo \
+	src/shared/libshared_ell_la-gatt-db.lo \
+	src/shared/libshared_ell_la-gap.lo \
+	src/shared/libshared_ell_la-log.lo \
+	src/shared/libshared_ell_la-bap.lo \
+	src/shared/libshared_ell_la-bap-debug.lo \
+	src/shared/libshared_ell_la-mcp.lo \
+	src/shared/libshared_ell_la-vcp.lo \
+	src/shared/libshared_ell_la-micp.lo \
+	src/shared/libshared_ell_la-csip.lo \
+	src/shared/libshared_ell_la-bass.lo \
+	src/shared/libshared_ell_la-ccp.lo \
+	src/shared/libshared_ell_la-asha.lo $(am__objects_5)
+@LIBSHARED_ELL_TRUE@am_src_libshared_ell_la_OBJECTS =  \
+@LIBSHARED_ELL_TRUE@	$(am__objects_6) \
+@LIBSHARED_ELL_TRUE@	src/shared/libshared_ell_la-io-ell.lo \
+@LIBSHARED_ELL_TRUE@	src/shared/libshared_ell_la-timeout-ell.lo \
+@LIBSHARED_ELL_TRUE@	src/shared/libshared_ell_la-mainloop-ell.lo
+src_libshared_ell_la_OBJECTS = $(am_src_libshared_ell_la_OBJECTS)
+src_libshared_ell_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(src_libshared_ell_la_CFLAGS) $(CFLAGS) \
+	$(src_libshared_ell_la_LDFLAGS) $(LDFLAGS) -o $@
+@LIBSHARED_ELL_TRUE@am_src_libshared_ell_la_rpath =
+src_libshared_glib_la_LIBADD =
+am__src_libshared_glib_la_SOURCES_DIST = src/shared/io.h \
+	src/shared/timeout.h src/shared/queue.h src/shared/queue.c \
+	src/shared/util.h src/shared/util.c src/shared/mgmt.h \
+	src/shared/mgmt.c src/shared/crypto.h src/shared/crypto.c \
+	src/shared/ecc.h src/shared/ecc.c src/shared/ringbuf.h \
+	src/shared/ringbuf.c src/shared/tester.h src/shared/hci.h \
+	src/shared/hci.c src/shared/hci-crypto.h \
+	src/shared/hci-crypto.c src/shared/hfp.h src/shared/hfp.c \
+	src/shared/uhid.h src/shared/uhid.c src/shared/pcap.h \
+	src/shared/pcap.c src/shared/btsnoop.h src/shared/btsnoop.c \
+	src/shared/ad.h src/shared/ad.c src/shared/att-types.h \
+	src/shared/att.h src/shared/att.c src/shared/gatt-helpers.h \
+	src/shared/gatt-helpers.c src/shared/gatt-client.h \
+	src/shared/gatt-client.c src/shared/gatt-server.h \
+	src/shared/gatt-server.c src/shared/gatt-db.h \
+	src/shared/gatt-db.c src/shared/gap.h src/shared/gap.c \
+	src/shared/log.h src/shared/log.c src/shared/bap.h \
+	src/shared/bap.c src/shared/ascs.h src/shared/bap-debug.h \
+	src/shared/bap-debug.c src/shared/mcs.h src/shared/mcp.h \
+	src/shared/mcp.c src/shared/vcp.c src/shared/vcp.h \
+	src/shared/micp.c src/shared/micp.h src/shared/csip.c \
+	src/shared/csip.h src/shared/bass.h src/shared/bass.c \
+	src/shared/ccp.h src/shared/ccp.c src/shared/lc3.h \
+	src/shared/tty.h src/shared/bap-defs.h src/shared/asha.h \
+	src/shared/asha.c src/shared/shell.c src/shared/shell.h \
+	src/shared/io-glib.c src/shared/timeout-glib.c \
+	src/shared/mainloop-glib.c src/shared/mainloop-notify.h \
+	src/shared/mainloop-notify.c src/shared/tester.c
+@READLINE_TRUE@am__objects_7 = src/shared/libshared_glib_la-shell.lo
+am__objects_8 = src/shared/libshared_glib_la-queue.lo \
+	src/shared/libshared_glib_la-util.lo \
+	src/shared/libshared_glib_la-mgmt.lo \
+	src/shared/libshared_glib_la-crypto.lo \
+	src/shared/libshared_glib_la-ecc.lo \
+	src/shared/libshared_glib_la-ringbuf.lo \
+	src/shared/libshared_glib_la-hci.lo \
+	src/shared/libshared_glib_la-hci-crypto.lo \
+	src/shared/libshared_glib_la-hfp.lo \
+	src/shared/libshared_glib_la-uhid.lo \
+	src/shared/libshared_glib_la-pcap.lo \
+	src/shared/libshared_glib_la-btsnoop.lo \
+	src/shared/libshared_glib_la-ad.lo \
+	src/shared/libshared_glib_la-att.lo \
+	src/shared/libshared_glib_la-gatt-helpers.lo \
+	src/shared/libshared_glib_la-gatt-client.lo \
+	src/shared/libshared_glib_la-gatt-server.lo \
+	src/shared/libshared_glib_la-gatt-db.lo \
+	src/shared/libshared_glib_la-gap.lo \
+	src/shared/libshared_glib_la-log.lo \
+	src/shared/libshared_glib_la-bap.lo \
+	src/shared/libshared_glib_la-bap-debug.lo \
+	src/shared/libshared_glib_la-mcp.lo \
+	src/shared/libshared_glib_la-vcp.lo \
+	src/shared/libshared_glib_la-micp.lo \
+	src/shared/libshared_glib_la-csip.lo \
+	src/shared/libshared_glib_la-bass.lo \
+	src/shared/libshared_glib_la-ccp.lo \
+	src/shared/libshared_glib_la-asha.lo $(am__objects_7)
+am_src_libshared_glib_la_OBJECTS = $(am__objects_8) \
+	src/shared/libshared_glib_la-io-glib.lo \
+	src/shared/libshared_glib_la-timeout-glib.lo \
+	src/shared/libshared_glib_la-mainloop-glib.lo \
+	src/shared/libshared_glib_la-mainloop-notify.lo \
+	src/shared/libshared_glib_la-tester.lo
+src_libshared_glib_la_OBJECTS = $(am_src_libshared_glib_la_OBJECTS)
+src_libshared_glib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(src_libshared_glib_la_CFLAGS) $(CFLAGS) \
+	$(src_libshared_glib_la_LDFLAGS) $(LDFLAGS) -o $@
+src_libshared_mainloop_la_LIBADD =
+am__src_libshared_mainloop_la_SOURCES_DIST = src/shared/io.h \
+	src/shared/timeout.h src/shared/queue.h src/shared/queue.c \
+	src/shared/util.h src/shared/util.c src/shared/mgmt.h \
+	src/shared/mgmt.c src/shared/crypto.h src/shared/crypto.c \
+	src/shared/ecc.h src/shared/ecc.c src/shared/ringbuf.h \
+	src/shared/ringbuf.c src/shared/tester.h src/shared/hci.h \
+	src/shared/hci.c src/shared/hci-crypto.h \
+	src/shared/hci-crypto.c src/shared/hfp.h src/shared/hfp.c \
+	src/shared/uhid.h src/shared/uhid.c src/shared/pcap.h \
+	src/shared/pcap.c src/shared/btsnoop.h src/shared/btsnoop.c \
+	src/shared/ad.h src/shared/ad.c src/shared/att-types.h \
+	src/shared/att.h src/shared/att.c src/shared/gatt-helpers.h \
+	src/shared/gatt-helpers.c src/shared/gatt-client.h \
+	src/shared/gatt-client.c src/shared/gatt-server.h \
+	src/shared/gatt-server.c src/shared/gatt-db.h \
+	src/shared/gatt-db.c src/shared/gap.h src/shared/gap.c \
+	src/shared/log.h src/shared/log.c src/shared/bap.h \
+	src/shared/bap.c src/shared/ascs.h src/shared/bap-debug.h \
+	src/shared/bap-debug.c src/shared/mcs.h src/shared/mcp.h \
+	src/shared/mcp.c src/shared/vcp.c src/shared/vcp.h \
+	src/shared/micp.c src/shared/micp.h src/shared/csip.c \
+	src/shared/csip.h src/shared/bass.h src/shared/bass.c \
+	src/shared/ccp.h src/shared/ccp.c src/shared/lc3.h \
+	src/shared/tty.h src/shared/bap-defs.h src/shared/asha.h \
+	src/shared/asha.c src/shared/shell.c src/shared/shell.h \
+	src/shared/io-mainloop.c src/shared/timeout-mainloop.c \
+	src/shared/mainloop.h src/shared/mainloop.c \
+	src/shared/mainloop-notify.h src/shared/mainloop-notify.c
+@READLINE_TRUE@am__objects_9 =  \
+@READLINE_TRUE@	src/shared/libshared_mainloop_la-shell.lo
+am__objects_10 = src/shared/libshared_mainloop_la-queue.lo \
+	src/shared/libshared_mainloop_la-util.lo \
+	src/shared/libshared_mainloop_la-mgmt.lo \
+	src/shared/libshared_mainloop_la-crypto.lo \
+	src/shared/libshared_mainloop_la-ecc.lo \
+	src/shared/libshared_mainloop_la-ringbuf.lo \
+	src/shared/libshared_mainloop_la-hci.lo \
+	src/shared/libshared_mainloop_la-hci-crypto.lo \
+	src/shared/libshared_mainloop_la-hfp.lo \
+	src/shared/libshared_mainloop_la-uhid.lo \
+	src/shared/libshared_mainloop_la-pcap.lo \
+	src/shared/libshared_mainloop_la-btsnoop.lo \
+	src/shared/libshared_mainloop_la-ad.lo \
+	src/shared/libshared_mainloop_la-att.lo \
+	src/shared/libshared_mainloop_la-gatt-helpers.lo \
+	src/shared/libshared_mainloop_la-gatt-client.lo \
+	src/shared/libshared_mainloop_la-gatt-server.lo \
+	src/shared/libshared_mainloop_la-gatt-db.lo \
+	src/shared/libshared_mainloop_la-gap.lo \
+	src/shared/libshared_mainloop_la-log.lo \
+	src/shared/libshared_mainloop_la-bap.lo \
+	src/shared/libshared_mainloop_la-bap-debug.lo \
+	src/shared/libshared_mainloop_la-mcp.lo \
+	src/shared/libshared_mainloop_la-vcp.lo \
+	src/shared/libshared_mainloop_la-micp.lo \
+	src/shared/libshared_mainloop_la-csip.lo \
+	src/shared/libshared_mainloop_la-bass.lo \
+	src/shared/libshared_mainloop_la-ccp.lo \
+	src/shared/libshared_mainloop_la-asha.lo $(am__objects_9)
+am_src_libshared_mainloop_la_OBJECTS = $(am__objects_10) \
+	src/shared/libshared_mainloop_la-io-mainloop.lo \
+	src/shared/libshared_mainloop_la-timeout-mainloop.lo \
+	src/shared/libshared_mainloop_la-mainloop.lo \
+	src/shared/libshared_mainloop_la-mainloop-notify.lo
+src_libshared_mainloop_la_OBJECTS =  \
+	$(am_src_libshared_mainloop_la_OBJECTS)
+src_libshared_mainloop_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) \
+	$(src_libshared_mainloop_la_LDFLAGS) $(LDFLAGS) -o $@
+am__android_android_tester_SOURCES_DIST = emulator/hciemu.h \
+	emulator/hciemu.c emulator/vhci.h emulator/vhci.c \
+	emulator/btdev.h emulator/btdev.c emulator/bthost.h \
+	emulator/bthost.c emulator/smp.c monitor/rfcomm.h \
+	android/hardware/hardware.c android/tester-bluetooth.c \
+	android/tester-socket.c android/tester-hidhost.c \
+	android/tester-pan.c android/tester-hdp.c \
+	android/tester-a2dp.c android/tester-avrcp.c \
+	android/tester-gatt.c android/tester-map-client.c \
+	android/tester-main.h android/tester-main.c
+@ANDROID_TRUE@am_android_android_tester_OBJECTS = emulator/android_android_tester-hciemu.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_android_tester-vhci.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_android_tester-btdev.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_android_tester-bthost.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_android_tester-smp.$(OBJEXT) \
+@ANDROID_TRUE@	android/hardware/android_tester-hardware.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-bluetooth.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-socket.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-hidhost.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-pan.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-hdp.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-a2dp.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-avrcp.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-gatt.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-map-client.$(OBJEXT) \
+@ANDROID_TRUE@	android/android_tester-tester-main.$(OBJEXT)
+android_android_tester_OBJECTS = $(am_android_android_tester_OBJECTS)
+@ANDROID_TRUE@android_android_tester_DEPENDENCIES =  \
+@ANDROID_TRUE@	lib/libbluetooth-internal.la \
+@ANDROID_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+android_android_tester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(android_android_tester_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am__android_avdtptest_SOURCES_DIST = android/avdtptest.c src/log.h \
+	src/log.c btio/btio.h btio/btio.c src/shared/util.h \
+	src/shared/util.c src/shared/queue.h src/shared/queue.c \
+	src/shared/log.h src/shared/log.c android/avdtp.h \
+	android/avdtp.c
+@ANDROID_TRUE@am_android_avdtptest_OBJECTS =  \
+@ANDROID_TRUE@	android/avdtptest-avdtptest.$(OBJEXT) \
+@ANDROID_TRUE@	src/android_avdtptest-log.$(OBJEXT) \
+@ANDROID_TRUE@	btio/android_avdtptest-btio.$(OBJEXT) \
+@ANDROID_TRUE@	src/shared/android_avdtptest-util.$(OBJEXT) \
+@ANDROID_TRUE@	src/shared/android_avdtptest-queue.$(OBJEXT) \
+@ANDROID_TRUE@	src/shared/android_avdtptest-log.$(OBJEXT) \
+@ANDROID_TRUE@	android/avdtptest-avdtp.$(OBJEXT)
+android_avdtptest_OBJECTS = $(am_android_avdtptest_OBJECTS)
+@ANDROID_TRUE@android_avdtptest_DEPENDENCIES =  \
+@ANDROID_TRUE@	lib/libbluetooth-internal.la \
+@ANDROID_TRUE@	$(am__DEPENDENCIES_1)
+android_avdtptest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(android_avdtptest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+am__android_bluetoothd_SOURCES_DIST = android/main.c src/log.c \
+	android/hal-msg.h android/audio-msg.h android/sco-msg.h \
+	android/utils.h src/sdpd-database.c src/sdpd-server.c \
+	src/sdpd-service.c src/sdpd-request.c src/uuid-helper.h \
+	src/uuid-helper.c src/eir.h src/eir.c android/bluetooth.h \
+	android/bluetooth.c android/hidhost.h android/hidhost.c \
+	profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
+	profiles/deviceinfo/dis.h profiles/deviceinfo/dis.c \
+	profiles/battery/bas.h profiles/battery/bas.c \
+	profiles/input/hog-lib.h profiles/input/hog-lib.c \
+	android/ipc-common.h android/ipc.h android/ipc.c \
+	android/avdtp.h android/avdtp.c android/a2dp.h android/a2dp.c \
+	android/a2dp-sink.h android/a2dp-sink.c android/avctp.h \
+	android/avctp.c android/avrcp.h android/avrcp.c \
+	android/avrcp-lib.h android/avrcp-lib.c android/socket.h \
+	android/socket.c android/sco.h android/sco.c android/pan.h \
+	android/pan.c android/handsfree.h android/handsfree.c \
+	android/handsfree-client.c android/handsfree-client.h \
+	android/gatt.h android/gatt.c android/health.h \
+	android/health.c profiles/health/mcap.h profiles/health/mcap.c \
+	android/map-client.h android/map-client.c attrib/att.c \
+	attrib/att.h attrib/gatt.c attrib/gatt.h attrib/gattrib.c \
+	attrib/gattrib.h btio/btio.h btio/btio.c src/sdp-client.h \
+	src/sdp-client.c profiles/network/bnep.h \
+	profiles/network/bnep.c
+@ANDROID_TRUE@am_android_bluetoothd_OBJECTS = android/main.$(OBJEXT) \
+@ANDROID_TRUE@	src/log.$(OBJEXT) src/sdpd-database.$(OBJEXT) \
+@ANDROID_TRUE@	src/sdpd-server.$(OBJEXT) \
+@ANDROID_TRUE@	src/sdpd-service.$(OBJEXT) \
+@ANDROID_TRUE@	src/sdpd-request.$(OBJEXT) \
+@ANDROID_TRUE@	src/uuid-helper.$(OBJEXT) src/eir.$(OBJEXT) \
+@ANDROID_TRUE@	android/bluetooth.$(OBJEXT) \
+@ANDROID_TRUE@	android/hidhost.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/scanparam/scpp.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/deviceinfo/dis.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/battery/bas.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/input/hog-lib.$(OBJEXT) \
+@ANDROID_TRUE@	android/ipc.$(OBJEXT) android/avdtp.$(OBJEXT) \
+@ANDROID_TRUE@	android/a2dp.$(OBJEXT) \
+@ANDROID_TRUE@	android/a2dp-sink.$(OBJEXT) \
+@ANDROID_TRUE@	android/avctp.$(OBJEXT) android/avrcp.$(OBJEXT) \
+@ANDROID_TRUE@	android/avrcp-lib.$(OBJEXT) \
+@ANDROID_TRUE@	android/socket.$(OBJEXT) android/sco.$(OBJEXT) \
+@ANDROID_TRUE@	android/pan.$(OBJEXT) \
+@ANDROID_TRUE@	android/handsfree.$(OBJEXT) \
+@ANDROID_TRUE@	android/handsfree-client.$(OBJEXT) \
+@ANDROID_TRUE@	android/gatt.$(OBJEXT) android/health.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/health/mcap.$(OBJEXT) \
+@ANDROID_TRUE@	android/map-client.$(OBJEXT) \
+@ANDROID_TRUE@	attrib/att.$(OBJEXT) attrib/gatt.$(OBJEXT) \
+@ANDROID_TRUE@	attrib/gattrib.$(OBJEXT) btio/btio.$(OBJEXT) \
+@ANDROID_TRUE@	src/sdp-client.$(OBJEXT) \
+@ANDROID_TRUE@	profiles/network/bnep.$(OBJEXT)
+android_bluetoothd_OBJECTS = $(am_android_bluetoothd_OBJECTS)
+@ANDROID_TRUE@android_bluetoothd_DEPENDENCIES =  \
+@ANDROID_TRUE@	lib/libbluetooth-internal.la \
+@ANDROID_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__android_bluetoothd_snoop_SOURCES_DIST =  \
+	android/bluetoothd-snoop.c src/log.c
+@ANDROID_TRUE@am_android_bluetoothd_snoop_OBJECTS =  \
+@ANDROID_TRUE@	android/bluetoothd-snoop.$(OBJEXT) \
+@ANDROID_TRUE@	src/log.$(OBJEXT)
+android_bluetoothd_snoop_OBJECTS =  \
+	$(am_android_bluetoothd_snoop_OBJECTS)
+@ANDROID_TRUE@android_bluetoothd_snoop_DEPENDENCIES =  \
+@ANDROID_TRUE@	src/libshared-mainloop.la $(am__DEPENDENCIES_1)
+am__android_haltest_SOURCES_DIST = android/client/haltest.c \
+	android/client/pollhandler.h android/client/pollhandler.c \
+	android/client/terminal.h android/client/terminal.c \
+	android/client/history.h android/client/history.c \
+	android/client/tabcompletion.c android/client/if-main.h \
+	android/client/if-av.c android/client/if-av-sink.c \
+	android/client/if-rc.c android/client/if-rc-ctrl.c \
+	android/client/if-bt.c android/client/if-gatt.c \
+	android/client/if-hf.c android/client/if-hf-client.c \
+	android/client/if-hh.c android/client/if-pan.c \
+	android/client/if-hl.c android/client/if-sock.c \
+	android/client/if-audio.c android/client/if-sco.c \
+	android/client/if-mce.c android/hardware/hardware.c \
+	android/hal-utils.h android/hal-utils.c
+@ANDROID_TRUE@am_android_haltest_OBJECTS =  \
+@ANDROID_TRUE@	android/client/haltest-haltest.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-pollhandler.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-terminal.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-history.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-tabcompletion.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-av.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-av-sink.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-rc.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-rc-ctrl.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-bt.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-gatt.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-hf.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-hf-client.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-hh.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-pan.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-hl.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-sock.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-audio.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-sco.$(OBJEXT) \
+@ANDROID_TRUE@	android/client/haltest-if-mce.$(OBJEXT) \
+@ANDROID_TRUE@	android/hardware/haltest-hardware.$(OBJEXT) \
+@ANDROID_TRUE@	android/haltest-hal-utils.$(OBJEXT)
+android_haltest_OBJECTS = $(am_android_haltest_OBJECTS)
+android_haltest_DEPENDENCIES =
+android_haltest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(android_haltest_LDFLAGS) $(LDFLAGS) \
+	-o $@
+am__android_ipc_tester_SOURCES_DIST = emulator/hciemu.h \
+	emulator/hciemu.c emulator/vhci.h emulator/vhci.c \
+	emulator/btdev.h emulator/btdev.c emulator/bthost.h \
+	emulator/bthost.c emulator/smp.c android/hal-utils.h \
+	android/hal-utils.c android/ipc-common.h android/ipc-tester.c
+@ANDROID_TRUE@am_android_ipc_tester_OBJECTS =  \
+@ANDROID_TRUE@	emulator/android_ipc_tester-hciemu.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_ipc_tester-vhci.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_ipc_tester-btdev.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_ipc_tester-bthost.$(OBJEXT) \
+@ANDROID_TRUE@	emulator/android_ipc_tester-smp.$(OBJEXT) \
+@ANDROID_TRUE@	android/ipc_tester-hal-utils.$(OBJEXT) \
+@ANDROID_TRUE@	android/ipc_tester-ipc-tester.$(OBJEXT)
+android_ipc_tester_OBJECTS = $(am_android_ipc_tester_OBJECTS)
+@ANDROID_TRUE@android_ipc_tester_DEPENDENCIES =  \
+@ANDROID_TRUE@	lib/libbluetooth-internal.la \
+@ANDROID_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__android_system_emulator_SOURCES_DIST = android/system-emulator.c
+@ANDROID_TRUE@am_android_system_emulator_OBJECTS =  \
+@ANDROID_TRUE@	android/system-emulator.$(OBJEXT)
+android_system_emulator_OBJECTS =  \
+	$(am_android_system_emulator_OBJECTS)
+@ANDROID_TRUE@android_system_emulator_DEPENDENCIES =  \
+@ANDROID_TRUE@	src/libshared-mainloop.la
+am__android_test_ipc_SOURCES_DIST = android/test-ipc.c src/log.h \
+	src/log.c android/ipc-common.h android/ipc.c android/ipc.h
+@ANDROID_TRUE@am_android_test_ipc_OBJECTS =  \
+@ANDROID_TRUE@	android/test-ipc.$(OBJEXT) src/log.$(OBJEXT) \
+@ANDROID_TRUE@	android/ipc.$(OBJEXT)
+android_test_ipc_OBJECTS = $(am_android_test_ipc_OBJECTS)
+@ANDROID_TRUE@android_test_ipc_DEPENDENCIES = src/libshared-glib.la \
+@ANDROID_TRUE@	$(am__DEPENDENCIES_1)
+am__attrib_gatttool_SOURCES_DIST = attrib/gatttool.c attrib/att.c \
+	attrib/gatt.c attrib/gattrib.c btio/btio.c attrib/gatttool.h \
+	attrib/interactive.c attrib/utils.c src/log.c client/display.c \
+	client/display.h
+@DEPRECATED_TRUE@@READLINE_TRUE@am_attrib_gatttool_OBJECTS =  \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/gatttool.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/att.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/gatt.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/gattrib.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	btio/btio.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/interactive.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	attrib/utils.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	src/log.$(OBJEXT) \
+@DEPRECATED_TRUE@@READLINE_TRUE@	client/display.$(OBJEXT)
+attrib_gatttool_OBJECTS = $(am_attrib_gatttool_OBJECTS)
+@DEPRECATED_TRUE@@READLINE_TRUE@attrib_gatttool_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@READLINE_TRUE@	lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@READLINE_TRUE@	src/libshared-glib.la \
+@DEPRECATED_TRUE@@READLINE_TRUE@	$(am__DEPENDENCIES_1)
+am__client_bluetoothctl_SOURCES_DIST = client/main.c client/print.h \
+	client/print.c client/display.h client/display.c \
+	client/agent.h client/agent.c client/advertising.h \
+	client/advertising.c client/adv_monitor.h client/adv_monitor.c \
+	client/gatt.h client/gatt.c client/admin.h client/admin.c \
+	client/player.h client/player.c client/mgmt.h client/mgmt.c \
+	client/assistant.h client/assistant.c
+@CLIENT_TRUE@am_client_bluetoothctl_OBJECTS = client/main.$(OBJEXT) \
+@CLIENT_TRUE@	client/print.$(OBJEXT) client/display.$(OBJEXT) \
+@CLIENT_TRUE@	client/agent.$(OBJEXT) \
+@CLIENT_TRUE@	client/advertising.$(OBJEXT) \
+@CLIENT_TRUE@	client/adv_monitor.$(OBJEXT) \
+@CLIENT_TRUE@	client/gatt.$(OBJEXT) client/admin.$(OBJEXT) \
+@CLIENT_TRUE@	client/player.$(OBJEXT) client/mgmt.$(OBJEXT) \
+@CLIENT_TRUE@	client/assistant.$(OBJEXT)
+client_bluetoothctl_OBJECTS = $(am_client_bluetoothctl_OBJECTS)
+@CLIENT_TRUE@client_bluetoothctl_DEPENDENCIES =  \
+@CLIENT_TRUE@	lib/libbluetooth-internal.la \
+@CLIENT_TRUE@	gdbus/libgdbus-internal.la src/libshared-glib.la \
+@CLIENT_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__emulator_b1ee_SOURCES_DIST = emulator/b1ee.c
+@TESTING_TRUE@am_emulator_b1ee_OBJECTS = emulator/b1ee.$(OBJEXT)
+emulator_b1ee_OBJECTS = $(am_emulator_b1ee_OBJECTS)
+@TESTING_TRUE@emulator_b1ee_DEPENDENCIES = src/libshared-mainloop.la
+am__emulator_btvirt_SOURCES_DIST = emulator/main.c monitor/bt.h \
+	emulator/serial.h emulator/serial.c emulator/server.h \
+	emulator/server.c emulator/vhci.h emulator/vhci.c \
+	emulator/btdev.h emulator/btdev.c emulator/bthost.h \
+	emulator/bthost.c emulator/smp.c emulator/phy.h emulator/phy.c \
+	emulator/amp.h emulator/amp.c emulator/le.h emulator/le.c
+@TESTING_TRUE@am_emulator_btvirt_OBJECTS = emulator/main.$(OBJEXT) \
+@TESTING_TRUE@	emulator/serial.$(OBJEXT) \
+@TESTING_TRUE@	emulator/server.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT) \
+@TESTING_TRUE@	emulator/phy.$(OBJEXT) emulator/amp.$(OBJEXT) \
+@TESTING_TRUE@	emulator/le.$(OBJEXT)
+emulator_btvirt_OBJECTS = $(am_emulator_btvirt_OBJECTS)
+@TESTING_TRUE@emulator_btvirt_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-mainloop.la
+am__emulator_hfp_SOURCES_DIST = emulator/hfp.c
+@TESTING_TRUE@am_emulator_hfp_OBJECTS = emulator/hfp.$(OBJEXT)
+emulator_hfp_OBJECTS = $(am_emulator_hfp_OBJECTS)
+@TESTING_TRUE@emulator_hfp_DEPENDENCIES = src/libshared-mainloop.la
+am__mesh_bluetooth_meshd_SOURCES_DIST = mesh/mesh.h mesh/mesh.c \
+	mesh/net-keys.h mesh/net-keys.c mesh/mesh-io.h mesh/mesh-io.c \
+	mesh/mesh-mgmt.h mesh/mesh-mgmt.c mesh/error.h \
+	mesh/mesh-io-api.h mesh/mesh-io-unit.h mesh/mesh-io-unit.c \
+	mesh/mesh-io-mgmt.h mesh/mesh-io-mgmt.c mesh/mesh-io-generic.h \
+	mesh/mesh-io-generic.c mesh/net.h mesh/net.c mesh/crypto.h \
+	mesh/crypto.c mesh/friend.h mesh/friend.c mesh/appkey.h \
+	mesh/appkey.c mesh/node.h mesh/node.c mesh/provision.h \
+	mesh/prov.h mesh/model.h mesh/model.c mesh/cfgmod.h \
+	mesh/cfgmod-server.c mesh/remprv.h mesh/remprv-server.c \
+	mesh/mesh-config.h mesh/mesh-config-json.c mesh/util.h \
+	mesh/util.c mesh/dbus.h mesh/dbus.c mesh/agent.h mesh/agent.c \
+	mesh/prov-acceptor.c mesh/prov-initiator.c mesh/manager.h \
+	mesh/manager.c mesh/pb-adv.h mesh/pb-adv.c mesh/keyring.h \
+	mesh/keyring.c mesh/rpl.h mesh/rpl.c mesh/prv-beacon.h \
+	mesh/prvbeac-server.c mesh/mesh-defs.h mesh/main.c
+@MESH_TRUE@am__objects_11 = mesh/mesh.$(OBJEXT) \
+@MESH_TRUE@	mesh/net-keys.$(OBJEXT) mesh/mesh-io.$(OBJEXT) \
+@MESH_TRUE@	mesh/mesh-mgmt.$(OBJEXT) \
+@MESH_TRUE@	mesh/mesh-io-unit.$(OBJEXT) \
+@MESH_TRUE@	mesh/mesh-io-mgmt.$(OBJEXT) \
+@MESH_TRUE@	mesh/mesh-io-generic.$(OBJEXT) mesh/net.$(OBJEXT) \
+@MESH_TRUE@	mesh/crypto.$(OBJEXT) mesh/friend.$(OBJEXT) \
+@MESH_TRUE@	mesh/appkey.$(OBJEXT) mesh/node.$(OBJEXT) \
+@MESH_TRUE@	mesh/model.$(OBJEXT) mesh/cfgmod-server.$(OBJEXT) \
+@MESH_TRUE@	mesh/remprv-server.$(OBJEXT) \
+@MESH_TRUE@	mesh/mesh-config-json.$(OBJEXT) mesh/util.$(OBJEXT) \
+@MESH_TRUE@	mesh/dbus.$(OBJEXT) mesh/agent.$(OBJEXT) \
+@MESH_TRUE@	mesh/prov-acceptor.$(OBJEXT) \
+@MESH_TRUE@	mesh/prov-initiator.$(OBJEXT) \
+@MESH_TRUE@	mesh/manager.$(OBJEXT) mesh/pb-adv.$(OBJEXT) \
+@MESH_TRUE@	mesh/keyring.$(OBJEXT) mesh/rpl.$(OBJEXT) \
+@MESH_TRUE@	mesh/prvbeac-server.$(OBJEXT)
+@MESH_TRUE@am_mesh_bluetooth_meshd_OBJECTS = $(am__objects_11) \
+@MESH_TRUE@	mesh/main.$(OBJEXT)
+mesh_bluetooth_meshd_OBJECTS = $(am_mesh_bluetooth_meshd_OBJECTS)
+@EXTERNAL_ELL_FALSE@am__DEPENDENCIES_2 = ell/libell-internal.la
+@MESH_TRUE@mesh_bluetooth_meshd_DEPENDENCIES = src/libshared-ell.la \
+@MESH_TRUE@	$(am__DEPENDENCIES_2)
+am__monitor_btmon_SOURCES_DIST = monitor/main.c monitor/bt.h \
+	monitor/display.h monitor/display.c monitor/hcidump.h \
+	monitor/hcidump.c monitor/ellisys.h monitor/ellisys.c \
+	monitor/control.h monitor/control.c monitor/packet.h \
+	monitor/packet.c monitor/vendor.h monitor/vendor.c \
+	monitor/lmp.h monitor/lmp.c monitor/crc.h monitor/crc.c \
+	monitor/ll.h monitor/ll.c monitor/l2cap.h monitor/l2cap.c \
+	monitor/sdp.h monitor/sdp.c monitor/avctp.h monitor/avctp.c \
+	monitor/avdtp.h monitor/avdtp.c monitor/a2dp.h monitor/a2dp.c \
+	monitor/rfcomm.h monitor/rfcomm.c monitor/bnep.h \
+	monitor/bnep.c monitor/hwdb.h monitor/hwdb.c monitor/keys.h \
+	monitor/keys.c monitor/analyze.h monitor/analyze.c \
+	monitor/intel.h monitor/intel.c monitor/broadcom.h \
+	monitor/broadcom.c monitor/msft.h monitor/msft.c \
+	monitor/jlink.h monitor/jlink.c monitor/tty.h \
+	monitor/emulator.h monitor/att.h monitor/att.c src/log.h \
+	src/log.c src/textfile.h src/textfile.c src/settings.h \
+	src/settings.c
+@MONITOR_TRUE@am_monitor_btmon_OBJECTS = monitor/main.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/display.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/hcidump.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/ellisys.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/control.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/packet.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/vendor.$(OBJEXT) monitor/lmp.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/crc.$(OBJEXT) monitor/ll.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/l2cap.$(OBJEXT) monitor/sdp.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/avctp.$(OBJEXT) monitor/avdtp.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/a2dp.$(OBJEXT) monitor/rfcomm.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/bnep.$(OBJEXT) monitor/hwdb.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/keys.$(OBJEXT) monitor/analyze.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/intel.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/broadcom.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/msft.$(OBJEXT) monitor/jlink.$(OBJEXT) \
+@MONITOR_TRUE@	monitor/att.$(OBJEXT) src/log.$(OBJEXT) \
+@MONITOR_TRUE@	src/textfile.$(OBJEXT) src/settings.$(OBJEXT)
+monitor_btmon_OBJECTS = $(am_monitor_btmon_OBJECTS)
+@MONITOR_TRUE@monitor_btmon_DEPENDENCIES =  \
+@MONITOR_TRUE@	lib/libbluetooth-internal.la \
+@MONITOR_TRUE@	src/libshared-mainloop.la $(am__DEPENDENCIES_1) \
+@MONITOR_TRUE@	$(am__DEPENDENCIES_1)
+am__obexd_src_obexd_SOURCES_DIST = btio/btio.h btio/btio.c \
+	gobex/gobex.h gobex/gobex.c gobex/gobex-defs.h \
+	gobex/gobex-defs.c gobex/gobex-packet.c gobex/gobex-packet.h \
+	gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h \
+	obexd/plugins/filesystem.c obexd/plugins/filesystem.h \
+	obexd/plugins/bluetooth.c obexd/plugins/pcsuite.c \
+	obexd/plugins/opp.c obexd/plugins/ftp.c obexd/plugins/ftp.h \
+	obexd/plugins/irmc.c obexd/plugins/pbap.c \
+	obexd/plugins/vcard.h obexd/plugins/vcard.c \
+	obexd/plugins/phonebook.h \
+	obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c \
+	obexd/plugins/mas.c obexd/src/map_ap.h \
+	obexd/plugins/messages.h obexd/plugins/messages-dummy.c \
+	obexd/client/mns.c obexd/client/map-event.h obexd/src/main.c \
+	obexd/src/obexd.h obexd/src/plugin.h obexd/src/plugin.c \
+	obexd/src/log.h obexd/src/log.c obexd/src/manager.h \
+	obexd/src/manager.c obexd/src/obex.h obexd/src/obex.c \
+	obexd/src/obex-priv.h obexd/src/mimetype.h \
+	obexd/src/mimetype.c obexd/src/service.h obexd/src/service.c \
+	obexd/src/transport.h obexd/src/transport.c obexd/src/server.h \
+	obexd/src/server.c obexd/client/manager.h \
+	obexd/client/manager.c obexd/client/session.h \
+	obexd/client/session.c obexd/client/bluetooth.h \
+	obexd/client/bluetooth.c obexd/client/sync.h \
+	obexd/client/sync.c obexd/client/pbap.h obexd/client/pbap.c \
+	obexd/client/ftp.h obexd/client/ftp.c obexd/client/opp.h \
+	obexd/client/opp.c obexd/client/map.h obexd/client/map.c \
+	obexd/client/bip.h obexd/client/bip.c \
+	obexd/client/bip-common.h obexd/client/bip-common.c \
+	obexd/client/map-event.c obexd/client/transfer.h \
+	obexd/client/transfer.c obexd/client/transport.h \
+	obexd/client/transport.c obexd/client/driver.h \
+	obexd/client/driver.c
+am__objects_12 = btio/obexd-btio.$(OBJEXT)
+am__objects_13 = gobex/obexd-gobex.$(OBJEXT) \
+	gobex/obexd-gobex-defs.$(OBJEXT) \
+	gobex/obexd-gobex-packet.$(OBJEXT) \
+	gobex/obexd-gobex-header.$(OBJEXT) \
+	gobex/obexd-gobex-transfer.$(OBJEXT) \
+	gobex/obexd-gobex-apparam.$(OBJEXT)
+@EXPERIMENTAL_TRUE@@OBEX_TRUE@am__objects_14 = obexd/plugins/obexd-pcsuite.$(OBJEXT)
+@OBEX_TRUE@am__objects_15 = obexd/plugins/obexd-filesystem.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-bluetooth.$(OBJEXT) \
+@OBEX_TRUE@	$(am__objects_14) obexd/plugins/obexd-opp.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-ftp.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-irmc.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-pbap.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-vcard.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-mas.$(OBJEXT) \
+@OBEX_TRUE@	obexd/plugins/obexd-messages-dummy.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-mns.$(OBJEXT)
+@OBEX_TRUE@am_obexd_src_obexd_OBJECTS = $(am__objects_12) \
+@OBEX_TRUE@	$(am__objects_13) $(am__objects_15) \
+@OBEX_TRUE@	obexd/src/obexd-main.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-plugin.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-log.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-manager.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-obex.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-mimetype.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-service.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-transport.$(OBJEXT) \
+@OBEX_TRUE@	obexd/src/obexd-server.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-manager.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-session.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-bluetooth.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-sync.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-pbap.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-ftp.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-opp.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-map.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-bip.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-bip-common.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-map-event.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-transfer.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-transport.$(OBJEXT) \
+@OBEX_TRUE@	obexd/client/obexd-driver.$(OBJEXT)
+am__objects_16 = $(am__objects_1)
+nodist_obexd_src_obexd_OBJECTS = $(am__objects_16)
+obexd_src_obexd_OBJECTS = $(am_obexd_src_obexd_OBJECTS) \
+	$(nodist_obexd_src_obexd_OBJECTS)
+@OBEX_TRUE@obexd_src_obexd_DEPENDENCIES =  \
+@OBEX_TRUE@	lib/libbluetooth-internal.la \
+@OBEX_TRUE@	gdbus/libgdbus-internal.la src/libshared-glib.la \
+@OBEX_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+@OBEX_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+obexd_src_obexd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(obexd_src_obexd_LDFLAGS) $(LDFLAGS) \
+	-o $@
+am__peripheral_btsensor_SOURCES_DIST = peripheral/main.c \
+	peripheral/efivars.h peripheral/efivars.c peripheral/attach.h \
+	peripheral/attach.c peripheral/log.h peripheral/log.c \
+	peripheral/gap.h peripheral/gap.c peripheral/gatt.h \
+	peripheral/gatt.c
+@TESTING_TRUE@am_peripheral_btsensor_OBJECTS =  \
+@TESTING_TRUE@	peripheral/main.$(OBJEXT) \
+@TESTING_TRUE@	peripheral/efivars.$(OBJEXT) \
+@TESTING_TRUE@	peripheral/attach.$(OBJEXT) \
+@TESTING_TRUE@	peripheral/log.$(OBJEXT) \
+@TESTING_TRUE@	peripheral/gap.$(OBJEXT) \
+@TESTING_TRUE@	peripheral/gatt.$(OBJEXT)
+peripheral_btsensor_OBJECTS = $(am_peripheral_btsensor_OBJECTS)
+@TESTING_TRUE@peripheral_btsensor_DEPENDENCIES =  \
+@TESTING_TRUE@	src/libshared-mainloop.la \
+@TESTING_TRUE@	lib/libbluetooth-internal.la
+am__profiles_cups_bluetooth_SOURCES_DIST = profiles/cups/main.c \
+	profiles/cups/cups.h profiles/cups/sdp.c profiles/cups/spp.c \
+	profiles/cups/hcrp.c
+@CUPS_TRUE@am_profiles_cups_bluetooth_OBJECTS =  \
+@CUPS_TRUE@	profiles/cups/main.$(OBJEXT) \
+@CUPS_TRUE@	profiles/cups/sdp.$(OBJEXT) \
+@CUPS_TRUE@	profiles/cups/spp.$(OBJEXT) \
+@CUPS_TRUE@	profiles/cups/hcrp.$(OBJEXT)
+profiles_cups_bluetooth_OBJECTS =  \
+	$(am_profiles_cups_bluetooth_OBJECTS)
+@CUPS_TRUE@profiles_cups_bluetooth_DEPENDENCIES =  \
+@CUPS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+@CUPS_TRUE@	lib/libbluetooth-internal.la \
+@CUPS_TRUE@	gdbus/libgdbus-internal.la
+am__profiles_iap_iapd_SOURCES_DIST = profiles/iap/main.c
+@TOOLS_TRUE@am_profiles_iap_iapd_OBJECTS =  \
+@TOOLS_TRUE@	profiles/iap/main.$(OBJEXT)
+profiles_iap_iapd_OBJECTS = $(am_profiles_iap_iapd_OBJECTS)
+@TOOLS_TRUE@profiles_iap_iapd_DEPENDENCIES =  \
+@TOOLS_TRUE@	gdbus/libgdbus-internal.la $(am__DEPENDENCIES_1) \
+@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__src_bluetoothd_SOURCES_DIST = plugins/hostname.c plugins/wiimote.c \
+	plugins/autopair.c plugins/policy.c plugins/admin.c \
+	plugins/neard.c profiles/sap/main.c profiles/sap/manager.h \
+	profiles/sap/manager.c profiles/sap/server.h \
+	profiles/sap/server.c profiles/sap/sap.h \
+	profiles/sap/sap-dummy.c profiles/audio/source.h \
+	profiles/audio/source.c profiles/audio/sink.h \
+	profiles/audio/sink.c profiles/audio/a2dp.h \
+	profiles/audio/a2dp.c profiles/audio/avdtp.h \
+	profiles/audio/avdtp.c profiles/audio/media.h \
+	profiles/audio/media.c profiles/audio/transport.h \
+	profiles/audio/transport.c profiles/audio/a2dp-codecs.h \
+	profiles/audio/control.h profiles/audio/control.c \
+	profiles/audio/avctp.h profiles/audio/avctp.c \
+	profiles/audio/avrcp.h profiles/audio/avrcp.c \
+	profiles/audio/player.h profiles/audio/player.c \
+	profiles/network/manager.c profiles/network/bnep.h \
+	profiles/network/bnep.c profiles/network/server.h \
+	profiles/network/server.c profiles/network/connection.h \
+	profiles/network/connection.c profiles/input/manager.c \
+	profiles/input/server.h profiles/input/server.c \
+	profiles/input/device.h profiles/input/device.c \
+	profiles/input/hidp_defs.h profiles/input/sixaxis.h \
+	profiles/input/hog.c profiles/input/hog-lib.c \
+	profiles/input/hog-lib.h profiles/deviceinfo/dis.c \
+	profiles/deviceinfo/dis.h profiles/battery/bas.c \
+	profiles/battery/bas.h profiles/scanparam/scpp.c \
+	profiles/scanparam/scpp.h profiles/input/suspend.h \
+	profiles/input/suspend-none.c profiles/health/mcap.h \
+	profiles/health/mcap.c profiles/health/hdp_main.c \
+	profiles/health/hdp_types.h profiles/health/hdp_manager.h \
+	profiles/health/hdp_manager.c profiles/health/hdp.h \
+	profiles/health/hdp.c profiles/health/hdp_util.h \
+	profiles/health/hdp_util.c profiles/gap/gas.c \
+	profiles/scanparam/scan.c profiles/deviceinfo/deviceinfo.c \
+	profiles/midi/midi.c profiles/midi/libmidi.h \
+	profiles/midi/libmidi.c profiles/battery/battery.c \
+	plugins/sixaxis.c profiles/audio/bap.h profiles/audio/bap.c \
+	profiles/audio/bass.h profiles/audio/bass.c \
+	profiles/audio/mcp.c profiles/audio/vcp.c \
+	profiles/audio/micp.c profiles/audio/ccp.c \
+	profiles/audio/csip.c profiles/audio/asha.h \
+	profiles/audio/asha.c attrib/att.h attrib/att-database.h \
+	attrib/att.c attrib/gatt.h attrib/gatt.c attrib/gattrib.h \
+	attrib/gattrib.c btio/btio.h btio/btio.c src/main.c src/log.h \
+	src/log.c src/backtrace.h src/backtrace.c src/rfkill.c \
+	src/btd.h src/sdpd.h src/sdpd-server.c src/sdpd-request.c \
+	src/sdpd-service.c src/sdpd-database.c src/gatt-database.h \
+	src/gatt-database.c src/sdp-xml.h src/sdp-xml.c \
+	src/sdp-client.h src/sdp-client.c src/textfile.h \
+	src/textfile.c src/uuid-helper.h src/uuid-helper.c \
+	src/plugin.h src/plugin.c src/storage.h src/storage.c \
+	src/advertising.h src/advertising.c src/agent.h src/agent.c \
+	src/error.h src/error.c src/adapter.h src/adapter.c \
+	src/profile.h src/profile.c src/service.h src/service.c \
+	src/gatt-client.h src/gatt-client.c src/device.h src/device.c \
+	src/dbus-common.c src/dbus-common.h src/eir.h src/eir.c \
+	src/adv_monitor.h src/adv_monitor.c src/battery.h \
+	src/battery.c src/settings.h src/settings.c src/set.h \
+	src/set.c src/bluetooth.ver
+@ADMIN_TRUE@am__objects_17 = plugins/bluetoothd-admin.$(OBJEXT)
+@NFC_TRUE@am__objects_18 = plugins/bluetoothd-neard.$(OBJEXT)
+@SAP_TRUE@am__objects_19 = profiles/sap/bluetoothd-main.$(OBJEXT) \
+@SAP_TRUE@	profiles/sap/bluetoothd-manager.$(OBJEXT) \
+@SAP_TRUE@	profiles/sap/bluetoothd-server.$(OBJEXT) \
+@SAP_TRUE@	profiles/sap/bluetoothd-sap-dummy.$(OBJEXT)
+@A2DP_TRUE@am__objects_20 =  \
+@A2DP_TRUE@	profiles/audio/bluetoothd-source.$(OBJEXT) \
+@A2DP_TRUE@	profiles/audio/bluetoothd-sink.$(OBJEXT) \
+@A2DP_TRUE@	profiles/audio/bluetoothd-a2dp.$(OBJEXT) \
+@A2DP_TRUE@	profiles/audio/bluetoothd-avdtp.$(OBJEXT) \
+@A2DP_TRUE@	profiles/audio/bluetoothd-media.$(OBJEXT) \
+@A2DP_TRUE@	profiles/audio/bluetoothd-transport.$(OBJEXT)
+@AVRCP_TRUE@am__objects_21 =  \
+@AVRCP_TRUE@	profiles/audio/bluetoothd-control.$(OBJEXT) \
+@AVRCP_TRUE@	profiles/audio/bluetoothd-avctp.$(OBJEXT) \
+@AVRCP_TRUE@	profiles/audio/bluetoothd-avrcp.$(OBJEXT) \
+@AVRCP_TRUE@	profiles/audio/bluetoothd-player.$(OBJEXT)
+@NETWORK_TRUE@am__objects_22 =  \
+@NETWORK_TRUE@	profiles/network/bluetoothd-manager.$(OBJEXT) \
+@NETWORK_TRUE@	profiles/network/bluetoothd-bnep.$(OBJEXT) \
+@NETWORK_TRUE@	profiles/network/bluetoothd-server.$(OBJEXT) \
+@NETWORK_TRUE@	profiles/network/bluetoothd-connection.$(OBJEXT)
+@HID_TRUE@am__objects_23 =  \
+@HID_TRUE@	profiles/input/bluetoothd-manager.$(OBJEXT) \
+@HID_TRUE@	profiles/input/bluetoothd-server.$(OBJEXT) \
+@HID_TRUE@	profiles/input/bluetoothd-device.$(OBJEXT)
+@HOG_TRUE@am__objects_24 = profiles/input/bluetoothd-hog.$(OBJEXT) \
+@HOG_TRUE@	profiles/input/bluetoothd-hog-lib.$(OBJEXT) \
+@HOG_TRUE@	profiles/deviceinfo/bluetoothd-dis.$(OBJEXT) \
+@HOG_TRUE@	profiles/battery/bluetoothd-bas.$(OBJEXT) \
+@HOG_TRUE@	profiles/scanparam/bluetoothd-scpp.$(OBJEXT) \
+@HOG_TRUE@	profiles/input/bluetoothd-suspend-none.$(OBJEXT)
+@HEALTH_TRUE@am__objects_25 =  \
+@HEALTH_TRUE@	profiles/health/bluetoothd-mcap.$(OBJEXT) \
+@HEALTH_TRUE@	profiles/health/bluetoothd-hdp_main.$(OBJEXT) \
+@HEALTH_TRUE@	profiles/health/bluetoothd-hdp_manager.$(OBJEXT) \
+@HEALTH_TRUE@	profiles/health/bluetoothd-hdp.$(OBJEXT) \
+@HEALTH_TRUE@	profiles/health/bluetoothd-hdp_util.$(OBJEXT)
+@MIDI_TRUE@am__objects_26 = profiles/midi/bluetoothd-midi.$(OBJEXT) \
+@MIDI_TRUE@	profiles/midi/bluetoothd-libmidi.$(OBJEXT)
+@SIXAXIS_TRUE@am__objects_27 = plugins/bluetoothd-sixaxis.$(OBJEXT)
+@BAP_TRUE@am__objects_28 = profiles/audio/bluetoothd-bap.$(OBJEXT)
+@BASS_TRUE@am__objects_29 = profiles/audio/bluetoothd-bass.$(OBJEXT)
+@MCP_TRUE@am__objects_30 = profiles/audio/bluetoothd-mcp.$(OBJEXT)
+@VCP_TRUE@am__objects_31 = profiles/audio/bluetoothd-vcp.$(OBJEXT)
+@MICP_TRUE@am__objects_32 = profiles/audio/bluetoothd-micp.$(OBJEXT)
+@CCP_TRUE@am__objects_33 = profiles/audio/bluetoothd-ccp.$(OBJEXT)
+@CSIP_TRUE@am__objects_34 = profiles/audio/bluetoothd-csip.$(OBJEXT)
+@ASHA_TRUE@am__objects_35 = profiles/audio/bluetoothd-asha.$(OBJEXT)
+am__objects_36 = plugins/bluetoothd-hostname.$(OBJEXT) \
+	plugins/bluetoothd-wiimote.$(OBJEXT) \
+	plugins/bluetoothd-autopair.$(OBJEXT) \
+	plugins/bluetoothd-policy.$(OBJEXT) $(am__objects_17) \
+	$(am__objects_18) $(am__objects_19) $(am__objects_20) \
+	$(am__objects_21) $(am__objects_22) $(am__objects_23) \
+	$(am__objects_24) $(am__objects_25) \
+	profiles/gap/bluetoothd-gas.$(OBJEXT) \
+	profiles/scanparam/bluetoothd-scan.$(OBJEXT) \
+	profiles/deviceinfo/bluetoothd-deviceinfo.$(OBJEXT) \
+	$(am__objects_26) \
+	profiles/battery/bluetoothd-battery.$(OBJEXT) \
+	$(am__objects_27) $(am__objects_28) $(am__objects_29) \
+	$(am__objects_30) $(am__objects_31) $(am__objects_32) \
+	$(am__objects_33) $(am__objects_34) $(am__objects_35)
+am__objects_37 = attrib/bluetoothd-att.$(OBJEXT) \
+	attrib/bluetoothd-gatt.$(OBJEXT) \
+	attrib/bluetoothd-gattrib.$(OBJEXT)
+am__objects_38 = btio/bluetoothd-btio.$(OBJEXT)
+am_src_bluetoothd_OBJECTS = $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) src/bluetoothd-main.$(OBJEXT) \
+	src/bluetoothd-log.$(OBJEXT) \
+	src/bluetoothd-backtrace.$(OBJEXT) \
+	src/bluetoothd-rfkill.$(OBJEXT) \
+	src/bluetoothd-sdpd-server.$(OBJEXT) \
+	src/bluetoothd-sdpd-request.$(OBJEXT) \
+	src/bluetoothd-sdpd-service.$(OBJEXT) \
+	src/bluetoothd-sdpd-database.$(OBJEXT) \
+	src/bluetoothd-gatt-database.$(OBJEXT) \
+	src/bluetoothd-sdp-xml.$(OBJEXT) \
+	src/bluetoothd-sdp-client.$(OBJEXT) \
+	src/bluetoothd-textfile.$(OBJEXT) \
+	src/bluetoothd-uuid-helper.$(OBJEXT) \
+	src/bluetoothd-plugin.$(OBJEXT) \
+	src/bluetoothd-storage.$(OBJEXT) \
+	src/bluetoothd-advertising.$(OBJEXT) \
+	src/bluetoothd-agent.$(OBJEXT) src/bluetoothd-error.$(OBJEXT) \
+	src/bluetoothd-adapter.$(OBJEXT) \
+	src/bluetoothd-profile.$(OBJEXT) \
+	src/bluetoothd-service.$(OBJEXT) \
+	src/bluetoothd-gatt-client.$(OBJEXT) \
+	src/bluetoothd-device.$(OBJEXT) \
+	src/bluetoothd-dbus-common.$(OBJEXT) \
+	src/bluetoothd-eir.$(OBJEXT) \
+	src/bluetoothd-adv_monitor.$(OBJEXT) \
+	src/bluetoothd-battery.$(OBJEXT) \
+	src/bluetoothd-settings.$(OBJEXT) src/bluetoothd-set.$(OBJEXT) \
+	$(am__objects_1)
+nodist_src_bluetoothd_OBJECTS = $(am__objects_1)
+src_bluetoothd_OBJECTS = $(am_src_bluetoothd_OBJECTS) \
+	$(nodist_src_bluetoothd_OBJECTS)
+@MIDI_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@SIXAXIS_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_5 = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
+src_bluetoothd_DEPENDENCIES = lib/libbluetooth-internal.la \
+	gdbus/libgdbus-internal.la src/libshared-glib.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_5)
+src_bluetoothd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(src_bluetoothd_LDFLAGS) $(LDFLAGS) -o \
+	$@
+am__tools_3dsp_SOURCES_DIST = tools/3dsp.c monitor/bt.h
+@TESTING_TRUE@am_tools_3dsp_OBJECTS = tools/3dsp.$(OBJEXT)
+tools_3dsp_OBJECTS = $(am_tools_3dsp_OBJECTS)
+@TESTING_TRUE@tools_3dsp_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_advtest_SOURCES_DIST = tools/advtest.c
+@TOOLS_TRUE@am_tools_advtest_OBJECTS = tools/advtest.$(OBJEXT)
+tools_advtest_OBJECTS = $(am_tools_advtest_OBJECTS)
+@TOOLS_TRUE@tools_advtest_DEPENDENCIES = lib/libbluetooth-internal.la \
+@TOOLS_TRUE@	src/libshared-mainloop.la
+tools_amptest_SOURCES = tools/amptest.c
+tools_amptest_OBJECTS = tools/amptest.$(OBJEXT)
+@TOOLS_TRUE@tools_amptest_DEPENDENCIES = lib/libbluetooth-internal.la
+tools_avinfo_SOURCES = tools/avinfo.c
+tools_avinfo_OBJECTS = tools/avinfo.$(OBJEXT)
+@TOOLS_TRUE@tools_avinfo_DEPENDENCIES = lib/libbluetooth-internal.la
+tools_avtest_SOURCES = tools/avtest.c
+tools_avtest_OBJECTS = tools/avtest.$(OBJEXT)
+@TOOLS_TRUE@tools_avtest_DEPENDENCIES = lib/libbluetooth-internal.la
+tools_bcmfw_SOURCES = tools/bcmfw.c
+tools_bcmfw_OBJECTS = tools/bcmfw.$(OBJEXT)
+tools_bcmfw_LDADD = $(LDADD)
+am__tools_bdaddr_SOURCES_DIST = tools/bdaddr.c src/oui.h src/oui.c
+@TOOLS_TRUE@am_tools_bdaddr_OBJECTS = tools/bdaddr.$(OBJEXT) \
+@TOOLS_TRUE@	src/oui.$(OBJEXT)
+tools_bdaddr_OBJECTS = $(am_tools_bdaddr_OBJECTS)
+@TOOLS_TRUE@tools_bdaddr_DEPENDENCIES = lib/libbluetooth-internal.la \
+@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_bluemoon_SOURCES_DIST = tools/bluemoon.c monitor/bt.h
+@TOOLS_TRUE@am_tools_bluemoon_OBJECTS = tools/bluemoon.$(OBJEXT)
+tools_bluemoon_OBJECTS = $(am_tools_bluemoon_OBJECTS)
+@TOOLS_TRUE@tools_bluemoon_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_bluetooth_player_SOURCES_DIST = tools/bluetooth-player.c \
+	client/print.c client/player.c
+@READLINE_TRUE@am_tools_bluetooth_player_OBJECTS =  \
+@READLINE_TRUE@	tools/bluetooth-player.$(OBJEXT) \
+@READLINE_TRUE@	client/print.$(OBJEXT) client/player.$(OBJEXT)
+tools_bluetooth_player_OBJECTS = $(am_tools_bluetooth_player_OBJECTS)
+@READLINE_TRUE@tools_bluetooth_player_DEPENDENCIES =  \
+@READLINE_TRUE@	gdbus/libgdbus-internal.la \
+@READLINE_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1) \
+@READLINE_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_bnep_tester_SOURCES_DIST = tools/bnep-tester.c monitor/bt.h \
+	emulator/hciemu.h emulator/hciemu.c emulator/vhci.h \
+	emulator/vhci.c emulator/btdev.h emulator/btdev.c \
+	emulator/bthost.h emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_bnep_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/bnep-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_bnep_tester_OBJECTS = $(am_tools_bnep_tester_OBJECTS)
+@TESTING_TRUE@tools_bnep_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_bneptest_SOURCES_DIST = tools/bneptest.c btio/btio.h \
+	btio/btio.c src/log.h src/log.c profiles/network/bnep.h \
+	profiles/network/bnep.c
+@TOOLS_TRUE@am_tools_bneptest_OBJECTS = tools/bneptest.$(OBJEXT) \
+@TOOLS_TRUE@	btio/btio.$(OBJEXT) src/log.$(OBJEXT) \
+@TOOLS_TRUE@	profiles/network/bnep.$(OBJEXT)
+tools_bneptest_OBJECTS = $(am_tools_bneptest_OBJECTS)
+@TOOLS_TRUE@tools_bneptest_DEPENDENCIES =  \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1) \
+@TOOLS_TRUE@	src/libshared-mainloop.la
+am__tools_btattach_SOURCES_DIST = tools/btattach.c monitor/bt.h
+@TOOLS_TRUE@am_tools_btattach_OBJECTS = tools/btattach.$(OBJEXT)
+tools_btattach_OBJECTS = $(am_tools_btattach_OBJECTS)
+@TOOLS_TRUE@tools_btattach_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_btconfig_SOURCES_DIST = tools/btconfig.c
+@TOOLS_TRUE@am_tools_btconfig_OBJECTS = tools/btconfig.$(OBJEXT)
+tools_btconfig_OBJECTS = $(am_tools_btconfig_OBJECTS)
+@TOOLS_TRUE@tools_btconfig_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_btgatt_client_SOURCES_DIST = tools/btgatt-client.c \
+	src/uuid-helper.c
+@TOOLS_TRUE@am_tools_btgatt_client_OBJECTS =  \
+@TOOLS_TRUE@	tools/btgatt-client.$(OBJEXT) \
+@TOOLS_TRUE@	src/uuid-helper.$(OBJEXT)
+tools_btgatt_client_OBJECTS = $(am_tools_btgatt_client_OBJECTS)
+@TOOLS_TRUE@tools_btgatt_client_DEPENDENCIES =  \
+@TOOLS_TRUE@	src/libshared-mainloop.la \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_btgatt_server_SOURCES_DIST = tools/btgatt-server.c \
+	src/uuid-helper.c
+@TOOLS_TRUE@am_tools_btgatt_server_OBJECTS =  \
+@TOOLS_TRUE@	tools/btgatt-server.$(OBJEXT) \
+@TOOLS_TRUE@	src/uuid-helper.$(OBJEXT)
+tools_btgatt_server_OBJECTS = $(am_tools_btgatt_server_OBJECTS)
+@TOOLS_TRUE@tools_btgatt_server_DEPENDENCIES =  \
+@TOOLS_TRUE@	src/libshared-mainloop.la \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_btinfo_SOURCES_DIST = tools/btinfo.c monitor/bt.h
+@TOOLS_TRUE@am_tools_btinfo_OBJECTS = tools/btinfo.$(OBJEXT)
+tools_btinfo_OBJECTS = $(am_tools_btinfo_OBJECTS)
+@TOOLS_TRUE@tools_btinfo_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_btiotest_SOURCES_DIST = tools/btiotest.c btio/btio.h \
+	btio/btio.c
+@TOOLS_TRUE@am_tools_btiotest_OBJECTS = tools/btiotest.$(OBJEXT) \
+@TOOLS_TRUE@	btio/btio.$(OBJEXT)
+tools_btiotest_OBJECTS = $(am_tools_btiotest_OBJECTS)
+@TOOLS_TRUE@tools_btiotest_DEPENDENCIES =  \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am__tools_btmgmt_SOURCES_DIST = tools/btmgmt.c src/uuid-helper.c \
+	client/display.c client/mgmt.c
+@READLINE_TRUE@am_tools_btmgmt_OBJECTS = tools/btmgmt.$(OBJEXT) \
+@READLINE_TRUE@	src/uuid-helper.$(OBJEXT) \
+@READLINE_TRUE@	client/display.$(OBJEXT) client/mgmt.$(OBJEXT)
+tools_btmgmt_OBJECTS = $(am_tools_btmgmt_OBJECTS)
+@READLINE_TRUE@tools_btmgmt_DEPENDENCIES =  \
+@READLINE_TRUE@	lib/libbluetooth-internal.la \
+@READLINE_TRUE@	src/libshared-mainloop.la
+am__tools_btmon_logger_SOURCES_DIST = tools/btmon-logger.c
+@LOGGER_TRUE@am_tools_btmon_logger_OBJECTS =  \
+@LOGGER_TRUE@	tools/btmon-logger.$(OBJEXT)
+tools_btmon_logger_OBJECTS = $(am_tools_btmon_logger_OBJECTS)
+@LOGGER_TRUE@tools_btmon_logger_DEPENDENCIES =  \
+@LOGGER_TRUE@	src/libshared-mainloop.la
+am__tools_btpclient_SOURCES_DIST = tools/btpclient.c src/shared/btp.c \
+	src/shared/btp.h
+@BTPCLIENT_TRUE@am_tools_btpclient_OBJECTS =  \
+@BTPCLIENT_TRUE@	tools/btpclient.$(OBJEXT) \
+@BTPCLIENT_TRUE@	src/shared/btp.$(OBJEXT)
+tools_btpclient_OBJECTS = $(am_tools_btpclient_OBJECTS)
+@BTPCLIENT_TRUE@tools_btpclient_DEPENDENCIES =  \
+@BTPCLIENT_TRUE@	lib/libbluetooth-internal.la \
+@BTPCLIENT_TRUE@	src/libshared-ell.la $(am__DEPENDENCIES_2)
+am__tools_btpclientctl_SOURCES_DIST = tools/btpclientctl.c \
+	client/display.c
+@BTPCLIENT_TRUE@am_tools_btpclientctl_OBJECTS =  \
+@BTPCLIENT_TRUE@	tools/btpclientctl.$(OBJEXT) \
+@BTPCLIENT_TRUE@	client/display.$(OBJEXT)
+tools_btpclientctl_OBJECTS = $(am_tools_btpclientctl_OBJECTS)
+@BTPCLIENT_TRUE@tools_btpclientctl_DEPENDENCIES =  \
+@BTPCLIENT_TRUE@	src/libshared-mainloop.la \
+@BTPCLIENT_TRUE@	src/libshared-glib.la \
+@BTPCLIENT_TRUE@	lib/libbluetooth-internal.la
+am__tools_btproxy_SOURCES_DIST = tools/btproxy.c monitor/bt.h
+@TOOLS_TRUE@am_tools_btproxy_OBJECTS = tools/btproxy.$(OBJEXT)
+tools_btproxy_OBJECTS = $(am_tools_btproxy_OBJECTS)
+@TOOLS_TRUE@tools_btproxy_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_btsnoop_SOURCES_DIST = tools/btsnoop.c
+@TOOLS_TRUE@am_tools_btsnoop_OBJECTS = tools/btsnoop.$(OBJEXT)
+tools_btsnoop_OBJECTS = $(am_tools_btsnoop_OBJECTS)
+@TOOLS_TRUE@tools_btsnoop_DEPENDENCIES = src/libshared-mainloop.la
+tools_check_selftest_SOURCES = tools/check-selftest.c
+tools_check_selftest_OBJECTS = tools/check-selftest.$(OBJEXT)
+tools_check_selftest_LDADD = $(LDADD)
+tools_ciptool_SOURCES = tools/ciptool.c
+tools_ciptool_OBJECTS = tools/ciptool.$(OBJEXT)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_ciptool_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_cltest_SOURCES_DIST = tools/cltest.c
+@TOOLS_TRUE@am_tools_cltest_OBJECTS = tools/cltest.$(OBJEXT)
+tools_cltest_OBJECTS = $(am_tools_cltest_OBJECTS)
+@TOOLS_TRUE@tools_cltest_DEPENDENCIES = lib/libbluetooth-internal.la \
+@TOOLS_TRUE@	src/libshared-mainloop.la
+am__tools_create_image_SOURCES_DIST = tools/create-image.c
+@TOOLS_TRUE@am_tools_create_image_OBJECTS =  \
+@TOOLS_TRUE@	tools/create-image.$(OBJEXT)
+tools_create_image_OBJECTS = $(am_tools_create_image_OBJECTS)
+tools_create_image_LDADD = $(LDADD)
+am__tools_eddystone_SOURCES_DIST = tools/eddystone.c monitor/bt.h
+@TOOLS_TRUE@am_tools_eddystone_OBJECTS = tools/eddystone.$(OBJEXT)
+tools_eddystone_OBJECTS = $(am_tools_eddystone_OBJECTS)
+@TOOLS_TRUE@tools_eddystone_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_gap_tester_SOURCES_DIST = tools/gap-tester.c monitor/bt.h \
+	emulator/hciemu.h emulator/hciemu.c emulator/vhci.h \
+	emulator/vhci.c emulator/btdev.h emulator/btdev.c \
+	emulator/bthost.h emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_gap_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/gap-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_gap_tester_OBJECTS = $(am_tools_gap_tester_OBJECTS)
+@TESTING_TRUE@tools_gap_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	gdbus/libgdbus-internal.la src/libshared-glib.la \
+@TESTING_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__tools_gatt_service_SOURCES_DIST = tools/gatt-service.c
+@TOOLS_TRUE@am_tools_gatt_service_OBJECTS =  \
+@TOOLS_TRUE@	tools/gatt-service.$(OBJEXT)
+tools_gatt_service_OBJECTS = $(am_tools_gatt_service_OBJECTS)
+@TOOLS_TRUE@tools_gatt_service_DEPENDENCIES =  \
+@TOOLS_TRUE@	gdbus/libgdbus-internal.la \
+@TOOLS_TRUE@	src/libshared-mainloop.la $(am__DEPENDENCIES_1) \
+@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_hci_tester_SOURCES_DIST = tools/hci-tester.c monitor/bt.h
+@TESTING_TRUE@am_tools_hci_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/hci-tester.$(OBJEXT)
+tools_hci_tester_OBJECTS = $(am_tools_hci_tester_OBJECTS)
+@TESTING_TRUE@tools_hci_tester_DEPENDENCIES = src/libshared-glib.la \
+@TESTING_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_hciattach_SOURCES_DIST = tools/hciattach.c tools/hciattach.h \
+	tools/hciattach_st.c tools/hciattach_ti.c \
+	tools/hciattach_tialt.c tools/hciattach_ath3k.c \
+	tools/hciattach_qualcomm.c tools/hciattach_intel.c \
+	tools/hciattach_bcm43xx.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@am_tools_hciattach_OBJECTS =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_st.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_ti.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_tialt.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_ath3k.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_qualcomm.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_intel.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciattach_bcm43xx.$(OBJEXT)
+tools_hciattach_OBJECTS = $(am_tools_hciattach_OBJECTS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciattach_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_hciconfig_SOURCES_DIST = tools/hciconfig.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@am_tools_hciconfig_OBJECTS =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hciconfig.$(OBJEXT)
+tools_hciconfig_OBJECTS = $(am_tools_hciconfig_OBJECTS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciconfig_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_hcidump_SOURCES_DIST = tools/hcidump.c tools/parser/parser.h \
+	tools/parser/parser.c tools/parser/lmp.c tools/parser/hci.c \
+	tools/parser/l2cap.h tools/parser/l2cap.c tools/parser/amp.c \
+	tools/parser/smp.c tools/parser/att.c tools/parser/sdp.h \
+	tools/parser/sdp.c tools/parser/rfcomm.h tools/parser/rfcomm.c \
+	tools/parser/bnep.c tools/parser/cmtp.c tools/parser/hidp.c \
+	tools/parser/hcrp.c tools/parser/avdtp.c tools/parser/avctp.c \
+	tools/parser/avrcp.c tools/parser/sap.c tools/parser/obex.c \
+	tools/parser/capi.c tools/parser/ppp.c tools/parser/tcpip.c \
+	tools/parser/ericsson.c tools/parser/csr.c tools/parser/bpa.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@am_tools_hcidump_OBJECTS =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hcidump.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/parser.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/lmp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/hci.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/l2cap.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/amp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/smp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/att.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/sdp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/rfcomm.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/bnep.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/cmtp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/hidp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/hcrp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/avdtp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/avctp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/avrcp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/sap.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/obex.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/capi.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/ppp.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/tcpip.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/ericsson.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/csr.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/parser/bpa.$(OBJEXT)
+tools_hcidump_OBJECTS = $(am_tools_hcidump_OBJECTS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcidump_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la
+tools_hcieventmask_SOURCES = tools/hcieventmask.c
+tools_hcieventmask_OBJECTS = tools/hcieventmask.$(OBJEXT)
+@TOOLS_TRUE@tools_hcieventmask_DEPENDENCIES =  \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la
+tools_hcisecfilter_SOURCES = tools/hcisecfilter.c
+tools_hcisecfilter_OBJECTS = tools/hcisecfilter.$(OBJEXT)
+tools_hcisecfilter_LDADD = $(LDADD)
+am__tools_hcitool_SOURCES_DIST = tools/hcitool.c src/oui.h src/oui.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@am_tools_hcitool_OBJECTS =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/hcitool.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	src/oui.$(OBJEXT)
+tools_hcitool_OBJECTS = $(am_tools_hcitool_OBJECTS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcitool_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_hex2hcd_SOURCES_DIST = tools/hex2hcd.c tools/missing.h
+@TOOLS_TRUE@am_tools_hex2hcd_OBJECTS = tools/hex2hcd.$(OBJEXT)
+tools_hex2hcd_OBJECTS = $(am_tools_hex2hcd_OBJECTS)
+tools_hex2hcd_LDADD = $(LDADD)
+tools_hid2hci_SOURCES = tools/hid2hci.c
+tools_hid2hci_OBJECTS = tools/hid2hci.$(OBJEXT)
+@HID2HCI_TRUE@tools_hid2hci_DEPENDENCIES = $(am__DEPENDENCIES_1)
+tools_hwdb_SOURCES = tools/hwdb.c
+tools_hwdb_OBJECTS = tools/hwdb.$(OBJEXT)
+@TOOLS_TRUE@tools_hwdb_DEPENDENCIES = lib/libbluetooth-internal.la
+am__tools_ibeacon_SOURCES_DIST = tools/ibeacon.c monitor/bt.h
+@TOOLS_TRUE@am_tools_ibeacon_OBJECTS = tools/ibeacon.$(OBJEXT)
+tools_ibeacon_OBJECTS = $(am_tools_ibeacon_OBJECTS)
+@TOOLS_TRUE@tools_ibeacon_DEPENDENCIES = src/libshared-mainloop.la
+am__tools_ioctl_tester_SOURCES_DIST = tools/ioctl-tester.c \
+	monitor/bt.h emulator/hciemu.h emulator/hciemu.c \
+	emulator/vhci.h emulator/vhci.c emulator/btdev.h \
+	emulator/btdev.c emulator/bthost.h emulator/bthost.c \
+	emulator/smp.c
+@TESTING_TRUE@am_tools_ioctl_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/ioctl-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_ioctl_tester_OBJECTS = $(am_tools_ioctl_tester_OBJECTS)
+@TESTING_TRUE@tools_ioctl_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_iso_tester_SOURCES_DIST = tools/iso-tester.c tools/tester.h \
+	monitor/bt.h emulator/hciemu.h emulator/hciemu.c \
+	emulator/vhci.h emulator/vhci.c emulator/btdev.h \
+	emulator/btdev.c emulator/bthost.h emulator/bthost.c \
+	emulator/smp.c
+@TESTING_TRUE@am_tools_iso_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/iso-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_iso_tester_OBJECTS = $(am_tools_iso_tester_OBJECTS)
+@TESTING_TRUE@tools_iso_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+tools_isotest_SOURCES = tools/isotest.c
+tools_isotest_OBJECTS = tools/isotest.$(OBJEXT)
+@TOOLS_TRUE@tools_isotest_DEPENDENCIES = lib/libbluetooth-internal.la
+am__tools_l2cap_tester_SOURCES_DIST = tools/l2cap-tester.c \
+	tools/tester.h monitor/bt.h emulator/hciemu.h \
+	emulator/hciemu.c emulator/vhci.h emulator/vhci.c \
+	emulator/btdev.h emulator/btdev.c emulator/bthost.h \
+	emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_l2cap_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/l2cap-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_l2cap_tester_OBJECTS = $(am_tools_l2cap_tester_OBJECTS)
+@TESTING_TRUE@tools_l2cap_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+tools_l2ping_SOURCES = tools/l2ping.c
+tools_l2ping_OBJECTS = tools/l2ping.$(OBJEXT)
+@TOOLS_TRUE@tools_l2ping_DEPENDENCIES = lib/libbluetooth-internal.la
+tools_l2test_SOURCES = tools/l2test.c
+tools_l2test_OBJECTS = tools/l2test.$(OBJEXT)
+@TOOLS_TRUE@tools_l2test_DEPENDENCIES = lib/libbluetooth-internal.la
+am__tools_mcaptest_SOURCES_DIST = tools/mcaptest.c btio/btio.h \
+	btio/btio.c src/log.c src/log.h profiles/health/mcap.h \
+	profiles/health/mcap.c
+@TOOLS_TRUE@am_tools_mcaptest_OBJECTS = tools/mcaptest.$(OBJEXT) \
+@TOOLS_TRUE@	btio/btio.$(OBJEXT) src/log.$(OBJEXT) \
+@TOOLS_TRUE@	profiles/health/mcap.$(OBJEXT)
+tools_mcaptest_OBJECTS = $(am_tools_mcaptest_OBJECTS)
+@TOOLS_TRUE@tools_mcaptest_DEPENDENCIES =  \
+@TOOLS_TRUE@	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1) \
+@TOOLS_TRUE@	src/libshared-mainloop.la
+am__tools_mesh_cfgclient_SOURCES_DIST = tools/mesh-cfgclient.c \
+	tools/mesh/model.h tools/mesh/config-model.h \
+	tools/mesh/cfgcli.h tools/mesh/cfgcli.c tools/mesh/keys.h \
+	tools/mesh/keys.c tools/mesh/util.h tools/mesh/util.c \
+	tools/mesh/remote.h tools/mesh/remote.c tools/mesh/agent.h \
+	tools/mesh/agent.c tools/mesh/mesh-db.h tools/mesh/mesh-db.c \
+	mesh/util.h mesh/util.c mesh/crypto.h mesh/crypto.c
+@MESH_TRUE@@TOOLS_TRUE@am_tools_mesh_cfgclient_OBJECTS =  \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-cfgclient.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/cfgcli.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/keys.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/util.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/remote.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/agent.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/mesh-db.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	mesh/util.$(OBJEXT) \
+@MESH_TRUE@@TOOLS_TRUE@	mesh/crypto.$(OBJEXT)
+tools_mesh_cfgclient_OBJECTS = $(am_tools_mesh_cfgclient_OBJECTS)
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgclient_DEPENDENCIES =  \
+@MESH_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la \
+@MESH_TRUE@@TOOLS_TRUE@	src/libshared-ell.la \
+@MESH_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_2)
+am__tools_mesh_cfgtest_SOURCES_DIST = tools/mesh-cfgtest.c
+@MESH_TRUE@@TOOLS_TRUE@am_tools_mesh_cfgtest_OBJECTS =  \
+@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-cfgtest.$(OBJEXT)
+tools_mesh_cfgtest_OBJECTS = $(am_tools_mesh_cfgtest_OBJECTS)
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgtest_DEPENDENCIES =  \
+@MESH_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la \
+@MESH_TRUE@@TOOLS_TRUE@	src/libshared-ell.la \
+@MESH_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_2)
+am__tools_mesh_tester_SOURCES_DIST = tools/mesh-tester.c monitor/bt.h \
+	emulator/hciemu.h emulator/hciemu.c emulator/vhci.h \
+	emulator/vhci.c emulator/btdev.h emulator/btdev.c \
+	emulator/bthost.h emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_mesh_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/mesh-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_mesh_tester_OBJECTS = $(am_tools_mesh_tester_OBJECTS)
+@TESTING_TRUE@tools_mesh_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_meshctl_SOURCES_DIST = tools/meshctl.c tools/mesh/agent.h \
+	tools/mesh/agent.c tools/mesh/config-model.h \
+	tools/mesh-gatt/mesh-net.h tools/mesh-gatt/node.h \
+	tools/mesh-gatt/node.c tools/mesh-gatt/gatt.h \
+	tools/mesh-gatt/gatt.c tools/mesh-gatt/crypto.h \
+	tools/mesh-gatt/crypto.c tools/mesh-gatt/keys.h \
+	tools/mesh-gatt/net.h tools/mesh-gatt/net.c \
+	tools/mesh-gatt/prov.h tools/mesh-gatt/prov.c \
+	tools/mesh-gatt/util.h tools/mesh-gatt/util.c \
+	tools/mesh-gatt/prov-db.h tools/mesh-gatt/prov-db.c \
+	tools/mesh-gatt/config-client.c \
+	tools/mesh-gatt/config-server.c tools/mesh-gatt/onoff-model.h \
+	tools/mesh-gatt/onoff-model.c
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@am_tools_meshctl_OBJECTS = tools/meshctl.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh/agent.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/node.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/gatt.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/crypto.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/net.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/prov.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/util.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/prov-db.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/config-client.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/config-server.$(OBJEXT) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	tools/mesh-gatt/onoff-model.$(OBJEXT)
+tools_meshctl_OBJECTS = $(am_tools_meshctl_OBJECTS)
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@tools_meshctl_DEPENDENCIES = gdbus/libgdbus-internal.la \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	src/libshared-glib.la \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_1) \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_mgmt_tester_SOURCES_DIST = tools/mgmt-tester.c monitor/bt.h \
+	emulator/hciemu.h emulator/hciemu.c emulator/vhci.h \
+	emulator/vhci.c emulator/btdev.h emulator/btdev.c \
+	emulator/bthost.h emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_mgmt_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/mgmt-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_mgmt_tester_OBJECTS = $(am_tools_mgmt_tester_OBJECTS)
+@TESTING_TRUE@tools_mgmt_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_mpris_proxy_SOURCES_DIST = tools/mpris-proxy.c
+@TOOLS_TRUE@am_tools_mpris_proxy_OBJECTS =  \
+@TOOLS_TRUE@	tools/mpris-proxy.$(OBJEXT)
+tools_mpris_proxy_OBJECTS = $(am_tools_mpris_proxy_OBJECTS)
+@TOOLS_TRUE@tools_mpris_proxy_DEPENDENCIES =  \
+@TOOLS_TRUE@	gdbus/libgdbus-internal.la $(am__DEPENDENCIES_1) \
+@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_nokfw_SOURCES_DIST = tools/nokfw.c
+@TOOLS_TRUE@am_tools_nokfw_OBJECTS = tools/nokfw.$(OBJEXT)
+tools_nokfw_OBJECTS = $(am_tools_nokfw_OBJECTS)
+tools_nokfw_LDADD = $(LDADD)
+am__tools_obex_client_tool_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h btio/btio.h \
+	btio/btio.c tools/obex-client-tool.c
+am__objects_39 = gobex/gobex.$(OBJEXT) gobex/gobex-defs.$(OBJEXT) \
+	gobex/gobex-packet.$(OBJEXT) gobex/gobex-header.$(OBJEXT) \
+	gobex/gobex-transfer.$(OBJEXT) gobex/gobex-apparam.$(OBJEXT)
+am__objects_40 = btio/btio.$(OBJEXT)
+@READLINE_TRUE@am_tools_obex_client_tool_OBJECTS = $(am__objects_39) \
+@READLINE_TRUE@	$(am__objects_40) \
+@READLINE_TRUE@	tools/obex-client-tool.$(OBJEXT)
+tools_obex_client_tool_OBJECTS = $(am_tools_obex_client_tool_OBJECTS)
+@READLINE_TRUE@tools_obex_client_tool_DEPENDENCIES =  \
+@READLINE_TRUE@	lib/libbluetooth-internal.la \
+@READLINE_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_obex_server_tool_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h btio/btio.h \
+	btio/btio.c tools/obex-server-tool.c
+@READLINE_TRUE@am_tools_obex_server_tool_OBJECTS = $(am__objects_39) \
+@READLINE_TRUE@	$(am__objects_40) \
+@READLINE_TRUE@	tools/obex-server-tool.$(OBJEXT)
+tools_obex_server_tool_OBJECTS = $(am_tools_obex_server_tool_OBJECTS)
+@READLINE_TRUE@tools_obex_server_tool_DEPENDENCIES =  \
+@READLINE_TRUE@	lib/libbluetooth-internal.la \
+@READLINE_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_obexctl_SOURCES_DIST = tools/obexctl.c
+@READLINE_TRUE@am_tools_obexctl_OBJECTS = tools/obexctl.$(OBJEXT)
+tools_obexctl_OBJECTS = $(am_tools_obexctl_OBJECTS)
+@READLINE_TRUE@tools_obexctl_DEPENDENCIES =  \
+@READLINE_TRUE@	gdbus/libgdbus-internal.la \
+@READLINE_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1) \
+@READLINE_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_oobtest_SOURCES_DIST = tools/oobtest.c
+@TOOLS_TRUE@am_tools_oobtest_OBJECTS = tools/oobtest.$(OBJEXT)
+tools_oobtest_OBJECTS = $(am_tools_oobtest_OBJECTS)
+@TOOLS_TRUE@tools_oobtest_DEPENDENCIES = lib/libbluetooth-internal.la \
+@TOOLS_TRUE@	src/libshared-mainloop.la
+tools_rctest_SOURCES = tools/rctest.c
+tools_rctest_OBJECTS = tools/rctest.$(OBJEXT)
+@TOOLS_TRUE@tools_rctest_DEPENDENCIES = lib/libbluetooth-internal.la
+tools_rfcomm_SOURCES = tools/rfcomm.c
+tools_rfcomm_OBJECTS = tools/rfcomm.$(OBJEXT)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_rfcomm_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la
+am__tools_rfcomm_tester_SOURCES_DIST = tools/rfcomm-tester.c \
+	monitor/bt.h emulator/hciemu.h emulator/hciemu.c \
+	emulator/vhci.h emulator/vhci.c emulator/btdev.h \
+	emulator/btdev.c emulator/bthost.h emulator/bthost.c \
+	emulator/smp.c
+@TESTING_TRUE@am_tools_rfcomm_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/rfcomm-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_rfcomm_tester_OBJECTS = $(am_tools_rfcomm_tester_OBJECTS)
+@TESTING_TRUE@tools_rfcomm_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__tools_rtlfw_SOURCES_DIST = tools/rtlfw.c
+@TOOLS_TRUE@am_tools_rtlfw_OBJECTS = tools/rtlfw.$(OBJEXT)
+tools_rtlfw_OBJECTS = $(am_tools_rtlfw_OBJECTS)
+tools_rtlfw_LDADD = $(LDADD)
+am__tools_sco_tester_SOURCES_DIST = tools/sco-tester.c tools/tester.h \
+	monitor/bt.h emulator/hciemu.h emulator/hciemu.c \
+	emulator/vhci.h emulator/vhci.c emulator/btdev.h \
+	emulator/btdev.c emulator/bthost.h emulator/bthost.c \
+	emulator/smp.c
+@TESTING_TRUE@am_tools_sco_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/sco-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_sco_tester_OBJECTS = $(am_tools_sco_tester_OBJECTS)
+@TESTING_TRUE@tools_sco_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+tools_scotest_SOURCES = tools/scotest.c
+tools_scotest_OBJECTS = tools/scotest.$(OBJEXT)
+@TOOLS_TRUE@tools_scotest_DEPENDENCIES = lib/libbluetooth-internal.la
+am__tools_sdptool_SOURCES_DIST = tools/sdptool.c src/sdp-xml.h \
+	src/sdp-xml.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@am_tools_sdptool_OBJECTS =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	tools/sdptool.$(OBJEXT) \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	src/sdp-xml.$(OBJEXT)
+tools_sdptool_OBJECTS = $(am_tools_sdptool_OBJECTS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_sdptool_DEPENDENCIES =  \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@TOOLS_TRUE@	$(am__DEPENDENCIES_1)
+am__tools_seq2bseq_SOURCES_DIST = tools/seq2bseq.c
+@TOOLS_TRUE@am_tools_seq2bseq_OBJECTS = tools/seq2bseq.$(OBJEXT)
+tools_seq2bseq_OBJECTS = $(am_tools_seq2bseq_OBJECTS)
+tools_seq2bseq_LDADD = $(LDADD)
+am__tools_smp_tester_SOURCES_DIST = tools/smp-tester.c monitor/bt.h \
+	emulator/hciemu.h emulator/hciemu.c emulator/vhci.h \
+	emulator/vhci.c emulator/btdev.h emulator/btdev.c \
+	emulator/bthost.h emulator/bthost.c emulator/smp.c
+@TESTING_TRUE@am_tools_smp_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/smp-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_smp_tester_OBJECTS = $(am_tools_smp_tester_OBJECTS)
+@TESTING_TRUE@tools_smp_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+tools_test_runner_SOURCES = tools/test-runner.c
+tools_test_runner_OBJECTS = tools/test-runner.$(OBJEXT)
+tools_test_runner_LDADD = $(LDADD)
+am__tools_userchan_tester_SOURCES_DIST = tools/userchan-tester.c \
+	monitor/bt.h emulator/hciemu.h emulator/hciemu.c \
+	emulator/vhci.h emulator/vhci.c emulator/btdev.h \
+	emulator/btdev.c emulator/bthost.h emulator/bthost.c \
+	emulator/smp.c
+@TESTING_TRUE@am_tools_userchan_tester_OBJECTS =  \
+@TESTING_TRUE@	tools/userchan-tester.$(OBJEXT) \
+@TESTING_TRUE@	emulator/hciemu.$(OBJEXT) \
+@TESTING_TRUE@	emulator/vhci.$(OBJEXT) emulator/btdev.$(OBJEXT) \
+@TESTING_TRUE@	emulator/bthost.$(OBJEXT) emulator/smp.$(OBJEXT)
+tools_userchan_tester_OBJECTS = $(am_tools_userchan_tester_OBJECTS)
+@TESTING_TRUE@tools_userchan_tester_DEPENDENCIES =  \
+@TESTING_TRUE@	lib/libbluetooth-internal.la \
+@TESTING_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am_unit_test_avctp_OBJECTS = unit/test-avctp.$(OBJEXT) \
+	src/log.$(OBJEXT) android/avctp.$(OBJEXT)
+unit_test_avctp_OBJECTS = $(am_unit_test_avctp_OBJECTS)
+unit_test_avctp_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_avdtp_OBJECTS = unit/test-avdtp.$(OBJEXT) \
+	src/log.$(OBJEXT) android/avdtp.$(OBJEXT)
+unit_test_avdtp_OBJECTS = $(am_unit_test_avdtp_OBJECTS)
+unit_test_avdtp_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_avrcp_OBJECTS = unit/test-avrcp.$(OBJEXT) \
+	src/log.$(OBJEXT) android/avctp.$(OBJEXT) \
+	android/avrcp-lib.$(OBJEXT)
+unit_test_avrcp_OBJECTS = $(am_unit_test_avrcp_OBJECTS)
+unit_test_avrcp_DEPENDENCIES = lib/libbluetooth-internal.la \
+	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am_unit_test_bap_OBJECTS = unit/test-bap.$(OBJEXT)
+unit_test_bap_OBJECTS = $(am_unit_test_bap_OBJECTS)
+unit_test_bap_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_bass_OBJECTS = unit/test-bass.$(OBJEXT) $(am__objects_40)
+unit_test_bass_OBJECTS = $(am_unit_test_bass_OBJECTS)
+unit_test_bass_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_crc_OBJECTS = unit/test-crc.$(OBJEXT) \
+	monitor/crc.$(OBJEXT)
+unit_test_crc_OBJECTS = $(am_unit_test_crc_OBJECTS)
+unit_test_crc_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_crypto_OBJECTS = unit/test-crypto.$(OBJEXT)
+unit_test_crypto_OBJECTS = $(am_unit_test_crypto_OBJECTS)
+unit_test_crypto_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_ecc_OBJECTS = unit/test-ecc.$(OBJEXT)
+unit_test_ecc_OBJECTS = $(am_unit_test_ecc_OBJECTS)
+unit_test_ecc_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_eir_OBJECTS = unit/test-eir.$(OBJEXT) src/eir.$(OBJEXT) \
+	src/uuid-helper.$(OBJEXT)
+unit_test_eir_OBJECTS = $(am_unit_test_eir_OBJECTS)
+unit_test_eir_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_gatt_OBJECTS = unit/test-gatt.$(OBJEXT)
+unit_test_gatt_OBJECTS = $(am_unit_test_gatt_OBJECTS)
+unit_test_gatt_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_gattrib_OBJECTS = unit/test-gattrib.$(OBJEXT) \
+	attrib/gattrib.$(OBJEXT) $(am__objects_40) src/log.$(OBJEXT)
+unit_test_gattrib_OBJECTS = $(am_unit_test_gattrib_OBJECTS)
+unit_test_gattrib_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_unit_test_gdbus_client_OBJECTS = unit/test-gdbus-client.$(OBJEXT)
+unit_test_gdbus_client_OBJECTS = $(am_unit_test_gdbus_client_OBJECTS)
+unit_test_gdbus_client_DEPENDENCIES = gdbus/libgdbus-internal.la \
+	src/libshared-glib.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am__unit_test_gobex_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h unit/util.c \
+	unit/util.h unit/test-gobex.c
+@OBEX_TRUE@am_unit_test_gobex_OBJECTS = $(am__objects_39) \
+@OBEX_TRUE@	unit/util.$(OBJEXT) unit/test-gobex.$(OBJEXT)
+unit_test_gobex_OBJECTS = $(am_unit_test_gobex_OBJECTS)
+@OBEX_TRUE@unit_test_gobex_DEPENDENCIES = src/libshared-glib.la \
+@OBEX_TRUE@	$(am__DEPENDENCIES_1)
+am__unit_test_gobex_apparam_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h unit/util.c \
+	unit/util.h unit/test-gobex-apparam.c
+@OBEX_TRUE@am_unit_test_gobex_apparam_OBJECTS = $(am__objects_39) \
+@OBEX_TRUE@	unit/util.$(OBJEXT) \
+@OBEX_TRUE@	unit/test-gobex-apparam.$(OBJEXT)
+unit_test_gobex_apparam_OBJECTS =  \
+	$(am_unit_test_gobex_apparam_OBJECTS)
+@OBEX_TRUE@unit_test_gobex_apparam_DEPENDENCIES =  \
+@OBEX_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__unit_test_gobex_header_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h unit/util.c \
+	unit/util.h unit/test-gobex-header.c
+@OBEX_TRUE@am_unit_test_gobex_header_OBJECTS = $(am__objects_39) \
+@OBEX_TRUE@	unit/util.$(OBJEXT) \
+@OBEX_TRUE@	unit/test-gobex-header.$(OBJEXT)
+unit_test_gobex_header_OBJECTS = $(am_unit_test_gobex_header_OBJECTS)
+@OBEX_TRUE@unit_test_gobex_header_DEPENDENCIES =  \
+@OBEX_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__unit_test_gobex_packet_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
+	gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \
+	gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \
+	gobex/gobex-transfer.c gobex/gobex-debug.h \
+	gobex/gobex-apparam.c gobex/gobex-apparam.h unit/util.c \
+	unit/util.h unit/test-gobex-packet.c
+@OBEX_TRUE@am_unit_test_gobex_packet_OBJECTS = $(am__objects_39) \
+@OBEX_TRUE@	unit/util.$(OBJEXT) \
+@OBEX_TRUE@	unit/test-gobex-packet.$(OBJEXT)
+unit_test_gobex_packet_OBJECTS = $(am_unit_test_gobex_packet_OBJECTS)
+@OBEX_TRUE@unit_test_gobex_packet_DEPENDENCIES =  \
+@OBEX_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am__unit_test_gobex_transfer_SOURCES_DIST = gobex/gobex.h \
+	gobex/gobex.c gobex/gobex-defs.h gobex/gobex-defs.c \
+	gobex/gobex-packet.c gobex/gobex-packet.h gobex/gobex-header.c \
+	gobex/gobex-header.h gobex/gobex-transfer.c \
+	gobex/gobex-debug.h gobex/gobex-apparam.c \
+	gobex/gobex-apparam.h unit/util.c unit/util.h \
+	unit/test-gobex-transfer.c
+@OBEX_TRUE@am_unit_test_gobex_transfer_OBJECTS = $(am__objects_39) \
+@OBEX_TRUE@	unit/util.$(OBJEXT) \
+@OBEX_TRUE@	unit/test-gobex-transfer.$(OBJEXT)
+unit_test_gobex_transfer_OBJECTS =  \
+	$(am_unit_test_gobex_transfer_OBJECTS)
+@OBEX_TRUE@unit_test_gobex_transfer_DEPENDENCIES =  \
+@OBEX_TRUE@	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am_unit_test_hfp_OBJECTS = unit/test-hfp.$(OBJEXT)
+unit_test_hfp_OBJECTS = $(am_unit_test_hfp_OBJECTS)
+unit_test_hfp_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_hog_OBJECTS = unit/test-hog.$(OBJEXT) $(am__objects_40) \
+	profiles/input/hog-lib.$(OBJEXT) \
+	profiles/scanparam/scpp.$(OBJEXT) \
+	profiles/battery/bas.$(OBJEXT) \
+	profiles/deviceinfo/dis.$(OBJEXT) src/log.$(OBJEXT) \
+	attrib/att.$(OBJEXT) attrib/gatt.$(OBJEXT) \
+	attrib/gattrib.$(OBJEXT)
+unit_test_hog_OBJECTS = $(am_unit_test_hog_OBJECTS)
+unit_test_hog_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_lib_OBJECTS = unit/test-lib.$(OBJEXT)
+unit_test_lib_OBJECTS = $(am_unit_test_lib_OBJECTS)
+unit_test_lib_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am__unit_test_mesh_crypto_SOURCES_DIST = unit/test-mesh-crypto.c \
+	mesh/crypto.h ell/internal ell/ell.h
+@MESH_TRUE@am_unit_test_mesh_crypto_OBJECTS =  \
+@MESH_TRUE@	unit/test_mesh_crypto-test-mesh-crypto.$(OBJEXT)
+unit_test_mesh_crypto_OBJECTS = $(am_unit_test_mesh_crypto_OBJECTS)
+@MESH_TRUE@unit_test_mesh_crypto_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_unit_test_mgmt_OBJECTS = unit/test-mgmt.$(OBJEXT)
+unit_test_mgmt_OBJECTS = $(am_unit_test_mgmt_OBJECTS)
+unit_test_mgmt_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_micp_OBJECTS = unit/test-micp.$(OBJEXT)
+unit_test_micp_OBJECTS = $(am_unit_test_micp_OBJECTS)
+unit_test_micp_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am__unit_test_midi_SOURCES_DIST = unit/test-midi.c \
+	profiles/midi/libmidi.h profiles/midi/libmidi.c
+@MIDI_TRUE@am_unit_test_midi_OBJECTS =  \
+@MIDI_TRUE@	unit/test_midi-test-midi.$(OBJEXT) \
+@MIDI_TRUE@	profiles/midi/unit_test_midi-libmidi.$(OBJEXT)
+unit_test_midi_OBJECTS = $(am_unit_test_midi_OBJECTS)
+@MIDI_TRUE@unit_test_midi_DEPENDENCIES = src/libshared-glib.la \
+@MIDI_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_unit_test_queue_OBJECTS = unit/test-queue.$(OBJEXT)
+unit_test_queue_OBJECTS = $(am_unit_test_queue_OBJECTS)
+unit_test_queue_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_ringbuf_OBJECTS = unit/test-ringbuf.$(OBJEXT)
+unit_test_ringbuf_OBJECTS = $(am_unit_test_ringbuf_OBJECTS)
+unit_test_ringbuf_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_sdp_OBJECTS = unit/test-sdp.$(OBJEXT) \
+	src/sdpd-database.$(OBJEXT) src/log.$(OBJEXT) \
+	src/sdpd-service.$(OBJEXT) src/sdpd-request.$(OBJEXT)
+unit_test_sdp_OBJECTS = $(am_unit_test_sdp_OBJECTS)
+unit_test_sdp_DEPENDENCIES = lib/libbluetooth-internal.la \
+	src/libshared-glib.la $(am__DEPENDENCIES_1)
+am_unit_test_tester_OBJECTS = unit/test-tester.$(OBJEXT)
+unit_test_tester_OBJECTS = $(am_unit_test_tester_OBJECTS)
+unit_test_tester_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_textfile_OBJECTS = unit/test-textfile.$(OBJEXT) \
+	src/textfile.$(OBJEXT)
+unit_test_textfile_OBJECTS = $(am_unit_test_textfile_OBJECTS)
+unit_test_textfile_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_uhid_OBJECTS = unit/test-uhid.$(OBJEXT)
+unit_test_uhid_OBJECTS = $(am_unit_test_uhid_OBJECTS)
+unit_test_uhid_DEPENDENCIES = src/libshared-glib.la \
+	$(am__DEPENDENCIES_1)
+am_unit_test_uuid_OBJECTS = unit/test-uuid.$(OBJEXT)
+unit_test_uuid_OBJECTS = $(am_unit_test_uuid_OBJECTS)
+unit_test_uuid_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+am_unit_test_vcp_OBJECTS = unit/test-vcp.$(OBJEXT) $(am__objects_40)
+unit_test_vcp_OBJECTS = $(am_unit_test_vcp_OBJECTS)
+unit_test_vcp_DEPENDENCIES = src/libshared-glib.la \
+	lib/libbluetooth-internal.la $(am__DEPENDENCIES_1)
+SCRIPTS = $(test_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = android/$(DEPDIR)/a2dp-sink.Po \
+	android/$(DEPDIR)/a2dp.Po \
+	android/$(DEPDIR)/android_tester-tester-a2dp.Po \
+	android/$(DEPDIR)/android_tester-tester-avrcp.Po \
+	android/$(DEPDIR)/android_tester-tester-bluetooth.Po \
+	android/$(DEPDIR)/android_tester-tester-gatt.Po \
+	android/$(DEPDIR)/android_tester-tester-hdp.Po \
+	android/$(DEPDIR)/android_tester-tester-hidhost.Po \
+	android/$(DEPDIR)/android_tester-tester-main.Po \
+	android/$(DEPDIR)/android_tester-tester-map-client.Po \
+	android/$(DEPDIR)/android_tester-tester-pan.Po \
+	android/$(DEPDIR)/android_tester-tester-socket.Po \
+	android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Plo \
+	android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Plo \
+	android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Plo \
+	android/$(DEPDIR)/audio_sco_default_la-hal-sco.Plo \
+	android/$(DEPDIR)/avctp.Po android/$(DEPDIR)/avdtp.Po \
+	android/$(DEPDIR)/avdtptest-avdtp.Po \
+	android/$(DEPDIR)/avdtptest-avdtptest.Po \
+	android/$(DEPDIR)/avrcp-lib.Po android/$(DEPDIR)/avrcp.Po \
+	android/$(DEPDIR)/bluetooth.Po \
+	android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-health.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-pan.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-socket.Plo \
+	android/$(DEPDIR)/bluetooth_default_la-hal-utils.Plo \
+	android/$(DEPDIR)/bluetoothd-snoop.Po \
+	android/$(DEPDIR)/gatt.Po \
+	android/$(DEPDIR)/haltest-hal-utils.Po \
+	android/$(DEPDIR)/handsfree-client.Po \
+	android/$(DEPDIR)/handsfree.Po android/$(DEPDIR)/health.Po \
+	android/$(DEPDIR)/hidhost.Po android/$(DEPDIR)/ipc.Po \
+	android/$(DEPDIR)/ipc_tester-hal-utils.Po \
+	android/$(DEPDIR)/ipc_tester-ipc-tester.Po \
+	android/$(DEPDIR)/main.Po android/$(DEPDIR)/map-client.Po \
+	android/$(DEPDIR)/pan.Po android/$(DEPDIR)/sco.Po \
+	android/$(DEPDIR)/socket.Po \
+	android/$(DEPDIR)/system-emulator.Po \
+	android/$(DEPDIR)/test-ipc.Po \
+	android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Plo \
+	android/client/$(DEPDIR)/haltest-haltest.Po \
+	android/client/$(DEPDIR)/haltest-history.Po \
+	android/client/$(DEPDIR)/haltest-if-audio.Po \
+	android/client/$(DEPDIR)/haltest-if-av-sink.Po \
+	android/client/$(DEPDIR)/haltest-if-av.Po \
+	android/client/$(DEPDIR)/haltest-if-bt.Po \
+	android/client/$(DEPDIR)/haltest-if-gatt.Po \
+	android/client/$(DEPDIR)/haltest-if-hf-client.Po \
+	android/client/$(DEPDIR)/haltest-if-hf.Po \
+	android/client/$(DEPDIR)/haltest-if-hh.Po \
+	android/client/$(DEPDIR)/haltest-if-hl.Po \
+	android/client/$(DEPDIR)/haltest-if-mce.Po \
+	android/client/$(DEPDIR)/haltest-if-pan.Po \
+	android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po \
+	android/client/$(DEPDIR)/haltest-if-rc.Po \
+	android/client/$(DEPDIR)/haltest-if-sco.Po \
+	android/client/$(DEPDIR)/haltest-if-sock.Po \
+	android/client/$(DEPDIR)/haltest-pollhandler.Po \
+	android/client/$(DEPDIR)/haltest-tabcompletion.Po \
+	android/client/$(DEPDIR)/haltest-terminal.Po \
+	android/hardware/$(DEPDIR)/android_tester-hardware.Po \
+	android/hardware/$(DEPDIR)/haltest-hardware.Po \
+	attrib/$(DEPDIR)/att.Po attrib/$(DEPDIR)/bluetoothd-att.Po \
+	attrib/$(DEPDIR)/bluetoothd-gatt.Po \
+	attrib/$(DEPDIR)/bluetoothd-gattrib.Po \
+	attrib/$(DEPDIR)/gatt.Po attrib/$(DEPDIR)/gattrib.Po \
+	attrib/$(DEPDIR)/gatttool.Po attrib/$(DEPDIR)/interactive.Po \
+	attrib/$(DEPDIR)/utils.Po \
+	btio/$(DEPDIR)/android_avdtptest-btio.Po \
+	btio/$(DEPDIR)/bluetoothd-btio.Po btio/$(DEPDIR)/btio.Po \
+	btio/$(DEPDIR)/obexd-btio.Po client/$(DEPDIR)/admin.Po \
+	client/$(DEPDIR)/adv_monitor.Po \
+	client/$(DEPDIR)/advertising.Po client/$(DEPDIR)/agent.Po \
+	client/$(DEPDIR)/assistant.Po client/$(DEPDIR)/display.Po \
+	client/$(DEPDIR)/gatt.Po client/$(DEPDIR)/main.Po \
+	client/$(DEPDIR)/mgmt.Po client/$(DEPDIR)/player.Po \
+	client/$(DEPDIR)/print.Po ell/$(DEPDIR)/base64.Plo \
+	ell/$(DEPDIR)/cert-crypto.Plo ell/$(DEPDIR)/cert.Plo \
+	ell/$(DEPDIR)/checksum.Plo ell/$(DEPDIR)/cipher.Plo \
+	ell/$(DEPDIR)/dbus-client.Plo ell/$(DEPDIR)/dbus-filter.Plo \
+	ell/$(DEPDIR)/dbus-message.Plo \
+	ell/$(DEPDIR)/dbus-name-cache.Plo \
+	ell/$(DEPDIR)/dbus-service.Plo ell/$(DEPDIR)/dbus-util.Plo \
+	ell/$(DEPDIR)/dbus.Plo ell/$(DEPDIR)/ecc-external.Plo \
+	ell/$(DEPDIR)/ecc.Plo ell/$(DEPDIR)/ecdh.Plo \
+	ell/$(DEPDIR)/gvariant-util.Plo ell/$(DEPDIR)/hashmap.Plo \
+	ell/$(DEPDIR)/idle.Plo ell/$(DEPDIR)/io.Plo \
+	ell/$(DEPDIR)/key.Plo ell/$(DEPDIR)/log.Plo \
+	ell/$(DEPDIR)/main.Plo ell/$(DEPDIR)/pem.Plo \
+	ell/$(DEPDIR)/queue.Plo ell/$(DEPDIR)/random.Plo \
+	ell/$(DEPDIR)/settings.Plo ell/$(DEPDIR)/signal.Plo \
+	ell/$(DEPDIR)/siphash.Plo ell/$(DEPDIR)/string.Plo \
+	ell/$(DEPDIR)/strv.Plo ell/$(DEPDIR)/tester.Plo \
+	ell/$(DEPDIR)/time.Plo ell/$(DEPDIR)/timeout.Plo \
+	ell/$(DEPDIR)/tls-extensions.Plo ell/$(DEPDIR)/tls-record.Plo \
+	ell/$(DEPDIR)/tls-suites.Plo ell/$(DEPDIR)/tls.Plo \
+	ell/$(DEPDIR)/utf8.Plo ell/$(DEPDIR)/util.Plo \
+	ell/$(DEPDIR)/uuid.Plo emulator/$(DEPDIR)/amp.Po \
+	emulator/$(DEPDIR)/android_android_tester-btdev.Po \
+	emulator/$(DEPDIR)/android_android_tester-bthost.Po \
+	emulator/$(DEPDIR)/android_android_tester-hciemu.Po \
+	emulator/$(DEPDIR)/android_android_tester-smp.Po \
+	emulator/$(DEPDIR)/android_android_tester-vhci.Po \
+	emulator/$(DEPDIR)/android_ipc_tester-btdev.Po \
+	emulator/$(DEPDIR)/android_ipc_tester-bthost.Po \
+	emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po \
+	emulator/$(DEPDIR)/android_ipc_tester-smp.Po \
+	emulator/$(DEPDIR)/android_ipc_tester-vhci.Po \
+	emulator/$(DEPDIR)/b1ee.Po emulator/$(DEPDIR)/btdev.Po \
+	emulator/$(DEPDIR)/bthost.Po emulator/$(DEPDIR)/hciemu.Po \
+	emulator/$(DEPDIR)/hfp.Po emulator/$(DEPDIR)/le.Po \
+	emulator/$(DEPDIR)/main.Po emulator/$(DEPDIR)/phy.Po \
+	emulator/$(DEPDIR)/serial.Po emulator/$(DEPDIR)/server.Po \
+	emulator/$(DEPDIR)/smp.Po emulator/$(DEPDIR)/vhci.Po \
+	gdbus/$(DEPDIR)/client.Plo gdbus/$(DEPDIR)/mainloop.Plo \
+	gdbus/$(DEPDIR)/object.Plo gdbus/$(DEPDIR)/polkit.Plo \
+	gdbus/$(DEPDIR)/watch.Plo gobex/$(DEPDIR)/gobex-apparam.Po \
+	gobex/$(DEPDIR)/gobex-defs.Po gobex/$(DEPDIR)/gobex-header.Po \
+	gobex/$(DEPDIR)/gobex-packet.Po \
+	gobex/$(DEPDIR)/gobex-transfer.Po gobex/$(DEPDIR)/gobex.Po \
+	gobex/$(DEPDIR)/obexd-gobex-apparam.Po \
+	gobex/$(DEPDIR)/obexd-gobex-defs.Po \
+	gobex/$(DEPDIR)/obexd-gobex-header.Po \
+	gobex/$(DEPDIR)/obexd-gobex-packet.Po \
+	gobex/$(DEPDIR)/obexd-gobex-transfer.Po \
+	gobex/$(DEPDIR)/obexd-gobex.Po lib/$(DEPDIR)/bluetooth.Plo \
+	lib/$(DEPDIR)/hci.Plo lib/$(DEPDIR)/sdp.Plo \
+	lib/$(DEPDIR)/uuid.Plo mesh/$(DEPDIR)/agent.Po \
+	mesh/$(DEPDIR)/appkey.Po mesh/$(DEPDIR)/cfgmod-server.Po \
+	mesh/$(DEPDIR)/crypto.Po mesh/$(DEPDIR)/dbus.Po \
+	mesh/$(DEPDIR)/friend.Po mesh/$(DEPDIR)/keyring.Po \
+	mesh/$(DEPDIR)/main.Po mesh/$(DEPDIR)/manager.Po \
+	mesh/$(DEPDIR)/mesh-config-json.Po \
+	mesh/$(DEPDIR)/mesh-io-generic.Po \
+	mesh/$(DEPDIR)/mesh-io-mgmt.Po mesh/$(DEPDIR)/mesh-io-unit.Po \
+	mesh/$(DEPDIR)/mesh-io.Po mesh/$(DEPDIR)/mesh-mgmt.Po \
+	mesh/$(DEPDIR)/mesh.Po mesh/$(DEPDIR)/model.Po \
+	mesh/$(DEPDIR)/net-keys.Po mesh/$(DEPDIR)/net.Po \
+	mesh/$(DEPDIR)/node.Po mesh/$(DEPDIR)/pb-adv.Po \
+	mesh/$(DEPDIR)/prov-acceptor.Po \
+	mesh/$(DEPDIR)/prov-initiator.Po \
+	mesh/$(DEPDIR)/prvbeac-server.Po \
+	mesh/$(DEPDIR)/remprv-server.Po mesh/$(DEPDIR)/rpl.Po \
+	mesh/$(DEPDIR)/util.Po monitor/$(DEPDIR)/a2dp.Po \
+	monitor/$(DEPDIR)/analyze.Po monitor/$(DEPDIR)/att.Po \
+	monitor/$(DEPDIR)/avctp.Po monitor/$(DEPDIR)/avdtp.Po \
+	monitor/$(DEPDIR)/bnep.Po monitor/$(DEPDIR)/broadcom.Po \
+	monitor/$(DEPDIR)/control.Po monitor/$(DEPDIR)/crc.Po \
+	monitor/$(DEPDIR)/display.Po monitor/$(DEPDIR)/ellisys.Po \
+	monitor/$(DEPDIR)/hcidump.Po monitor/$(DEPDIR)/hwdb.Po \
+	monitor/$(DEPDIR)/intel.Po monitor/$(DEPDIR)/jlink.Po \
+	monitor/$(DEPDIR)/keys.Po monitor/$(DEPDIR)/l2cap.Po \
+	monitor/$(DEPDIR)/ll.Po monitor/$(DEPDIR)/lmp.Po \
+	monitor/$(DEPDIR)/main.Po monitor/$(DEPDIR)/msft.Po \
+	monitor/$(DEPDIR)/packet.Po monitor/$(DEPDIR)/rfcomm.Po \
+	monitor/$(DEPDIR)/sdp.Po monitor/$(DEPDIR)/vendor.Po \
+	obexd/client/$(DEPDIR)/obexd-bip-common.Po \
+	obexd/client/$(DEPDIR)/obexd-bip.Po \
+	obexd/client/$(DEPDIR)/obexd-bluetooth.Po \
+	obexd/client/$(DEPDIR)/obexd-driver.Po \
+	obexd/client/$(DEPDIR)/obexd-ftp.Po \
+	obexd/client/$(DEPDIR)/obexd-manager.Po \
+	obexd/client/$(DEPDIR)/obexd-map-event.Po \
+	obexd/client/$(DEPDIR)/obexd-map.Po \
+	obexd/client/$(DEPDIR)/obexd-mns.Po \
+	obexd/client/$(DEPDIR)/obexd-opp.Po \
+	obexd/client/$(DEPDIR)/obexd-pbap.Po \
+	obexd/client/$(DEPDIR)/obexd-session.Po \
+	obexd/client/$(DEPDIR)/obexd-sync.Po \
+	obexd/client/$(DEPDIR)/obexd-transfer.Po \
+	obexd/client/$(DEPDIR)/obexd-transport.Po \
+	obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po \
+	obexd/plugins/$(DEPDIR)/obexd-filesystem.Po \
+	obexd/plugins/$(DEPDIR)/obexd-ftp.Po \
+	obexd/plugins/$(DEPDIR)/obexd-irmc.Po \
+	obexd/plugins/$(DEPDIR)/obexd-mas.Po \
+	obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po \
+	obexd/plugins/$(DEPDIR)/obexd-opp.Po \
+	obexd/plugins/$(DEPDIR)/obexd-pbap.Po \
+	obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po \
+	obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po \
+	obexd/plugins/$(DEPDIR)/obexd-vcard.Po \
+	obexd/src/$(DEPDIR)/obexd-log.Po \
+	obexd/src/$(DEPDIR)/obexd-main.Po \
+	obexd/src/$(DEPDIR)/obexd-manager.Po \
+	obexd/src/$(DEPDIR)/obexd-mimetype.Po \
+	obexd/src/$(DEPDIR)/obexd-obex.Po \
+	obexd/src/$(DEPDIR)/obexd-plugin.Po \
+	obexd/src/$(DEPDIR)/obexd-server.Po \
+	obexd/src/$(DEPDIR)/obexd-service.Po \
+	obexd/src/$(DEPDIR)/obexd-transport.Po \
+	peripheral/$(DEPDIR)/attach.Po peripheral/$(DEPDIR)/efivars.Po \
+	peripheral/$(DEPDIR)/gap.Po peripheral/$(DEPDIR)/gatt.Po \
+	peripheral/$(DEPDIR)/log.Po peripheral/$(DEPDIR)/main.Po \
+	plugins/$(DEPDIR)/bluetoothd-admin.Po \
+	plugins/$(DEPDIR)/bluetoothd-autopair.Po \
+	plugins/$(DEPDIR)/bluetoothd-hostname.Po \
+	plugins/$(DEPDIR)/bluetoothd-neard.Po \
+	plugins/$(DEPDIR)/bluetoothd-policy.Po \
+	plugins/$(DEPDIR)/bluetoothd-sixaxis.Po \
+	plugins/$(DEPDIR)/bluetoothd-wiimote.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-asha.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-bap.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-bass.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-control.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-csip.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-media.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-micp.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-player.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-sink.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-source.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-transport.Po \
+	profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po \
+	profiles/battery/$(DEPDIR)/bas.Po \
+	profiles/battery/$(DEPDIR)/bluetoothd-bas.Po \
+	profiles/battery/$(DEPDIR)/bluetoothd-battery.Po \
+	profiles/cups/$(DEPDIR)/hcrp.Po \
+	profiles/cups/$(DEPDIR)/main.Po profiles/cups/$(DEPDIR)/sdp.Po \
+	profiles/cups/$(DEPDIR)/spp.Po \
+	profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po \
+	profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po \
+	profiles/deviceinfo/$(DEPDIR)/dis.Po \
+	profiles/gap/$(DEPDIR)/bluetoothd-gas.Po \
+	profiles/health/$(DEPDIR)/bluetoothd-hdp.Po \
+	profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po \
+	profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po \
+	profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po \
+	profiles/health/$(DEPDIR)/bluetoothd-mcap.Po \
+	profiles/health/$(DEPDIR)/mcap.Po \
+	profiles/iap/$(DEPDIR)/main.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-device.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-hog.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-manager.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-server.Po \
+	profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po \
+	profiles/input/$(DEPDIR)/hog-lib.Po \
+	profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po \
+	profiles/midi/$(DEPDIR)/bluetoothd-midi.Po \
+	profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po \
+	profiles/network/$(DEPDIR)/bluetoothd-bnep.Po \
+	profiles/network/$(DEPDIR)/bluetoothd-connection.Po \
+	profiles/network/$(DEPDIR)/bluetoothd-manager.Po \
+	profiles/network/$(DEPDIR)/bluetoothd-server.Po \
+	profiles/network/$(DEPDIR)/bnep.Po \
+	profiles/sap/$(DEPDIR)/bluetoothd-main.Po \
+	profiles/sap/$(DEPDIR)/bluetoothd-manager.Po \
+	profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po \
+	profiles/sap/$(DEPDIR)/bluetoothd-server.Po \
+	profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po \
+	profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po \
+	profiles/scanparam/$(DEPDIR)/scpp.Po \
+	src/$(DEPDIR)/android_avdtptest-log.Po \
+	src/$(DEPDIR)/bluetoothd-adapter.Po \
+	src/$(DEPDIR)/bluetoothd-adv_monitor.Po \
+	src/$(DEPDIR)/bluetoothd-advertising.Po \
+	src/$(DEPDIR)/bluetoothd-agent.Po \
+	src/$(DEPDIR)/bluetoothd-backtrace.Po \
+	src/$(DEPDIR)/bluetoothd-battery.Po \
+	src/$(DEPDIR)/bluetoothd-dbus-common.Po \
+	src/$(DEPDIR)/bluetoothd-device.Po \
+	src/$(DEPDIR)/bluetoothd-eir.Po \
+	src/$(DEPDIR)/bluetoothd-error.Po \
+	src/$(DEPDIR)/bluetoothd-gatt-client.Po \
+	src/$(DEPDIR)/bluetoothd-gatt-database.Po \
+	src/$(DEPDIR)/bluetoothd-log.Po \
+	src/$(DEPDIR)/bluetoothd-main.Po \
+	src/$(DEPDIR)/bluetoothd-plugin.Po \
+	src/$(DEPDIR)/bluetoothd-profile.Po \
+	src/$(DEPDIR)/bluetoothd-rfkill.Po \
+	src/$(DEPDIR)/bluetoothd-sdp-client.Po \
+	src/$(DEPDIR)/bluetoothd-sdp-xml.Po \
+	src/$(DEPDIR)/bluetoothd-sdpd-database.Po \
+	src/$(DEPDIR)/bluetoothd-sdpd-request.Po \
+	src/$(DEPDIR)/bluetoothd-sdpd-server.Po \
+	src/$(DEPDIR)/bluetoothd-sdpd-service.Po \
+	src/$(DEPDIR)/bluetoothd-service.Po \
+	src/$(DEPDIR)/bluetoothd-set.Po \
+	src/$(DEPDIR)/bluetoothd-settings.Po \
+	src/$(DEPDIR)/bluetoothd-storage.Po \
+	src/$(DEPDIR)/bluetoothd-textfile.Po \
+	src/$(DEPDIR)/bluetoothd-uuid-helper.Po src/$(DEPDIR)/eir.Po \
+	src/$(DEPDIR)/log.Po src/$(DEPDIR)/oui.Po \
+	src/$(DEPDIR)/sdp-client.Po src/$(DEPDIR)/sdp-xml.Po \
+	src/$(DEPDIR)/sdpd-database.Po src/$(DEPDIR)/sdpd-request.Po \
+	src/$(DEPDIR)/sdpd-server.Po src/$(DEPDIR)/sdpd-service.Po \
+	src/$(DEPDIR)/settings.Po src/$(DEPDIR)/textfile.Po \
+	src/$(DEPDIR)/uuid-helper.Po \
+	src/shared/$(DEPDIR)/android_avdtptest-log.Po \
+	src/shared/$(DEPDIR)/android_avdtptest-queue.Po \
+	src/shared/$(DEPDIR)/android_avdtptest-util.Po \
+	src/shared/$(DEPDIR)/btp.Po \
+	src/shared/$(DEPDIR)/libshared_ell_la-ad.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-asha.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-att.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-bap.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-bass.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-ccp.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-csip.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-ecc.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-gap.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-hci.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-hfp.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-log.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-mcp.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-micp.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-pcap.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-queue.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-shell.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-uhid.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-util.Plo \
+	src/shared/$(DEPDIR)/libshared_ell_la-vcp.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-ad.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-asha.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-att.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-bap.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-bass.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-ccp.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-csip.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-ecc.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-gap.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-hci.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-hfp.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-log.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-mcp.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-micp.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-pcap.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-queue.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-shell.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-tester.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-uhid.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-util.Plo \
+	src/shared/$(DEPDIR)/libshared_glib_la-vcp.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-att.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-log.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-util.Plo \
+	src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Plo \
+	tools/$(DEPDIR)/3dsp.Po tools/$(DEPDIR)/advtest.Po \
+	tools/$(DEPDIR)/amptest.Po tools/$(DEPDIR)/avinfo.Po \
+	tools/$(DEPDIR)/avtest.Po tools/$(DEPDIR)/bcmfw.Po \
+	tools/$(DEPDIR)/bdaddr.Po tools/$(DEPDIR)/bluemoon.Po \
+	tools/$(DEPDIR)/bluetooth-player.Po \
+	tools/$(DEPDIR)/bnep-tester.Po tools/$(DEPDIR)/bneptest.Po \
+	tools/$(DEPDIR)/btattach.Po tools/$(DEPDIR)/btconfig.Po \
+	tools/$(DEPDIR)/btgatt-client.Po \
+	tools/$(DEPDIR)/btgatt-server.Po tools/$(DEPDIR)/btinfo.Po \
+	tools/$(DEPDIR)/btiotest.Po tools/$(DEPDIR)/btmgmt.Po \
+	tools/$(DEPDIR)/btmon-logger.Po tools/$(DEPDIR)/btpclient.Po \
+	tools/$(DEPDIR)/btpclientctl.Po tools/$(DEPDIR)/btproxy.Po \
+	tools/$(DEPDIR)/btsnoop.Po tools/$(DEPDIR)/check-selftest.Po \
+	tools/$(DEPDIR)/ciptool.Po tools/$(DEPDIR)/cltest.Po \
+	tools/$(DEPDIR)/create-image.Po tools/$(DEPDIR)/eddystone.Po \
+	tools/$(DEPDIR)/gap-tester.Po tools/$(DEPDIR)/gatt-service.Po \
+	tools/$(DEPDIR)/hci-tester.Po tools/$(DEPDIR)/hciattach.Po \
+	tools/$(DEPDIR)/hciattach_ath3k.Po \
+	tools/$(DEPDIR)/hciattach_bcm43xx.Po \
+	tools/$(DEPDIR)/hciattach_intel.Po \
+	tools/$(DEPDIR)/hciattach_qualcomm.Po \
+	tools/$(DEPDIR)/hciattach_st.Po \
+	tools/$(DEPDIR)/hciattach_ti.Po \
+	tools/$(DEPDIR)/hciattach_tialt.Po \
+	tools/$(DEPDIR)/hciconfig.Po tools/$(DEPDIR)/hcidump.Po \
+	tools/$(DEPDIR)/hcieventmask.Po \
+	tools/$(DEPDIR)/hcisecfilter.Po tools/$(DEPDIR)/hcitool.Po \
+	tools/$(DEPDIR)/hex2hcd.Po tools/$(DEPDIR)/hid2hci.Po \
+	tools/$(DEPDIR)/hwdb.Po tools/$(DEPDIR)/ibeacon.Po \
+	tools/$(DEPDIR)/ioctl-tester.Po tools/$(DEPDIR)/iso-tester.Po \
+	tools/$(DEPDIR)/isotest.Po tools/$(DEPDIR)/l2cap-tester.Po \
+	tools/$(DEPDIR)/l2ping.Po tools/$(DEPDIR)/l2test.Po \
+	tools/$(DEPDIR)/mcaptest.Po tools/$(DEPDIR)/mesh-cfgclient.Po \
+	tools/$(DEPDIR)/mesh-cfgtest.Po tools/$(DEPDIR)/mesh-tester.Po \
+	tools/$(DEPDIR)/meshctl.Po tools/$(DEPDIR)/mgmt-tester.Po \
+	tools/$(DEPDIR)/mpris-proxy.Po tools/$(DEPDIR)/nokfw.Po \
+	tools/$(DEPDIR)/obex-client-tool.Po \
+	tools/$(DEPDIR)/obex-server-tool.Po tools/$(DEPDIR)/obexctl.Po \
+	tools/$(DEPDIR)/oobtest.Po tools/$(DEPDIR)/rctest.Po \
+	tools/$(DEPDIR)/rfcomm-tester.Po tools/$(DEPDIR)/rfcomm.Po \
+	tools/$(DEPDIR)/rtlfw.Po tools/$(DEPDIR)/sco-tester.Po \
+	tools/$(DEPDIR)/scotest.Po tools/$(DEPDIR)/sdptool.Po \
+	tools/$(DEPDIR)/seq2bseq.Po tools/$(DEPDIR)/smp-tester.Po \
+	tools/$(DEPDIR)/test-runner.Po \
+	tools/$(DEPDIR)/userchan-tester.Po \
+	tools/mesh-gatt/$(DEPDIR)/config-client.Po \
+	tools/mesh-gatt/$(DEPDIR)/config-server.Po \
+	tools/mesh-gatt/$(DEPDIR)/crypto.Po \
+	tools/mesh-gatt/$(DEPDIR)/gatt.Po \
+	tools/mesh-gatt/$(DEPDIR)/net.Po \
+	tools/mesh-gatt/$(DEPDIR)/node.Po \
+	tools/mesh-gatt/$(DEPDIR)/onoff-model.Po \
+	tools/mesh-gatt/$(DEPDIR)/prov-db.Po \
+	tools/mesh-gatt/$(DEPDIR)/prov.Po \
+	tools/mesh-gatt/$(DEPDIR)/util.Po \
+	tools/mesh/$(DEPDIR)/agent.Po tools/mesh/$(DEPDIR)/cfgcli.Po \
+	tools/mesh/$(DEPDIR)/keys.Po tools/mesh/$(DEPDIR)/mesh-db.Po \
+	tools/mesh/$(DEPDIR)/remote.Po tools/mesh/$(DEPDIR)/util.Po \
+	tools/parser/$(DEPDIR)/amp.Po tools/parser/$(DEPDIR)/att.Po \
+	tools/parser/$(DEPDIR)/avctp.Po \
+	tools/parser/$(DEPDIR)/avdtp.Po \
+	tools/parser/$(DEPDIR)/avrcp.Po tools/parser/$(DEPDIR)/bnep.Po \
+	tools/parser/$(DEPDIR)/bpa.Po tools/parser/$(DEPDIR)/capi.Po \
+	tools/parser/$(DEPDIR)/cmtp.Po tools/parser/$(DEPDIR)/csr.Po \
+	tools/parser/$(DEPDIR)/ericsson.Po \
+	tools/parser/$(DEPDIR)/hci.Po tools/parser/$(DEPDIR)/hcrp.Po \
+	tools/parser/$(DEPDIR)/hidp.Po tools/parser/$(DEPDIR)/l2cap.Po \
+	tools/parser/$(DEPDIR)/lmp.Po tools/parser/$(DEPDIR)/obex.Po \
+	tools/parser/$(DEPDIR)/parser.Po tools/parser/$(DEPDIR)/ppp.Po \
+	tools/parser/$(DEPDIR)/rfcomm.Po tools/parser/$(DEPDIR)/sap.Po \
+	tools/parser/$(DEPDIR)/sdp.Po tools/parser/$(DEPDIR)/smp.Po \
+	tools/parser/$(DEPDIR)/tcpip.Po unit/$(DEPDIR)/test-avctp.Po \
+	unit/$(DEPDIR)/test-avdtp.Po unit/$(DEPDIR)/test-avrcp.Po \
+	unit/$(DEPDIR)/test-bap.Po unit/$(DEPDIR)/test-bass.Po \
+	unit/$(DEPDIR)/test-crc.Po unit/$(DEPDIR)/test-crypto.Po \
+	unit/$(DEPDIR)/test-ecc.Po unit/$(DEPDIR)/test-eir.Po \
+	unit/$(DEPDIR)/test-gatt.Po unit/$(DEPDIR)/test-gattrib.Po \
+	unit/$(DEPDIR)/test-gdbus-client.Po \
+	unit/$(DEPDIR)/test-gobex-apparam.Po \
+	unit/$(DEPDIR)/test-gobex-header.Po \
+	unit/$(DEPDIR)/test-gobex-packet.Po \
+	unit/$(DEPDIR)/test-gobex-transfer.Po \
+	unit/$(DEPDIR)/test-gobex.Po unit/$(DEPDIR)/test-hfp.Po \
+	unit/$(DEPDIR)/test-hog.Po unit/$(DEPDIR)/test-lib.Po \
+	unit/$(DEPDIR)/test-mgmt.Po unit/$(DEPDIR)/test-micp.Po \
+	unit/$(DEPDIR)/test-queue.Po unit/$(DEPDIR)/test-ringbuf.Po \
+	unit/$(DEPDIR)/test-sdp.Po unit/$(DEPDIR)/test-tester.Po \
+	unit/$(DEPDIR)/test-textfile.Po unit/$(DEPDIR)/test-uhid.Po \
+	unit/$(DEPDIR)/test-uuid.Po unit/$(DEPDIR)/test-vcp.Po \
+	unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po \
+	unit/$(DEPDIR)/test_midi-test-midi.Po unit/$(DEPDIR)/util.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(android_audio_a2dp_default_la_SOURCES) \
+	$(android_audio_sco_default_la_SOURCES) \
+	$(android_bluetooth_default_la_SOURCES) \
+	$(ell_libell_internal_la_SOURCES) \
+	$(gdbus_libgdbus_internal_la_SOURCES) \
+	$(lib_libbluetooth_internal_la_SOURCES) \
+	$(lib_libbluetooth_la_SOURCES) $(src_libshared_ell_la_SOURCES) \
+	$(src_libshared_glib_la_SOURCES) \
+	$(src_libshared_mainloop_la_SOURCES) \
+	$(android_android_tester_SOURCES) $(android_avdtptest_SOURCES) \
+	$(android_bluetoothd_SOURCES) \
+	$(android_bluetoothd_snoop_SOURCES) $(android_haltest_SOURCES) \
+	$(android_ipc_tester_SOURCES) \
+	$(android_system_emulator_SOURCES) $(android_test_ipc_SOURCES) \
+	$(attrib_gatttool_SOURCES) $(client_bluetoothctl_SOURCES) \
+	$(emulator_b1ee_SOURCES) $(emulator_btvirt_SOURCES) \
+	$(emulator_hfp_SOURCES) $(mesh_bluetooth_meshd_SOURCES) \
+	$(monitor_btmon_SOURCES) $(obexd_src_obexd_SOURCES) \
+	$(nodist_obexd_src_obexd_SOURCES) \
+	$(peripheral_btsensor_SOURCES) \
+	$(profiles_cups_bluetooth_SOURCES) \
+	$(profiles_iap_iapd_SOURCES) $(src_bluetoothd_SOURCES) \
+	$(nodist_src_bluetoothd_SOURCES) $(tools_3dsp_SOURCES) \
+	$(tools_advtest_SOURCES) tools/amptest.c tools/avinfo.c \
+	tools/avtest.c tools/bcmfw.c $(tools_bdaddr_SOURCES) \
+	$(tools_bluemoon_SOURCES) $(tools_bluetooth_player_SOURCES) \
+	$(tools_bnep_tester_SOURCES) $(tools_bneptest_SOURCES) \
+	$(tools_btattach_SOURCES) $(tools_btconfig_SOURCES) \
+	$(tools_btgatt_client_SOURCES) $(tools_btgatt_server_SOURCES) \
+	$(tools_btinfo_SOURCES) $(tools_btiotest_SOURCES) \
+	$(tools_btmgmt_SOURCES) $(tools_btmon_logger_SOURCES) \
+	$(tools_btpclient_SOURCES) $(tools_btpclientctl_SOURCES) \
+	$(tools_btproxy_SOURCES) $(tools_btsnoop_SOURCES) \
+	tools/check-selftest.c tools/ciptool.c $(tools_cltest_SOURCES) \
+	$(tools_create_image_SOURCES) $(tools_eddystone_SOURCES) \
+	$(tools_gap_tester_SOURCES) $(tools_gatt_service_SOURCES) \
+	$(tools_hci_tester_SOURCES) $(tools_hciattach_SOURCES) \
+	$(tools_hciconfig_SOURCES) $(tools_hcidump_SOURCES) \
+	tools/hcieventmask.c tools/hcisecfilter.c \
+	$(tools_hcitool_SOURCES) $(tools_hex2hcd_SOURCES) \
+	tools/hid2hci.c tools/hwdb.c $(tools_ibeacon_SOURCES) \
+	$(tools_ioctl_tester_SOURCES) $(tools_iso_tester_SOURCES) \
+	tools/isotest.c $(tools_l2cap_tester_SOURCES) tools/l2ping.c \
+	tools/l2test.c $(tools_mcaptest_SOURCES) \
+	$(tools_mesh_cfgclient_SOURCES) $(tools_mesh_cfgtest_SOURCES) \
+	$(tools_mesh_tester_SOURCES) $(tools_meshctl_SOURCES) \
+	$(tools_mgmt_tester_SOURCES) $(tools_mpris_proxy_SOURCES) \
+	$(tools_nokfw_SOURCES) $(tools_obex_client_tool_SOURCES) \
+	$(tools_obex_server_tool_SOURCES) $(tools_obexctl_SOURCES) \
+	$(tools_oobtest_SOURCES) tools/rctest.c tools/rfcomm.c \
+	$(tools_rfcomm_tester_SOURCES) $(tools_rtlfw_SOURCES) \
+	$(tools_sco_tester_SOURCES) tools/scotest.c \
+	$(tools_sdptool_SOURCES) $(tools_seq2bseq_SOURCES) \
+	$(tools_smp_tester_SOURCES) tools/test-runner.c \
+	$(tools_userchan_tester_SOURCES) $(unit_test_avctp_SOURCES) \
+	$(unit_test_avdtp_SOURCES) $(unit_test_avrcp_SOURCES) \
+	$(unit_test_bap_SOURCES) $(unit_test_bass_SOURCES) \
+	$(unit_test_crc_SOURCES) $(unit_test_crypto_SOURCES) \
+	$(unit_test_ecc_SOURCES) $(unit_test_eir_SOURCES) \
+	$(unit_test_gatt_SOURCES) $(unit_test_gattrib_SOURCES) \
+	$(unit_test_gdbus_client_SOURCES) $(unit_test_gobex_SOURCES) \
+	$(unit_test_gobex_apparam_SOURCES) \
+	$(unit_test_gobex_header_SOURCES) \
+	$(unit_test_gobex_packet_SOURCES) \
+	$(unit_test_gobex_transfer_SOURCES) $(unit_test_hfp_SOURCES) \
+	$(unit_test_hog_SOURCES) $(unit_test_lib_SOURCES) \
+	$(unit_test_mesh_crypto_SOURCES) $(unit_test_mgmt_SOURCES) \
+	$(unit_test_micp_SOURCES) $(unit_test_midi_SOURCES) \
+	$(unit_test_queue_SOURCES) $(unit_test_ringbuf_SOURCES) \
+	$(unit_test_sdp_SOURCES) $(unit_test_tester_SOURCES) \
+	$(unit_test_textfile_SOURCES) $(unit_test_uhid_SOURCES) \
+	$(unit_test_uuid_SOURCES) $(unit_test_vcp_SOURCES)
+DIST_SOURCES = $(am__android_audio_a2dp_default_la_SOURCES_DIST) \
+	$(am__android_audio_sco_default_la_SOURCES_DIST) \
+	$(am__android_bluetooth_default_la_SOURCES_DIST) \
+	$(am__ell_libell_internal_la_SOURCES_DIST) \
+	$(gdbus_libgdbus_internal_la_SOURCES) \
+	$(lib_libbluetooth_internal_la_SOURCES) \
+	$(am__lib_libbluetooth_la_SOURCES_DIST) \
+	$(am__src_libshared_ell_la_SOURCES_DIST) \
+	$(am__src_libshared_glib_la_SOURCES_DIST) \
+	$(am__src_libshared_mainloop_la_SOURCES_DIST) \
+	$(am__android_android_tester_SOURCES_DIST) \
+	$(am__android_avdtptest_SOURCES_DIST) \
+	$(am__android_bluetoothd_SOURCES_DIST) \
+	$(am__android_bluetoothd_snoop_SOURCES_DIST) \
+	$(am__android_haltest_SOURCES_DIST) \
+	$(am__android_ipc_tester_SOURCES_DIST) \
+	$(am__android_system_emulator_SOURCES_DIST) \
+	$(am__android_test_ipc_SOURCES_DIST) \
+	$(am__attrib_gatttool_SOURCES_DIST) \
+	$(am__client_bluetoothctl_SOURCES_DIST) \
+	$(am__emulator_b1ee_SOURCES_DIST) \
+	$(am__emulator_btvirt_SOURCES_DIST) \
+	$(am__emulator_hfp_SOURCES_DIST) \
+	$(am__mesh_bluetooth_meshd_SOURCES_DIST) \
+	$(am__monitor_btmon_SOURCES_DIST) \
+	$(am__obexd_src_obexd_SOURCES_DIST) \
+	$(am__peripheral_btsensor_SOURCES_DIST) \
+	$(am__profiles_cups_bluetooth_SOURCES_DIST) \
+	$(am__profiles_iap_iapd_SOURCES_DIST) \
+	$(am__src_bluetoothd_SOURCES_DIST) \
+	$(am__tools_3dsp_SOURCES_DIST) \
+	$(am__tools_advtest_SOURCES_DIST) tools/amptest.c \
+	tools/avinfo.c tools/avtest.c tools/bcmfw.c \
+	$(am__tools_bdaddr_SOURCES_DIST) \
+	$(am__tools_bluemoon_SOURCES_DIST) \
+	$(am__tools_bluetooth_player_SOURCES_DIST) \
+	$(am__tools_bnep_tester_SOURCES_DIST) \
+	$(am__tools_bneptest_SOURCES_DIST) \
+	$(am__tools_btattach_SOURCES_DIST) \
+	$(am__tools_btconfig_SOURCES_DIST) \
+	$(am__tools_btgatt_client_SOURCES_DIST) \
+	$(am__tools_btgatt_server_SOURCES_DIST) \
+	$(am__tools_btinfo_SOURCES_DIST) \
+	$(am__tools_btiotest_SOURCES_DIST) \
+	$(am__tools_btmgmt_SOURCES_DIST) \
+	$(am__tools_btmon_logger_SOURCES_DIST) \
+	$(am__tools_btpclient_SOURCES_DIST) \
+	$(am__tools_btpclientctl_SOURCES_DIST) \
+	$(am__tools_btproxy_SOURCES_DIST) \
+	$(am__tools_btsnoop_SOURCES_DIST) tools/check-selftest.c \
+	tools/ciptool.c $(am__tools_cltest_SOURCES_DIST) \
+	$(am__tools_create_image_SOURCES_DIST) \
+	$(am__tools_eddystone_SOURCES_DIST) \
+	$(am__tools_gap_tester_SOURCES_DIST) \
+	$(am__tools_gatt_service_SOURCES_DIST) \
+	$(am__tools_hci_tester_SOURCES_DIST) \
+	$(am__tools_hciattach_SOURCES_DIST) \
+	$(am__tools_hciconfig_SOURCES_DIST) \
+	$(am__tools_hcidump_SOURCES_DIST) tools/hcieventmask.c \
+	tools/hcisecfilter.c $(am__tools_hcitool_SOURCES_DIST) \
+	$(am__tools_hex2hcd_SOURCES_DIST) tools/hid2hci.c tools/hwdb.c \
+	$(am__tools_ibeacon_SOURCES_DIST) \
+	$(am__tools_ioctl_tester_SOURCES_DIST) \
+	$(am__tools_iso_tester_SOURCES_DIST) tools/isotest.c \
+	$(am__tools_l2cap_tester_SOURCES_DIST) tools/l2ping.c \
+	tools/l2test.c $(am__tools_mcaptest_SOURCES_DIST) \
+	$(am__tools_mesh_cfgclient_SOURCES_DIST) \
+	$(am__tools_mesh_cfgtest_SOURCES_DIST) \
+	$(am__tools_mesh_tester_SOURCES_DIST) \
+	$(am__tools_meshctl_SOURCES_DIST) \
+	$(am__tools_mgmt_tester_SOURCES_DIST) \
+	$(am__tools_mpris_proxy_SOURCES_DIST) \
+	$(am__tools_nokfw_SOURCES_DIST) \
+	$(am__tools_obex_client_tool_SOURCES_DIST) \
+	$(am__tools_obex_server_tool_SOURCES_DIST) \
+	$(am__tools_obexctl_SOURCES_DIST) \
+	$(am__tools_oobtest_SOURCES_DIST) tools/rctest.c \
+	tools/rfcomm.c $(am__tools_rfcomm_tester_SOURCES_DIST) \
+	$(am__tools_rtlfw_SOURCES_DIST) \
+	$(am__tools_sco_tester_SOURCES_DIST) tools/scotest.c \
+	$(am__tools_sdptool_SOURCES_DIST) \
+	$(am__tools_seq2bseq_SOURCES_DIST) \
+	$(am__tools_smp_tester_SOURCES_DIST) tools/test-runner.c \
+	$(am__tools_userchan_tester_SOURCES_DIST) \
+	$(unit_test_avctp_SOURCES) $(unit_test_avdtp_SOURCES) \
+	$(unit_test_avrcp_SOURCES) $(unit_test_bap_SOURCES) \
+	$(unit_test_bass_SOURCES) $(unit_test_crc_SOURCES) \
+	$(unit_test_crypto_SOURCES) $(unit_test_ecc_SOURCES) \
+	$(unit_test_eir_SOURCES) $(unit_test_gatt_SOURCES) \
+	$(unit_test_gattrib_SOURCES) $(unit_test_gdbus_client_SOURCES) \
+	$(am__unit_test_gobex_SOURCES_DIST) \
+	$(am__unit_test_gobex_apparam_SOURCES_DIST) \
+	$(am__unit_test_gobex_header_SOURCES_DIST) \
+	$(am__unit_test_gobex_packet_SOURCES_DIST) \
+	$(am__unit_test_gobex_transfer_SOURCES_DIST) \
+	$(unit_test_hfp_SOURCES) $(unit_test_hog_SOURCES) \
+	$(unit_test_lib_SOURCES) \
+	$(am__unit_test_mesh_crypto_SOURCES_DIST) \
+	$(unit_test_mgmt_SOURCES) $(unit_test_micp_SOURCES) \
+	$(am__unit_test_midi_SOURCES_DIST) $(unit_test_queue_SOURCES) \
+	$(unit_test_ringbuf_SOURCES) $(unit_test_sdp_SOURCES) \
+	$(unit_test_tester_SOURCES) $(unit_test_textfile_SOURCES) \
+	$(unit_test_uhid_SOURCES) $(unit_test_uuid_SOURCES) \
+	$(unit_test_vcp_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+man1dir = $(mandir)/man1
+man5dir = $(mandir)/man5
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+am__dist_zshcompletion_DATA_DIST = completion/zsh/_bluetoothctl
+DATA = $(conf_DATA) $(dbus_DATA) $(dbussessionbus_DATA) \
+	$(dbussystembus_DATA) $(dist_zshcompletion_DATA) \
+	$(pkgconfig_DATA) $(rules_DATA) $(state_DATA) \
+	$(systemdsystemunit_DATA) $(systemduserunit_DATA)
+am__pkginclude_HEADERS_DIST = lib/bluetooth.h lib/hci.h lib/hci_lib.h \
+	lib/sco.h lib/l2cap.h lib/sdp.h lib/sdp_lib.h lib/rfcomm.h \
+	lib/bnep.h lib/cmtp.h lib/hidp.h
+HEADERS = $(pkginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
+	config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+AM_RECURSIVE_TARGETS = cscope check recheck
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red=''; \
+    grn=''; \
+    lgn=''; \
+    blu=''; \
+    mgn=''; \
+    brg=''; \
+    std=''; \
+  fi; \
+}
+am__recheck_rx = ^[ 	]*:recheck:[ 	]*
+am__global_test_result_rx = ^[ 	]*:global-test-result:[ 	]*
+am__copy_in_global_log_rx = ^[ 	]*:copy-in-global-log:[ 	]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+	    recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[ 	]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);					\
+$(am__vpath_adj_setup) $(am__vpath_adj)			\
+$(am__tty_colors);					\
+srcdir=$(srcdir); export srcdir;			\
+case "$@" in						\
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;	\
+    *) am__odir=.;; 					\
+esac;							\
+test "x$$am__odir" = x"." || test -d "$$am__odir" 	\
+  || $(MKDIR_P) "$$am__odir" || exit $$?;		\
+if test -f "./$$f"; then dir=./;			\
+elif test -f "$$f"; then dir=;				\
+else dir="$(srcdir)/"; fi;				\
+tst=$$dir$$f; log='$@'; 				\
+if test -n '$(DISABLE_HARD_ERRORS)'; then		\
+  am__enable_hard_errors=no; 				\
+else							\
+  am__enable_hard_errors=yes; 				\
+fi; 							\
+case " $(XFAIL_TESTS) " in				\
+  *[\ \	]$$f[\ \	]* | *[\ \	]$$dir$$f[\ \	]*) \
+    am__expect_failure=yes;;				\
+  *)							\
+    am__expect_failure=no;;				\
+esac; 							\
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+	$(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.mesh \
+	$(srcdir)/Makefile.obexd $(srcdir)/Makefile.plugins \
+	$(srcdir)/Makefile.tools $(srcdir)/android/Makefile.am \
+	$(srcdir)/config.h.in $(top_srcdir)/lib/bluez.pc.in \
+	$(top_srcdir)/mesh/bluetooth-mesh.service.in \
+	$(top_srcdir)/mesh/bluetooth-meshd.rst.in \
+	$(top_srcdir)/obexd/src/obex.service.in \
+	$(top_srcdir)/obexd/src/org.bluez.obex.service.in \
+	$(top_srcdir)/src/bluetooth.service.in \
+	$(top_srcdir)/src/bluetoothd.rst.in \
+	$(top_srcdir)/tools/bluetooth-logger.service.in \
+	$(top_srcdir)/tools/mpris-proxy.service.in AUTHORS COPYING \
+	COPYING.LIB ChangeLog INSTALL NEWS README TODO compile \
+	config.guess config.sub depcomp install-sh ltmain.sh missing \
+	test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+GZIP_ENV = --best
+DIST_ARCHIVES = $(distdir).tar.xz
+DIST_TARGETS = dist-xz
+# Exists only to be overridden by the user if desired.
+AM_DISTCHECK_DVI_TARGET = dvi
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+pkgincludedir = $(includedir)/bluetooth
+pkglibexecdir = @PKGLIBEXECDIR@
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASAN_LIB = @ASAN_LIB@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BACKTRACE_CFLAGS = @BACKTRACE_CFLAGS@
+BACKTRACE_LIBS = @BACKTRACE_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGDIR = @CONFIGDIR@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CUPS_SERVERBIN = @CUPS_SERVERBIN@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_CONFDIR = @DBUS_CONFDIR@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SESSIONBUSDIR = @DBUS_SESSIONBUSDIR@
+DBUS_SYSTEMBUSDIR = @DBUS_SYSTEMBUSDIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ELL_CFLAGS = @ELL_CFLAGS@
+ELL_LIBS = @ELL_LIBS@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GREP = @GREP@
+GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
+GTHREAD_LIBS = @GTHREAD_LIBS@
+ICAL_CFLAGS = @ICAL_CFLAGS@
+ICAL_LIBS = @ICAL_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JSONC_CFLAGS = @JSONC_CFLAGS@
+JSONC_LIBS = @JSONC_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBEBOOK_CFLAGS = @LIBEBOOK_CFLAGS@
+LIBEBOOK_LIBS = @LIBEBOOK_LIBS@
+LIBEDATESERVER_CFLAGS = @LIBEDATESERVER_CFLAGS@
+LIBEDATESERVER_LIBS = @LIBEDATESERVER_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MESH_STORAGEDIR = @MESH_STORAGEDIR@
+MISC_CFLAGS = @MISC_CFLAGS@
+MISC_LDFLAGS = @MISC_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGBINDIR = @PKGBINDIR@
+PKGLIBEXECDIR = @PKGLIBEXECDIR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_PHONEBOOK = @PLUGIN_PHONEBOOK@
+RANLIB = @RANLIB@
+RST2MAN = @RST2MAN@
+SBC_CFLAGS = @SBC_CFLAGS@
+SBC_LIBS = @SBC_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEXDSP_CFLAGS = @SPEEXDSP_CFLAGS@
+SPEEXDSP_LIBS = @SPEEXDSP_LIBS@
+STRIP = @STRIP@
+SYSTEMD_SYSTEMUNITDIR = @SYSTEMD_SYSTEMUNITDIR@
+SYSTEMD_USERUNITDIR = @SYSTEMD_USERUNITDIR@
+UDEV_CFLAGS = @UDEV_CFLAGS@
+UDEV_DIR = @UDEV_DIR@
+UDEV_LIBS = @UDEV_LIBS@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+ZSH_COMPLETIONDIR = @ZSH_COMPLETIONDIR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_coverage = @enable_coverage@
+enable_dbus_run_session = @enable_dbus_run_session@
+enable_valgrind = @enable_valgrind@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# SPDX-License-Identifier: GPL-2.0
+AM_MAKEFLAGS = --no-print-directory
+AM_CPPFLAGS = $(am__append_72) $(DBUS_CFLAGS) $(GLIB_CFLAGS) \
+	-I$(builddir)/lib
+lib_LTLIBRARIES = $(am__append_2)
+noinst_LIBRARIES = 
+noinst_LTLIBRARIES = lib/libbluetooth-internal.la \
+	gdbus/libgdbus-internal.la $(am__append_3) \
+	src/libshared-glib.la src/libshared-mainloop.la \
+	$(am__append_4)
+CLEANFILES = $(ell_built_sources) $(builtin_files) obexd/src/builtin.h \
+	$(am__append_83)
+EXTRA_DIST = src/org.bluez.service src/genbuiltin src/bluetooth.conf \
+	src/main.conf profiles/network/network.conf \
+	profiles/input/input.conf $(am__append_59) $(am__append_70) \
+	obexd/src/genbuiltin android/Android.mk android/README \
+	android/compat/readline/history.h \
+	android/compat/readline/readline.h android/compat/wordexp.h \
+	android/bluetoothd-wrapper.c android/log.c \
+	android/bluetoothd.te android/bluetoothd_snoop.te \
+	android/init.bluetooth.rc android/hal-ipc-api.txt \
+	android/audio-ipc-api.txt android/cts.txt \
+	android/pics-rfcomm.txt android/pics-spp.txt \
+	android/pics-sdp.txt android/pics-l2cap.txt \
+	android/pics-gap.txt android/pics-did.txt android/pics-hid.txt \
+	android/pics-pan.txt android/pics-opp.txt android/pics-map.txt \
+	android/pics-pbap.txt android/pics-a2dp.txt \
+	android/pics-avctp.txt android/pics-avrcp.txt \
+	android/pics-hsp.txt android/pics-hfp.txt \
+	android/pics-gatt.txt android/pics-mcap.txt \
+	android/pics-hdp.txt android/pics-iopt.txt android/pics-sm.txt \
+	android/pics-mps.txt android/pics-hogp.txt \
+	android/pics-scpp.txt android/pics-dis.txt \
+	android/pics-avdtp.txt android/pics-gavdp.txt \
+	android/pics-bnep.txt android/pixit-l2cap.txt \
+	android/pixit-gap.txt android/pixit-did.txt \
+	android/pixit-hid.txt android/pixit-pan.txt \
+	android/pixit-opp.txt android/pixit-map.txt \
+	android/pixit-pbap.txt android/pixit-a2dp.txt \
+	android/pixit-avctp.txt android/pixit-avrcp.txt \
+	android/pixit-hsp.txt android/pixit-hfp.txt \
+	android/pixit-gatt.txt android/pixit-mcap.txt \
+	android/pixit-hdp.txt android/pixit-iopt.txt \
+	android/pixit-sm.txt android/pixit-mps.txt \
+	android/pixit-hogp.txt android/pixit-scpp.txt \
+	android/pixit-dis.txt android/pixit-rfcomm.txt \
+	android/pixit-spp.txt android/pixit-avdtp.txt \
+	android/pixit-gavdp.txt android/pixit-sdp.txt \
+	android/pixit-bnep.txt android/pts-rfcomm.txt \
+	android/pts-spp.txt android/pts-l2cap.txt android/pts-gap.txt \
+	android/pts-did.txt android/pts-hid.txt android/pts-pan.txt \
+	android/pts-opp.txt android/pts-map.txt android/pts-a2dp.txt \
+	android/pts-avrcp.txt android/pts-avctp.txt \
+	android/pts-pbap.txt android/pts-hfp.txt android/pts-gatt.txt \
+	android/pts-hsp.txt android/pts-iopt.txt android/pts-hdp.txt \
+	android/pts-mcap.txt android/pts-mps.txt android/pts-sm.txt \
+	android/pts-hogp.txt android/pts-scpp.txt android/pts-dis.txt \
+	android/pts-avdtp.txt android/pts-gavdp.txt \
+	android/pts-sdp.txt android/pts-bnep.txt \
+	mesh/bluetooth-mesh.conf mesh/org.bluez.mesh.service \
+	mesh/mesh-main.conf tools/hid2hci.rules $(test_scripts) \
+	doc/assigned-numbers.txt doc/supported-features.txt \
+	doc/test-coverage.txt doc/test-runner.rst \
+	doc/settings-storage.txt doc/mgmt-api.txt doc/health-api.txt \
+	doc/sap-api.txt doc/hci.rst doc/l2cap.rst doc/rfcomm.rst \
+	doc/org.bluez.Adapter.rst doc/org.bluez.Device.rst \
+	doc/org.bluez.DeviceSet.rst doc/org.bluez.AgentManager.rst \
+	doc/org.bluez.Agent.rst doc/org.bluez.ProfileManager.rst \
+	doc/org.bluez.Profile.rst doc/org.bluez.NetworkServer.rst \
+	doc/org.bluez.Network.rst doc/org.bluez.Input.rst \
+	doc/org.bluez.BatteryProviderManager.rst \
+	doc/org.bluez.BatteryProvider.rst doc/org.bluez.Battery.rst \
+	doc/org.bluez.AdminPolicySet.rst \
+	doc/org.bluez.AdminPolicyStatus.rst doc/org.bluez.Media.rst \
+	doc/org.bluez.MediaControl.rst doc/org.bluez.MediaPlayer.rst \
+	doc/org.bluez.MediaFolder.rst doc/org.bluez.MediaItem.rst \
+	doc/org.bluez.MediaEndpoint.rst \
+	doc/org.bluez.MediaTransport.rst \
+	doc/org.bluez.MediaAssistant.rst doc/org.bluez.GattManager.rst \
+	doc/org.bluez.GattProfile.rst doc/org.bluez.GattService.rst \
+	doc/org.bluez.GattCharacteristic.rst \
+	doc/org.bluez.GattDescriptor.rst \
+	doc/org.bluez.LEAdvertisingManager.rst \
+	doc/org.bluez.LEAdvertisement.rst \
+	doc/org.bluez.AdvertisementMonitorManager.rst \
+	doc/org.bluez.AdvertisementMonitor.rst \
+	doc/org.bluez.obex.Client.rst doc/org.bluez.obex.Session.rst \
+	doc/org.bluez.obex.Transfer.rst \
+	doc/org.bluez.obex.ObjectPush.rst \
+	doc/org.bluez.obex.FileTransfer.rst \
+	doc/org.bluez.obex.Synchronization.rst \
+	doc/org.bluez.obex.PhonebookAccess.rst \
+	doc/org.bluez.obex.MessageAccess.rst \
+	doc/org.bluez.obex.Message.rst \
+	doc/org.bluez.obex.AgentManager.rst \
+	doc/org.bluez.obex.Agent.rst doc/org.bluez.obex.Image.rst \
+	doc/pics-opp.txt doc/pixit-opp.txt doc/pts-opp.txt \
+	doc/btsnoop.txt tools/magic.btsnoop $(manual_pages) $(patsubst \
+	%.1,%.rst, $(patsubst %.8,%.rst,$(manual_pages)))
+pkginclude_HEADERS = $(am__append_1)
+AM_CFLAGS = $(MISC_CFLAGS) $(WARNING_CFLAGS) $(UDEV_CFLAGS) $(LIBEBOOK_CFLAGS) \
+				$(LIBEDATASERVER_CFLAGS) $(ell_cflags)
+
+AM_LDFLAGS = $(MISC_LDFLAGS)
+confdir = $(sysconfdir)/bluetooth
+statedir = $(localstatedir)/lib/bluetooth
+@DATAFILES_TRUE@dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d
+@DATAFILES_TRUE@dbus_DATA = src/bluetooth.conf $(am__append_76)
+@DATAFILES_TRUE@conf_DATA = src/main.conf profiles/input/input.conf \
+@DATAFILES_TRUE@	profiles/network/network.conf $(am__append_77)
+@DATAFILES_TRUE@state_DATA = 
+@SYSTEMD_TRUE@systemdsystemunitdir = $(SYSTEMD_SYSTEMUNITDIR)
+@SYSTEMD_TRUE@systemdsystemunit_DATA = src/bluetooth.service \
+@SYSTEMD_TRUE@	$(am__append_52) $(am__append_78)
+@SYSTEMD_TRUE@systemduserunitdir = $(SYSTEMD_USERUNITDIR)
+@SYSTEMD_TRUE@systemduserunit_DATA = $(am__append_56) $(am__append_67)
+@SYSTEMD_TRUE@dbussystembusdir = $(DBUS_SYSTEMBUSDIR)
+@SYSTEMD_TRUE@dbussystembus_DATA = src/org.bluez.service \
+@SYSTEMD_TRUE@	$(am__append_79)
+plugindir = $(libdir)/bluetooth/plugins
+build_plugindir = $(plugindir)
+@MANPAGES_TRUE@man_MANS = src/bluetoothd.8 doc/hci.7 doc/l2cap.7 \
+@MANPAGES_TRUE@	doc/rfcomm.7 doc/org.bluez.Adapter.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Device.5 \
+@MANPAGES_TRUE@	doc/org.bluez.DeviceSet.5 \
+@MANPAGES_TRUE@	doc/org.bluez.AgentManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Agent.5 \
+@MANPAGES_TRUE@	doc/org.bluez.ProfileManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Profile.5 \
+@MANPAGES_TRUE@	doc/org.bluez.NetworkServer.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Network.5 doc/org.bluez.Input.5 \
+@MANPAGES_TRUE@	doc/org.bluez.BatteryProviderManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.BatteryProvider.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Battery.5 \
+@MANPAGES_TRUE@	doc/org.bluez.AdminPolicySet.5 \
+@MANPAGES_TRUE@	doc/org.bluez.AdminPolicyStatus.5 \
+@MANPAGES_TRUE@	doc/org.bluez.Media.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaControl.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaPlayer.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaFolder.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaItem.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaEndpoint.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaTransport.5 \
+@MANPAGES_TRUE@	doc/org.bluez.MediaAssistant.5 \
+@MANPAGES_TRUE@	doc/org.bluez.GattManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.GattProfile.5 \
+@MANPAGES_TRUE@	doc/org.bluez.GattService.5 \
+@MANPAGES_TRUE@	doc/org.bluez.GattCharacteristic.5 \
+@MANPAGES_TRUE@	doc/org.bluez.GattDescriptor.5 \
+@MANPAGES_TRUE@	doc/org.bluez.LEAdvertisingManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.LEAdvertisement.5 \
+@MANPAGES_TRUE@	doc/org.bluez.AdvertisementMonitorManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.AdvertisementMonitor.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Client.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Session.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Transfer.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.ObjectPush.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.FileTransfer.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Synchronization.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.PhonebookAccess.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.MessageAccess.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Message.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.AgentManager.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Agent.5 \
+@MANPAGES_TRUE@	doc/org.bluez.obex.Image.5 $(am__append_50) \
+@MANPAGES_TRUE@	$(am__append_57) $(am__append_62) \
+@MANPAGES_TRUE@	$(am__append_63) $(am__append_81)
+manual_pages = src/bluetoothd.8 doc/hci.7 doc/l2cap.7 doc/rfcomm.7 \
+	doc/org.bluez.Adapter.5 doc/org.bluez.Device.5 \
+	doc/org.bluez.DeviceSet.5 doc/org.bluez.AgentManager.5 \
+	doc/org.bluez.Agent.5 doc/org.bluez.ProfileManager.5 \
+	doc/org.bluez.Profile.5 doc/org.bluez.NetworkServer.5 \
+	doc/org.bluez.Network.5 doc/org.bluez.Input.5 \
+	doc/org.bluez.BatteryProviderManager.5 \
+	doc/org.bluez.BatteryProvider.5 doc/org.bluez.Battery.5 \
+	doc/org.bluez.AdminPolicySet.5 \
+	doc/org.bluez.AdminPolicyStatus.5 doc/org.bluez.Media.5 \
+	doc/org.bluez.MediaControl.5 doc/org.bluez.MediaPlayer.5 \
+	doc/org.bluez.MediaFolder.5 doc/org.bluez.MediaItem.5 \
+	doc/org.bluez.MediaEndpoint.5 doc/org.bluez.MediaTransport.5 \
+	doc/org.bluez.MediaAssistant.5 doc/org.bluez.GattManager.5 \
+	doc/org.bluez.GattProfile.5 doc/org.bluez.GattService.5 \
+	doc/org.bluez.GattCharacteristic.5 \
+	doc/org.bluez.GattDescriptor.5 \
+	doc/org.bluez.LEAdvertisingManager.5 \
+	doc/org.bluez.LEAdvertisement.5 \
+	doc/org.bluez.AdvertisementMonitorManager.5 \
+	doc/org.bluez.AdvertisementMonitor.5 \
+	doc/org.bluez.obex.Client.5 doc/org.bluez.obex.Session.5 \
+	doc/org.bluez.obex.Transfer.5 doc/org.bluez.obex.ObjectPush.5 \
+	doc/org.bluez.obex.FileTransfer.5 \
+	doc/org.bluez.obex.Synchronization.5 \
+	doc/org.bluez.obex.PhonebookAccess.5 \
+	doc/org.bluez.obex.MessageAccess.5 \
+	doc/org.bluez.obex.Message.5 doc/org.bluez.obex.AgentManager.5 \
+	doc/org.bluez.obex.Agent.5 doc/org.bluez.obex.Image.5 \
+	monitor/btmon.1 tools/hciattach.1 tools/hciconfig.1 \
+	tools/hcitool.1 tools/hcidump.1 tools/rfcomm.1 tools/sdptool.1 \
+	tools/ciptool.1 tools/rctest.1 tools/l2ping.1 tools/btattach.1 \
+	tools/bdaddr.1 tools/isotest.1 tools/btmgmt.1 \
+	client/bluetoothctl.1 client/bluetoothctl-mgmt.1 \
+	client/bluetoothctl-monitor.1 client/bluetoothctl-admin.1 \
+	client/bluetoothctl-advertise.1 client/bluetoothctl-endpoint.1 \
+	client/bluetoothctl-gatt.1 client/bluetoothctl-player.1 \
+	client/bluetoothctl-scan.1 client/bluetoothctl-transport.1 \
+	client/bluetoothctl-assistant.1 tools/hid2hci.1 \
+	$(am__append_82)
+plugin_LTLIBRARIES = $(am__append_74)
+lib_sources = lib/bluetooth.c lib/hci.c lib/sdp.c
+lib_headers = lib/bluetooth.h lib/hci.h lib/hci_lib.h \
+		lib/sco.h lib/l2cap.h lib/sdp.h lib/sdp_lib.h \
+		lib/rfcomm.h lib/bnep.h lib/cmtp.h lib/hidp.h
+
+extra_headers = lib/mgmt.h lib/uuid.h lib/a2mp.h lib/amp.h lib/iso.h
+extra_sources = lib/uuid.c
+local_headers = $(foreach file,$(lib_headers), lib/bluetooth/$(notdir $(file)))
+BUILT_SOURCES = $(local_headers) $(ell_built_sources) src/builtin.h \
+	obexd/src/builtin.h
+@LIBRARY_TRUE@lib_libbluetooth_la_SOURCES = $(lib_headers) $(lib_sources)
+@LIBRARY_TRUE@lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 22:15:19
+lib_libbluetooth_internal_la_SOURCES = $(lib_headers) $(lib_sources) \
+					$(extra_headers) $(extra_sources)
+
+gdbus_libgdbus_internal_la_SOURCES = gdbus/gdbus.h \
+				gdbus/mainloop.c gdbus/watch.c \
+				gdbus/object.c gdbus/client.c gdbus/polkit.c
+
+@EXTERNAL_ELL_FALSE@ell_cflags = 
+@EXTERNAL_ELL_TRUE@ell_cflags = @ELL_CFLAGS@
+@EXTERNAL_ELL_FALSE@ell_ldadd = ell/libell-internal.la
+@EXTERNAL_ELL_TRUE@ell_ldadd = @ELL_LIBS@
+@EXTERNAL_ELL_FALSE@ell_built_sources = ell/shared ell/internal ell/ell.h
+@EXTERNAL_ELL_TRUE@ell_built_sources = ell/shared
+@EXTERNAL_ELL_FALSE@ell_headers = ell/util.h \
+@EXTERNAL_ELL_FALSE@			ell/log.h \
+@EXTERNAL_ELL_FALSE@			ell/queue.h \
+@EXTERNAL_ELL_FALSE@			ell/hashmap.h \
+@EXTERNAL_ELL_FALSE@			ell/random.h \
+@EXTERNAL_ELL_FALSE@			ell/signal.h \
+@EXTERNAL_ELL_FALSE@			ell/time.h \
+@EXTERNAL_ELL_FALSE@			ell/time-private.h \
+@EXTERNAL_ELL_FALSE@			ell/timeout.h \
+@EXTERNAL_ELL_FALSE@			ell/cipher.h \
+@EXTERNAL_ELL_FALSE@			ell/checksum.h \
+@EXTERNAL_ELL_FALSE@			ell/io.h \
+@EXTERNAL_ELL_FALSE@			ell/idle.h \
+@EXTERNAL_ELL_FALSE@			ell/main.h \
+@EXTERNAL_ELL_FALSE@			ell/settings.h \
+@EXTERNAL_ELL_FALSE@			ell/strv.h \
+@EXTERNAL_ELL_FALSE@			ell/string.h \
+@EXTERNAL_ELL_FALSE@			ell/utf8.h \
+@EXTERNAL_ELL_FALSE@			ell/dbus.h \
+@EXTERNAL_ELL_FALSE@			ell/dbus-service.h \
+@EXTERNAL_ELL_FALSE@			ell/dbus-client.h \
+@EXTERNAL_ELL_FALSE@			ell/key.h \
+@EXTERNAL_ELL_FALSE@			ell/cert.h \
+@EXTERNAL_ELL_FALSE@			ell/pem.h \
+@EXTERNAL_ELL_FALSE@			ell/base64.h \
+@EXTERNAL_ELL_FALSE@			ell/asn1-private.h \
+@EXTERNAL_ELL_FALSE@			ell/cert-private.h \
+@EXTERNAL_ELL_FALSE@			ell/pem-private.h \
+@EXTERNAL_ELL_FALSE@			ell/uuid.h \
+@EXTERNAL_ELL_FALSE@			ell/useful.h \
+@EXTERNAL_ELL_FALSE@			ell/main-private.h \
+@EXTERNAL_ELL_FALSE@			ell/tester.h \
+@EXTERNAL_ELL_FALSE@			ell/tls.h \
+@EXTERNAL_ELL_FALSE@			ell/tls-private.h \
+@EXTERNAL_ELL_FALSE@			ell/ecc.h \
+@EXTERNAL_ELL_FALSE@			ell/ecc-private.h \
+@EXTERNAL_ELL_FALSE@			ell/cleanup.h \
+@EXTERNAL_ELL_FALSE@			ell/ecdh.h
+
+@EXTERNAL_ELL_FALSE@ell_sources = ell/private.h ell/missing.h \
+@EXTERNAL_ELL_FALSE@			ell/util.c \
+@EXTERNAL_ELL_FALSE@			ell/log.c \
+@EXTERNAL_ELL_FALSE@			ell/queue.c \
+@EXTERNAL_ELL_FALSE@			ell/hashmap.c \
+@EXTERNAL_ELL_FALSE@			ell/random.c \
+@EXTERNAL_ELL_FALSE@			ell/signal.c \
+@EXTERNAL_ELL_FALSE@			ell/time.c \
+@EXTERNAL_ELL_FALSE@			ell/timeout.c \
+@EXTERNAL_ELL_FALSE@			ell/io.c \
+@EXTERNAL_ELL_FALSE@			ell/idle.c \
+@EXTERNAL_ELL_FALSE@			ell/main.c \
+@EXTERNAL_ELL_FALSE@			ell/settings.c \
+@EXTERNAL_ELL_FALSE@			ell/strv.c \
+@EXTERNAL_ELL_FALSE@			ell/string.c \
+@EXTERNAL_ELL_FALSE@			ell/cipher.c \
+@EXTERNAL_ELL_FALSE@			ell/checksum.c \
+@EXTERNAL_ELL_FALSE@			ell/pem.c \
+@EXTERNAL_ELL_FALSE@			ell/cert.c \
+@EXTERNAL_ELL_FALSE@			ell/cert-crypto.c \
+@EXTERNAL_ELL_FALSE@			ell/key.c \
+@EXTERNAL_ELL_FALSE@			ell/base64.c \
+@EXTERNAL_ELL_FALSE@			ell/utf8.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-private.h \
+@EXTERNAL_ELL_FALSE@			ell/dbus.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-message.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-util.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-service.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-client.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-name-cache.c \
+@EXTERNAL_ELL_FALSE@			ell/dbus-filter.c \
+@EXTERNAL_ELL_FALSE@			ell/gvariant-private.h \
+@EXTERNAL_ELL_FALSE@			ell/gvariant-util.c \
+@EXTERNAL_ELL_FALSE@			ell/siphash-private.h \
+@EXTERNAL_ELL_FALSE@			ell/siphash.c \
+@EXTERNAL_ELL_FALSE@			ell/uuid.c \
+@EXTERNAL_ELL_FALSE@			ell/tester.c \
+@EXTERNAL_ELL_FALSE@			ell/tls.c \
+@EXTERNAL_ELL_FALSE@			ell/tls-extensions.c \
+@EXTERNAL_ELL_FALSE@			ell/tls-suites.c \
+@EXTERNAL_ELL_FALSE@			ell/tls-record.c \
+@EXTERNAL_ELL_FALSE@			ell/ecc.c \
+@EXTERNAL_ELL_FALSE@			ell/ecc-external.c \
+@EXTERNAL_ELL_FALSE@			ell/ecdh.c
+
+@EXTERNAL_ELL_FALSE@ell_shared = ell/useful.h
+@EXTERNAL_ELL_FALSE@ell_libell_internal_la_SOURCES = $(ell_headers) $(ell_sources) $(ell_shared)
+shared_sources = src/shared/io.h src/shared/timeout.h \
+	src/shared/queue.h src/shared/queue.c src/shared/util.h \
+	src/shared/util.c src/shared/mgmt.h src/shared/mgmt.c \
+	src/shared/crypto.h src/shared/crypto.c src/shared/ecc.h \
+	src/shared/ecc.c src/shared/ringbuf.h src/shared/ringbuf.c \
+	src/shared/tester.h src/shared/hci.h src/shared/hci.c \
+	src/shared/hci-crypto.h src/shared/hci-crypto.c \
+	src/shared/hfp.h src/shared/hfp.c src/shared/uhid.h \
+	src/shared/uhid.c src/shared/pcap.h src/shared/pcap.c \
+	src/shared/btsnoop.h src/shared/btsnoop.c src/shared/ad.h \
+	src/shared/ad.c src/shared/att-types.h src/shared/att.h \
+	src/shared/att.c src/shared/gatt-helpers.h \
+	src/shared/gatt-helpers.c src/shared/gatt-client.h \
+	src/shared/gatt-client.c src/shared/gatt-server.h \
+	src/shared/gatt-server.c src/shared/gatt-db.h \
+	src/shared/gatt-db.c src/shared/gap.h src/shared/gap.c \
+	src/shared/log.h src/shared/log.c src/shared/bap.h \
+	src/shared/bap.c src/shared/ascs.h src/shared/bap-debug.h \
+	src/shared/bap-debug.c src/shared/mcs.h src/shared/mcp.h \
+	src/shared/mcp.c src/shared/vcp.c src/shared/vcp.h \
+	src/shared/micp.c src/shared/micp.h src/shared/csip.c \
+	src/shared/csip.h src/shared/bass.h src/shared/bass.c \
+	src/shared/ccp.h src/shared/ccp.c src/shared/lc3.h \
+	src/shared/tty.h src/shared/bap-defs.h src/shared/asha.h \
+	src/shared/asha.c $(am__append_5)
+src_libshared_glib_la_SOURCES = $(shared_sources) \
+				src/shared/io-glib.c \
+				src/shared/timeout-glib.c \
+				src/shared/mainloop-glib.c \
+				src/shared/mainloop-notify.h \
+				src/shared/mainloop-notify.c \
+				src/shared/tester.c
+
+src_libshared_glib_la_LDFLAGS = $(AM_LDFLAGS)
+src_libshared_glib_la_CFLAGS = $(AM_CFLAGS)
+src_libshared_mainloop_la_SOURCES = $(shared_sources) \
+				src/shared/io-mainloop.c \
+				src/shared/timeout-mainloop.c \
+				src/shared/mainloop.h src/shared/mainloop.c \
+				src/shared/mainloop-notify.h \
+				src/shared/mainloop-notify.c
+
+src_libshared_mainloop_la_LDFLAGS = $(AM_LDFLAGS)
+src_libshared_mainloop_la_CFLAGS = $(AM_CFLAGS)
+@LIBSHARED_ELL_TRUE@src_libshared_ell_la_SOURCES = $(shared_sources) \
+@LIBSHARED_ELL_TRUE@				src/shared/io-ell.c \
+@LIBSHARED_ELL_TRUE@				src/shared/timeout-ell.c \
+@LIBSHARED_ELL_TRUE@				src/shared/mainloop.h \
+@LIBSHARED_ELL_TRUE@				src/shared/mainloop-ell.c
+
+@LIBSHARED_ELL_TRUE@src_libshared_ell_la_LDFLAGS = $(AM_LDFLAGS)
+@LIBSHARED_ELL_TRUE@src_libshared_ell_la_CFLAGS = $(AM_CFLAGS)
+attrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
+		attrib/gatt.h attrib/gatt.c \
+		attrib/gattrib.h attrib/gattrib.c
+
+btio_sources = btio/btio.h btio/btio.c
+gobex_sources = gobex/gobex.h gobex/gobex.c \
+			gobex/gobex-defs.h gobex/gobex-defs.c \
+			gobex/gobex-packet.c gobex/gobex-packet.h \
+			gobex/gobex-header.c gobex/gobex-header.h \
+			gobex/gobex-transfer.c gobex/gobex-debug.h \
+			gobex/gobex-apparam.c gobex/gobex-apparam.h
+
+
+# SPDX-License-Identifier: GPL-2.0
+builtin_modules = hostname wiimote autopair policy $(am__append_6) \
+	$(am__append_8) $(am__append_10) $(am__append_12) \
+	$(am__append_14) $(am__append_16) $(am__append_18) \
+	$(am__append_20) $(am__append_22) gap scanparam deviceinfo \
+	$(am__append_24) battery $(am__append_28) $(am__append_31) \
+	$(am__append_33) $(am__append_35) $(am__append_37) \
+	$(am__append_39) $(am__append_41) $(am__append_43) \
+	$(am__append_45)
+builtin_sources = plugins/hostname.c plugins/wiimote.c \
+	plugins/autopair.c plugins/policy.c $(am__append_7) \
+	$(am__append_9) $(am__append_11) $(am__append_13) \
+	$(am__append_15) $(am__append_17) $(am__append_19) \
+	$(am__append_21) $(am__append_23) profiles/gap/gas.c \
+	profiles/scanparam/scan.c profiles/deviceinfo/deviceinfo.c \
+	$(am__append_25) profiles/battery/battery.c $(am__append_29) \
+	$(am__append_32) $(am__append_34) $(am__append_36) \
+	$(am__append_38) $(am__append_40) $(am__append_42) \
+	$(am__append_44) $(am__append_46)
+builtin_cppflags = $(am__append_26)
+builtin_ldadd = $(am__append_27) $(am__append_30)
+src_bluetoothd_SOURCES = $(builtin_sources) $(attrib_sources) \
+	$(btio_sources) src/main.c src/log.h src/log.c src/backtrace.h \
+	src/backtrace.c src/rfkill.c src/btd.h src/sdpd.h \
+	src/sdpd-server.c src/sdpd-request.c src/sdpd-service.c \
+	src/sdpd-database.c src/gatt-database.h src/gatt-database.c \
+	src/sdp-xml.h src/sdp-xml.c src/sdp-client.h src/sdp-client.c \
+	src/textfile.h src/textfile.c src/uuid-helper.h \
+	src/uuid-helper.c src/plugin.h src/plugin.c src/storage.h \
+	src/storage.c src/advertising.h src/advertising.c src/agent.h \
+	src/agent.c src/error.h src/error.c src/adapter.h \
+	src/adapter.c src/profile.h src/profile.c src/service.h \
+	src/service.c src/gatt-client.h src/gatt-client.c src/device.h \
+	src/device.c src/dbus-common.c src/dbus-common.h src/eir.h \
+	src/eir.c src/adv_monitor.h src/adv_monitor.c src/battery.h \
+	src/battery.c src/settings.h src/settings.c src/set.h \
+	src/set.c $(am__append_47)
+src_bluetoothd_LDADD = lib/libbluetooth-internal.la \
+			gdbus/libgdbus-internal.la \
+			src/libshared-glib.la \
+			$(BACKTRACE_LIBS) $(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt \
+			$(builtin_ldadd)
+
+@EXTERNAL_PLUGINS_TRUE@src_bluetoothd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic \
+@EXTERNAL_PLUGINS_TRUE@				-Wl,--version-script=$(srcdir)/src/bluetooth.ver
+
+src_bluetoothd_CPPFLAGS = $(AM_CPPFLAGS) -DBLUETOOTH_PLUGIN_BUILTIN \
+					-DPLUGINDIR=\""$(build_plugindir)"\" \
+					$(BACKTRACE_CFLAGS) $(builtin_cppflags)
+
+src_bluetoothd_SHORTNAME = bluetoothd
+builtin_files = src/builtin.h
+nodist_src_bluetoothd_SOURCES = $(builtin_files)
+test_scripts = test/sap_client.py test/bluezutils.py test/dbusdef.py \
+	test/monitor-bluetooth test/list-devices test/test-discovery \
+	test/test-manager test/test-adapter test/test-device \
+	test/simple-agent test/simple-endpoint test/test-sap-server \
+	test/test-network test/test-profile test/test-health \
+	test/test-health-sink test/service-record.dtd \
+	test/service-did.xml test/service-spp.xml test/service-opp.xml \
+	test/service-ftp.xml test/simple-player test/test-nap \
+	test/test-hfp test/opp-client test/ftp-client test/pbap-client \
+	test/map-client test/example-advertisement \
+	test/example-gatt-server test/example-gatt-client \
+	test/test-gatt-profile test/test-mesh test/agent.py
+unit_tests = $(am__append_75) unit/test-tester unit/test-eir \
+	unit/test-uuid unit/test-textfile unit/test-crc \
+	unit/test-crypto unit/test-ecc unit/test-ringbuf \
+	unit/test-queue unit/test-mgmt unit/test-uhid unit/test-sdp \
+	unit/test-avdtp unit/test-avctp unit/test-avrcp unit/test-hfp \
+	unit/test-gdbus-client $(am__append_84) unit/test-lib \
+	unit/test-gatt unit/test-hog unit/test-gattrib unit/test-bap \
+	unit/test-micp unit/test-bass unit/test-vcp $(am__append_85) \
+	$(am__append_86)
+@CLIENT_TRUE@client_bluetoothctl_SOURCES = client/main.c \
+@CLIENT_TRUE@					client/print.h client/print.c \
+@CLIENT_TRUE@					client/display.h client/display.c \
+@CLIENT_TRUE@					client/agent.h client/agent.c \
+@CLIENT_TRUE@					client/advertising.h \
+@CLIENT_TRUE@					client/advertising.c \
+@CLIENT_TRUE@					client/adv_monitor.h \
+@CLIENT_TRUE@					client/adv_monitor.c \
+@CLIENT_TRUE@					client/gatt.h client/gatt.c \
+@CLIENT_TRUE@					client/admin.h client/admin.c \
+@CLIENT_TRUE@					client/player.h client/player.c \
+@CLIENT_TRUE@					client/mgmt.h client/mgmt.c \
+@CLIENT_TRUE@					client/assistant.h client/assistant.c
+
+@CLIENT_TRUE@client_bluetoothctl_LDADD = lib/libbluetooth-internal.la \
+@CLIENT_TRUE@			gdbus/libgdbus-internal.la src/libshared-glib.la \
+@CLIENT_TRUE@			$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
+
+@ZSH_COMPLETIONS_TRUE@zshcompletiondir = $(ZSH_COMPLETIONDIR)
+@ZSH_COMPLETIONS_TRUE@dist_zshcompletion_DATA = completion/zsh/_bluetoothctl
+@MONITOR_TRUE@monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
+@MONITOR_TRUE@				monitor/display.h monitor/display.c \
+@MONITOR_TRUE@				monitor/hcidump.h monitor/hcidump.c \
+@MONITOR_TRUE@				monitor/ellisys.h monitor/ellisys.c \
+@MONITOR_TRUE@				monitor/control.h monitor/control.c \
+@MONITOR_TRUE@				monitor/packet.h monitor/packet.c \
+@MONITOR_TRUE@				monitor/vendor.h monitor/vendor.c \
+@MONITOR_TRUE@				monitor/lmp.h monitor/lmp.c \
+@MONITOR_TRUE@				monitor/crc.h monitor/crc.c \
+@MONITOR_TRUE@				monitor/ll.h monitor/ll.c \
+@MONITOR_TRUE@				monitor/l2cap.h monitor/l2cap.c \
+@MONITOR_TRUE@				monitor/sdp.h monitor/sdp.c \
+@MONITOR_TRUE@				monitor/avctp.h monitor/avctp.c \
+@MONITOR_TRUE@				monitor/avdtp.h monitor/avdtp.c \
+@MONITOR_TRUE@				monitor/a2dp.h monitor/a2dp.c \
+@MONITOR_TRUE@				monitor/rfcomm.h monitor/rfcomm.c \
+@MONITOR_TRUE@				monitor/bnep.h monitor/bnep.c \
+@MONITOR_TRUE@				monitor/hwdb.h monitor/hwdb.c \
+@MONITOR_TRUE@				monitor/keys.h monitor/keys.c \
+@MONITOR_TRUE@				monitor/analyze.h monitor/analyze.c \
+@MONITOR_TRUE@				monitor/intel.h monitor/intel.c \
+@MONITOR_TRUE@				monitor/broadcom.h monitor/broadcom.c \
+@MONITOR_TRUE@				monitor/msft.h monitor/msft.c \
+@MONITOR_TRUE@				monitor/jlink.h monitor/jlink.c \
+@MONITOR_TRUE@				monitor/tty.h monitor/emulator.h \
+@MONITOR_TRUE@				monitor/att.h monitor/att.c \
+@MONITOR_TRUE@				src/log.h src/log.c \
+@MONITOR_TRUE@				src/textfile.h src/textfile.c \
+@MONITOR_TRUE@				src/settings.h src/settings.c
+
+@MONITOR_TRUE@monitor_btmon_LDADD = lib/libbluetooth-internal.la \
+@MONITOR_TRUE@				src/libshared-mainloop.la \
+@MONITOR_TRUE@				$(GLIB_LIBS) $(UDEV_LIBS) -ldl
+
+@LOGGER_TRUE@tools_btmon_logger_SOURCES = tools/btmon-logger.c
+@LOGGER_TRUE@tools_btmon_logger_LDADD = src/libshared-mainloop.la
+@TESTING_TRUE@emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \
+@TESTING_TRUE@				emulator/serial.h emulator/serial.c \
+@TESTING_TRUE@				emulator/server.h emulator/server.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c \
+@TESTING_TRUE@				emulator/phy.h emulator/phy.c \
+@TESTING_TRUE@				emulator/amp.h emulator/amp.c \
+@TESTING_TRUE@				emulator/le.h emulator/le.c
+
+@TESTING_TRUE@emulator_btvirt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
+@TESTING_TRUE@emulator_b1ee_SOURCES = emulator/b1ee.c
+@TESTING_TRUE@emulator_b1ee_LDADD = src/libshared-mainloop.la
+@TESTING_TRUE@emulator_hfp_SOURCES = emulator/hfp.c
+@TESTING_TRUE@emulator_hfp_LDADD = src/libshared-mainloop.la
+@TESTING_TRUE@peripheral_btsensor_SOURCES = peripheral/main.c \
+@TESTING_TRUE@				peripheral/efivars.h peripheral/efivars.c \
+@TESTING_TRUE@				peripheral/attach.h peripheral/attach.c \
+@TESTING_TRUE@				peripheral/log.h peripheral/log.c \
+@TESTING_TRUE@				peripheral/gap.h peripheral/gap.c \
+@TESTING_TRUE@				peripheral/gatt.h peripheral/gatt.c
+
+@TESTING_TRUE@peripheral_btsensor_LDADD = src/libshared-mainloop.la \
+@TESTING_TRUE@				lib/libbluetooth-internal.la
+
+@TESTING_TRUE@tools_3dsp_SOURCES = tools/3dsp.c monitor/bt.h
+@TESTING_TRUE@tools_3dsp_LDADD = src/libshared-mainloop.la
+@TESTING_TRUE@tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_mesh_tester_SOURCES = tools/mesh-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_mesh_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_l2cap_tester_SOURCES = tools/l2cap-tester.c tools/tester.h monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_bnep_tester_SOURCES = tools/bnep-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_bnep_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_smp_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_gap_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				gdbus/libgdbus-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la \
+@TESTING_TRUE@				$(GLIB_LIBS) $(DBUS_LIBS)
+
+@TESTING_TRUE@tools_sco_tester_SOURCES = tools/sco-tester.c tools/tester.h monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_sco_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h
+@TESTING_TRUE@tools_hci_tester_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@TESTING_TRUE@tools_userchan_tester_SOURCES = tools/userchan-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_userchan_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_iso_tester_SOURCES = tools/iso-tester.c tools/tester.h monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_iso_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TESTING_TRUE@tools_ioctl_tester_SOURCES = tools/ioctl-tester.c monitor/bt.h \
+@TESTING_TRUE@				emulator/hciemu.h emulator/hciemu.c \
+@TESTING_TRUE@				emulator/vhci.h emulator/vhci.c \
+@TESTING_TRUE@				emulator/btdev.h emulator/btdev.c \
+@TESTING_TRUE@				emulator/bthost.h emulator/bthost.c \
+@TESTING_TRUE@				emulator/smp.c
+
+@TESTING_TRUE@tools_ioctl_tester_LDADD = lib/libbluetooth-internal.la \
+@TESTING_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@TOOLS_TRUE@tools_bdaddr_SOURCES = tools/bdaddr.c src/oui.h src/oui.c
+@TOOLS_TRUE@tools_bdaddr_LDADD = lib/libbluetooth-internal.la $(UDEV_LIBS)
+@TOOLS_TRUE@tools_avinfo_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_avtest_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_scotest_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_amptest_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_hwdb_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_hcieventmask_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_btinfo_SOURCES = tools/btinfo.c monitor/bt.h
+@TOOLS_TRUE@tools_btinfo_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btattach_SOURCES = tools/btattach.c monitor/bt.h
+@TOOLS_TRUE@tools_btattach_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btconfig_SOURCES = tools/btconfig.c
+@TOOLS_TRUE@tools_btconfig_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btsnoop_SOURCES = tools/btsnoop.c
+@TOOLS_TRUE@tools_btsnoop_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btproxy_SOURCES = tools/btproxy.c monitor/bt.h
+@TOOLS_TRUE@tools_btproxy_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btiotest_SOURCES = tools/btiotest.c btio/btio.h btio/btio.c
+@TOOLS_TRUE@tools_btiotest_LDADD = lib/libbluetooth-internal.la $(GLIB_LIBS)
+@TOOLS_TRUE@tools_mcaptest_SOURCES = tools/mcaptest.c \
+@TOOLS_TRUE@				btio/btio.h btio/btio.c \
+@TOOLS_TRUE@				src/log.c src/log.h \
+@TOOLS_TRUE@				profiles/health/mcap.h profiles/health/mcap.c
+
+@TOOLS_TRUE@tools_mcaptest_LDADD = lib/libbluetooth-internal.la $(GLIB_LIBS) \
+@TOOLS_TRUE@				src/libshared-mainloop.la -lrt
+
+@TOOLS_TRUE@tools_bneptest_SOURCES = tools/bneptest.c \
+@TOOLS_TRUE@				btio/btio.h btio/btio.c \
+@TOOLS_TRUE@				src/log.h src/log.c \
+@TOOLS_TRUE@				profiles/network/bnep.h profiles/network/bnep.c
+
+@TOOLS_TRUE@tools_bneptest_LDADD = lib/libbluetooth-internal.la $(GLIB_LIBS) \
+@TOOLS_TRUE@				src/libshared-mainloop.la
+
+@TOOLS_TRUE@tools_cltest_SOURCES = tools/cltest.c
+@TOOLS_TRUE@tools_cltest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
+@TOOLS_TRUE@tools_oobtest_SOURCES = tools/oobtest.c
+@TOOLS_TRUE@tools_oobtest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
+@TOOLS_TRUE@tools_advtest_SOURCES = tools/advtest.c
+@TOOLS_TRUE@tools_advtest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
+@TOOLS_TRUE@tools_seq2bseq_SOURCES = tools/seq2bseq.c
+@TOOLS_TRUE@tools_nokfw_SOURCES = tools/nokfw.c
+@TOOLS_TRUE@tools_rtlfw_SOURCES = tools/rtlfw.c
+@TOOLS_TRUE@tools_create_image_SOURCES = tools/create-image.c
+@TOOLS_TRUE@tools_eddystone_SOURCES = tools/eddystone.c monitor/bt.h
+@TOOLS_TRUE@tools_eddystone_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_ibeacon_SOURCES = tools/ibeacon.c monitor/bt.h
+@TOOLS_TRUE@tools_ibeacon_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_btgatt_client_SOURCES = tools/btgatt-client.c src/uuid-helper.c
+@TOOLS_TRUE@tools_btgatt_client_LDADD = src/libshared-mainloop.la \
+@TOOLS_TRUE@						lib/libbluetooth-internal.la
+
+@TOOLS_TRUE@tools_btgatt_server_SOURCES = tools/btgatt-server.c src/uuid-helper.c
+@TOOLS_TRUE@tools_btgatt_server_LDADD = src/libshared-mainloop.la \
+@TOOLS_TRUE@						lib/libbluetooth-internal.la
+
+@TOOLS_TRUE@tools_rctest_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_l2test_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_l2ping_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@tools_bluemoon_SOURCES = tools/bluemoon.c monitor/bt.h
+@TOOLS_TRUE@tools_bluemoon_LDADD = src/libshared-mainloop.la
+@TOOLS_TRUE@tools_hex2hcd_SOURCES = tools/hex2hcd.c tools/missing.h
+@TOOLS_TRUE@tools_mpris_proxy_SOURCES = tools/mpris-proxy.c
+@TOOLS_TRUE@tools_mpris_proxy_LDADD = gdbus/libgdbus-internal.la $(GLIB_LIBS) $(DBUS_LIBS)
+@TOOLS_TRUE@tools_gatt_service_SOURCES = tools/gatt-service.c
+@TOOLS_TRUE@tools_gatt_service_LDADD = gdbus/libgdbus-internal.la \
+@TOOLS_TRUE@			   src/libshared-mainloop.la $(GLIB_LIBS) $(DBUS_LIBS)
+
+@TOOLS_TRUE@tools_isotest_LDADD = lib/libbluetooth-internal.la
+@TOOLS_TRUE@profiles_iap_iapd_SOURCES = profiles/iap/main.c
+@TOOLS_TRUE@profiles_iap_iapd_LDADD = gdbus/libgdbus-internal.la $(GLIB_LIBS) $(DBUS_LIBS)
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@tools_meshctl_SOURCES = tools/meshctl.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/agent.h tools/mesh/agent.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/config-model.h\
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/mesh-net.h \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/node.h tools/mesh-gatt/node.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/gatt.h tools/mesh-gatt/gatt.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/crypto.h\
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/crypto.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/keys.h \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/net.h tools/mesh-gatt/net.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/prov.h tools/mesh-gatt/prov.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/util.h tools/mesh-gatt/util.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/prov-db.h \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/prov-db.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/config-client.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/config-server.c \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/onoff-model.h \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				tools/mesh-gatt/onoff-model.c
+
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@tools_meshctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@MESH_TRUE@@TOOLS_TRUE@				$(GLIB_LIBS) $(DBUS_LIBS) -ljson-c -lreadline
+
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgclient_SOURCES = tools/mesh-cfgclient.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/model.h tools/mesh/config-model.h \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/cfgcli.h tools/mesh/cfgcli.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/keys.h tools/mesh/keys.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/util.h tools/mesh/util.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/remote.h tools/mesh/remote.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/agent.h tools/mesh/agent.c \
+@MESH_TRUE@@TOOLS_TRUE@				tools/mesh/mesh-db.h tools/mesh/mesh-db.c \
+@MESH_TRUE@@TOOLS_TRUE@				mesh/util.h mesh/util.c \
+@MESH_TRUE@@TOOLS_TRUE@				mesh/crypto.h mesh/crypto.c
+
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgclient_LDADD = lib/libbluetooth-internal.la src/libshared-ell.la \
+@MESH_TRUE@@TOOLS_TRUE@						$(ell_ldadd) -ljson-c -lreadline
+
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgtest_SOURCES = tools/mesh-cfgtest.c
+@MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgtest_LDADD = lib/libbluetooth-internal.la src/libshared-ell.la \
+@MESH_TRUE@@TOOLS_TRUE@						$(ell_ldadd)
+
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciattach_SOURCES = tools/hciattach.c tools/hciattach.h \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_st.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_ti.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_tialt.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_ath3k.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_qualcomm.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_intel.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@						tools/hciattach_bcm43xx.c
+
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciattach_LDADD = lib/libbluetooth-internal.la
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciconfig_SOURCES = tools/hciconfig.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hciconfig_LDADD = lib/libbluetooth-internal.la
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcitool_SOURCES = tools/hcitool.c src/oui.h src/oui.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcitool_LDADD = lib/libbluetooth-internal.la $(UDEV_LIBS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcidump_SOURCES = tools/hcidump.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/parser.h tools/parser/parser.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/lmp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/hci.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/l2cap.h tools/parser/l2cap.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/amp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/smp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/att.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/sdp.h tools/parser/sdp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/rfcomm.h tools/parser/rfcomm.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/bnep.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/cmtp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/hidp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/hcrp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/avdtp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/avctp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/avrcp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/sap.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/obex.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/capi.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/ppp.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/tcpip.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/ericsson.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/csr.c \
+@DEPRECATED_TRUE@@TOOLS_TRUE@				tools/parser/bpa.c
+
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_sdptool_SOURCES = tools/sdptool.c src/sdp-xml.h src/sdp-xml.c
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_sdptool_LDADD = lib/libbluetooth-internal.la $(GLIB_LIBS)
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_ciptool_LDADD = lib/libbluetooth-internal.la
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_hcidump_LDADD = lib/libbluetooth-internal.la
+@DEPRECATED_TRUE@@TOOLS_TRUE@tools_rfcomm_LDADD = lib/libbluetooth-internal.la
+@HID2HCI_TRUE@udevdir = $(UDEV_DIR)
+@HID2HCI_TRUE@tools_hid2hci_LDADD = $(UDEV_LIBS)
+@READLINE_TRUE@tools_obex_client_tool_SOURCES = $(gobex_sources) $(btio_sources) \
+@READLINE_TRUE@						tools/obex-client-tool.c
+
+@READLINE_TRUE@tools_obex_client_tool_LDADD = lib/libbluetooth-internal.la \
+@READLINE_TRUE@			       src/libshared-glib.la $(GLIB_LIBS) -lreadline
+
+@READLINE_TRUE@tools_obex_server_tool_SOURCES = $(gobex_sources) $(btio_sources) \
+@READLINE_TRUE@						tools/obex-server-tool.c
+
+@READLINE_TRUE@tools_obex_server_tool_LDADD = lib/libbluetooth-internal.la \
+@READLINE_TRUE@			       src/libshared-glib.la $(GLIB_LIBS)
+
+@READLINE_TRUE@tools_bluetooth_player_SOURCES = tools/bluetooth-player.c client/print.c \
+@READLINE_TRUE@				client/player.c
+
+@READLINE_TRUE@tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \
+@READLINE_TRUE@				src/libshared-glib.la \
+@READLINE_TRUE@				$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
+
+@READLINE_TRUE@tools_obexctl_SOURCES = tools/obexctl.c
+@READLINE_TRUE@tools_obexctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
+@READLINE_TRUE@			$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
+
+@READLINE_TRUE@tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c client/display.c \
+@READLINE_TRUE@			client/mgmt.c
+
+@READLINE_TRUE@tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la \
+@READLINE_TRUE@				-lreadline
+
+@DEPRECATED_TRUE@@READLINE_TRUE@attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
+@DEPRECATED_TRUE@@READLINE_TRUE@				attrib/gattrib.c btio/btio.c \
+@DEPRECATED_TRUE@@READLINE_TRUE@				attrib/gatttool.h attrib/interactive.c \
+@DEPRECATED_TRUE@@READLINE_TRUE@				attrib/utils.c src/log.c client/display.c \
+@DEPRECATED_TRUE@@READLINE_TRUE@				client/display.h
+
+@DEPRECATED_TRUE@@READLINE_TRUE@attrib_gatttool_LDADD = lib/libbluetooth-internal.la \
+@DEPRECATED_TRUE@@READLINE_TRUE@			src/libshared-glib.la $(GLIB_LIBS) -lreadline
+
+@CUPS_SERVERBIN_FALSE@@CUPS_TRUE@cupsdir = $(libdir)/cups/backend
+@CUPS_SERVERBIN_TRUE@@CUPS_TRUE@cupsdir = $(CUPS_SERVERBIN)/backend
+@CUPS_TRUE@profiles_cups_bluetooth_SOURCES = profiles/cups/main.c \
+@CUPS_TRUE@					profiles/cups/cups.h \
+@CUPS_TRUE@					profiles/cups/sdp.c \
+@CUPS_TRUE@					profiles/cups/spp.c \
+@CUPS_TRUE@					profiles/cups/hcrp.c
+
+@CUPS_TRUE@profiles_cups_bluetooth_LDADD = $(GLIB_LIBS) $(DBUS_LIBS) \
+@CUPS_TRUE@				lib/libbluetooth-internal.la \
+@CUPS_TRUE@				gdbus/libgdbus-internal.la
+
+@BTPCLIENT_TRUE@tools_btpclient_SOURCES = tools/btpclient.c src/shared/btp.c src/shared/btp.h
+@BTPCLIENT_TRUE@tools_btpclient_LDADD = lib/libbluetooth-internal.la \
+@BTPCLIENT_TRUE@				src/libshared-ell.la $(ell_ldadd)
+
+@BTPCLIENT_TRUE@tools_btpclientctl_SOURCES = tools/btpclientctl.c client/display.c
+@BTPCLIENT_TRUE@tools_btpclientctl_LDADD = src/libshared-mainloop.la src/libshared-glib.la \
+@BTPCLIENT_TRUE@				lib/libbluetooth-internal.la -lreadline
+
+@OBEX_TRUE@@SYSTEMD_TRUE@dbussessionbusdir = $(DBUS_SESSIONBUSDIR)
+@OBEX_TRUE@@SYSTEMD_TRUE@dbussessionbus_DATA = obexd/src/org.bluez.obex.service
+@OBEX_TRUE@obex_plugindir = $(libdir)/obex/plugins
+@OBEX_TRUE@obexd_builtin_modules = filesystem bluetooth \
+@OBEX_TRUE@	$(am__append_68) opp ftp irmc pbap mas mns
+@OBEX_TRUE@obexd_builtin_sources = obexd/plugins/filesystem.c \
+@OBEX_TRUE@	obexd/plugins/filesystem.h \
+@OBEX_TRUE@	obexd/plugins/bluetooth.c $(am__append_69) \
+@OBEX_TRUE@	obexd/plugins/opp.c obexd/plugins/ftp.c \
+@OBEX_TRUE@	obexd/plugins/ftp.h obexd/plugins/irmc.c \
+@OBEX_TRUE@	obexd/plugins/pbap.c obexd/plugins/vcard.h \
+@OBEX_TRUE@	obexd/plugins/vcard.c obexd/plugins/phonebook.h \
+@OBEX_TRUE@	obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c \
+@OBEX_TRUE@	obexd/plugins/mas.c obexd/src/map_ap.h \
+@OBEX_TRUE@	obexd/plugins/messages.h \
+@OBEX_TRUE@	obexd/plugins/messages-dummy.c obexd/client/mns.c \
+@OBEX_TRUE@	obexd/src/map_ap.h obexd/client/map-event.h
+@OBEX_TRUE@obexd_builtin_nodist = 
+@OBEX_TRUE@obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \
+@OBEX_TRUE@			$(obexd_builtin_sources) \
+@OBEX_TRUE@			obexd/src/main.c obexd/src/obexd.h \
+@OBEX_TRUE@			obexd/src/plugin.h obexd/src/plugin.c \
+@OBEX_TRUE@			obexd/src/log.h obexd/src/log.c \
+@OBEX_TRUE@			obexd/src/manager.h obexd/src/manager.c \
+@OBEX_TRUE@			obexd/src/obex.h obexd/src/obex.c obexd/src/obex-priv.h \
+@OBEX_TRUE@			obexd/src/mimetype.h obexd/src/mimetype.c \
+@OBEX_TRUE@			obexd/src/service.h obexd/src/service.c \
+@OBEX_TRUE@			obexd/src/transport.h obexd/src/transport.c \
+@OBEX_TRUE@			obexd/src/server.h obexd/src/server.c \
+@OBEX_TRUE@			obexd/client/manager.h obexd/client/manager.c \
+@OBEX_TRUE@			obexd/client/session.h obexd/client/session.c \
+@OBEX_TRUE@			obexd/client/bluetooth.h obexd/client/bluetooth.c \
+@OBEX_TRUE@			obexd/client/sync.h obexd/client/sync.c \
+@OBEX_TRUE@			obexd/client/pbap.h obexd/client/pbap.c \
+@OBEX_TRUE@			obexd/client/ftp.h obexd/client/ftp.c \
+@OBEX_TRUE@			obexd/client/opp.h obexd/client/opp.c \
+@OBEX_TRUE@			obexd/client/map.h obexd/client/map.c \
+@OBEX_TRUE@			obexd/client/bip.h obexd/client/bip.c \
+@OBEX_TRUE@			obexd/client/bip-common.h obexd/client/bip-common.c \
+@OBEX_TRUE@			obexd/client/map-event.h obexd/client/map-event.c \
+@OBEX_TRUE@			obexd/client/transfer.h obexd/client/transfer.c \
+@OBEX_TRUE@			obexd/client/transport.h obexd/client/transport.c \
+@OBEX_TRUE@			obexd/client/driver.h obexd/client/driver.c \
+@OBEX_TRUE@			obexd/src/map_ap.h
+
+@OBEX_TRUE@obexd_src_obexd_LDADD = lib/libbluetooth-internal.la \
+@OBEX_TRUE@			gdbus/libgdbus-internal.la \
+@OBEX_TRUE@			src/libshared-glib.la \
+@OBEX_TRUE@			$(ICAL_LIBS) $(DBUS_LIBS) $(LIBEBOOK_LIBS) \
+@OBEX_TRUE@			$(LIBEDATASERVER_LIBS) $(GLIB_LIBS) -ldl
+
+@EXTERNAL_PLUGINS_TRUE@@OBEX_TRUE@obexd_src_obexd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic
+@OBEX_TRUE@obexd_src_obexd_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+@OBEX_TRUE@				$(ICAL_CFLAGS) -DOBEX_PLUGIN_BUILTIN \
+@OBEX_TRUE@				-DPLUGINDIR=\""$(obex_plugindir)"\" \
+@OBEX_TRUE@				-D_FILE_OFFSET_BITS=64 \
+@OBEX_TRUE@				-I$(builddir)/obexd/src
+
+obexd_src_obexd_SHORTNAME = obexd
+obexd_builtin_files = obexd/src/builtin.h $(obexd_builtin_nodist)
+nodist_obexd_src_obexd_SOURCES = $(obexd_builtin_files)
+@ANDROID_TRUE@android_plugindir = $(abs_top_srcdir)/android/.libs
+@ANDROID_TRUE@android_system_emulator_SOURCES = android/system-emulator.c
+@ANDROID_TRUE@android_system_emulator_LDADD = src/libshared-mainloop.la
+@ANDROID_TRUE@android_bluetoothd_snoop_SOURCES = android/bluetoothd-snoop.c src/log.c
+@ANDROID_TRUE@android_bluetoothd_snoop_LDADD = src/libshared-mainloop.la $(GLIB_LIBS)
+@ANDROID_TRUE@android_bluetoothd_SOURCES = android/main.c \
+@ANDROID_TRUE@				src/log.c \
+@ANDROID_TRUE@				android/hal-msg.h \
+@ANDROID_TRUE@				android/audio-msg.h \
+@ANDROID_TRUE@				android/sco-msg.h \
+@ANDROID_TRUE@				android/utils.h \
+@ANDROID_TRUE@				src/sdpd-database.c src/sdpd-server.c \
+@ANDROID_TRUE@				src/sdpd-service.c src/sdpd-request.c \
+@ANDROID_TRUE@				src/uuid-helper.h src/uuid-helper.c \
+@ANDROID_TRUE@				src/eir.h src/eir.c \
+@ANDROID_TRUE@				android/bluetooth.h android/bluetooth.c \
+@ANDROID_TRUE@				android/hidhost.h android/hidhost.c \
+@ANDROID_TRUE@				profiles/scanparam/scpp.h \
+@ANDROID_TRUE@				profiles/scanparam/scpp.c \
+@ANDROID_TRUE@				profiles/deviceinfo/dis.h \
+@ANDROID_TRUE@				profiles/deviceinfo/dis.c \
+@ANDROID_TRUE@				profiles/battery/bas.h profiles/battery/bas.c \
+@ANDROID_TRUE@				profiles/input/hog-lib.h \
+@ANDROID_TRUE@				profiles/input/hog-lib.c \
+@ANDROID_TRUE@				android/ipc-common.h \
+@ANDROID_TRUE@				android/ipc.h android/ipc.c \
+@ANDROID_TRUE@				android/avdtp.h android/avdtp.c \
+@ANDROID_TRUE@				android/a2dp.h android/a2dp.c \
+@ANDROID_TRUE@				android/a2dp-sink.h android/a2dp-sink.c \
+@ANDROID_TRUE@				android/avctp.h android/avctp.c \
+@ANDROID_TRUE@				android/avrcp.h android/avrcp.c \
+@ANDROID_TRUE@				android/avrcp-lib.h android/avrcp-lib.c \
+@ANDROID_TRUE@				android/socket.h android/socket.c \
+@ANDROID_TRUE@				android/sco.h android/sco.c \
+@ANDROID_TRUE@				android/pan.h android/pan.c \
+@ANDROID_TRUE@				android/handsfree.h android/handsfree.c \
+@ANDROID_TRUE@				android/handsfree-client.c android/handsfree-client.h \
+@ANDROID_TRUE@				android/gatt.h android/gatt.c \
+@ANDROID_TRUE@				android/health.h android/health.c \
+@ANDROID_TRUE@				profiles/health/mcap.h profiles/health/mcap.c \
+@ANDROID_TRUE@				android/map-client.h android/map-client.c \
+@ANDROID_TRUE@				attrib/att.c attrib/att.h \
+@ANDROID_TRUE@				attrib/gatt.c attrib/gatt.h \
+@ANDROID_TRUE@				attrib/gattrib.c attrib/gattrib.h \
+@ANDROID_TRUE@				btio/btio.h btio/btio.c \
+@ANDROID_TRUE@				src/sdp-client.h src/sdp-client.c \
+@ANDROID_TRUE@				profiles/network/bnep.h profiles/network/bnep.c
+
+@ANDROID_TRUE@android_bluetoothd_LDADD = lib/libbluetooth-internal.la \
+@ANDROID_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@ANDROID_TRUE@android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
+@ANDROID_TRUE@					android/hal-socket.c \
+@ANDROID_TRUE@					android/hal-hidhost.c \
+@ANDROID_TRUE@					android/hal-health.c \
+@ANDROID_TRUE@					android/hal-pan.c \
+@ANDROID_TRUE@					android/hal-a2dp.c \
+@ANDROID_TRUE@					android/hal-a2dp-sink.c \
+@ANDROID_TRUE@					android/hal-avrcp.c \
+@ANDROID_TRUE@					android/hal-avrcp-ctrl.c \
+@ANDROID_TRUE@					android/hal-handsfree.c \
+@ANDROID_TRUE@					android/hal-handsfree-client.c \
+@ANDROID_TRUE@					android/hal-gatt.c \
+@ANDROID_TRUE@					android/hal-map-client.c \
+@ANDROID_TRUE@					android/hardware/bluetooth.h \
+@ANDROID_TRUE@					android/hardware/bt_av.h \
+@ANDROID_TRUE@					android/hardware/bt_gatt.h \
+@ANDROID_TRUE@					android/hardware/bt_gatt_client.h \
+@ANDROID_TRUE@					android/hardware/bt_gatt_server.h \
+@ANDROID_TRUE@					android/hardware/bt_gatt_types.h \
+@ANDROID_TRUE@					android/hardware/bt_hf.h \
+@ANDROID_TRUE@					android/hardware/bt_hh.h \
+@ANDROID_TRUE@					android/hardware/bt_hl.h \
+@ANDROID_TRUE@					android/hardware/bt_pan.h \
+@ANDROID_TRUE@					android/hardware/bt_rc.h \
+@ANDROID_TRUE@					android/hardware/bt_sock.h \
+@ANDROID_TRUE@					android/hardware/bt_hf_client.h \
+@ANDROID_TRUE@					android/hardware/bt_mce.h \
+@ANDROID_TRUE@					android/hardware/hardware.h \
+@ANDROID_TRUE@					android/cutils/properties.h \
+@ANDROID_TRUE@					android/ipc-common.h \
+@ANDROID_TRUE@					android/hal-log.h \
+@ANDROID_TRUE@					android/hal-ipc.h android/hal-ipc.c \
+@ANDROID_TRUE@					android/hal-utils.h android/hal-utils.c
+
+@ANDROID_TRUE@android_bluetooth_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+@ANDROID_TRUE@android_bluetooth_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android
+@ANDROID_TRUE@android_bluetooth_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+@ANDROID_TRUE@					-no-undefined
+
+@ANDROID_TRUE@android_avdtptest_SOURCES = android/avdtptest.c \
+@ANDROID_TRUE@				src/log.h src/log.c \
+@ANDROID_TRUE@				btio/btio.h btio/btio.c \
+@ANDROID_TRUE@				src/shared/util.h src/shared/util.c \
+@ANDROID_TRUE@				src/shared/queue.h src/shared/queue.c \
+@ANDROID_TRUE@				src/shared/log.h src/shared/log.c \
+@ANDROID_TRUE@				android/avdtp.h android/avdtp.c
+
+@ANDROID_TRUE@android_avdtptest_CFLAGS = $(AM_CFLAGS)
+@ANDROID_TRUE@android_avdtptest_LDADD = lib/libbluetooth-internal.la $(GLIB_LIBS)
+@ANDROID_TRUE@android_haltest_SOURCES = android/client/haltest.c \
+@ANDROID_TRUE@				android/client/pollhandler.h \
+@ANDROID_TRUE@				android/client/pollhandler.c \
+@ANDROID_TRUE@				android/client/terminal.h \
+@ANDROID_TRUE@				android/client/terminal.c \
+@ANDROID_TRUE@				android/client/history.h \
+@ANDROID_TRUE@				android/client/history.c \
+@ANDROID_TRUE@				android/client/tabcompletion.c \
+@ANDROID_TRUE@				android/client/if-main.h \
+@ANDROID_TRUE@				android/client/if-av.c \
+@ANDROID_TRUE@				android/client/if-av-sink.c \
+@ANDROID_TRUE@				android/client/if-rc.c \
+@ANDROID_TRUE@				android/client/if-rc-ctrl.c \
+@ANDROID_TRUE@				android/client/if-bt.c \
+@ANDROID_TRUE@				android/client/if-gatt.c \
+@ANDROID_TRUE@				android/client/if-hf.c \
+@ANDROID_TRUE@				android/client/if-hf-client.c \
+@ANDROID_TRUE@				android/client/if-hh.c \
+@ANDROID_TRUE@				android/client/if-pan.c \
+@ANDROID_TRUE@				android/client/if-hl.c \
+@ANDROID_TRUE@				android/client/if-sock.c \
+@ANDROID_TRUE@				android/client/if-audio.c \
+@ANDROID_TRUE@				android/client/if-sco.c \
+@ANDROID_TRUE@				android/client/if-mce.c \
+@ANDROID_TRUE@				android/hardware/hardware.c \
+@ANDROID_TRUE@				android/hal-utils.h android/hal-utils.c
+
+@ANDROID_TRUE@android_haltest_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android \
+@ANDROID_TRUE@				-DPLUGINDIR=\""$(android_plugindir)"\"
+
+@ANDROID_TRUE@android_haltest_LDFLAGS = $(AM_LDFLAGS) -pthread
+@ANDROID_TRUE@android_haltest_LDADD = -ldl -lm
+@ANDROID_TRUE@android_android_tester_SOURCES = emulator/hciemu.h emulator/hciemu.c \
+@ANDROID_TRUE@				emulator/vhci.h emulator/vhci.c \
+@ANDROID_TRUE@				emulator/btdev.h emulator/btdev.c \
+@ANDROID_TRUE@				emulator/bthost.h emulator/bthost.c \
+@ANDROID_TRUE@				emulator/smp.c \
+@ANDROID_TRUE@				monitor/rfcomm.h \
+@ANDROID_TRUE@				android/hardware/hardware.c \
+@ANDROID_TRUE@				android/tester-bluetooth.c \
+@ANDROID_TRUE@				android/tester-socket.c \
+@ANDROID_TRUE@				android/tester-hidhost.c \
+@ANDROID_TRUE@				android/tester-pan.c \
+@ANDROID_TRUE@				android/tester-hdp.c \
+@ANDROID_TRUE@				android/tester-a2dp.c \
+@ANDROID_TRUE@				android/tester-avrcp.c \
+@ANDROID_TRUE@				android/tester-gatt.c \
+@ANDROID_TRUE@				android/tester-map-client.c \
+@ANDROID_TRUE@				android/tester-main.h android/tester-main.c
+
+@ANDROID_TRUE@android_android_tester_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android \
+@ANDROID_TRUE@				-DPLUGINDIR=\""$(android_plugindir)"\"
+
+@ANDROID_TRUE@android_android_tester_LDADD = lib/libbluetooth-internal.la \
+@ANDROID_TRUE@				src/libshared-glib.la $(GLIB_LIBS) -ldl
+
+@ANDROID_TRUE@android_android_tester_LDFLAGS = $(AM_LDFLAGS) -pthread
+@ANDROID_TRUE@android_ipc_tester_SOURCES = emulator/hciemu.h emulator/hciemu.c \
+@ANDROID_TRUE@				emulator/vhci.h emulator/vhci.c \
+@ANDROID_TRUE@				emulator/btdev.h emulator/btdev.c \
+@ANDROID_TRUE@				emulator/bthost.h emulator/bthost.c \
+@ANDROID_TRUE@				emulator/smp.c \
+@ANDROID_TRUE@				android/hal-utils.h android/hal-utils.c \
+@ANDROID_TRUE@				android/ipc-common.h android/ipc-tester.c
+
+@ANDROID_TRUE@android_ipc_tester_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android
+@ANDROID_TRUE@android_ipc_tester_LDADD = lib/libbluetooth-internal.la \
+@ANDROID_TRUE@				src/libshared-glib.la $(GLIB_LIBS)
+
+@ANDROID_TRUE@android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
+@ANDROID_TRUE@					android/hal-msg.h \
+@ANDROID_TRUE@					android/hal-audio.h \
+@ANDROID_TRUE@					android/hal-audio.c \
+@ANDROID_TRUE@					android/hal-audio-sbc.c \
+@ANDROID_TRUE@					android/hal-audio-aptx.c \
+@ANDROID_TRUE@					android/hardware/audio.h \
+@ANDROID_TRUE@					android/hardware/audio_effect.h \
+@ANDROID_TRUE@					android/hardware/hardware.h \
+@ANDROID_TRUE@					android/system/audio.h
+
+@ANDROID_TRUE@android_audio_a2dp_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+@ANDROID_TRUE@android_audio_a2dp_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android \
+@ANDROID_TRUE@					$(SBC_CFLAGS)
+
+@ANDROID_TRUE@android_audio_a2dp_default_la_LIBADD = $(SBC_LIBS) -lrt
+@ANDROID_TRUE@android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+@ANDROID_TRUE@					-no-undefined -pthread
+
+@ANDROID_TRUE@android_audio_sco_default_la_SOURCES = android/hal-log.h \
+@ANDROID_TRUE@					android/sco-msg.h \
+@ANDROID_TRUE@					android/hal-sco.c \
+@ANDROID_TRUE@					android/hardware/audio.h \
+@ANDROID_TRUE@					android/hardware/audio_effect.h \
+@ANDROID_TRUE@					android/hardware/hardware.h \
+@ANDROID_TRUE@					android/audio_utils/resampler.c \
+@ANDROID_TRUE@					android/audio_utils/resampler.h \
+@ANDROID_TRUE@					android/system/audio.h
+
+@ANDROID_TRUE@android_audio_sco_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+@ANDROID_TRUE@android_audio_sco_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android
+@ANDROID_TRUE@android_audio_sco_default_la_LIBADD = $(SPEEXDSP_LIBS) -lrt
+@ANDROID_TRUE@android_audio_sco_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+@ANDROID_TRUE@					-no-undefined
+
+@ANDROID_TRUE@android_test_ipc_SOURCES = android/test-ipc.c \
+@ANDROID_TRUE@				src/log.h src/log.c \
+@ANDROID_TRUE@				android/ipc-common.h \
+@ANDROID_TRUE@				android/ipc.c android/ipc.h
+
+@ANDROID_TRUE@android_test_ipc_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@MESH_TRUE@mesh_sources = mesh/mesh.h mesh/mesh.c \
+@MESH_TRUE@				mesh/net-keys.h mesh/net-keys.c \
+@MESH_TRUE@				mesh/mesh-io.h mesh/mesh-io.c \
+@MESH_TRUE@				mesh/mesh-mgmt.h  mesh/mesh-mgmt.c \
+@MESH_TRUE@				mesh/error.h mesh/mesh-io-api.h \
+@MESH_TRUE@				mesh/mesh-io-unit.h mesh/mesh-io-unit.c \
+@MESH_TRUE@				mesh/mesh-io-mgmt.h mesh/mesh-io-mgmt.c \
+@MESH_TRUE@				mesh/mesh-io-generic.h mesh/mesh-io-generic.c \
+@MESH_TRUE@				mesh/net.h mesh/net.c \
+@MESH_TRUE@				mesh/crypto.h mesh/crypto.c \
+@MESH_TRUE@				mesh/friend.h mesh/friend.c \
+@MESH_TRUE@				mesh/appkey.h mesh/appkey.c \
+@MESH_TRUE@				mesh/node.h mesh/node.c \
+@MESH_TRUE@				mesh/provision.h mesh/prov.h \
+@MESH_TRUE@				mesh/model.h mesh/model.c \
+@MESH_TRUE@				mesh/cfgmod.h mesh/cfgmod-server.c \
+@MESH_TRUE@				mesh/remprv.h mesh/remprv-server.c \
+@MESH_TRUE@				mesh/mesh-config.h mesh/mesh-config-json.c \
+@MESH_TRUE@				mesh/util.h mesh/util.c \
+@MESH_TRUE@				mesh/dbus.h mesh/dbus.c \
+@MESH_TRUE@				mesh/agent.h mesh/agent.c \
+@MESH_TRUE@				mesh/prov-acceptor.c mesh/prov-initiator.c \
+@MESH_TRUE@				mesh/manager.h mesh/manager.c \
+@MESH_TRUE@				mesh/pb-adv.h mesh/pb-adv.c \
+@MESH_TRUE@				mesh/keyring.h mesh/keyring.c \
+@MESH_TRUE@				mesh/rpl.h mesh/rpl.c \
+@MESH_TRUE@				mesh/prv-beacon.h mesh/prvbeac-server.c \
+@MESH_TRUE@				mesh/mesh-defs.h
+
+@MESH_TRUE@mesh_bluetooth_meshd_SOURCES = $(mesh_sources) mesh/main.c
+@MESH_TRUE@mesh_bluetooth_meshd_LDADD = src/libshared-ell.la $(ell_ldadd) -ljson-c
+@HID2HCI_TRUE@rulesdir = $(UDEV_DIR)/rules.d
+@HID2HCI_TRUE@rules_DATA = tools/97-hid2hci.rules
+@TEST_TRUE@testdir = $(pkglibdir)/test
+@TEST_TRUE@test_SCRIPTS = $(test_scripts)
+unit_test_tester_SOURCES = unit/test-tester.c
+unit_test_tester_LDADD = src/libshared-glib.la lib/libbluetooth-internal.la \
+								$(GLIB_LIBS)
+
+unit_test_eir_SOURCES = unit/test-eir.c src/eir.c src/uuid-helper.c
+unit_test_eir_LDADD = src/libshared-glib.la lib/libbluetooth-internal.la \
+								$(GLIB_LIBS)
+
+unit_test_uuid_SOURCES = unit/test-uuid.c
+unit_test_uuid_LDADD = src/libshared-glib.la lib/libbluetooth-internal.la \
+								$(GLIB_LIBS)
+
+unit_test_textfile_SOURCES = unit/test-textfile.c src/textfile.h src/textfile.c
+unit_test_textfile_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_crc_SOURCES = unit/test-crc.c monitor/crc.h monitor/crc.c
+unit_test_crc_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_crypto_SOURCES = unit/test-crypto.c
+unit_test_crypto_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_ecc_SOURCES = unit/test-ecc.c
+unit_test_ecc_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_ringbuf_SOURCES = unit/test-ringbuf.c
+unit_test_ringbuf_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_queue_SOURCES = unit/test-queue.c
+unit_test_queue_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_mgmt_SOURCES = unit/test-mgmt.c
+unit_test_mgmt_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_uhid_SOURCES = unit/test-uhid.c
+unit_test_uhid_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_sdp_SOURCES = unit/test-sdp.c \
+				src/sdpd.h src/sdpd-database.c \
+				src/log.h src/log.c \
+				src/sdpd-service.c src/sdpd-request.c
+
+unit_test_sdp_LDADD = lib/libbluetooth-internal.la \
+				src/libshared-glib.la $(GLIB_LIBS)
+
+unit_test_avdtp_SOURCES = unit/test-avdtp.c \
+				src/log.h src/log.c \
+				android/avdtp.c android/avdtp.h
+
+unit_test_avdtp_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_avctp_SOURCES = unit/test-avctp.c \
+				src/log.h src/log.c \
+				android/avctp.c android/avctp.h
+
+unit_test_avctp_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_avrcp_SOURCES = unit/test-avrcp.c \
+				src/log.h src/log.c \
+				android/avctp.c android/avctp.h \
+				android/avrcp-lib.c android/avrcp-lib.h
+
+unit_test_avrcp_LDADD = lib/libbluetooth-internal.la \
+				src/libshared-glib.la $(GLIB_LIBS)
+
+unit_test_hfp_SOURCES = unit/test-hfp.c
+unit_test_hfp_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_gdbus_client_SOURCES = unit/test-gdbus-client.c
+unit_test_gdbus_client_LDADD = gdbus/libgdbus-internal.la \
+				src/libshared-glib.la $(GLIB_LIBS) $(DBUS_LIBS)
+
+@OBEX_TRUE@unit_test_gobex_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
+@OBEX_TRUE@						unit/test-gobex.c
+
+@OBEX_TRUE@unit_test_gobex_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@OBEX_TRUE@unit_test_gobex_packet_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
+@OBEX_TRUE@						unit/test-gobex-packet.c
+
+@OBEX_TRUE@unit_test_gobex_packet_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@OBEX_TRUE@unit_test_gobex_header_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
+@OBEX_TRUE@						unit/test-gobex-header.c
+
+@OBEX_TRUE@unit_test_gobex_header_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@OBEX_TRUE@unit_test_gobex_transfer_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
+@OBEX_TRUE@						unit/test-gobex-transfer.c
+
+@OBEX_TRUE@unit_test_gobex_transfer_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+@OBEX_TRUE@unit_test_gobex_apparam_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
+@OBEX_TRUE@						unit/test-gobex-apparam.c
+
+@OBEX_TRUE@unit_test_gobex_apparam_LDADD = src/libshared-glib.la $(GLIB_LIBS)
+unit_test_lib_SOURCES = unit/test-lib.c
+unit_test_lib_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_gatt_SOURCES = unit/test-gatt.c
+unit_test_gatt_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_hog_SOURCES = unit/test-hog.c \
+			$(btio_sources) \
+			profiles/input/hog-lib.h profiles/input/hog-lib.c \
+			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
+			profiles/battery/bas.h profiles/battery/bas.c \
+			profiles/deviceinfo/dis.h profiles/deviceinfo/dis.c \
+			src/log.h src/log.c \
+			attrib/att.h attrib/att.c \
+			attrib/gatt.h attrib/gatt.c \
+			attrib/gattrib.h attrib/gattrib.c
+
+unit_test_hog_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_gattrib_SOURCES = unit/test-gattrib.c attrib/gattrib.c \
+					$(btio_sources) src/log.h src/log.c
+
+unit_test_gattrib_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la \
+				$(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt
+
+unit_test_bap_SOURCES = unit/test-bap.c
+unit_test_bap_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_micp_SOURCES = unit/test-micp.c
+unit_test_micp_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_bass_SOURCES = unit/test-bass.c $(btio_sources)
+unit_test_bass_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+unit_test_vcp_SOURCES = unit/test-vcp.c $(btio_sources)
+unit_test_vcp_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
+@MIDI_TRUE@unit_test_midi_CPPFLAGS = $(AM_CPPFLAGS) $(ALSA_CFLAGS) -DMIDI_TEST
+@MIDI_TRUE@unit_test_midi_SOURCES = unit/test-midi.c \
+@MIDI_TRUE@			profiles/midi/libmidi.h \
+@MIDI_TRUE@			profiles/midi/libmidi.c
+
+@MIDI_TRUE@unit_test_midi_LDADD = src/libshared-glib.la \
+@MIDI_TRUE@			$(GLIB_LIBS) $(ALSA_LIBS)
+
+@MESH_TRUE@unit_test_mesh_crypto_CPPFLAGS = $(ell_cflags)
+@MESH_TRUE@unit_test_mesh_crypto_SOURCES = unit/test-mesh-crypto.c \
+@MESH_TRUE@				mesh/crypto.h ell/internal ell/ell.h
+
+@MESH_TRUE@unit_test_mesh_crypto_LDADD = $(ell_ldadd)
+AM_TESTS_ENVIRONMENT = MALLOC_CHECK_=3 MALLOC_PERTURB_=69 \
+	$(am__append_88)
+@VALGRIND_TRUE@LOG_COMPILER = valgrind --error-exitcode=1 --num-callers=30
+@VALGRIND_TRUE@LOG_FLAGS = --trace-children=yes --leak-check=full --show-reachable=no \
+@VALGRIND_TRUE@		--suppressions=$(srcdir)/tools/valgrind.supp --quiet
+
+pkgconfigdir = $(libdir)/pkgconfig
+@LIBRARY_TRUE@pkgconfig_DATA = lib/bluez.pc
+DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles --enable-library \
+						--enable-health \
+						--enable-midi \
+						--enable-manpages \
+						--enable-android \
+						--enable-mesh \
+						--enable-btpclient \
+						--disable-systemd \
+						--disable-udev
+
+DISTCLEANFILES = $(pkgconfig_DATA) $(unit_tests) $(manual_pages)
+MAINTAINERCLEANFILES = Makefile.in \
+	aclocal.m4 configure config.h.in config.sub config.guess \
+	ltmain.sh depcomp compile missing install-sh mkinstalldirs test-driver
+
+@RUN_RST2MAN_FALSE@RST2MAN_PROCESS = $(AM_V_GEN)test -f $@ || \
+@RUN_RST2MAN_FALSE@		{ echo "Generated manual page $@ does not exist"; false; }
+
+@RUN_RST2MAN_TRUE@RST2MAN_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
+@RUN_RST2MAN_TRUE@			$(RST2MAN) --strict --no-raw \
+@RUN_RST2MAN_TRUE@			--no-generator --no-datestamp $< $@
+
+all: $(BUILT_SOURCES) config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+am--refresh: Makefile
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd $(srcdir)/android/Makefile.am $(srcdir)/Makefile.mesh $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+	esac;
+$(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd $(srcdir)/android/Makefile.am $(srcdir)/Makefile.mesh $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@test -f $@ || rm -f stamp-h1
+	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+lib/bluez.pc: $(top_builddir)/config.status $(top_srcdir)/lib/bluez.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+mesh/bluetooth-meshd.rst: $(top_builddir)/config.status $(top_srcdir)/mesh/bluetooth-meshd.rst.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+mesh/bluetooth-mesh.service: $(top_builddir)/config.status $(top_srcdir)/mesh/bluetooth-mesh.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+obexd/src/obex.service: $(top_builddir)/config.status $(top_srcdir)/obexd/src/obex.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+obexd/src/org.bluez.obex.service: $(top_builddir)/config.status $(top_srcdir)/obexd/src/org.bluez.obex.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+src/bluetoothd.rst: $(top_builddir)/config.status $(top_srcdir)/src/bluetoothd.rst.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+src/bluetooth.service: $(top_builddir)/config.status $(top_srcdir)/src/bluetooth.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+tools/bluetooth-logger.service: $(top_builddir)/config.status $(top_srcdir)/tools/bluetooth-logger.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+tools/mpris-proxy.service: $(top_builddir)/config.status $(top_srcdir)/tools/mpris-proxy.service.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-cupsPROGRAMS: $(cups_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(cups_PROGRAMS)'; test -n "$(cupsdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(cupsdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(cupsdir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cupsdir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cupsdir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-cupsPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(cups_PROGRAMS)'; test -n "$(cupsdir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(cupsdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(cupsdir)" && rm -f $$files
+
+clean-cupsPROGRAMS:
+	@list='$(cups_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-pkglibexecPROGRAMS: $(pkglibexec_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-pkglibexecPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(pkglibexecdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(pkglibexecdir)" && rm -f $$files
+
+clean-pkglibexecPROGRAMS:
+	@list='$(pkglibexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-udevPROGRAMS: $(udev_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(udev_PROGRAMS)'; test -n "$(udevdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(udevdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(udevdir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(udevdir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(udevdir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-udevPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(udev_PROGRAMS)'; test -n "$(udevdir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(udevdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(udevdir)" && rm -f $$files
+
+clean-udevPROGRAMS:
+	@list='$(udev_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+	}
+
+uninstall-pluginLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+	done
+
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+android/$(am__dirstamp):
+	@$(MKDIR_P) android
+	@: > android/$(am__dirstamp)
+android/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) android/$(DEPDIR)
+	@: > android/$(DEPDIR)/$(am__dirstamp)
+android/audio_a2dp_default_la-hal-audio.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/audio_a2dp_default_la-hal-audio-sbc.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/audio_a2dp_default_la-hal-audio-aptx.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+
+android/audio.a2dp.default.la: $(android_audio_a2dp_default_la_OBJECTS) $(android_audio_a2dp_default_la_DEPENDENCIES) $(EXTRA_android_audio_a2dp_default_la_DEPENDENCIES) android/$(am__dirstamp)
+	$(AM_V_CCLD)$(android_audio_a2dp_default_la_LINK) $(am_android_audio_a2dp_default_la_rpath) $(android_audio_a2dp_default_la_OBJECTS) $(android_audio_a2dp_default_la_LIBADD) $(LIBS)
+android/audio_sco_default_la-hal-sco.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/audio_utils/$(am__dirstamp):
+	@$(MKDIR_P) android/audio_utils
+	@: > android/audio_utils/$(am__dirstamp)
+android/audio_utils/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) android/audio_utils/$(DEPDIR)
+	@: > android/audio_utils/$(DEPDIR)/$(am__dirstamp)
+android/audio_utils/audio_sco_default_la-resampler.lo:  \
+	android/audio_utils/$(am__dirstamp) \
+	android/audio_utils/$(DEPDIR)/$(am__dirstamp)
+
+android/audio.sco.default.la: $(android_audio_sco_default_la_OBJECTS) $(android_audio_sco_default_la_DEPENDENCIES) $(EXTRA_android_audio_sco_default_la_DEPENDENCIES) android/$(am__dirstamp)
+	$(AM_V_CCLD)$(android_audio_sco_default_la_LINK) $(am_android_audio_sco_default_la_rpath) $(android_audio_sco_default_la_OBJECTS) $(android_audio_sco_default_la_LIBADD) $(LIBS)
+android/bluetooth_default_la-hal-bluetooth.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-socket.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-hidhost.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-health.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-pan.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-a2dp.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-a2dp-sink.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-avrcp.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-avrcp-ctrl.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-handsfree.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-handsfree-client.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-gatt.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-map-client.lo:  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-ipc.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth_default_la-hal-utils.lo: android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/bluetooth.default.la: $(android_bluetooth_default_la_OBJECTS) $(android_bluetooth_default_la_DEPENDENCIES) $(EXTRA_android_bluetooth_default_la_DEPENDENCIES) android/$(am__dirstamp)
+	$(AM_V_CCLD)$(android_bluetooth_default_la_LINK) $(am_android_bluetooth_default_la_rpath) $(android_bluetooth_default_la_OBJECTS) $(android_bluetooth_default_la_LIBADD) $(LIBS)
+ell/$(am__dirstamp):
+	@$(MKDIR_P) ell
+	@: > ell/$(am__dirstamp)
+ell/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) ell/$(DEPDIR)
+	@: > ell/$(DEPDIR)/$(am__dirstamp)
+ell/util.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/log.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/queue.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/hashmap.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/random.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/signal.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/time.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/timeout.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/io.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/idle.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/main.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/settings.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/strv.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/string.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/cipher.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/checksum.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/pem.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/cert.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/cert-crypto.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/key.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/base64.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/utf8.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-message.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-util.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-service.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-client.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-name-cache.lo: ell/$(am__dirstamp) \
+	ell/$(DEPDIR)/$(am__dirstamp)
+ell/dbus-filter.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/gvariant-util.lo: ell/$(am__dirstamp) \
+	ell/$(DEPDIR)/$(am__dirstamp)
+ell/siphash.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/uuid.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/tester.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/tls.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/tls-extensions.lo: ell/$(am__dirstamp) \
+	ell/$(DEPDIR)/$(am__dirstamp)
+ell/tls-suites.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/tls-record.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/ecc.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/ecc-external.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+ell/ecdh.lo: ell/$(am__dirstamp) ell/$(DEPDIR)/$(am__dirstamp)
+
+ell/libell-internal.la: $(ell_libell_internal_la_OBJECTS) $(ell_libell_internal_la_DEPENDENCIES) $(EXTRA_ell_libell_internal_la_DEPENDENCIES) ell/$(am__dirstamp)
+	$(AM_V_CCLD)$(LINK) $(am_ell_libell_internal_la_rpath) $(ell_libell_internal_la_OBJECTS) $(ell_libell_internal_la_LIBADD) $(LIBS)
+gdbus/$(am__dirstamp):
+	@$(MKDIR_P) gdbus
+	@: > gdbus/$(am__dirstamp)
+gdbus/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) gdbus/$(DEPDIR)
+	@: > gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/mainloop.lo: gdbus/$(am__dirstamp) \
+	gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/watch.lo: gdbus/$(am__dirstamp) gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/object.lo: gdbus/$(am__dirstamp) gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/client.lo: gdbus/$(am__dirstamp) gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/polkit.lo: gdbus/$(am__dirstamp) gdbus/$(DEPDIR)/$(am__dirstamp)
+
+gdbus/libgdbus-internal.la: $(gdbus_libgdbus_internal_la_OBJECTS) $(gdbus_libgdbus_internal_la_DEPENDENCIES) $(EXTRA_gdbus_libgdbus_internal_la_DEPENDENCIES) gdbus/$(am__dirstamp)
+	$(AM_V_CCLD)$(LINK)  $(gdbus_libgdbus_internal_la_OBJECTS) $(gdbus_libgdbus_internal_la_LIBADD) $(LIBS)
+lib/$(am__dirstamp):
+	@$(MKDIR_P) lib
+	@: > lib/$(am__dirstamp)
+lib/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) lib/$(DEPDIR)
+	@: > lib/$(DEPDIR)/$(am__dirstamp)
+lib/bluetooth.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp)
+lib/hci.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp)
+lib/sdp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp)
+lib/uuid.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/libbluetooth-internal.la: $(lib_libbluetooth_internal_la_OBJECTS) $(lib_libbluetooth_internal_la_DEPENDENCIES) $(EXTRA_lib_libbluetooth_internal_la_DEPENDENCIES) lib/$(am__dirstamp)
+	$(AM_V_CCLD)$(LINK)  $(lib_libbluetooth_internal_la_OBJECTS) $(lib_libbluetooth_internal_la_LIBADD) $(LIBS)
+
+lib/libbluetooth.la: $(lib_libbluetooth_la_OBJECTS) $(lib_libbluetooth_la_DEPENDENCIES) $(EXTRA_lib_libbluetooth_la_DEPENDENCIES) lib/$(am__dirstamp)
+	$(AM_V_CCLD)$(lib_libbluetooth_la_LINK) $(am_lib_libbluetooth_la_rpath) $(lib_libbluetooth_la_OBJECTS) $(lib_libbluetooth_la_LIBADD) $(LIBS)
+src/shared/$(am__dirstamp):
+	@$(MKDIR_P) src/shared
+	@: > src/shared/$(am__dirstamp)
+src/shared/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/shared/$(DEPDIR)
+	@: > src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-queue.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-util.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-mgmt.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-crypto.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-ecc.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-ringbuf.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-hci.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-hci-crypto.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-hfp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-uhid.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-pcap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-btsnoop.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-ad.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-att.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-gatt-helpers.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-gatt-client.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-gatt-server.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-gatt-db.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-gap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-log.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-bap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-bap-debug.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-mcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-vcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-micp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-csip.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-bass.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-ccp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-asha.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-shell.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-io-ell.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-timeout-ell.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_ell_la-mainloop-ell.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/$(am__dirstamp):
+	@$(MKDIR_P) src
+	@: > src/$(am__dirstamp)
+
+src/libshared-ell.la: $(src_libshared_ell_la_OBJECTS) $(src_libshared_ell_la_DEPENDENCIES) $(EXTRA_src_libshared_ell_la_DEPENDENCIES) src/$(am__dirstamp)
+	$(AM_V_CCLD)$(src_libshared_ell_la_LINK) $(am_src_libshared_ell_la_rpath) $(src_libshared_ell_la_OBJECTS) $(src_libshared_ell_la_LIBADD) $(LIBS)
+src/shared/libshared_glib_la-queue.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-util.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-mgmt.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-crypto.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-ecc.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-ringbuf.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-hci.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-hci-crypto.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-hfp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-uhid.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-pcap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-btsnoop.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-ad.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-att.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-gatt-helpers.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-gatt-client.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-gatt-server.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-gatt-db.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-gap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-log.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-bap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-bap-debug.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-mcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-vcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-micp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-csip.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-bass.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-ccp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-asha.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-shell.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-io-glib.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-timeout-glib.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-mainloop-glib.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-mainloop-notify.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_glib_la-tester.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+
+src/libshared-glib.la: $(src_libshared_glib_la_OBJECTS) $(src_libshared_glib_la_DEPENDENCIES) $(EXTRA_src_libshared_glib_la_DEPENDENCIES) src/$(am__dirstamp)
+	$(AM_V_CCLD)$(src_libshared_glib_la_LINK)  $(src_libshared_glib_la_OBJECTS) $(src_libshared_glib_la_LIBADD) $(LIBS)
+src/shared/libshared_mainloop_la-queue.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-util.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-mgmt.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-crypto.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-ecc.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-ringbuf.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-hci.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-hci-crypto.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-hfp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-uhid.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-pcap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-btsnoop.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-ad.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-att.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-gatt-helpers.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-gatt-client.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-gatt-server.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-gatt-db.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-gap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-log.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-bap.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-bap-debug.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-mcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-vcp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-micp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-csip.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-bass.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-ccp.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-asha.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-shell.lo: src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-io-mainloop.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-timeout-mainloop.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-mainloop.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/libshared_mainloop_la-mainloop-notify.lo:  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+
+src/libshared-mainloop.la: $(src_libshared_mainloop_la_OBJECTS) $(src_libshared_mainloop_la_DEPENDENCIES) $(EXTRA_src_libshared_mainloop_la_DEPENDENCIES) src/$(am__dirstamp)
+	$(AM_V_CCLD)$(src_libshared_mainloop_la_LINK)  $(src_libshared_mainloop_la_OBJECTS) $(src_libshared_mainloop_la_LIBADD) $(LIBS)
+emulator/$(am__dirstamp):
+	@$(MKDIR_P) emulator
+	@: > emulator/$(am__dirstamp)
+emulator/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) emulator/$(DEPDIR)
+	@: > emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_android_tester-hciemu.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_android_tester-vhci.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_android_tester-btdev.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_android_tester-bthost.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_android_tester-smp.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+android/hardware/$(am__dirstamp):
+	@$(MKDIR_P) android/hardware
+	@: > android/hardware/$(am__dirstamp)
+android/hardware/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) android/hardware/$(DEPDIR)
+	@: > android/hardware/$(DEPDIR)/$(am__dirstamp)
+android/hardware/android_tester-hardware.$(OBJEXT):  \
+	android/hardware/$(am__dirstamp) \
+	android/hardware/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-bluetooth.$(OBJEXT):  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-socket.$(OBJEXT):  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-hidhost.$(OBJEXT):  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-pan.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-hdp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-a2dp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-avrcp.$(OBJEXT):  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-gatt.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-map-client.$(OBJEXT):  \
+	android/$(am__dirstamp) android/$(DEPDIR)/$(am__dirstamp)
+android/android_tester-tester-main.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/android-tester$(EXEEXT): $(android_android_tester_OBJECTS) $(android_android_tester_DEPENDENCIES) $(EXTRA_android_android_tester_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/android-tester$(EXEEXT)
+	$(AM_V_CCLD)$(android_android_tester_LINK) $(android_android_tester_OBJECTS) $(android_android_tester_LDADD) $(LIBS)
+android/avdtptest-avdtptest.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/$(DEPDIR)
+	@: > src/$(DEPDIR)/$(am__dirstamp)
+src/android_avdtptest-log.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+btio/$(am__dirstamp):
+	@$(MKDIR_P) btio
+	@: > btio/$(am__dirstamp)
+btio/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) btio/$(DEPDIR)
+	@: > btio/$(DEPDIR)/$(am__dirstamp)
+btio/android_avdtptest-btio.$(OBJEXT): btio/$(am__dirstamp) \
+	btio/$(DEPDIR)/$(am__dirstamp)
+src/shared/android_avdtptest-util.$(OBJEXT):  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/android_avdtptest-queue.$(OBJEXT):  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+src/shared/android_avdtptest-log.$(OBJEXT):  \
+	src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+android/avdtptest-avdtp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/avdtptest$(EXEEXT): $(android_avdtptest_OBJECTS) $(android_avdtptest_DEPENDENCIES) $(EXTRA_android_avdtptest_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/avdtptest$(EXEEXT)
+	$(AM_V_CCLD)$(android_avdtptest_LINK) $(android_avdtptest_OBJECTS) $(android_avdtptest_LDADD) $(LIBS)
+android/main.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/sdpd-database.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/sdpd-server.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/sdpd-service.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/sdpd-request.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/uuid-helper.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/eir.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+android/bluetooth.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/hidhost.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+profiles/scanparam/$(am__dirstamp):
+	@$(MKDIR_P) profiles/scanparam
+	@: > profiles/scanparam/$(am__dirstamp)
+profiles/scanparam/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/scanparam/$(DEPDIR)
+	@: > profiles/scanparam/$(DEPDIR)/$(am__dirstamp)
+profiles/scanparam/scpp.$(OBJEXT): profiles/scanparam/$(am__dirstamp) \
+	profiles/scanparam/$(DEPDIR)/$(am__dirstamp)
+profiles/deviceinfo/$(am__dirstamp):
+	@$(MKDIR_P) profiles/deviceinfo
+	@: > profiles/deviceinfo/$(am__dirstamp)
+profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/deviceinfo/$(DEPDIR)
+	@: > profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp)
+profiles/deviceinfo/dis.$(OBJEXT):  \
+	profiles/deviceinfo/$(am__dirstamp) \
+	profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp)
+profiles/battery/$(am__dirstamp):
+	@$(MKDIR_P) profiles/battery
+	@: > profiles/battery/$(am__dirstamp)
+profiles/battery/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/battery/$(DEPDIR)
+	@: > profiles/battery/$(DEPDIR)/$(am__dirstamp)
+profiles/battery/bas.$(OBJEXT): profiles/battery/$(am__dirstamp) \
+	profiles/battery/$(DEPDIR)/$(am__dirstamp)
+profiles/input/$(am__dirstamp):
+	@$(MKDIR_P) profiles/input
+	@: > profiles/input/$(am__dirstamp)
+profiles/input/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/input/$(DEPDIR)
+	@: > profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/input/hog-lib.$(OBJEXT): profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+android/ipc.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/avdtp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/a2dp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/a2dp-sink.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/avctp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/avrcp.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/avrcp-lib.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/socket.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/sco.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/pan.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/handsfree.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/handsfree-client.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/gatt.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/health.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+profiles/health/$(am__dirstamp):
+	@$(MKDIR_P) profiles/health
+	@: > profiles/health/$(am__dirstamp)
+profiles/health/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/health/$(DEPDIR)
+	@: > profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/health/mcap.$(OBJEXT): profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+android/map-client.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+attrib/$(am__dirstamp):
+	@$(MKDIR_P) attrib
+	@: > attrib/$(am__dirstamp)
+attrib/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) attrib/$(DEPDIR)
+	@: > attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/att.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/gatt.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/gattrib.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+btio/btio.$(OBJEXT): btio/$(am__dirstamp) \
+	btio/$(DEPDIR)/$(am__dirstamp)
+src/sdp-client.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+profiles/network/$(am__dirstamp):
+	@$(MKDIR_P) profiles/network
+	@: > profiles/network/$(am__dirstamp)
+profiles/network/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/network/$(DEPDIR)
+	@: > profiles/network/$(DEPDIR)/$(am__dirstamp)
+profiles/network/bnep.$(OBJEXT): profiles/network/$(am__dirstamp) \
+	profiles/network/$(DEPDIR)/$(am__dirstamp)
+
+android/bluetoothd$(EXEEXT): $(android_bluetoothd_OBJECTS) $(android_bluetoothd_DEPENDENCIES) $(EXTRA_android_bluetoothd_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/bluetoothd$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(android_bluetoothd_OBJECTS) $(android_bluetoothd_LDADD) $(LIBS)
+android/bluetoothd-snoop.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/bluetoothd-snoop$(EXEEXT): $(android_bluetoothd_snoop_OBJECTS) $(android_bluetoothd_snoop_DEPENDENCIES) $(EXTRA_android_bluetoothd_snoop_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/bluetoothd-snoop$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(android_bluetoothd_snoop_OBJECTS) $(android_bluetoothd_snoop_LDADD) $(LIBS)
+android/client/$(am__dirstamp):
+	@$(MKDIR_P) android/client
+	@: > android/client/$(am__dirstamp)
+android/client/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) android/client/$(DEPDIR)
+	@: > android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-haltest.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-pollhandler.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-terminal.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-history.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-tabcompletion.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-av.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-av-sink.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-rc.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-rc-ctrl.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-bt.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-gatt.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-hf.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-hf-client.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-hh.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-pan.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-hl.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-sock.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-audio.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-sco.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/client/haltest-if-mce.$(OBJEXT):  \
+	android/client/$(am__dirstamp) \
+	android/client/$(DEPDIR)/$(am__dirstamp)
+android/hardware/haltest-hardware.$(OBJEXT):  \
+	android/hardware/$(am__dirstamp) \
+	android/hardware/$(DEPDIR)/$(am__dirstamp)
+android/haltest-hal-utils.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/haltest$(EXEEXT): $(android_haltest_OBJECTS) $(android_haltest_DEPENDENCIES) $(EXTRA_android_haltest_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/haltest$(EXEEXT)
+	$(AM_V_CCLD)$(android_haltest_LINK) $(android_haltest_OBJECTS) $(android_haltest_LDADD) $(LIBS)
+emulator/android_ipc_tester-hciemu.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_ipc_tester-vhci.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_ipc_tester-btdev.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_ipc_tester-bthost.$(OBJEXT):  \
+	emulator/$(am__dirstamp) emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/android_ipc_tester-smp.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+android/ipc_tester-hal-utils.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+android/ipc_tester-ipc-tester.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/ipc-tester$(EXEEXT): $(android_ipc_tester_OBJECTS) $(android_ipc_tester_DEPENDENCIES) $(EXTRA_android_ipc_tester_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/ipc-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(android_ipc_tester_OBJECTS) $(android_ipc_tester_LDADD) $(LIBS)
+android/system-emulator.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/system-emulator$(EXEEXT): $(android_system_emulator_OBJECTS) $(android_system_emulator_DEPENDENCIES) $(EXTRA_android_system_emulator_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/system-emulator$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(android_system_emulator_OBJECTS) $(android_system_emulator_LDADD) $(LIBS)
+android/test-ipc.$(OBJEXT): android/$(am__dirstamp) \
+	android/$(DEPDIR)/$(am__dirstamp)
+
+android/test-ipc$(EXEEXT): $(android_test_ipc_OBJECTS) $(android_test_ipc_DEPENDENCIES) $(EXTRA_android_test_ipc_DEPENDENCIES) android/$(am__dirstamp)
+	@rm -f android/test-ipc$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(android_test_ipc_OBJECTS) $(android_test_ipc_LDADD) $(LIBS)
+attrib/gatttool.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/interactive.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/utils.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+client/$(am__dirstamp):
+	@$(MKDIR_P) client
+	@: > client/$(am__dirstamp)
+client/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) client/$(DEPDIR)
+	@: > client/$(DEPDIR)/$(am__dirstamp)
+client/display.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+
+attrib/gatttool$(EXEEXT): $(attrib_gatttool_OBJECTS) $(attrib_gatttool_DEPENDENCIES) $(EXTRA_attrib_gatttool_DEPENDENCIES) attrib/$(am__dirstamp)
+	@rm -f attrib/gatttool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(attrib_gatttool_OBJECTS) $(attrib_gatttool_LDADD) $(LIBS)
+client/main.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/print.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/agent.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/advertising.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/adv_monitor.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/gatt.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/admin.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/player.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/mgmt.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+client/assistant.$(OBJEXT): client/$(am__dirstamp) \
+	client/$(DEPDIR)/$(am__dirstamp)
+
+client/bluetoothctl$(EXEEXT): $(client_bluetoothctl_OBJECTS) $(client_bluetoothctl_DEPENDENCIES) $(EXTRA_client_bluetoothctl_DEPENDENCIES) client/$(am__dirstamp)
+	@rm -f client/bluetoothctl$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(client_bluetoothctl_OBJECTS) $(client_bluetoothctl_LDADD) $(LIBS)
+emulator/b1ee.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+
+emulator/b1ee$(EXEEXT): $(emulator_b1ee_OBJECTS) $(emulator_b1ee_DEPENDENCIES) $(EXTRA_emulator_b1ee_DEPENDENCIES) emulator/$(am__dirstamp)
+	@rm -f emulator/b1ee$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(emulator_b1ee_OBJECTS) $(emulator_b1ee_LDADD) $(LIBS)
+emulator/main.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/serial.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/server.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/vhci.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/btdev.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/bthost.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/smp.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/phy.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/amp.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/le.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+
+emulator/btvirt$(EXEEXT): $(emulator_btvirt_OBJECTS) $(emulator_btvirt_DEPENDENCIES) $(EXTRA_emulator_btvirt_DEPENDENCIES) emulator/$(am__dirstamp)
+	@rm -f emulator/btvirt$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(emulator_btvirt_OBJECTS) $(emulator_btvirt_LDADD) $(LIBS)
+emulator/hfp.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+
+emulator/hfp$(EXEEXT): $(emulator_hfp_OBJECTS) $(emulator_hfp_DEPENDENCIES) $(EXTRA_emulator_hfp_DEPENDENCIES) emulator/$(am__dirstamp)
+	@rm -f emulator/hfp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(emulator_hfp_OBJECTS) $(emulator_hfp_LDADD) $(LIBS)
+mesh/$(am__dirstamp):
+	@$(MKDIR_P) mesh
+	@: > mesh/$(am__dirstamp)
+mesh/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) mesh/$(DEPDIR)
+	@: > mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/net-keys.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-io.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-mgmt.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-io-unit.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-io-mgmt.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-io-generic.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/net.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/crypto.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/friend.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/appkey.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/node.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/model.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/cfgmod-server.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/remprv-server.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/mesh-config-json.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/util.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/dbus.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/agent.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/prov-acceptor.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/prov-initiator.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/manager.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/pb-adv.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/keyring.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/rpl.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/prvbeac-server.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+mesh/main.$(OBJEXT): mesh/$(am__dirstamp) \
+	mesh/$(DEPDIR)/$(am__dirstamp)
+
+mesh/bluetooth-meshd$(EXEEXT): $(mesh_bluetooth_meshd_OBJECTS) $(mesh_bluetooth_meshd_DEPENDENCIES) $(EXTRA_mesh_bluetooth_meshd_DEPENDENCIES) mesh/$(am__dirstamp)
+	@rm -f mesh/bluetooth-meshd$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(mesh_bluetooth_meshd_OBJECTS) $(mesh_bluetooth_meshd_LDADD) $(LIBS)
+monitor/$(am__dirstamp):
+	@$(MKDIR_P) monitor
+	@: > monitor/$(am__dirstamp)
+monitor/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) monitor/$(DEPDIR)
+	@: > monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/main.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/display.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/hcidump.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/ellisys.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/control.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/packet.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/vendor.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/lmp.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/crc.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/ll.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/l2cap.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/sdp.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/avctp.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/avdtp.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/a2dp.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/rfcomm.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/bnep.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/hwdb.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/keys.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/analyze.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/intel.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/broadcom.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/msft.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/jlink.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+monitor/att.$(OBJEXT): monitor/$(am__dirstamp) \
+	monitor/$(DEPDIR)/$(am__dirstamp)
+src/textfile.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/settings.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+
+monitor/btmon$(EXEEXT): $(monitor_btmon_OBJECTS) $(monitor_btmon_DEPENDENCIES) $(EXTRA_monitor_btmon_DEPENDENCIES) monitor/$(am__dirstamp)
+	@rm -f monitor/btmon$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(monitor_btmon_OBJECTS) $(monitor_btmon_LDADD) $(LIBS)
+btio/obexd-btio.$(OBJEXT): btio/$(am__dirstamp) \
+	btio/$(DEPDIR)/$(am__dirstamp)
+gobex/$(am__dirstamp):
+	@$(MKDIR_P) gobex
+	@: > gobex/$(am__dirstamp)
+gobex/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) gobex/$(DEPDIR)
+	@: > gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex-defs.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex-packet.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex-header.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex-transfer.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/obexd-gobex-apparam.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/$(am__dirstamp):
+	@$(MKDIR_P) obexd/plugins
+	@: > obexd/plugins/$(am__dirstamp)
+obexd/plugins/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) obexd/plugins/$(DEPDIR)
+	@: > obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-filesystem.$(OBJEXT):  \
+	obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-bluetooth.$(OBJEXT):  \
+	obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-pcsuite.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-opp.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-ftp.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-irmc.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-pbap.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-vcard.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.$(OBJEXT):  \
+	obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-mas.$(OBJEXT): obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/plugins/obexd-messages-dummy.$(OBJEXT):  \
+	obexd/plugins/$(am__dirstamp) \
+	obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+obexd/client/$(am__dirstamp):
+	@$(MKDIR_P) obexd/client
+	@: > obexd/client/$(am__dirstamp)
+obexd/client/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) obexd/client/$(DEPDIR)
+	@: > obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-mns.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/src/$(am__dirstamp):
+	@$(MKDIR_P) obexd/src
+	@: > obexd/src/$(am__dirstamp)
+obexd/src/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) obexd/src/$(DEPDIR)
+	@: > obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-main.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-plugin.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-log.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-manager.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-obex.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-mimetype.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-service.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-transport.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/src/obexd-server.$(OBJEXT): obexd/src/$(am__dirstamp) \
+	obexd/src/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-manager.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-session.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-bluetooth.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-sync.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-pbap.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-ftp.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-opp.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-map.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-bip.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-bip-common.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-map-event.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-transfer.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-transport.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+obexd/client/obexd-driver.$(OBJEXT): obexd/client/$(am__dirstamp) \
+	obexd/client/$(DEPDIR)/$(am__dirstamp)
+
+obexd/src/obexd$(EXEEXT): $(obexd_src_obexd_OBJECTS) $(obexd_src_obexd_DEPENDENCIES) $(EXTRA_obexd_src_obexd_DEPENDENCIES) obexd/src/$(am__dirstamp)
+	@rm -f obexd/src/obexd$(EXEEXT)
+	$(AM_V_CCLD)$(obexd_src_obexd_LINK) $(obexd_src_obexd_OBJECTS) $(obexd_src_obexd_LDADD) $(LIBS)
+peripheral/$(am__dirstamp):
+	@$(MKDIR_P) peripheral
+	@: > peripheral/$(am__dirstamp)
+peripheral/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) peripheral/$(DEPDIR)
+	@: > peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/main.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/efivars.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/attach.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/log.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/gap.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+peripheral/gatt.$(OBJEXT): peripheral/$(am__dirstamp) \
+	peripheral/$(DEPDIR)/$(am__dirstamp)
+
+peripheral/btsensor$(EXEEXT): $(peripheral_btsensor_OBJECTS) $(peripheral_btsensor_DEPENDENCIES) $(EXTRA_peripheral_btsensor_DEPENDENCIES) peripheral/$(am__dirstamp)
+	@rm -f peripheral/btsensor$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(peripheral_btsensor_OBJECTS) $(peripheral_btsensor_LDADD) $(LIBS)
+profiles/cups/$(am__dirstamp):
+	@$(MKDIR_P) profiles/cups
+	@: > profiles/cups/$(am__dirstamp)
+profiles/cups/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/cups/$(DEPDIR)
+	@: > profiles/cups/$(DEPDIR)/$(am__dirstamp)
+profiles/cups/main.$(OBJEXT): profiles/cups/$(am__dirstamp) \
+	profiles/cups/$(DEPDIR)/$(am__dirstamp)
+profiles/cups/sdp.$(OBJEXT): profiles/cups/$(am__dirstamp) \
+	profiles/cups/$(DEPDIR)/$(am__dirstamp)
+profiles/cups/spp.$(OBJEXT): profiles/cups/$(am__dirstamp) \
+	profiles/cups/$(DEPDIR)/$(am__dirstamp)
+profiles/cups/hcrp.$(OBJEXT): profiles/cups/$(am__dirstamp) \
+	profiles/cups/$(DEPDIR)/$(am__dirstamp)
+
+profiles/cups/bluetooth$(EXEEXT): $(profiles_cups_bluetooth_OBJECTS) $(profiles_cups_bluetooth_DEPENDENCIES) $(EXTRA_profiles_cups_bluetooth_DEPENDENCIES) profiles/cups/$(am__dirstamp)
+	@rm -f profiles/cups/bluetooth$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(profiles_cups_bluetooth_OBJECTS) $(profiles_cups_bluetooth_LDADD) $(LIBS)
+profiles/iap/$(am__dirstamp):
+	@$(MKDIR_P) profiles/iap
+	@: > profiles/iap/$(am__dirstamp)
+profiles/iap/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/iap/$(DEPDIR)
+	@: > profiles/iap/$(DEPDIR)/$(am__dirstamp)
+profiles/iap/main.$(OBJEXT): profiles/iap/$(am__dirstamp) \
+	profiles/iap/$(DEPDIR)/$(am__dirstamp)
+
+profiles/iap/iapd$(EXEEXT): $(profiles_iap_iapd_OBJECTS) $(profiles_iap_iapd_DEPENDENCIES) $(EXTRA_profiles_iap_iapd_DEPENDENCIES) profiles/iap/$(am__dirstamp)
+	@rm -f profiles/iap/iapd$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(profiles_iap_iapd_OBJECTS) $(profiles_iap_iapd_LDADD) $(LIBS)
+plugins/$(am__dirstamp):
+	@$(MKDIR_P) plugins
+	@: > plugins/$(am__dirstamp)
+plugins/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) plugins/$(DEPDIR)
+	@: > plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-hostname.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-wiimote.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-autopair.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-policy.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-admin.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-neard.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+profiles/sap/$(am__dirstamp):
+	@$(MKDIR_P) profiles/sap
+	@: > profiles/sap/$(am__dirstamp)
+profiles/sap/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/sap/$(DEPDIR)
+	@: > profiles/sap/$(DEPDIR)/$(am__dirstamp)
+profiles/sap/bluetoothd-main.$(OBJEXT): profiles/sap/$(am__dirstamp) \
+	profiles/sap/$(DEPDIR)/$(am__dirstamp)
+profiles/sap/bluetoothd-manager.$(OBJEXT):  \
+	profiles/sap/$(am__dirstamp) \
+	profiles/sap/$(DEPDIR)/$(am__dirstamp)
+profiles/sap/bluetoothd-server.$(OBJEXT):  \
+	profiles/sap/$(am__dirstamp) \
+	profiles/sap/$(DEPDIR)/$(am__dirstamp)
+profiles/sap/bluetoothd-sap-dummy.$(OBJEXT):  \
+	profiles/sap/$(am__dirstamp) \
+	profiles/sap/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/$(am__dirstamp):
+	@$(MKDIR_P) profiles/audio
+	@: > profiles/audio/$(am__dirstamp)
+profiles/audio/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/audio/$(DEPDIR)
+	@: > profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-source.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-sink.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-a2dp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-avdtp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-media.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-transport.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-control.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-avctp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-avrcp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-player.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/network/bluetoothd-manager.$(OBJEXT):  \
+	profiles/network/$(am__dirstamp) \
+	profiles/network/$(DEPDIR)/$(am__dirstamp)
+profiles/network/bluetoothd-bnep.$(OBJEXT):  \
+	profiles/network/$(am__dirstamp) \
+	profiles/network/$(DEPDIR)/$(am__dirstamp)
+profiles/network/bluetoothd-server.$(OBJEXT):  \
+	profiles/network/$(am__dirstamp) \
+	profiles/network/$(DEPDIR)/$(am__dirstamp)
+profiles/network/bluetoothd-connection.$(OBJEXT):  \
+	profiles/network/$(am__dirstamp) \
+	profiles/network/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-manager.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-server.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-device.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-hog.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-hog-lib.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/deviceinfo/bluetoothd-dis.$(OBJEXT):  \
+	profiles/deviceinfo/$(am__dirstamp) \
+	profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp)
+profiles/battery/bluetoothd-bas.$(OBJEXT):  \
+	profiles/battery/$(am__dirstamp) \
+	profiles/battery/$(DEPDIR)/$(am__dirstamp)
+profiles/scanparam/bluetoothd-scpp.$(OBJEXT):  \
+	profiles/scanparam/$(am__dirstamp) \
+	profiles/scanparam/$(DEPDIR)/$(am__dirstamp)
+profiles/input/bluetoothd-suspend-none.$(OBJEXT):  \
+	profiles/input/$(am__dirstamp) \
+	profiles/input/$(DEPDIR)/$(am__dirstamp)
+profiles/health/bluetoothd-mcap.$(OBJEXT):  \
+	profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/health/bluetoothd-hdp_main.$(OBJEXT):  \
+	profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/health/bluetoothd-hdp_manager.$(OBJEXT):  \
+	profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/health/bluetoothd-hdp.$(OBJEXT):  \
+	profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/health/bluetoothd-hdp_util.$(OBJEXT):  \
+	profiles/health/$(am__dirstamp) \
+	profiles/health/$(DEPDIR)/$(am__dirstamp)
+profiles/gap/$(am__dirstamp):
+	@$(MKDIR_P) profiles/gap
+	@: > profiles/gap/$(am__dirstamp)
+profiles/gap/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/gap/$(DEPDIR)
+	@: > profiles/gap/$(DEPDIR)/$(am__dirstamp)
+profiles/gap/bluetoothd-gas.$(OBJEXT): profiles/gap/$(am__dirstamp) \
+	profiles/gap/$(DEPDIR)/$(am__dirstamp)
+profiles/scanparam/bluetoothd-scan.$(OBJEXT):  \
+	profiles/scanparam/$(am__dirstamp) \
+	profiles/scanparam/$(DEPDIR)/$(am__dirstamp)
+profiles/deviceinfo/bluetoothd-deviceinfo.$(OBJEXT):  \
+	profiles/deviceinfo/$(am__dirstamp) \
+	profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp)
+profiles/midi/$(am__dirstamp):
+	@$(MKDIR_P) profiles/midi
+	@: > profiles/midi/$(am__dirstamp)
+profiles/midi/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) profiles/midi/$(DEPDIR)
+	@: > profiles/midi/$(DEPDIR)/$(am__dirstamp)
+profiles/midi/bluetoothd-midi.$(OBJEXT):  \
+	profiles/midi/$(am__dirstamp) \
+	profiles/midi/$(DEPDIR)/$(am__dirstamp)
+profiles/midi/bluetoothd-libmidi.$(OBJEXT):  \
+	profiles/midi/$(am__dirstamp) \
+	profiles/midi/$(DEPDIR)/$(am__dirstamp)
+profiles/battery/bluetoothd-battery.$(OBJEXT):  \
+	profiles/battery/$(am__dirstamp) \
+	profiles/battery/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetoothd-sixaxis.$(OBJEXT): plugins/$(am__dirstamp) \
+	plugins/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-bap.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-bass.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-mcp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-vcp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-micp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-ccp.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-csip.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+profiles/audio/bluetoothd-asha.$(OBJEXT):  \
+	profiles/audio/$(am__dirstamp) \
+	profiles/audio/$(DEPDIR)/$(am__dirstamp)
+attrib/bluetoothd-att.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/bluetoothd-gatt.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+attrib/bluetoothd-gattrib.$(OBJEXT): attrib/$(am__dirstamp) \
+	attrib/$(DEPDIR)/$(am__dirstamp)
+btio/bluetoothd-btio.$(OBJEXT): btio/$(am__dirstamp) \
+	btio/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-main.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-log.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-backtrace.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-rfkill.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdpd-server.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdpd-request.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdpd-service.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdpd-database.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-gatt-database.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdp-xml.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-sdp-client.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-textfile.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-uuid-helper.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-plugin.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-storage.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-advertising.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-agent.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-error.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-adapter.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-profile.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-service.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-gatt-client.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-device.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-dbus-common.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-eir.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-adv_monitor.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-battery.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-settings.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+src/bluetoothd-set.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+
+src/bluetoothd$(EXEEXT): $(src_bluetoothd_OBJECTS) $(src_bluetoothd_DEPENDENCIES) $(EXTRA_src_bluetoothd_DEPENDENCIES) src/$(am__dirstamp)
+	@rm -f src/bluetoothd$(EXEEXT)
+	$(AM_V_CCLD)$(src_bluetoothd_LINK) $(src_bluetoothd_OBJECTS) $(src_bluetoothd_LDADD) $(LIBS)
+tools/$(am__dirstamp):
+	@$(MKDIR_P) tools
+	@: > tools/$(am__dirstamp)
+tools/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) tools/$(DEPDIR)
+	@: > tools/$(DEPDIR)/$(am__dirstamp)
+tools/3dsp.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/3dsp$(EXEEXT): $(tools_3dsp_OBJECTS) $(tools_3dsp_DEPENDENCIES) $(EXTRA_tools_3dsp_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/3dsp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_3dsp_OBJECTS) $(tools_3dsp_LDADD) $(LIBS)
+tools/advtest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/advtest$(EXEEXT): $(tools_advtest_OBJECTS) $(tools_advtest_DEPENDENCIES) $(EXTRA_tools_advtest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/advtest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_advtest_OBJECTS) $(tools_advtest_LDADD) $(LIBS)
+tools/amptest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/amptest$(EXEEXT): $(tools_amptest_OBJECTS) $(tools_amptest_DEPENDENCIES) $(EXTRA_tools_amptest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/amptest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_amptest_OBJECTS) $(tools_amptest_LDADD) $(LIBS)
+tools/avinfo.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/avinfo$(EXEEXT): $(tools_avinfo_OBJECTS) $(tools_avinfo_DEPENDENCIES) $(EXTRA_tools_avinfo_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/avinfo$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_avinfo_OBJECTS) $(tools_avinfo_LDADD) $(LIBS)
+tools/avtest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/avtest$(EXEEXT): $(tools_avtest_OBJECTS) $(tools_avtest_DEPENDENCIES) $(EXTRA_tools_avtest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/avtest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_avtest_OBJECTS) $(tools_avtest_LDADD) $(LIBS)
+tools/bcmfw.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/bcmfw$(EXEEXT): $(tools_bcmfw_OBJECTS) $(tools_bcmfw_DEPENDENCIES) $(EXTRA_tools_bcmfw_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bcmfw$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bcmfw_OBJECTS) $(tools_bcmfw_LDADD) $(LIBS)
+tools/bdaddr.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+src/oui.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+
+tools/bdaddr$(EXEEXT): $(tools_bdaddr_OBJECTS) $(tools_bdaddr_DEPENDENCIES) $(EXTRA_tools_bdaddr_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bdaddr$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bdaddr_OBJECTS) $(tools_bdaddr_LDADD) $(LIBS)
+tools/bluemoon.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/bluemoon$(EXEEXT): $(tools_bluemoon_OBJECTS) $(tools_bluemoon_DEPENDENCIES) $(EXTRA_tools_bluemoon_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bluemoon$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bluemoon_OBJECTS) $(tools_bluemoon_LDADD) $(LIBS)
+tools/bluetooth-player.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/bluetooth-player$(EXEEXT): $(tools_bluetooth_player_OBJECTS) $(tools_bluetooth_player_DEPENDENCIES) $(EXTRA_tools_bluetooth_player_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bluetooth-player$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bluetooth_player_OBJECTS) $(tools_bluetooth_player_LDADD) $(LIBS)
+tools/bnep-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+emulator/hciemu.$(OBJEXT): emulator/$(am__dirstamp) \
+	emulator/$(DEPDIR)/$(am__dirstamp)
+
+tools/bnep-tester$(EXEEXT): $(tools_bnep_tester_OBJECTS) $(tools_bnep_tester_DEPENDENCIES) $(EXTRA_tools_bnep_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bnep-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bnep_tester_OBJECTS) $(tools_bnep_tester_LDADD) $(LIBS)
+tools/bneptest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/bneptest$(EXEEXT): $(tools_bneptest_OBJECTS) $(tools_bneptest_DEPENDENCIES) $(EXTRA_tools_bneptest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/bneptest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_bneptest_OBJECTS) $(tools_bneptest_LDADD) $(LIBS)
+tools/btattach.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btattach$(EXEEXT): $(tools_btattach_OBJECTS) $(tools_btattach_DEPENDENCIES) $(EXTRA_tools_btattach_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btattach$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btattach_OBJECTS) $(tools_btattach_LDADD) $(LIBS)
+tools/btconfig.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btconfig$(EXEEXT): $(tools_btconfig_OBJECTS) $(tools_btconfig_DEPENDENCIES) $(EXTRA_tools_btconfig_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btconfig$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btconfig_OBJECTS) $(tools_btconfig_LDADD) $(LIBS)
+tools/btgatt-client.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btgatt-client$(EXEEXT): $(tools_btgatt_client_OBJECTS) $(tools_btgatt_client_DEPENDENCIES) $(EXTRA_tools_btgatt_client_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btgatt-client$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btgatt_client_OBJECTS) $(tools_btgatt_client_LDADD) $(LIBS)
+tools/btgatt-server.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btgatt-server$(EXEEXT): $(tools_btgatt_server_OBJECTS) $(tools_btgatt_server_DEPENDENCIES) $(EXTRA_tools_btgatt_server_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btgatt-server$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btgatt_server_OBJECTS) $(tools_btgatt_server_LDADD) $(LIBS)
+tools/btinfo.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btinfo$(EXEEXT): $(tools_btinfo_OBJECTS) $(tools_btinfo_DEPENDENCIES) $(EXTRA_tools_btinfo_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btinfo$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btinfo_OBJECTS) $(tools_btinfo_LDADD) $(LIBS)
+tools/btiotest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btiotest$(EXEEXT): $(tools_btiotest_OBJECTS) $(tools_btiotest_DEPENDENCIES) $(EXTRA_tools_btiotest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btiotest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btiotest_OBJECTS) $(tools_btiotest_LDADD) $(LIBS)
+tools/btmgmt.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btmgmt$(EXEEXT): $(tools_btmgmt_OBJECTS) $(tools_btmgmt_DEPENDENCIES) $(EXTRA_tools_btmgmt_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btmgmt$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btmgmt_OBJECTS) $(tools_btmgmt_LDADD) $(LIBS)
+tools/btmon-logger.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btmon-logger$(EXEEXT): $(tools_btmon_logger_OBJECTS) $(tools_btmon_logger_DEPENDENCIES) $(EXTRA_tools_btmon_logger_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btmon-logger$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btmon_logger_OBJECTS) $(tools_btmon_logger_LDADD) $(LIBS)
+tools/btpclient.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+src/shared/btp.$(OBJEXT): src/shared/$(am__dirstamp) \
+	src/shared/$(DEPDIR)/$(am__dirstamp)
+
+tools/btpclient$(EXEEXT): $(tools_btpclient_OBJECTS) $(tools_btpclient_DEPENDENCIES) $(EXTRA_tools_btpclient_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btpclient$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btpclient_OBJECTS) $(tools_btpclient_LDADD) $(LIBS)
+tools/btpclientctl.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btpclientctl$(EXEEXT): $(tools_btpclientctl_OBJECTS) $(tools_btpclientctl_DEPENDENCIES) $(EXTRA_tools_btpclientctl_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btpclientctl$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btpclientctl_OBJECTS) $(tools_btpclientctl_LDADD) $(LIBS)
+tools/btproxy.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btproxy$(EXEEXT): $(tools_btproxy_OBJECTS) $(tools_btproxy_DEPENDENCIES) $(EXTRA_tools_btproxy_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btproxy$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btproxy_OBJECTS) $(tools_btproxy_LDADD) $(LIBS)
+tools/btsnoop.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/btsnoop$(EXEEXT): $(tools_btsnoop_OBJECTS) $(tools_btsnoop_DEPENDENCIES) $(EXTRA_tools_btsnoop_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/btsnoop$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_btsnoop_OBJECTS) $(tools_btsnoop_LDADD) $(LIBS)
+tools/check-selftest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/check-selftest$(EXEEXT): $(tools_check_selftest_OBJECTS) $(tools_check_selftest_DEPENDENCIES) $(EXTRA_tools_check_selftest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/check-selftest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_check_selftest_OBJECTS) $(tools_check_selftest_LDADD) $(LIBS)
+tools/ciptool.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/ciptool$(EXEEXT): $(tools_ciptool_OBJECTS) $(tools_ciptool_DEPENDENCIES) $(EXTRA_tools_ciptool_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/ciptool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_ciptool_OBJECTS) $(tools_ciptool_LDADD) $(LIBS)
+tools/cltest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/cltest$(EXEEXT): $(tools_cltest_OBJECTS) $(tools_cltest_DEPENDENCIES) $(EXTRA_tools_cltest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/cltest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_cltest_OBJECTS) $(tools_cltest_LDADD) $(LIBS)
+tools/create-image.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/create-image$(EXEEXT): $(tools_create_image_OBJECTS) $(tools_create_image_DEPENDENCIES) $(EXTRA_tools_create_image_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/create-image$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_create_image_OBJECTS) $(tools_create_image_LDADD) $(LIBS)
+tools/eddystone.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/eddystone$(EXEEXT): $(tools_eddystone_OBJECTS) $(tools_eddystone_DEPENDENCIES) $(EXTRA_tools_eddystone_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/eddystone$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_eddystone_OBJECTS) $(tools_eddystone_LDADD) $(LIBS)
+tools/gap-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/gap-tester$(EXEEXT): $(tools_gap_tester_OBJECTS) $(tools_gap_tester_DEPENDENCIES) $(EXTRA_tools_gap_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/gap-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_gap_tester_OBJECTS) $(tools_gap_tester_LDADD) $(LIBS)
+tools/gatt-service.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/gatt-service$(EXEEXT): $(tools_gatt_service_OBJECTS) $(tools_gatt_service_DEPENDENCIES) $(EXTRA_tools_gatt_service_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/gatt-service$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_gatt_service_OBJECTS) $(tools_gatt_service_LDADD) $(LIBS)
+tools/hci-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hci-tester$(EXEEXT): $(tools_hci_tester_OBJECTS) $(tools_hci_tester_DEPENDENCIES) $(EXTRA_tools_hci_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hci-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hci_tester_OBJECTS) $(tools_hci_tester_LDADD) $(LIBS)
+tools/hciattach.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_st.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_ti.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_tialt.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_ath3k.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_qualcomm.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_intel.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_bcm43xx.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hciattach$(EXEEXT): $(tools_hciattach_OBJECTS) $(tools_hciattach_DEPENDENCIES) $(EXTRA_tools_hciattach_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hciattach$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hciattach_OBJECTS) $(tools_hciattach_LDADD) $(LIBS)
+tools/hciconfig.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hciconfig$(EXEEXT): $(tools_hciconfig_OBJECTS) $(tools_hciconfig_DEPENDENCIES) $(EXTRA_tools_hciconfig_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hciconfig$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hciconfig_OBJECTS) $(tools_hciconfig_LDADD) $(LIBS)
+tools/hcidump.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/parser/$(am__dirstamp):
+	@$(MKDIR_P) tools/parser
+	@: > tools/parser/$(am__dirstamp)
+tools/parser/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) tools/parser/$(DEPDIR)
+	@: > tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/parser.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/lmp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/hci.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/l2cap.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/amp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/smp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/att.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/sdp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/rfcomm.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/bnep.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/cmtp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/hidp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/hcrp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/avdtp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/avctp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/avrcp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/sap.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/obex.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/capi.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/ppp.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/tcpip.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/ericsson.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/csr.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+tools/parser/bpa.$(OBJEXT): tools/parser/$(am__dirstamp) \
+	tools/parser/$(DEPDIR)/$(am__dirstamp)
+
+tools/hcidump$(EXEEXT): $(tools_hcidump_OBJECTS) $(tools_hcidump_DEPENDENCIES) $(EXTRA_tools_hcidump_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hcidump$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hcidump_OBJECTS) $(tools_hcidump_LDADD) $(LIBS)
+tools/hcieventmask.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hcieventmask$(EXEEXT): $(tools_hcieventmask_OBJECTS) $(tools_hcieventmask_DEPENDENCIES) $(EXTRA_tools_hcieventmask_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hcieventmask$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hcieventmask_OBJECTS) $(tools_hcieventmask_LDADD) $(LIBS)
+tools/hcisecfilter.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hcisecfilter$(EXEEXT): $(tools_hcisecfilter_OBJECTS) $(tools_hcisecfilter_DEPENDENCIES) $(EXTRA_tools_hcisecfilter_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hcisecfilter$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hcisecfilter_OBJECTS) $(tools_hcisecfilter_LDADD) $(LIBS)
+tools/hcitool.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hcitool$(EXEEXT): $(tools_hcitool_OBJECTS) $(tools_hcitool_DEPENDENCIES) $(EXTRA_tools_hcitool_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hcitool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hcitool_OBJECTS) $(tools_hcitool_LDADD) $(LIBS)
+tools/hex2hcd.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hex2hcd$(EXEEXT): $(tools_hex2hcd_OBJECTS) $(tools_hex2hcd_DEPENDENCIES) $(EXTRA_tools_hex2hcd_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hex2hcd$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hex2hcd_OBJECTS) $(tools_hex2hcd_LDADD) $(LIBS)
+tools/hid2hci.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hid2hci$(EXEEXT): $(tools_hid2hci_OBJECTS) $(tools_hid2hci_DEPENDENCIES) $(EXTRA_tools_hid2hci_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hid2hci$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hid2hci_OBJECTS) $(tools_hid2hci_LDADD) $(LIBS)
+tools/hwdb.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/hwdb$(EXEEXT): $(tools_hwdb_OBJECTS) $(tools_hwdb_DEPENDENCIES) $(EXTRA_tools_hwdb_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/hwdb$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_hwdb_OBJECTS) $(tools_hwdb_LDADD) $(LIBS)
+tools/ibeacon.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/ibeacon$(EXEEXT): $(tools_ibeacon_OBJECTS) $(tools_ibeacon_DEPENDENCIES) $(EXTRA_tools_ibeacon_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/ibeacon$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_ibeacon_OBJECTS) $(tools_ibeacon_LDADD) $(LIBS)
+tools/ioctl-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/ioctl-tester$(EXEEXT): $(tools_ioctl_tester_OBJECTS) $(tools_ioctl_tester_DEPENDENCIES) $(EXTRA_tools_ioctl_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/ioctl-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_ioctl_tester_OBJECTS) $(tools_ioctl_tester_LDADD) $(LIBS)
+tools/iso-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/iso-tester$(EXEEXT): $(tools_iso_tester_OBJECTS) $(tools_iso_tester_DEPENDENCIES) $(EXTRA_tools_iso_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/iso-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_iso_tester_OBJECTS) $(tools_iso_tester_LDADD) $(LIBS)
+tools/isotest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/isotest$(EXEEXT): $(tools_isotest_OBJECTS) $(tools_isotest_DEPENDENCIES) $(EXTRA_tools_isotest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/isotest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_isotest_OBJECTS) $(tools_isotest_LDADD) $(LIBS)
+tools/l2cap-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/l2cap-tester$(EXEEXT): $(tools_l2cap_tester_OBJECTS) $(tools_l2cap_tester_DEPENDENCIES) $(EXTRA_tools_l2cap_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/l2cap-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_l2cap_tester_OBJECTS) $(tools_l2cap_tester_LDADD) $(LIBS)
+tools/l2ping.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/l2ping$(EXEEXT): $(tools_l2ping_OBJECTS) $(tools_l2ping_DEPENDENCIES) $(EXTRA_tools_l2ping_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/l2ping$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_l2ping_OBJECTS) $(tools_l2ping_LDADD) $(LIBS)
+tools/l2test.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/l2test$(EXEEXT): $(tools_l2test_OBJECTS) $(tools_l2test_DEPENDENCIES) $(EXTRA_tools_l2test_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/l2test$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_l2test_OBJECTS) $(tools_l2test_LDADD) $(LIBS)
+tools/mcaptest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/mcaptest$(EXEEXT): $(tools_mcaptest_OBJECTS) $(tools_mcaptest_DEPENDENCIES) $(EXTRA_tools_mcaptest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mcaptest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mcaptest_OBJECTS) $(tools_mcaptest_LDADD) $(LIBS)
+tools/mesh-cfgclient.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/$(am__dirstamp):
+	@$(MKDIR_P) tools/mesh
+	@: > tools/mesh/$(am__dirstamp)
+tools/mesh/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) tools/mesh/$(DEPDIR)
+	@: > tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/cfgcli.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/keys.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/util.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/remote.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/agent.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+tools/mesh/mesh-db.$(OBJEXT): tools/mesh/$(am__dirstamp) \
+	tools/mesh/$(DEPDIR)/$(am__dirstamp)
+
+tools/mesh-cfgclient$(EXEEXT): $(tools_mesh_cfgclient_OBJECTS) $(tools_mesh_cfgclient_DEPENDENCIES) $(EXTRA_tools_mesh_cfgclient_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mesh-cfgclient$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mesh_cfgclient_OBJECTS) $(tools_mesh_cfgclient_LDADD) $(LIBS)
+tools/mesh-cfgtest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/mesh-cfgtest$(EXEEXT): $(tools_mesh_cfgtest_OBJECTS) $(tools_mesh_cfgtest_DEPENDENCIES) $(EXTRA_tools_mesh_cfgtest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mesh-cfgtest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mesh_cfgtest_OBJECTS) $(tools_mesh_cfgtest_LDADD) $(LIBS)
+tools/mesh-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/mesh-tester$(EXEEXT): $(tools_mesh_tester_OBJECTS) $(tools_mesh_tester_DEPENDENCIES) $(EXTRA_tools_mesh_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mesh-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mesh_tester_OBJECTS) $(tools_mesh_tester_LDADD) $(LIBS)
+tools/meshctl.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/$(am__dirstamp):
+	@$(MKDIR_P) tools/mesh-gatt
+	@: > tools/mesh-gatt/$(am__dirstamp)
+tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) tools/mesh-gatt/$(DEPDIR)
+	@: > tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/node.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/gatt.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/crypto.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/net.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/prov.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/util.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/prov-db.$(OBJEXT): tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/config-client.$(OBJEXT):  \
+	tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/config-server.$(OBJEXT):  \
+	tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+tools/mesh-gatt/onoff-model.$(OBJEXT):  \
+	tools/mesh-gatt/$(am__dirstamp) \
+	tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+
+tools/meshctl$(EXEEXT): $(tools_meshctl_OBJECTS) $(tools_meshctl_DEPENDENCIES) $(EXTRA_tools_meshctl_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/meshctl$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_meshctl_OBJECTS) $(tools_meshctl_LDADD) $(LIBS)
+tools/mgmt-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/mgmt-tester$(EXEEXT): $(tools_mgmt_tester_OBJECTS) $(tools_mgmt_tester_DEPENDENCIES) $(EXTRA_tools_mgmt_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mgmt-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mgmt_tester_OBJECTS) $(tools_mgmt_tester_LDADD) $(LIBS)
+tools/mpris-proxy.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/mpris-proxy$(EXEEXT): $(tools_mpris_proxy_OBJECTS) $(tools_mpris_proxy_DEPENDENCIES) $(EXTRA_tools_mpris_proxy_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/mpris-proxy$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_mpris_proxy_OBJECTS) $(tools_mpris_proxy_LDADD) $(LIBS)
+tools/nokfw.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/nokfw$(EXEEXT): $(tools_nokfw_OBJECTS) $(tools_nokfw_DEPENDENCIES) $(EXTRA_tools_nokfw_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/nokfw$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_nokfw_OBJECTS) $(tools_nokfw_LDADD) $(LIBS)
+gobex/gobex.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/gobex-defs.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/gobex-packet.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/gobex-header.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/gobex-transfer.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+gobex/gobex-apparam.$(OBJEXT): gobex/$(am__dirstamp) \
+	gobex/$(DEPDIR)/$(am__dirstamp)
+tools/obex-client-tool.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/obex-client-tool$(EXEEXT): $(tools_obex_client_tool_OBJECTS) $(tools_obex_client_tool_DEPENDENCIES) $(EXTRA_tools_obex_client_tool_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/obex-client-tool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_obex_client_tool_OBJECTS) $(tools_obex_client_tool_LDADD) $(LIBS)
+tools/obex-server-tool.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/obex-server-tool$(EXEEXT): $(tools_obex_server_tool_OBJECTS) $(tools_obex_server_tool_DEPENDENCIES) $(EXTRA_tools_obex_server_tool_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/obex-server-tool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_obex_server_tool_OBJECTS) $(tools_obex_server_tool_LDADD) $(LIBS)
+tools/obexctl.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/obexctl$(EXEEXT): $(tools_obexctl_OBJECTS) $(tools_obexctl_DEPENDENCIES) $(EXTRA_tools_obexctl_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/obexctl$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_obexctl_OBJECTS) $(tools_obexctl_LDADD) $(LIBS)
+tools/oobtest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/oobtest$(EXEEXT): $(tools_oobtest_OBJECTS) $(tools_oobtest_DEPENDENCIES) $(EXTRA_tools_oobtest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/oobtest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_oobtest_OBJECTS) $(tools_oobtest_LDADD) $(LIBS)
+tools/rctest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/rctest$(EXEEXT): $(tools_rctest_OBJECTS) $(tools_rctest_DEPENDENCIES) $(EXTRA_tools_rctest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/rctest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_rctest_OBJECTS) $(tools_rctest_LDADD) $(LIBS)
+tools/rfcomm.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/rfcomm$(EXEEXT): $(tools_rfcomm_OBJECTS) $(tools_rfcomm_DEPENDENCIES) $(EXTRA_tools_rfcomm_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/rfcomm$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_rfcomm_OBJECTS) $(tools_rfcomm_LDADD) $(LIBS)
+tools/rfcomm-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/rfcomm-tester$(EXEEXT): $(tools_rfcomm_tester_OBJECTS) $(tools_rfcomm_tester_DEPENDENCIES) $(EXTRA_tools_rfcomm_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/rfcomm-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_rfcomm_tester_OBJECTS) $(tools_rfcomm_tester_LDADD) $(LIBS)
+tools/rtlfw.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/rtlfw$(EXEEXT): $(tools_rtlfw_OBJECTS) $(tools_rtlfw_DEPENDENCIES) $(EXTRA_tools_rtlfw_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/rtlfw$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_rtlfw_OBJECTS) $(tools_rtlfw_LDADD) $(LIBS)
+tools/sco-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/sco-tester$(EXEEXT): $(tools_sco_tester_OBJECTS) $(tools_sco_tester_DEPENDENCIES) $(EXTRA_tools_sco_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/sco-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_sco_tester_OBJECTS) $(tools_sco_tester_LDADD) $(LIBS)
+tools/scotest.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/scotest$(EXEEXT): $(tools_scotest_OBJECTS) $(tools_scotest_DEPENDENCIES) $(EXTRA_tools_scotest_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/scotest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_scotest_OBJECTS) $(tools_scotest_LDADD) $(LIBS)
+tools/sdptool.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+src/sdp-xml.$(OBJEXT): src/$(am__dirstamp) \
+	src/$(DEPDIR)/$(am__dirstamp)
+
+tools/sdptool$(EXEEXT): $(tools_sdptool_OBJECTS) $(tools_sdptool_DEPENDENCIES) $(EXTRA_tools_sdptool_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/sdptool$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_sdptool_OBJECTS) $(tools_sdptool_LDADD) $(LIBS)
+tools/seq2bseq.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/seq2bseq$(EXEEXT): $(tools_seq2bseq_OBJECTS) $(tools_seq2bseq_DEPENDENCIES) $(EXTRA_tools_seq2bseq_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/seq2bseq$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_seq2bseq_OBJECTS) $(tools_seq2bseq_LDADD) $(LIBS)
+tools/smp-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/smp-tester$(EXEEXT): $(tools_smp_tester_OBJECTS) $(tools_smp_tester_DEPENDENCIES) $(EXTRA_tools_smp_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/smp-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_smp_tester_OBJECTS) $(tools_smp_tester_LDADD) $(LIBS)
+tools/test-runner.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/test-runner$(EXEEXT): $(tools_test_runner_OBJECTS) $(tools_test_runner_DEPENDENCIES) $(EXTRA_tools_test_runner_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/test-runner$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_test_runner_OBJECTS) $(tools_test_runner_LDADD) $(LIBS)
+tools/userchan-tester.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+
+tools/userchan-tester$(EXEEXT): $(tools_userchan_tester_OBJECTS) $(tools_userchan_tester_DEPENDENCIES) $(EXTRA_tools_userchan_tester_DEPENDENCIES) tools/$(am__dirstamp)
+	@rm -f tools/userchan-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(tools_userchan_tester_OBJECTS) $(tools_userchan_tester_LDADD) $(LIBS)
+unit/$(am__dirstamp):
+	@$(MKDIR_P) unit
+	@: > unit/$(am__dirstamp)
+unit/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) unit/$(DEPDIR)
+	@: > unit/$(DEPDIR)/$(am__dirstamp)
+unit/test-avctp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-avctp$(EXEEXT): $(unit_test_avctp_OBJECTS) $(unit_test_avctp_DEPENDENCIES) $(EXTRA_unit_test_avctp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-avctp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_avctp_OBJECTS) $(unit_test_avctp_LDADD) $(LIBS)
+unit/test-avdtp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-avdtp$(EXEEXT): $(unit_test_avdtp_OBJECTS) $(unit_test_avdtp_DEPENDENCIES) $(EXTRA_unit_test_avdtp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-avdtp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_avdtp_OBJECTS) $(unit_test_avdtp_LDADD) $(LIBS)
+unit/test-avrcp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-avrcp$(EXEEXT): $(unit_test_avrcp_OBJECTS) $(unit_test_avrcp_DEPENDENCIES) $(EXTRA_unit_test_avrcp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-avrcp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_avrcp_OBJECTS) $(unit_test_avrcp_LDADD) $(LIBS)
+unit/test-bap.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-bap$(EXEEXT): $(unit_test_bap_OBJECTS) $(unit_test_bap_DEPENDENCIES) $(EXTRA_unit_test_bap_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-bap$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_bap_OBJECTS) $(unit_test_bap_LDADD) $(LIBS)
+unit/test-bass.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-bass$(EXEEXT): $(unit_test_bass_OBJECTS) $(unit_test_bass_DEPENDENCIES) $(EXTRA_unit_test_bass_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-bass$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_bass_OBJECTS) $(unit_test_bass_LDADD) $(LIBS)
+unit/test-crc.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-crc$(EXEEXT): $(unit_test_crc_OBJECTS) $(unit_test_crc_DEPENDENCIES) $(EXTRA_unit_test_crc_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-crc$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_crc_OBJECTS) $(unit_test_crc_LDADD) $(LIBS)
+unit/test-crypto.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-crypto$(EXEEXT): $(unit_test_crypto_OBJECTS) $(unit_test_crypto_DEPENDENCIES) $(EXTRA_unit_test_crypto_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-crypto$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_crypto_OBJECTS) $(unit_test_crypto_LDADD) $(LIBS)
+unit/test-ecc.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-ecc$(EXEEXT): $(unit_test_ecc_OBJECTS) $(unit_test_ecc_DEPENDENCIES) $(EXTRA_unit_test_ecc_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-ecc$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_ecc_OBJECTS) $(unit_test_ecc_LDADD) $(LIBS)
+unit/test-eir.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-eir$(EXEEXT): $(unit_test_eir_OBJECTS) $(unit_test_eir_DEPENDENCIES) $(EXTRA_unit_test_eir_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-eir$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_eir_OBJECTS) $(unit_test_eir_LDADD) $(LIBS)
+unit/test-gatt.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gatt$(EXEEXT): $(unit_test_gatt_OBJECTS) $(unit_test_gatt_DEPENDENCIES) $(EXTRA_unit_test_gatt_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gatt$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gatt_OBJECTS) $(unit_test_gatt_LDADD) $(LIBS)
+unit/test-gattrib.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gattrib$(EXEEXT): $(unit_test_gattrib_OBJECTS) $(unit_test_gattrib_DEPENDENCIES) $(EXTRA_unit_test_gattrib_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gattrib$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gattrib_OBJECTS) $(unit_test_gattrib_LDADD) $(LIBS)
+unit/test-gdbus-client.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gdbus-client$(EXEEXT): $(unit_test_gdbus_client_OBJECTS) $(unit_test_gdbus_client_DEPENDENCIES) $(EXTRA_unit_test_gdbus_client_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gdbus-client$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gdbus_client_OBJECTS) $(unit_test_gdbus_client_LDADD) $(LIBS)
+unit/util.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+unit/test-gobex.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gobex$(EXEEXT): $(unit_test_gobex_OBJECTS) $(unit_test_gobex_DEPENDENCIES) $(EXTRA_unit_test_gobex_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gobex$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gobex_OBJECTS) $(unit_test_gobex_LDADD) $(LIBS)
+unit/test-gobex-apparam.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gobex-apparam$(EXEEXT): $(unit_test_gobex_apparam_OBJECTS) $(unit_test_gobex_apparam_DEPENDENCIES) $(EXTRA_unit_test_gobex_apparam_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gobex-apparam$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gobex_apparam_OBJECTS) $(unit_test_gobex_apparam_LDADD) $(LIBS)
+unit/test-gobex-header.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gobex-header$(EXEEXT): $(unit_test_gobex_header_OBJECTS) $(unit_test_gobex_header_DEPENDENCIES) $(EXTRA_unit_test_gobex_header_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gobex-header$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gobex_header_OBJECTS) $(unit_test_gobex_header_LDADD) $(LIBS)
+unit/test-gobex-packet.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gobex-packet$(EXEEXT): $(unit_test_gobex_packet_OBJECTS) $(unit_test_gobex_packet_DEPENDENCIES) $(EXTRA_unit_test_gobex_packet_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gobex-packet$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gobex_packet_OBJECTS) $(unit_test_gobex_packet_LDADD) $(LIBS)
+unit/test-gobex-transfer.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-gobex-transfer$(EXEEXT): $(unit_test_gobex_transfer_OBJECTS) $(unit_test_gobex_transfer_DEPENDENCIES) $(EXTRA_unit_test_gobex_transfer_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-gobex-transfer$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_gobex_transfer_OBJECTS) $(unit_test_gobex_transfer_LDADD) $(LIBS)
+unit/test-hfp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-hfp$(EXEEXT): $(unit_test_hfp_OBJECTS) $(unit_test_hfp_DEPENDENCIES) $(EXTRA_unit_test_hfp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-hfp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_hfp_OBJECTS) $(unit_test_hfp_LDADD) $(LIBS)
+unit/test-hog.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-hog$(EXEEXT): $(unit_test_hog_OBJECTS) $(unit_test_hog_DEPENDENCIES) $(EXTRA_unit_test_hog_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-hog$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_hog_OBJECTS) $(unit_test_hog_LDADD) $(LIBS)
+unit/test-lib.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-lib$(EXEEXT): $(unit_test_lib_OBJECTS) $(unit_test_lib_DEPENDENCIES) $(EXTRA_unit_test_lib_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-lib$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_lib_OBJECTS) $(unit_test_lib_LDADD) $(LIBS)
+unit/test_mesh_crypto-test-mesh-crypto.$(OBJEXT):  \
+	unit/$(am__dirstamp) unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-mesh-crypto$(EXEEXT): $(unit_test_mesh_crypto_OBJECTS) $(unit_test_mesh_crypto_DEPENDENCIES) $(EXTRA_unit_test_mesh_crypto_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-mesh-crypto$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_mesh_crypto_OBJECTS) $(unit_test_mesh_crypto_LDADD) $(LIBS)
+unit/test-mgmt.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-mgmt$(EXEEXT): $(unit_test_mgmt_OBJECTS) $(unit_test_mgmt_DEPENDENCIES) $(EXTRA_unit_test_mgmt_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-mgmt$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_mgmt_OBJECTS) $(unit_test_mgmt_LDADD) $(LIBS)
+unit/test-micp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-micp$(EXEEXT): $(unit_test_micp_OBJECTS) $(unit_test_micp_DEPENDENCIES) $(EXTRA_unit_test_micp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-micp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_micp_OBJECTS) $(unit_test_micp_LDADD) $(LIBS)
+unit/test_midi-test-midi.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+profiles/midi/unit_test_midi-libmidi.$(OBJEXT):  \
+	profiles/midi/$(am__dirstamp) \
+	profiles/midi/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-midi$(EXEEXT): $(unit_test_midi_OBJECTS) $(unit_test_midi_DEPENDENCIES) $(EXTRA_unit_test_midi_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-midi$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_midi_OBJECTS) $(unit_test_midi_LDADD) $(LIBS)
+unit/test-queue.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-queue$(EXEEXT): $(unit_test_queue_OBJECTS) $(unit_test_queue_DEPENDENCIES) $(EXTRA_unit_test_queue_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-queue$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_queue_OBJECTS) $(unit_test_queue_LDADD) $(LIBS)
+unit/test-ringbuf.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-ringbuf$(EXEEXT): $(unit_test_ringbuf_OBJECTS) $(unit_test_ringbuf_DEPENDENCIES) $(EXTRA_unit_test_ringbuf_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-ringbuf$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_ringbuf_OBJECTS) $(unit_test_ringbuf_LDADD) $(LIBS)
+unit/test-sdp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-sdp$(EXEEXT): $(unit_test_sdp_OBJECTS) $(unit_test_sdp_DEPENDENCIES) $(EXTRA_unit_test_sdp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-sdp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_sdp_OBJECTS) $(unit_test_sdp_LDADD) $(LIBS)
+unit/test-tester.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-tester$(EXEEXT): $(unit_test_tester_OBJECTS) $(unit_test_tester_DEPENDENCIES) $(EXTRA_unit_test_tester_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-tester$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_tester_OBJECTS) $(unit_test_tester_LDADD) $(LIBS)
+unit/test-textfile.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-textfile$(EXEEXT): $(unit_test_textfile_OBJECTS) $(unit_test_textfile_DEPENDENCIES) $(EXTRA_unit_test_textfile_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-textfile$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_textfile_OBJECTS) $(unit_test_textfile_LDADD) $(LIBS)
+unit/test-uhid.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-uhid$(EXEEXT): $(unit_test_uhid_OBJECTS) $(unit_test_uhid_DEPENDENCIES) $(EXTRA_unit_test_uhid_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-uhid$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_uhid_OBJECTS) $(unit_test_uhid_LDADD) $(LIBS)
+unit/test-uuid.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-uuid$(EXEEXT): $(unit_test_uuid_OBJECTS) $(unit_test_uuid_DEPENDENCIES) $(EXTRA_unit_test_uuid_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-uuid$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_uuid_OBJECTS) $(unit_test_uuid_LDADD) $(LIBS)
+unit/test-vcp.$(OBJEXT): unit/$(am__dirstamp) \
+	unit/$(DEPDIR)/$(am__dirstamp)
+
+unit/test-vcp$(EXEEXT): $(unit_test_vcp_OBJECTS) $(unit_test_vcp_DEPENDENCIES) $(EXTRA_unit_test_vcp_DEPENDENCIES) unit/$(am__dirstamp)
+	@rm -f unit/test-vcp$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(unit_test_vcp_OBJECTS) $(unit_test_vcp_LDADD) $(LIBS)
+install-testSCRIPTS: $(test_SCRIPTS)
+	@$(NORMAL_INSTALL)
+	@list='$(test_SCRIPTS)'; test -n "$(testdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(testdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(testdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n' \
+	    -e 'h;s|.*|.|' \
+	    -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+	      if (++n[d] == $(am__install_max)) { \
+		print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+	    else { print "f", d "/" $$4, $$1 } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	     if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	     test -z "$$files" || { \
+	       echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(testdir)$$dir'"; \
+	       $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(testdir)$$dir" || exit $$?; \
+	     } \
+	; done
+
+uninstall-testSCRIPTS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(test_SCRIPTS)'; test -n "$(testdir)" || exit 0; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	       sed -e 's,.*/,,;$(transform)'`; \
+	dir='$(DESTDIR)$(testdir)'; $(am__uninstall_files_from_dir)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+	-rm -f android/*.$(OBJEXT)
+	-rm -f android/*.lo
+	-rm -f android/audio_utils/*.$(OBJEXT)
+	-rm -f android/audio_utils/*.lo
+	-rm -f android/client/*.$(OBJEXT)
+	-rm -f android/hardware/*.$(OBJEXT)
+	-rm -f attrib/*.$(OBJEXT)
+	-rm -f btio/*.$(OBJEXT)
+	-rm -f client/*.$(OBJEXT)
+	-rm -f ell/*.$(OBJEXT)
+	-rm -f ell/*.lo
+	-rm -f emulator/*.$(OBJEXT)
+	-rm -f gdbus/*.$(OBJEXT)
+	-rm -f gdbus/*.lo
+	-rm -f gobex/*.$(OBJEXT)
+	-rm -f lib/*.$(OBJEXT)
+	-rm -f lib/*.lo
+	-rm -f mesh/*.$(OBJEXT)
+	-rm -f monitor/*.$(OBJEXT)
+	-rm -f obexd/client/*.$(OBJEXT)
+	-rm -f obexd/plugins/*.$(OBJEXT)
+	-rm -f obexd/src/*.$(OBJEXT)
+	-rm -f peripheral/*.$(OBJEXT)
+	-rm -f plugins/*.$(OBJEXT)
+	-rm -f profiles/audio/*.$(OBJEXT)
+	-rm -f profiles/battery/*.$(OBJEXT)
+	-rm -f profiles/cups/*.$(OBJEXT)
+	-rm -f profiles/deviceinfo/*.$(OBJEXT)
+	-rm -f profiles/gap/*.$(OBJEXT)
+	-rm -f profiles/health/*.$(OBJEXT)
+	-rm -f profiles/iap/*.$(OBJEXT)
+	-rm -f profiles/input/*.$(OBJEXT)
+	-rm -f profiles/midi/*.$(OBJEXT)
+	-rm -f profiles/network/*.$(OBJEXT)
+	-rm -f profiles/sap/*.$(OBJEXT)
+	-rm -f profiles/scanparam/*.$(OBJEXT)
+	-rm -f src/*.$(OBJEXT)
+	-rm -f src/shared/*.$(OBJEXT)
+	-rm -f src/shared/*.lo
+	-rm -f tools/*.$(OBJEXT)
+	-rm -f tools/mesh-gatt/*.$(OBJEXT)
+	-rm -f tools/mesh/*.$(OBJEXT)
+	-rm -f tools/parser/*.$(OBJEXT)
+	-rm -f unit/*.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/a2dp-sink.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/a2dp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-a2dp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-avrcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-bluetooth.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-hdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-hidhost.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-map-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-pan.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/android_tester-tester-socket.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/audio_sco_default_la-hal-sco.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avctp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avdtptest-avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avdtptest-avdtptest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avrcp-lib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/avrcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-health.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-pan.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-socket.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetooth_default_la-hal-utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/bluetoothd-snoop.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/haltest-hal-utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/handsfree-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/handsfree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/health.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/hidhost.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/ipc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/ipc_tester-hal-utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/ipc_tester-ipc-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/map-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/pan.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/sco.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/socket.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/system-emulator.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/test-ipc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-haltest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-history.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-audio.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-av-sink.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-av.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-bt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-hf-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-hf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-hh.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-hl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-mce.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-pan.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-rc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-sco.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-if-sock.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-pollhandler.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-tabcompletion.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/client/$(DEPDIR)/haltest-terminal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/hardware/$(DEPDIR)/android_tester-hardware.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@android/hardware/$(DEPDIR)/haltest-hardware.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/att.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/bluetoothd-att.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/bluetoothd-gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/bluetoothd-gattrib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/gattrib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/gatttool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/interactive.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@btio/$(DEPDIR)/android_avdtptest-btio.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@btio/$(DEPDIR)/bluetoothd-btio.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@btio/$(DEPDIR)/btio.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@btio/$(DEPDIR)/obexd-btio.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/admin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/adv_monitor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/advertising.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/agent.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/assistant.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/display.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/mgmt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/player.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/print.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/base64.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/cert-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/cert.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/checksum.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/cipher.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-filter.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-message.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-name-cache.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-service.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus-util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/dbus.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/ecc-external.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/ecc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/ecdh.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/gvariant-util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/hashmap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/idle.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/io.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/key.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/log.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/main.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/pem.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/random.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/settings.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/signal.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/siphash.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/string.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/strv.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/tester.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/time.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/timeout.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/tls-extensions.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/tls-record.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/tls-suites.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/tls.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/utf8.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@ell/$(DEPDIR)/uuid.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/amp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_android_tester-btdev.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_android_tester-bthost.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_android_tester-hciemu.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_android_tester-smp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_android_tester-vhci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_ipc_tester-btdev.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_ipc_tester-bthost.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_ipc_tester-smp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/android_ipc_tester-vhci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/b1ee.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/btdev.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/bthost.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/hciemu.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/hfp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/le.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/phy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/serial.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/smp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/vhci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/mainloop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/object.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/polkit.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/watch.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-apparam.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-defs.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-header.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-packet.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-transfer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex-apparam.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex-defs.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex-header.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex-packet.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex-transfer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/obexd-gobex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/bluetooth.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/hci.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/sdp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/uuid.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/agent.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/appkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/cfgmod-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/dbus.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/friend.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/keyring.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-config-json.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-io-generic.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-io-mgmt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-io-unit.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-io.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh-mgmt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/mesh.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/model.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/net-keys.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/net.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/node.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/pb-adv.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/prov-acceptor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/prov-initiator.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/prvbeac-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/remprv-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/rpl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@mesh/$(DEPDIR)/util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/a2dp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/analyze.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/att.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/avctp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/bnep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/broadcom.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/control.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/crc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/display.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/ellisys.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/hcidump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/hwdb.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/intel.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/jlink.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/keys.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/l2cap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/ll.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/lmp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/msft.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/packet.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/rfcomm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/sdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@monitor/$(DEPDIR)/vendor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-bip-common.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-bip.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-bluetooth.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-driver.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-ftp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-map-event.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-map.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-mns.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-opp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-pbap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-session.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-sync.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-transfer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/client/$(DEPDIR)/obexd-transport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-filesystem.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-ftp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-irmc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-mas.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-opp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-pbap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/plugins/$(DEPDIR)/obexd-vcard.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-mimetype.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-obex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-plugin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-service.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@obexd/src/$(DEPDIR)/obexd-transport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/attach.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/efivars.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/gap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@peripheral/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-admin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-autopair.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-hostname.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-neard.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-policy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-sixaxis.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetoothd-wiimote.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-asha.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-bap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-bass.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-control.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-csip.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-media.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-micp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-player.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-sink.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-source.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-transport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/battery/$(DEPDIR)/bas.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/battery/$(DEPDIR)/bluetoothd-bas.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/battery/$(DEPDIR)/bluetoothd-battery.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/cups/$(DEPDIR)/hcrp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/cups/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/cups/$(DEPDIR)/sdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/cups/$(DEPDIR)/spp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/deviceinfo/$(DEPDIR)/dis.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/gap/$(DEPDIR)/bluetoothd-gas.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/bluetoothd-hdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/bluetoothd-mcap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/health/$(DEPDIR)/mcap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/iap/$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-device.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-hog.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/input/$(DEPDIR)/hog-lib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/midi/$(DEPDIR)/bluetoothd-midi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/network/$(DEPDIR)/bluetoothd-bnep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/network/$(DEPDIR)/bluetoothd-connection.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/network/$(DEPDIR)/bluetoothd-manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/network/$(DEPDIR)/bluetoothd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/network/$(DEPDIR)/bnep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/sap/$(DEPDIR)/bluetoothd-main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/sap/$(DEPDIR)/bluetoothd-manager.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/sap/$(DEPDIR)/bluetoothd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@profiles/scanparam/$(DEPDIR)/scpp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/android_avdtptest-log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-adapter.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-adv_monitor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-advertising.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-agent.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-backtrace.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-battery.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-dbus-common.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-device.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-eir.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-error.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-gatt-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-gatt-database.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-plugin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-profile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-rfkill.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdp-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdp-xml.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdpd-database.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdpd-request.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdpd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-sdpd-service.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-service.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-set.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-settings.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-storage.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-textfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetoothd-uuid-helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/eir.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/oui.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdp-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdp-xml.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdpd-database.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdpd-request.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdpd-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sdpd-service.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/settings.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/textfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/uuid-helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/android_avdtptest-log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/android_avdtptest-queue.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/android_avdtptest-util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/btp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-ad.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-asha.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-att.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-bap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-bass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-ccp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-csip.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-ecc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-gap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-hci.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-hfp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-log.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-mcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-micp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-pcap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-shell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-uhid.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_ell_la-vcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-ad.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-asha.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-att.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-bap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-bass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-ccp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-csip.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-ecc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-gap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-hci.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-hfp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-log.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-mcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-micp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-pcap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-shell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-tester.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-uhid.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_glib_la-vcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-att.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-log.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/3dsp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/advtest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/amptest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/avinfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/avtest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bcmfw.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bdaddr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bluemoon.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bluetooth-player.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bnep-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bneptest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btattach.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btconfig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btgatt-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btgatt-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btinfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btiotest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btmgmt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btmon-logger.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btpclient.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btpclientctl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btproxy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btsnoop.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/check-selftest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/ciptool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/cltest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/create-image.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/eddystone.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/gap-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/gatt-service.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hci-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_ath3k.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_bcm43xx.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_intel.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_qualcomm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_st.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_ti.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_tialt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciconfig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hcidump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hcieventmask.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hcisecfilter.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hcitool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hex2hcd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hid2hci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hwdb.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/ibeacon.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/ioctl-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/iso-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/isotest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/l2cap-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/l2ping.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/l2test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mcaptest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mesh-cfgclient.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mesh-cfgtest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mesh-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/meshctl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mgmt-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mpris-proxy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/nokfw.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obex-client-tool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obex-server-tool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obexctl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/oobtest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rctest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rfcomm-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rfcomm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rtlfw.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/sco-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/scotest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/sdptool.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/seq2bseq.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/smp-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/test-runner.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/userchan-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/config-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/config-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/net.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/node.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/onoff-model.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/prov-db.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/prov.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh-gatt/$(DEPDIR)/util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/agent.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/cfgcli.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/keys.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/mesh-db.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/remote.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/mesh/$(DEPDIR)/util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/amp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/att.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/avctp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/avrcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/bnep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/bpa.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/capi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/cmtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/csr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/ericsson.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/hci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/hcrp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/hidp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/l2cap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/lmp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/obex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/parser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/ppp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/rfcomm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/sap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/sdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/smp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tools/parser/$(DEPDIR)/tcpip.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-avctp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-avdtp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-avrcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-bap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-bass.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-crc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-crypto.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-ecc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-eir.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gatt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gattrib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gdbus-client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-apparam.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-header.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-packet.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-transfer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-hfp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-hog.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-lib.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-mgmt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-micp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-queue.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-ringbuf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-sdp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-tester.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-textfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-uhid.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-uuid.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-vcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test_midi-test-midi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/util.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+	@$(MKDIR_P) $(@D)
+	@echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+android/audio_a2dp_default_la-hal-audio.lo: android/hal-audio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -MT android/audio_a2dp_default_la-hal-audio.lo -MD -MP -MF android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Tpo -c -o android/audio_a2dp_default_la-hal-audio.lo `test -f 'android/hal-audio.c' || echo '$(srcdir)/'`android/hal-audio.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Tpo android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-audio.c' object='android/audio_a2dp_default_la-hal-audio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -c -o android/audio_a2dp_default_la-hal-audio.lo `test -f 'android/hal-audio.c' || echo '$(srcdir)/'`android/hal-audio.c
+
+android/audio_a2dp_default_la-hal-audio-sbc.lo: android/hal-audio-sbc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -MT android/audio_a2dp_default_la-hal-audio-sbc.lo -MD -MP -MF android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Tpo -c -o android/audio_a2dp_default_la-hal-audio-sbc.lo `test -f 'android/hal-audio-sbc.c' || echo '$(srcdir)/'`android/hal-audio-sbc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Tpo android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-audio-sbc.c' object='android/audio_a2dp_default_la-hal-audio-sbc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -c -o android/audio_a2dp_default_la-hal-audio-sbc.lo `test -f 'android/hal-audio-sbc.c' || echo '$(srcdir)/'`android/hal-audio-sbc.c
+
+android/audio_a2dp_default_la-hal-audio-aptx.lo: android/hal-audio-aptx.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -MT android/audio_a2dp_default_la-hal-audio-aptx.lo -MD -MP -MF android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Tpo -c -o android/audio_a2dp_default_la-hal-audio-aptx.lo `test -f 'android/hal-audio-aptx.c' || echo '$(srcdir)/'`android/hal-audio-aptx.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Tpo android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-audio-aptx.c' object='android/audio_a2dp_default_la-hal-audio-aptx.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_a2dp_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_a2dp_default_la_CFLAGS) $(CFLAGS) -c -o android/audio_a2dp_default_la-hal-audio-aptx.lo `test -f 'android/hal-audio-aptx.c' || echo '$(srcdir)/'`android/hal-audio-aptx.c
+
+android/audio_sco_default_la-hal-sco.lo: android/hal-sco.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_sco_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_sco_default_la_CFLAGS) $(CFLAGS) -MT android/audio_sco_default_la-hal-sco.lo -MD -MP -MF android/$(DEPDIR)/audio_sco_default_la-hal-sco.Tpo -c -o android/audio_sco_default_la-hal-sco.lo `test -f 'android/hal-sco.c' || echo '$(srcdir)/'`android/hal-sco.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/audio_sco_default_la-hal-sco.Tpo android/$(DEPDIR)/audio_sco_default_la-hal-sco.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-sco.c' object='android/audio_sco_default_la-hal-sco.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_sco_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_sco_default_la_CFLAGS) $(CFLAGS) -c -o android/audio_sco_default_la-hal-sco.lo `test -f 'android/hal-sco.c' || echo '$(srcdir)/'`android/hal-sco.c
+
+android/audio_utils/audio_sco_default_la-resampler.lo: android/audio_utils/resampler.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_sco_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_sco_default_la_CFLAGS) $(CFLAGS) -MT android/audio_utils/audio_sco_default_la-resampler.lo -MD -MP -MF android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Tpo -c -o android/audio_utils/audio_sco_default_la-resampler.lo `test -f 'android/audio_utils/resampler.c' || echo '$(srcdir)/'`android/audio_utils/resampler.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Tpo android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/audio_utils/resampler.c' object='android/audio_utils/audio_sco_default_la-resampler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_audio_sco_default_la_CPPFLAGS) $(CPPFLAGS) $(android_audio_sco_default_la_CFLAGS) $(CFLAGS) -c -o android/audio_utils/audio_sco_default_la-resampler.lo `test -f 'android/audio_utils/resampler.c' || echo '$(srcdir)/'`android/audio_utils/resampler.c
+
+android/bluetooth_default_la-hal-bluetooth.lo: android/hal-bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-bluetooth.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Tpo -c -o android/bluetooth_default_la-hal-bluetooth.lo `test -f 'android/hal-bluetooth.c' || echo '$(srcdir)/'`android/hal-bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-bluetooth.c' object='android/bluetooth_default_la-hal-bluetooth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-bluetooth.lo `test -f 'android/hal-bluetooth.c' || echo '$(srcdir)/'`android/hal-bluetooth.c
+
+android/bluetooth_default_la-hal-socket.lo: android/hal-socket.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-socket.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-socket.Tpo -c -o android/bluetooth_default_la-hal-socket.lo `test -f 'android/hal-socket.c' || echo '$(srcdir)/'`android/hal-socket.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-socket.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-socket.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-socket.c' object='android/bluetooth_default_la-hal-socket.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-socket.lo `test -f 'android/hal-socket.c' || echo '$(srcdir)/'`android/hal-socket.c
+
+android/bluetooth_default_la-hal-hidhost.lo: android/hal-hidhost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-hidhost.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Tpo -c -o android/bluetooth_default_la-hal-hidhost.lo `test -f 'android/hal-hidhost.c' || echo '$(srcdir)/'`android/hal-hidhost.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-hidhost.c' object='android/bluetooth_default_la-hal-hidhost.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-hidhost.lo `test -f 'android/hal-hidhost.c' || echo '$(srcdir)/'`android/hal-hidhost.c
+
+android/bluetooth_default_la-hal-health.lo: android/hal-health.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-health.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-health.Tpo -c -o android/bluetooth_default_la-hal-health.lo `test -f 'android/hal-health.c' || echo '$(srcdir)/'`android/hal-health.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-health.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-health.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-health.c' object='android/bluetooth_default_la-hal-health.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-health.lo `test -f 'android/hal-health.c' || echo '$(srcdir)/'`android/hal-health.c
+
+android/bluetooth_default_la-hal-pan.lo: android/hal-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-pan.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-pan.Tpo -c -o android/bluetooth_default_la-hal-pan.lo `test -f 'android/hal-pan.c' || echo '$(srcdir)/'`android/hal-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-pan.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-pan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-pan.c' object='android/bluetooth_default_la-hal-pan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-pan.lo `test -f 'android/hal-pan.c' || echo '$(srcdir)/'`android/hal-pan.c
+
+android/bluetooth_default_la-hal-a2dp.lo: android/hal-a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-a2dp.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Tpo -c -o android/bluetooth_default_la-hal-a2dp.lo `test -f 'android/hal-a2dp.c' || echo '$(srcdir)/'`android/hal-a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-a2dp.c' object='android/bluetooth_default_la-hal-a2dp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-a2dp.lo `test -f 'android/hal-a2dp.c' || echo '$(srcdir)/'`android/hal-a2dp.c
+
+android/bluetooth_default_la-hal-a2dp-sink.lo: android/hal-a2dp-sink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-a2dp-sink.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Tpo -c -o android/bluetooth_default_la-hal-a2dp-sink.lo `test -f 'android/hal-a2dp-sink.c' || echo '$(srcdir)/'`android/hal-a2dp-sink.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-a2dp-sink.c' object='android/bluetooth_default_la-hal-a2dp-sink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-a2dp-sink.lo `test -f 'android/hal-a2dp-sink.c' || echo '$(srcdir)/'`android/hal-a2dp-sink.c
+
+android/bluetooth_default_la-hal-avrcp.lo: android/hal-avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-avrcp.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Tpo -c -o android/bluetooth_default_la-hal-avrcp.lo `test -f 'android/hal-avrcp.c' || echo '$(srcdir)/'`android/hal-avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-avrcp.c' object='android/bluetooth_default_la-hal-avrcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-avrcp.lo `test -f 'android/hal-avrcp.c' || echo '$(srcdir)/'`android/hal-avrcp.c
+
+android/bluetooth_default_la-hal-avrcp-ctrl.lo: android/hal-avrcp-ctrl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-avrcp-ctrl.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Tpo -c -o android/bluetooth_default_la-hal-avrcp-ctrl.lo `test -f 'android/hal-avrcp-ctrl.c' || echo '$(srcdir)/'`android/hal-avrcp-ctrl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-avrcp-ctrl.c' object='android/bluetooth_default_la-hal-avrcp-ctrl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-avrcp-ctrl.lo `test -f 'android/hal-avrcp-ctrl.c' || echo '$(srcdir)/'`android/hal-avrcp-ctrl.c
+
+android/bluetooth_default_la-hal-handsfree.lo: android/hal-handsfree.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-handsfree.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Tpo -c -o android/bluetooth_default_la-hal-handsfree.lo `test -f 'android/hal-handsfree.c' || echo '$(srcdir)/'`android/hal-handsfree.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-handsfree.c' object='android/bluetooth_default_la-hal-handsfree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-handsfree.lo `test -f 'android/hal-handsfree.c' || echo '$(srcdir)/'`android/hal-handsfree.c
+
+android/bluetooth_default_la-hal-handsfree-client.lo: android/hal-handsfree-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-handsfree-client.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Tpo -c -o android/bluetooth_default_la-hal-handsfree-client.lo `test -f 'android/hal-handsfree-client.c' || echo '$(srcdir)/'`android/hal-handsfree-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-handsfree-client.c' object='android/bluetooth_default_la-hal-handsfree-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-handsfree-client.lo `test -f 'android/hal-handsfree-client.c' || echo '$(srcdir)/'`android/hal-handsfree-client.c
+
+android/bluetooth_default_la-hal-gatt.lo: android/hal-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-gatt.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Tpo -c -o android/bluetooth_default_la-hal-gatt.lo `test -f 'android/hal-gatt.c' || echo '$(srcdir)/'`android/hal-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-gatt.c' object='android/bluetooth_default_la-hal-gatt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-gatt.lo `test -f 'android/hal-gatt.c' || echo '$(srcdir)/'`android/hal-gatt.c
+
+android/bluetooth_default_la-hal-map-client.lo: android/hal-map-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-map-client.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Tpo -c -o android/bluetooth_default_la-hal-map-client.lo `test -f 'android/hal-map-client.c' || echo '$(srcdir)/'`android/hal-map-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-map-client.c' object='android/bluetooth_default_la-hal-map-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-map-client.lo `test -f 'android/hal-map-client.c' || echo '$(srcdir)/'`android/hal-map-client.c
+
+android/bluetooth_default_la-hal-ipc.lo: android/hal-ipc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-ipc.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Tpo -c -o android/bluetooth_default_la-hal-ipc.lo `test -f 'android/hal-ipc.c' || echo '$(srcdir)/'`android/hal-ipc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-ipc.c' object='android/bluetooth_default_la-hal-ipc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-ipc.lo `test -f 'android/hal-ipc.c' || echo '$(srcdir)/'`android/hal-ipc.c
+
+android/bluetooth_default_la-hal-utils.lo: android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -MT android/bluetooth_default_la-hal-utils.lo -MD -MP -MF android/$(DEPDIR)/bluetooth_default_la-hal-utils.Tpo -c -o android/bluetooth_default_la-hal-utils.lo `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/bluetooth_default_la-hal-utils.Tpo android/$(DEPDIR)/bluetooth_default_la-hal-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-utils.c' object='android/bluetooth_default_la-hal-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_bluetooth_default_la_CPPFLAGS) $(CPPFLAGS) $(android_bluetooth_default_la_CFLAGS) $(CFLAGS) -c -o android/bluetooth_default_la-hal-utils.lo `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+
+src/shared/libshared_ell_la-queue.lo: src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-queue.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-queue.Tpo -c -o src/shared/libshared_ell_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-queue.Tpo src/shared/$(DEPDIR)/libshared_ell_la-queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/queue.c' object='src/shared/libshared_ell_la-queue.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+
+src/shared/libshared_ell_la-util.lo: src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-util.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-util.Tpo -c -o src/shared/libshared_ell_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-util.Tpo src/shared/$(DEPDIR)/libshared_ell_la-util.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/util.c' object='src/shared/libshared_ell_la-util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+
+src/shared/libshared_ell_la-mgmt.lo: src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-mgmt.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Tpo -c -o src/shared/libshared_ell_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Tpo src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mgmt.c' object='src/shared/libshared_ell_la-mgmt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+
+src/shared/libshared_ell_la-crypto.lo: src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-crypto.Tpo -c -o src/shared/libshared_ell_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-crypto.Tpo src/shared/$(DEPDIR)/libshared_ell_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/crypto.c' object='src/shared/libshared_ell_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+
+src/shared/libshared_ell_la-ecc.lo: src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-ecc.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-ecc.Tpo -c -o src/shared/libshared_ell_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-ecc.Tpo src/shared/$(DEPDIR)/libshared_ell_la-ecc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ecc.c' object='src/shared/libshared_ell_la-ecc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+
+src/shared/libshared_ell_la-ringbuf.lo: src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-ringbuf.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Tpo -c -o src/shared/libshared_ell_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Tpo src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ringbuf.c' object='src/shared/libshared_ell_la-ringbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+
+src/shared/libshared_ell_la-hci.lo: src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-hci.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-hci.Tpo -c -o src/shared/libshared_ell_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-hci.Tpo src/shared/$(DEPDIR)/libshared_ell_la-hci.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci.c' object='src/shared/libshared_ell_la-hci.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+
+src/shared/libshared_ell_la-hci-crypto.lo: src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-hci-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Tpo -c -o src/shared/libshared_ell_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Tpo src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci-crypto.c' object='src/shared/libshared_ell_la-hci-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+
+src/shared/libshared_ell_la-hfp.lo: src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-hfp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-hfp.Tpo -c -o src/shared/libshared_ell_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-hfp.Tpo src/shared/$(DEPDIR)/libshared_ell_la-hfp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hfp.c' object='src/shared/libshared_ell_la-hfp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+
+src/shared/libshared_ell_la-uhid.lo: src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-uhid.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-uhid.Tpo -c -o src/shared/libshared_ell_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-uhid.Tpo src/shared/$(DEPDIR)/libshared_ell_la-uhid.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/uhid.c' object='src/shared/libshared_ell_la-uhid.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+
+src/shared/libshared_ell_la-pcap.lo: src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-pcap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-pcap.Tpo -c -o src/shared/libshared_ell_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-pcap.Tpo src/shared/$(DEPDIR)/libshared_ell_la-pcap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/pcap.c' object='src/shared/libshared_ell_la-pcap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+
+src/shared/libshared_ell_la-btsnoop.lo: src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-btsnoop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Tpo -c -o src/shared/libshared_ell_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Tpo src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/btsnoop.c' object='src/shared/libshared_ell_la-btsnoop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+
+src/shared/libshared_ell_la-ad.lo: src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-ad.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-ad.Tpo -c -o src/shared/libshared_ell_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-ad.Tpo src/shared/$(DEPDIR)/libshared_ell_la-ad.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ad.c' object='src/shared/libshared_ell_la-ad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+
+src/shared/libshared_ell_la-att.lo: src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-att.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-att.Tpo -c -o src/shared/libshared_ell_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-att.Tpo src/shared/$(DEPDIR)/libshared_ell_la-att.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/att.c' object='src/shared/libshared_ell_la-att.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+
+src/shared/libshared_ell_la-gatt-helpers.lo: src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-gatt-helpers.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Tpo -c -o src/shared/libshared_ell_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Tpo src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-helpers.c' object='src/shared/libshared_ell_la-gatt-helpers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+
+src/shared/libshared_ell_la-gatt-client.lo: src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-gatt-client.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Tpo -c -o src/shared/libshared_ell_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Tpo src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-client.c' object='src/shared/libshared_ell_la-gatt-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+
+src/shared/libshared_ell_la-gatt-server.lo: src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-gatt-server.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Tpo -c -o src/shared/libshared_ell_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Tpo src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-server.c' object='src/shared/libshared_ell_la-gatt-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+
+src/shared/libshared_ell_la-gatt-db.lo: src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-gatt-db.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Tpo -c -o src/shared/libshared_ell_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Tpo src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-db.c' object='src/shared/libshared_ell_la-gatt-db.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+
+src/shared/libshared_ell_la-gap.lo: src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-gap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-gap.Tpo -c -o src/shared/libshared_ell_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-gap.Tpo src/shared/$(DEPDIR)/libshared_ell_la-gap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gap.c' object='src/shared/libshared_ell_la-gap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+
+src/shared/libshared_ell_la-log.lo: src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-log.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-log.Tpo -c -o src/shared/libshared_ell_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-log.Tpo src/shared/$(DEPDIR)/libshared_ell_la-log.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/log.c' object='src/shared/libshared_ell_la-log.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+
+src/shared/libshared_ell_la-bap.lo: src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-bap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-bap.Tpo -c -o src/shared/libshared_ell_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-bap.Tpo src/shared/$(DEPDIR)/libshared_ell_la-bap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap.c' object='src/shared/libshared_ell_la-bap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+
+src/shared/libshared_ell_la-bap-debug.lo: src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-bap-debug.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Tpo -c -o src/shared/libshared_ell_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Tpo src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap-debug.c' object='src/shared/libshared_ell_la-bap-debug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+
+src/shared/libshared_ell_la-mcp.lo: src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-mcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-mcp.Tpo -c -o src/shared/libshared_ell_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-mcp.Tpo src/shared/$(DEPDIR)/libshared_ell_la-mcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mcp.c' object='src/shared/libshared_ell_la-mcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+
+src/shared/libshared_ell_la-vcp.lo: src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-vcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-vcp.Tpo -c -o src/shared/libshared_ell_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-vcp.Tpo src/shared/$(DEPDIR)/libshared_ell_la-vcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/vcp.c' object='src/shared/libshared_ell_la-vcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+
+src/shared/libshared_ell_la-micp.lo: src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-micp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-micp.Tpo -c -o src/shared/libshared_ell_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-micp.Tpo src/shared/$(DEPDIR)/libshared_ell_la-micp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/micp.c' object='src/shared/libshared_ell_la-micp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+
+src/shared/libshared_ell_la-csip.lo: src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-csip.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-csip.Tpo -c -o src/shared/libshared_ell_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-csip.Tpo src/shared/$(DEPDIR)/libshared_ell_la-csip.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/csip.c' object='src/shared/libshared_ell_la-csip.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+
+src/shared/libshared_ell_la-bass.lo: src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-bass.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-bass.Tpo -c -o src/shared/libshared_ell_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-bass.Tpo src/shared/$(DEPDIR)/libshared_ell_la-bass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bass.c' object='src/shared/libshared_ell_la-bass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+
+src/shared/libshared_ell_la-ccp.lo: src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-ccp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-ccp.Tpo -c -o src/shared/libshared_ell_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-ccp.Tpo src/shared/$(DEPDIR)/libshared_ell_la-ccp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ccp.c' object='src/shared/libshared_ell_la-ccp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+
+src/shared/libshared_ell_la-asha.lo: src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-asha.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-asha.Tpo -c -o src/shared/libshared_ell_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-asha.Tpo src/shared/$(DEPDIR)/libshared_ell_la-asha.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/asha.c' object='src/shared/libshared_ell_la-asha.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+
+src/shared/libshared_ell_la-shell.lo: src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-shell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-shell.Tpo -c -o src/shared/libshared_ell_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-shell.Tpo src/shared/$(DEPDIR)/libshared_ell_la-shell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/shell.c' object='src/shared/libshared_ell_la-shell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+
+src/shared/libshared_ell_la-io-ell.lo: src/shared/io-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-io-ell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Tpo -c -o src/shared/libshared_ell_la-io-ell.lo `test -f 'src/shared/io-ell.c' || echo '$(srcdir)/'`src/shared/io-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Tpo src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/io-ell.c' object='src/shared/libshared_ell_la-io-ell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-io-ell.lo `test -f 'src/shared/io-ell.c' || echo '$(srcdir)/'`src/shared/io-ell.c
+
+src/shared/libshared_ell_la-timeout-ell.lo: src/shared/timeout-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-timeout-ell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Tpo -c -o src/shared/libshared_ell_la-timeout-ell.lo `test -f 'src/shared/timeout-ell.c' || echo '$(srcdir)/'`src/shared/timeout-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Tpo src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/timeout-ell.c' object='src/shared/libshared_ell_la-timeout-ell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-timeout-ell.lo `test -f 'src/shared/timeout-ell.c' || echo '$(srcdir)/'`src/shared/timeout-ell.c
+
+src/shared/libshared_ell_la-mainloop-ell.lo: src/shared/mainloop-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_ell_la-mainloop-ell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Tpo -c -o src/shared/libshared_ell_la-mainloop-ell.lo `test -f 'src/shared/mainloop-ell.c' || echo '$(srcdir)/'`src/shared/mainloop-ell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Tpo src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mainloop-ell.c' object='src/shared/libshared_ell_la-mainloop-ell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_ell_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_ell_la-mainloop-ell.lo `test -f 'src/shared/mainloop-ell.c' || echo '$(srcdir)/'`src/shared/mainloop-ell.c
+
+src/shared/libshared_glib_la-queue.lo: src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-queue.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-queue.Tpo -c -o src/shared/libshared_glib_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-queue.Tpo src/shared/$(DEPDIR)/libshared_glib_la-queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/queue.c' object='src/shared/libshared_glib_la-queue.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+
+src/shared/libshared_glib_la-util.lo: src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-util.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-util.Tpo -c -o src/shared/libshared_glib_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-util.Tpo src/shared/$(DEPDIR)/libshared_glib_la-util.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/util.c' object='src/shared/libshared_glib_la-util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+
+src/shared/libshared_glib_la-mgmt.lo: src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-mgmt.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Tpo -c -o src/shared/libshared_glib_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Tpo src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mgmt.c' object='src/shared/libshared_glib_la-mgmt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+
+src/shared/libshared_glib_la-crypto.lo: src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-crypto.Tpo -c -o src/shared/libshared_glib_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-crypto.Tpo src/shared/$(DEPDIR)/libshared_glib_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/crypto.c' object='src/shared/libshared_glib_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+
+src/shared/libshared_glib_la-ecc.lo: src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-ecc.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-ecc.Tpo -c -o src/shared/libshared_glib_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-ecc.Tpo src/shared/$(DEPDIR)/libshared_glib_la-ecc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ecc.c' object='src/shared/libshared_glib_la-ecc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+
+src/shared/libshared_glib_la-ringbuf.lo: src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-ringbuf.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Tpo -c -o src/shared/libshared_glib_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Tpo src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ringbuf.c' object='src/shared/libshared_glib_la-ringbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+
+src/shared/libshared_glib_la-hci.lo: src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-hci.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-hci.Tpo -c -o src/shared/libshared_glib_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-hci.Tpo src/shared/$(DEPDIR)/libshared_glib_la-hci.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci.c' object='src/shared/libshared_glib_la-hci.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+
+src/shared/libshared_glib_la-hci-crypto.lo: src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-hci-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Tpo -c -o src/shared/libshared_glib_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Tpo src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci-crypto.c' object='src/shared/libshared_glib_la-hci-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+
+src/shared/libshared_glib_la-hfp.lo: src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-hfp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-hfp.Tpo -c -o src/shared/libshared_glib_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-hfp.Tpo src/shared/$(DEPDIR)/libshared_glib_la-hfp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hfp.c' object='src/shared/libshared_glib_la-hfp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+
+src/shared/libshared_glib_la-uhid.lo: src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-uhid.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-uhid.Tpo -c -o src/shared/libshared_glib_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-uhid.Tpo src/shared/$(DEPDIR)/libshared_glib_la-uhid.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/uhid.c' object='src/shared/libshared_glib_la-uhid.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+
+src/shared/libshared_glib_la-pcap.lo: src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-pcap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-pcap.Tpo -c -o src/shared/libshared_glib_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-pcap.Tpo src/shared/$(DEPDIR)/libshared_glib_la-pcap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/pcap.c' object='src/shared/libshared_glib_la-pcap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+
+src/shared/libshared_glib_la-btsnoop.lo: src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-btsnoop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Tpo -c -o src/shared/libshared_glib_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Tpo src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/btsnoop.c' object='src/shared/libshared_glib_la-btsnoop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+
+src/shared/libshared_glib_la-ad.lo: src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-ad.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-ad.Tpo -c -o src/shared/libshared_glib_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-ad.Tpo src/shared/$(DEPDIR)/libshared_glib_la-ad.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ad.c' object='src/shared/libshared_glib_la-ad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+
+src/shared/libshared_glib_la-att.lo: src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-att.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-att.Tpo -c -o src/shared/libshared_glib_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-att.Tpo src/shared/$(DEPDIR)/libshared_glib_la-att.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/att.c' object='src/shared/libshared_glib_la-att.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+
+src/shared/libshared_glib_la-gatt-helpers.lo: src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-gatt-helpers.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Tpo -c -o src/shared/libshared_glib_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Tpo src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-helpers.c' object='src/shared/libshared_glib_la-gatt-helpers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+
+src/shared/libshared_glib_la-gatt-client.lo: src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-gatt-client.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Tpo -c -o src/shared/libshared_glib_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Tpo src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-client.c' object='src/shared/libshared_glib_la-gatt-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+
+src/shared/libshared_glib_la-gatt-server.lo: src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-gatt-server.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Tpo -c -o src/shared/libshared_glib_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Tpo src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-server.c' object='src/shared/libshared_glib_la-gatt-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+
+src/shared/libshared_glib_la-gatt-db.lo: src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-gatt-db.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Tpo -c -o src/shared/libshared_glib_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Tpo src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-db.c' object='src/shared/libshared_glib_la-gatt-db.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+
+src/shared/libshared_glib_la-gap.lo: src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-gap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-gap.Tpo -c -o src/shared/libshared_glib_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-gap.Tpo src/shared/$(DEPDIR)/libshared_glib_la-gap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gap.c' object='src/shared/libshared_glib_la-gap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+
+src/shared/libshared_glib_la-log.lo: src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-log.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-log.Tpo -c -o src/shared/libshared_glib_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-log.Tpo src/shared/$(DEPDIR)/libshared_glib_la-log.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/log.c' object='src/shared/libshared_glib_la-log.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+
+src/shared/libshared_glib_la-bap.lo: src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-bap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-bap.Tpo -c -o src/shared/libshared_glib_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-bap.Tpo src/shared/$(DEPDIR)/libshared_glib_la-bap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap.c' object='src/shared/libshared_glib_la-bap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+
+src/shared/libshared_glib_la-bap-debug.lo: src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-bap-debug.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Tpo -c -o src/shared/libshared_glib_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Tpo src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap-debug.c' object='src/shared/libshared_glib_la-bap-debug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+
+src/shared/libshared_glib_la-mcp.lo: src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-mcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-mcp.Tpo -c -o src/shared/libshared_glib_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-mcp.Tpo src/shared/$(DEPDIR)/libshared_glib_la-mcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mcp.c' object='src/shared/libshared_glib_la-mcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+
+src/shared/libshared_glib_la-vcp.lo: src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-vcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-vcp.Tpo -c -o src/shared/libshared_glib_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-vcp.Tpo src/shared/$(DEPDIR)/libshared_glib_la-vcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/vcp.c' object='src/shared/libshared_glib_la-vcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+
+src/shared/libshared_glib_la-micp.lo: src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-micp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-micp.Tpo -c -o src/shared/libshared_glib_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-micp.Tpo src/shared/$(DEPDIR)/libshared_glib_la-micp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/micp.c' object='src/shared/libshared_glib_la-micp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+
+src/shared/libshared_glib_la-csip.lo: src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-csip.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-csip.Tpo -c -o src/shared/libshared_glib_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-csip.Tpo src/shared/$(DEPDIR)/libshared_glib_la-csip.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/csip.c' object='src/shared/libshared_glib_la-csip.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+
+src/shared/libshared_glib_la-bass.lo: src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-bass.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-bass.Tpo -c -o src/shared/libshared_glib_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-bass.Tpo src/shared/$(DEPDIR)/libshared_glib_la-bass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bass.c' object='src/shared/libshared_glib_la-bass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+
+src/shared/libshared_glib_la-ccp.lo: src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-ccp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-ccp.Tpo -c -o src/shared/libshared_glib_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-ccp.Tpo src/shared/$(DEPDIR)/libshared_glib_la-ccp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ccp.c' object='src/shared/libshared_glib_la-ccp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+
+src/shared/libshared_glib_la-asha.lo: src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-asha.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-asha.Tpo -c -o src/shared/libshared_glib_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-asha.Tpo src/shared/$(DEPDIR)/libshared_glib_la-asha.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/asha.c' object='src/shared/libshared_glib_la-asha.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+
+src/shared/libshared_glib_la-shell.lo: src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-shell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-shell.Tpo -c -o src/shared/libshared_glib_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-shell.Tpo src/shared/$(DEPDIR)/libshared_glib_la-shell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/shell.c' object='src/shared/libshared_glib_la-shell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+
+src/shared/libshared_glib_la-io-glib.lo: src/shared/io-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-io-glib.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Tpo -c -o src/shared/libshared_glib_la-io-glib.lo `test -f 'src/shared/io-glib.c' || echo '$(srcdir)/'`src/shared/io-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Tpo src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/io-glib.c' object='src/shared/libshared_glib_la-io-glib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-io-glib.lo `test -f 'src/shared/io-glib.c' || echo '$(srcdir)/'`src/shared/io-glib.c
+
+src/shared/libshared_glib_la-timeout-glib.lo: src/shared/timeout-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-timeout-glib.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Tpo -c -o src/shared/libshared_glib_la-timeout-glib.lo `test -f 'src/shared/timeout-glib.c' || echo '$(srcdir)/'`src/shared/timeout-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Tpo src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/timeout-glib.c' object='src/shared/libshared_glib_la-timeout-glib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-timeout-glib.lo `test -f 'src/shared/timeout-glib.c' || echo '$(srcdir)/'`src/shared/timeout-glib.c
+
+src/shared/libshared_glib_la-mainloop-glib.lo: src/shared/mainloop-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-mainloop-glib.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Tpo -c -o src/shared/libshared_glib_la-mainloop-glib.lo `test -f 'src/shared/mainloop-glib.c' || echo '$(srcdir)/'`src/shared/mainloop-glib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Tpo src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mainloop-glib.c' object='src/shared/libshared_glib_la-mainloop-glib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-mainloop-glib.lo `test -f 'src/shared/mainloop-glib.c' || echo '$(srcdir)/'`src/shared/mainloop-glib.c
+
+src/shared/libshared_glib_la-mainloop-notify.lo: src/shared/mainloop-notify.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-mainloop-notify.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Tpo -c -o src/shared/libshared_glib_la-mainloop-notify.lo `test -f 'src/shared/mainloop-notify.c' || echo '$(srcdir)/'`src/shared/mainloop-notify.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Tpo src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mainloop-notify.c' object='src/shared/libshared_glib_la-mainloop-notify.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-mainloop-notify.lo `test -f 'src/shared/mainloop-notify.c' || echo '$(srcdir)/'`src/shared/mainloop-notify.c
+
+src/shared/libshared_glib_la-tester.lo: src/shared/tester.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_glib_la-tester.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_glib_la-tester.Tpo -c -o src/shared/libshared_glib_la-tester.lo `test -f 'src/shared/tester.c' || echo '$(srcdir)/'`src/shared/tester.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_glib_la-tester.Tpo src/shared/$(DEPDIR)/libshared_glib_la-tester.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/tester.c' object='src/shared/libshared_glib_la-tester.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_glib_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_glib_la-tester.lo `test -f 'src/shared/tester.c' || echo '$(srcdir)/'`src/shared/tester.c
+
+src/shared/libshared_mainloop_la-queue.lo: src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-queue.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Tpo -c -o src/shared/libshared_mainloop_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/queue.c' object='src/shared/libshared_mainloop_la-queue.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-queue.lo `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+
+src/shared/libshared_mainloop_la-util.lo: src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-util.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-util.Tpo -c -o src/shared/libshared_mainloop_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-util.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-util.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/util.c' object='src/shared/libshared_mainloop_la-util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-util.lo `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+
+src/shared/libshared_mainloop_la-mgmt.lo: src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-mgmt.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Tpo -c -o src/shared/libshared_mainloop_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mgmt.c' object='src/shared/libshared_mainloop_la-mgmt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-mgmt.lo `test -f 'src/shared/mgmt.c' || echo '$(srcdir)/'`src/shared/mgmt.c
+
+src/shared/libshared_mainloop_la-crypto.lo: src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Tpo -c -o src/shared/libshared_mainloop_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/crypto.c' object='src/shared/libshared_mainloop_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-crypto.lo `test -f 'src/shared/crypto.c' || echo '$(srcdir)/'`src/shared/crypto.c
+
+src/shared/libshared_mainloop_la-ecc.lo: src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-ecc.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Tpo -c -o src/shared/libshared_mainloop_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ecc.c' object='src/shared/libshared_mainloop_la-ecc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-ecc.lo `test -f 'src/shared/ecc.c' || echo '$(srcdir)/'`src/shared/ecc.c
+
+src/shared/libshared_mainloop_la-ringbuf.lo: src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-ringbuf.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Tpo -c -o src/shared/libshared_mainloop_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ringbuf.c' object='src/shared/libshared_mainloop_la-ringbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-ringbuf.lo `test -f 'src/shared/ringbuf.c' || echo '$(srcdir)/'`src/shared/ringbuf.c
+
+src/shared/libshared_mainloop_la-hci.lo: src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-hci.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Tpo -c -o src/shared/libshared_mainloop_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci.c' object='src/shared/libshared_mainloop_la-hci.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-hci.lo `test -f 'src/shared/hci.c' || echo '$(srcdir)/'`src/shared/hci.c
+
+src/shared/libshared_mainloop_la-hci-crypto.lo: src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-hci-crypto.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Tpo -c -o src/shared/libshared_mainloop_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hci-crypto.c' object='src/shared/libshared_mainloop_la-hci-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-hci-crypto.lo `test -f 'src/shared/hci-crypto.c' || echo '$(srcdir)/'`src/shared/hci-crypto.c
+
+src/shared/libshared_mainloop_la-hfp.lo: src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-hfp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Tpo -c -o src/shared/libshared_mainloop_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/hfp.c' object='src/shared/libshared_mainloop_la-hfp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-hfp.lo `test -f 'src/shared/hfp.c' || echo '$(srcdir)/'`src/shared/hfp.c
+
+src/shared/libshared_mainloop_la-uhid.lo: src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-uhid.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Tpo -c -o src/shared/libshared_mainloop_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/uhid.c' object='src/shared/libshared_mainloop_la-uhid.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-uhid.lo `test -f 'src/shared/uhid.c' || echo '$(srcdir)/'`src/shared/uhid.c
+
+src/shared/libshared_mainloop_la-pcap.lo: src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-pcap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Tpo -c -o src/shared/libshared_mainloop_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/pcap.c' object='src/shared/libshared_mainloop_la-pcap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-pcap.lo `test -f 'src/shared/pcap.c' || echo '$(srcdir)/'`src/shared/pcap.c
+
+src/shared/libshared_mainloop_la-btsnoop.lo: src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-btsnoop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Tpo -c -o src/shared/libshared_mainloop_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/btsnoop.c' object='src/shared/libshared_mainloop_la-btsnoop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-btsnoop.lo `test -f 'src/shared/btsnoop.c' || echo '$(srcdir)/'`src/shared/btsnoop.c
+
+src/shared/libshared_mainloop_la-ad.lo: src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-ad.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Tpo -c -o src/shared/libshared_mainloop_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ad.c' object='src/shared/libshared_mainloop_la-ad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-ad.lo `test -f 'src/shared/ad.c' || echo '$(srcdir)/'`src/shared/ad.c
+
+src/shared/libshared_mainloop_la-att.lo: src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-att.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-att.Tpo -c -o src/shared/libshared_mainloop_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-att.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-att.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/att.c' object='src/shared/libshared_mainloop_la-att.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-att.lo `test -f 'src/shared/att.c' || echo '$(srcdir)/'`src/shared/att.c
+
+src/shared/libshared_mainloop_la-gatt-helpers.lo: src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-gatt-helpers.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Tpo -c -o src/shared/libshared_mainloop_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-helpers.c' object='src/shared/libshared_mainloop_la-gatt-helpers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-gatt-helpers.lo `test -f 'src/shared/gatt-helpers.c' || echo '$(srcdir)/'`src/shared/gatt-helpers.c
+
+src/shared/libshared_mainloop_la-gatt-client.lo: src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-gatt-client.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Tpo -c -o src/shared/libshared_mainloop_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-client.c' object='src/shared/libshared_mainloop_la-gatt-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-gatt-client.lo `test -f 'src/shared/gatt-client.c' || echo '$(srcdir)/'`src/shared/gatt-client.c
+
+src/shared/libshared_mainloop_la-gatt-server.lo: src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-gatt-server.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Tpo -c -o src/shared/libshared_mainloop_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-server.c' object='src/shared/libshared_mainloop_la-gatt-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-gatt-server.lo `test -f 'src/shared/gatt-server.c' || echo '$(srcdir)/'`src/shared/gatt-server.c
+
+src/shared/libshared_mainloop_la-gatt-db.lo: src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-gatt-db.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Tpo -c -o src/shared/libshared_mainloop_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gatt-db.c' object='src/shared/libshared_mainloop_la-gatt-db.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-gatt-db.lo `test -f 'src/shared/gatt-db.c' || echo '$(srcdir)/'`src/shared/gatt-db.c
+
+src/shared/libshared_mainloop_la-gap.lo: src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-gap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Tpo -c -o src/shared/libshared_mainloop_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/gap.c' object='src/shared/libshared_mainloop_la-gap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-gap.lo `test -f 'src/shared/gap.c' || echo '$(srcdir)/'`src/shared/gap.c
+
+src/shared/libshared_mainloop_la-log.lo: src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-log.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-log.Tpo -c -o src/shared/libshared_mainloop_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-log.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-log.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/log.c' object='src/shared/libshared_mainloop_la-log.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-log.lo `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+
+src/shared/libshared_mainloop_la-bap.lo: src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-bap.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Tpo -c -o src/shared/libshared_mainloop_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap.c' object='src/shared/libshared_mainloop_la-bap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-bap.lo `test -f 'src/shared/bap.c' || echo '$(srcdir)/'`src/shared/bap.c
+
+src/shared/libshared_mainloop_la-bap-debug.lo: src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-bap-debug.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Tpo -c -o src/shared/libshared_mainloop_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bap-debug.c' object='src/shared/libshared_mainloop_la-bap-debug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-bap-debug.lo `test -f 'src/shared/bap-debug.c' || echo '$(srcdir)/'`src/shared/bap-debug.c
+
+src/shared/libshared_mainloop_la-mcp.lo: src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-mcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Tpo -c -o src/shared/libshared_mainloop_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mcp.c' object='src/shared/libshared_mainloop_la-mcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-mcp.lo `test -f 'src/shared/mcp.c' || echo '$(srcdir)/'`src/shared/mcp.c
+
+src/shared/libshared_mainloop_la-vcp.lo: src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-vcp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Tpo -c -o src/shared/libshared_mainloop_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/vcp.c' object='src/shared/libshared_mainloop_la-vcp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-vcp.lo `test -f 'src/shared/vcp.c' || echo '$(srcdir)/'`src/shared/vcp.c
+
+src/shared/libshared_mainloop_la-micp.lo: src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-micp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Tpo -c -o src/shared/libshared_mainloop_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/micp.c' object='src/shared/libshared_mainloop_la-micp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-micp.lo `test -f 'src/shared/micp.c' || echo '$(srcdir)/'`src/shared/micp.c
+
+src/shared/libshared_mainloop_la-csip.lo: src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-csip.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Tpo -c -o src/shared/libshared_mainloop_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/csip.c' object='src/shared/libshared_mainloop_la-csip.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-csip.lo `test -f 'src/shared/csip.c' || echo '$(srcdir)/'`src/shared/csip.c
+
+src/shared/libshared_mainloop_la-bass.lo: src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-bass.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Tpo -c -o src/shared/libshared_mainloop_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/bass.c' object='src/shared/libshared_mainloop_la-bass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-bass.lo `test -f 'src/shared/bass.c' || echo '$(srcdir)/'`src/shared/bass.c
+
+src/shared/libshared_mainloop_la-ccp.lo: src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-ccp.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Tpo -c -o src/shared/libshared_mainloop_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/ccp.c' object='src/shared/libshared_mainloop_la-ccp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-ccp.lo `test -f 'src/shared/ccp.c' || echo '$(srcdir)/'`src/shared/ccp.c
+
+src/shared/libshared_mainloop_la-asha.lo: src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-asha.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Tpo -c -o src/shared/libshared_mainloop_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/asha.c' object='src/shared/libshared_mainloop_la-asha.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-asha.lo `test -f 'src/shared/asha.c' || echo '$(srcdir)/'`src/shared/asha.c
+
+src/shared/libshared_mainloop_la-shell.lo: src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-shell.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Tpo -c -o src/shared/libshared_mainloop_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/shell.c' object='src/shared/libshared_mainloop_la-shell.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-shell.lo `test -f 'src/shared/shell.c' || echo '$(srcdir)/'`src/shared/shell.c
+
+src/shared/libshared_mainloop_la-io-mainloop.lo: src/shared/io-mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-io-mainloop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Tpo -c -o src/shared/libshared_mainloop_la-io-mainloop.lo `test -f 'src/shared/io-mainloop.c' || echo '$(srcdir)/'`src/shared/io-mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/io-mainloop.c' object='src/shared/libshared_mainloop_la-io-mainloop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-io-mainloop.lo `test -f 'src/shared/io-mainloop.c' || echo '$(srcdir)/'`src/shared/io-mainloop.c
+
+src/shared/libshared_mainloop_la-timeout-mainloop.lo: src/shared/timeout-mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-timeout-mainloop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Tpo -c -o src/shared/libshared_mainloop_la-timeout-mainloop.lo `test -f 'src/shared/timeout-mainloop.c' || echo '$(srcdir)/'`src/shared/timeout-mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/timeout-mainloop.c' object='src/shared/libshared_mainloop_la-timeout-mainloop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-timeout-mainloop.lo `test -f 'src/shared/timeout-mainloop.c' || echo '$(srcdir)/'`src/shared/timeout-mainloop.c
+
+src/shared/libshared_mainloop_la-mainloop.lo: src/shared/mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-mainloop.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Tpo -c -o src/shared/libshared_mainloop_la-mainloop.lo `test -f 'src/shared/mainloop.c' || echo '$(srcdir)/'`src/shared/mainloop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mainloop.c' object='src/shared/libshared_mainloop_la-mainloop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-mainloop.lo `test -f 'src/shared/mainloop.c' || echo '$(srcdir)/'`src/shared/mainloop.c
+
+src/shared/libshared_mainloop_la-mainloop-notify.lo: src/shared/mainloop-notify.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -MT src/shared/libshared_mainloop_la-mainloop-notify.lo -MD -MP -MF src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Tpo -c -o src/shared/libshared_mainloop_la-mainloop-notify.lo `test -f 'src/shared/mainloop-notify.c' || echo '$(srcdir)/'`src/shared/mainloop-notify.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Tpo src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/mainloop-notify.c' object='src/shared/libshared_mainloop_la-mainloop-notify.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libshared_mainloop_la_CFLAGS) $(CFLAGS) -c -o src/shared/libshared_mainloop_la-mainloop-notify.lo `test -f 'src/shared/mainloop-notify.c' || echo '$(srcdir)/'`src/shared/mainloop-notify.c
+
+emulator/android_android_tester-hciemu.o: emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-hciemu.o -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-hciemu.Tpo -c -o emulator/android_android_tester-hciemu.o `test -f 'emulator/hciemu.c' || echo '$(srcdir)/'`emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-hciemu.Tpo emulator/$(DEPDIR)/android_android_tester-hciemu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/hciemu.c' object='emulator/android_android_tester-hciemu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-hciemu.o `test -f 'emulator/hciemu.c' || echo '$(srcdir)/'`emulator/hciemu.c
+
+emulator/android_android_tester-hciemu.obj: emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-hciemu.obj -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-hciemu.Tpo -c -o emulator/android_android_tester-hciemu.obj `if test -f 'emulator/hciemu.c'; then $(CYGPATH_W) 'emulator/hciemu.c'; else $(CYGPATH_W) '$(srcdir)/emulator/hciemu.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-hciemu.Tpo emulator/$(DEPDIR)/android_android_tester-hciemu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/hciemu.c' object='emulator/android_android_tester-hciemu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-hciemu.obj `if test -f 'emulator/hciemu.c'; then $(CYGPATH_W) 'emulator/hciemu.c'; else $(CYGPATH_W) '$(srcdir)/emulator/hciemu.c'; fi`
+
+emulator/android_android_tester-vhci.o: emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-vhci.o -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-vhci.Tpo -c -o emulator/android_android_tester-vhci.o `test -f 'emulator/vhci.c' || echo '$(srcdir)/'`emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-vhci.Tpo emulator/$(DEPDIR)/android_android_tester-vhci.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/vhci.c' object='emulator/android_android_tester-vhci.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-vhci.o `test -f 'emulator/vhci.c' || echo '$(srcdir)/'`emulator/vhci.c
+
+emulator/android_android_tester-vhci.obj: emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-vhci.obj -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-vhci.Tpo -c -o emulator/android_android_tester-vhci.obj `if test -f 'emulator/vhci.c'; then $(CYGPATH_W) 'emulator/vhci.c'; else $(CYGPATH_W) '$(srcdir)/emulator/vhci.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-vhci.Tpo emulator/$(DEPDIR)/android_android_tester-vhci.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/vhci.c' object='emulator/android_android_tester-vhci.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-vhci.obj `if test -f 'emulator/vhci.c'; then $(CYGPATH_W) 'emulator/vhci.c'; else $(CYGPATH_W) '$(srcdir)/emulator/vhci.c'; fi`
+
+emulator/android_android_tester-btdev.o: emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-btdev.o -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-btdev.Tpo -c -o emulator/android_android_tester-btdev.o `test -f 'emulator/btdev.c' || echo '$(srcdir)/'`emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-btdev.Tpo emulator/$(DEPDIR)/android_android_tester-btdev.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/btdev.c' object='emulator/android_android_tester-btdev.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-btdev.o `test -f 'emulator/btdev.c' || echo '$(srcdir)/'`emulator/btdev.c
+
+emulator/android_android_tester-btdev.obj: emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-btdev.obj -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-btdev.Tpo -c -o emulator/android_android_tester-btdev.obj `if test -f 'emulator/btdev.c'; then $(CYGPATH_W) 'emulator/btdev.c'; else $(CYGPATH_W) '$(srcdir)/emulator/btdev.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-btdev.Tpo emulator/$(DEPDIR)/android_android_tester-btdev.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/btdev.c' object='emulator/android_android_tester-btdev.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-btdev.obj `if test -f 'emulator/btdev.c'; then $(CYGPATH_W) 'emulator/btdev.c'; else $(CYGPATH_W) '$(srcdir)/emulator/btdev.c'; fi`
+
+emulator/android_android_tester-bthost.o: emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-bthost.o -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-bthost.Tpo -c -o emulator/android_android_tester-bthost.o `test -f 'emulator/bthost.c' || echo '$(srcdir)/'`emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-bthost.Tpo emulator/$(DEPDIR)/android_android_tester-bthost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/bthost.c' object='emulator/android_android_tester-bthost.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-bthost.o `test -f 'emulator/bthost.c' || echo '$(srcdir)/'`emulator/bthost.c
+
+emulator/android_android_tester-bthost.obj: emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-bthost.obj -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-bthost.Tpo -c -o emulator/android_android_tester-bthost.obj `if test -f 'emulator/bthost.c'; then $(CYGPATH_W) 'emulator/bthost.c'; else $(CYGPATH_W) '$(srcdir)/emulator/bthost.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-bthost.Tpo emulator/$(DEPDIR)/android_android_tester-bthost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/bthost.c' object='emulator/android_android_tester-bthost.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-bthost.obj `if test -f 'emulator/bthost.c'; then $(CYGPATH_W) 'emulator/bthost.c'; else $(CYGPATH_W) '$(srcdir)/emulator/bthost.c'; fi`
+
+emulator/android_android_tester-smp.o: emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-smp.o -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-smp.Tpo -c -o emulator/android_android_tester-smp.o `test -f 'emulator/smp.c' || echo '$(srcdir)/'`emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-smp.Tpo emulator/$(DEPDIR)/android_android_tester-smp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/smp.c' object='emulator/android_android_tester-smp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-smp.o `test -f 'emulator/smp.c' || echo '$(srcdir)/'`emulator/smp.c
+
+emulator/android_android_tester-smp.obj: emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_android_tester-smp.obj -MD -MP -MF emulator/$(DEPDIR)/android_android_tester-smp.Tpo -c -o emulator/android_android_tester-smp.obj `if test -f 'emulator/smp.c'; then $(CYGPATH_W) 'emulator/smp.c'; else $(CYGPATH_W) '$(srcdir)/emulator/smp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_android_tester-smp.Tpo emulator/$(DEPDIR)/android_android_tester-smp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/smp.c' object='emulator/android_android_tester-smp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_android_tester-smp.obj `if test -f 'emulator/smp.c'; then $(CYGPATH_W) 'emulator/smp.c'; else $(CYGPATH_W) '$(srcdir)/emulator/smp.c'; fi`
+
+android/hardware/android_tester-hardware.o: android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/hardware/android_tester-hardware.o -MD -MP -MF android/hardware/$(DEPDIR)/android_tester-hardware.Tpo -c -o android/hardware/android_tester-hardware.o `test -f 'android/hardware/hardware.c' || echo '$(srcdir)/'`android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/hardware/$(DEPDIR)/android_tester-hardware.Tpo android/hardware/$(DEPDIR)/android_tester-hardware.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hardware/hardware.c' object='android/hardware/android_tester-hardware.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/hardware/android_tester-hardware.o `test -f 'android/hardware/hardware.c' || echo '$(srcdir)/'`android/hardware/hardware.c
+
+android/hardware/android_tester-hardware.obj: android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/hardware/android_tester-hardware.obj -MD -MP -MF android/hardware/$(DEPDIR)/android_tester-hardware.Tpo -c -o android/hardware/android_tester-hardware.obj `if test -f 'android/hardware/hardware.c'; then $(CYGPATH_W) 'android/hardware/hardware.c'; else $(CYGPATH_W) '$(srcdir)/android/hardware/hardware.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/hardware/$(DEPDIR)/android_tester-hardware.Tpo android/hardware/$(DEPDIR)/android_tester-hardware.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hardware/hardware.c' object='android/hardware/android_tester-hardware.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/hardware/android_tester-hardware.obj `if test -f 'android/hardware/hardware.c'; then $(CYGPATH_W) 'android/hardware/hardware.c'; else $(CYGPATH_W) '$(srcdir)/android/hardware/hardware.c'; fi`
+
+android/android_tester-tester-bluetooth.o: android/tester-bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-bluetooth.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-bluetooth.Tpo -c -o android/android_tester-tester-bluetooth.o `test -f 'android/tester-bluetooth.c' || echo '$(srcdir)/'`android/tester-bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-bluetooth.Tpo android/$(DEPDIR)/android_tester-tester-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-bluetooth.c' object='android/android_tester-tester-bluetooth.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-bluetooth.o `test -f 'android/tester-bluetooth.c' || echo '$(srcdir)/'`android/tester-bluetooth.c
+
+android/android_tester-tester-bluetooth.obj: android/tester-bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-bluetooth.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-bluetooth.Tpo -c -o android/android_tester-tester-bluetooth.obj `if test -f 'android/tester-bluetooth.c'; then $(CYGPATH_W) 'android/tester-bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-bluetooth.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-bluetooth.Tpo android/$(DEPDIR)/android_tester-tester-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-bluetooth.c' object='android/android_tester-tester-bluetooth.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-bluetooth.obj `if test -f 'android/tester-bluetooth.c'; then $(CYGPATH_W) 'android/tester-bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-bluetooth.c'; fi`
+
+android/android_tester-tester-socket.o: android/tester-socket.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-socket.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-socket.Tpo -c -o android/android_tester-tester-socket.o `test -f 'android/tester-socket.c' || echo '$(srcdir)/'`android/tester-socket.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-socket.Tpo android/$(DEPDIR)/android_tester-tester-socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-socket.c' object='android/android_tester-tester-socket.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-socket.o `test -f 'android/tester-socket.c' || echo '$(srcdir)/'`android/tester-socket.c
+
+android/android_tester-tester-socket.obj: android/tester-socket.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-socket.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-socket.Tpo -c -o android/android_tester-tester-socket.obj `if test -f 'android/tester-socket.c'; then $(CYGPATH_W) 'android/tester-socket.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-socket.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-socket.Tpo android/$(DEPDIR)/android_tester-tester-socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-socket.c' object='android/android_tester-tester-socket.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-socket.obj `if test -f 'android/tester-socket.c'; then $(CYGPATH_W) 'android/tester-socket.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-socket.c'; fi`
+
+android/android_tester-tester-hidhost.o: android/tester-hidhost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-hidhost.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-hidhost.Tpo -c -o android/android_tester-tester-hidhost.o `test -f 'android/tester-hidhost.c' || echo '$(srcdir)/'`android/tester-hidhost.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-hidhost.Tpo android/$(DEPDIR)/android_tester-tester-hidhost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-hidhost.c' object='android/android_tester-tester-hidhost.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-hidhost.o `test -f 'android/tester-hidhost.c' || echo '$(srcdir)/'`android/tester-hidhost.c
+
+android/android_tester-tester-hidhost.obj: android/tester-hidhost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-hidhost.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-hidhost.Tpo -c -o android/android_tester-tester-hidhost.obj `if test -f 'android/tester-hidhost.c'; then $(CYGPATH_W) 'android/tester-hidhost.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-hidhost.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-hidhost.Tpo android/$(DEPDIR)/android_tester-tester-hidhost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-hidhost.c' object='android/android_tester-tester-hidhost.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-hidhost.obj `if test -f 'android/tester-hidhost.c'; then $(CYGPATH_W) 'android/tester-hidhost.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-hidhost.c'; fi`
+
+android/android_tester-tester-pan.o: android/tester-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-pan.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-pan.Tpo -c -o android/android_tester-tester-pan.o `test -f 'android/tester-pan.c' || echo '$(srcdir)/'`android/tester-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-pan.Tpo android/$(DEPDIR)/android_tester-tester-pan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-pan.c' object='android/android_tester-tester-pan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-pan.o `test -f 'android/tester-pan.c' || echo '$(srcdir)/'`android/tester-pan.c
+
+android/android_tester-tester-pan.obj: android/tester-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-pan.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-pan.Tpo -c -o android/android_tester-tester-pan.obj `if test -f 'android/tester-pan.c'; then $(CYGPATH_W) 'android/tester-pan.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-pan.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-pan.Tpo android/$(DEPDIR)/android_tester-tester-pan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-pan.c' object='android/android_tester-tester-pan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-pan.obj `if test -f 'android/tester-pan.c'; then $(CYGPATH_W) 'android/tester-pan.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-pan.c'; fi`
+
+android/android_tester-tester-hdp.o: android/tester-hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-hdp.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-hdp.Tpo -c -o android/android_tester-tester-hdp.o `test -f 'android/tester-hdp.c' || echo '$(srcdir)/'`android/tester-hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-hdp.Tpo android/$(DEPDIR)/android_tester-tester-hdp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-hdp.c' object='android/android_tester-tester-hdp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-hdp.o `test -f 'android/tester-hdp.c' || echo '$(srcdir)/'`android/tester-hdp.c
+
+android/android_tester-tester-hdp.obj: android/tester-hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-hdp.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-hdp.Tpo -c -o android/android_tester-tester-hdp.obj `if test -f 'android/tester-hdp.c'; then $(CYGPATH_W) 'android/tester-hdp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-hdp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-hdp.Tpo android/$(DEPDIR)/android_tester-tester-hdp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-hdp.c' object='android/android_tester-tester-hdp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-hdp.obj `if test -f 'android/tester-hdp.c'; then $(CYGPATH_W) 'android/tester-hdp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-hdp.c'; fi`
+
+android/android_tester-tester-a2dp.o: android/tester-a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-a2dp.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-a2dp.Tpo -c -o android/android_tester-tester-a2dp.o `test -f 'android/tester-a2dp.c' || echo '$(srcdir)/'`android/tester-a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-a2dp.Tpo android/$(DEPDIR)/android_tester-tester-a2dp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-a2dp.c' object='android/android_tester-tester-a2dp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-a2dp.o `test -f 'android/tester-a2dp.c' || echo '$(srcdir)/'`android/tester-a2dp.c
+
+android/android_tester-tester-a2dp.obj: android/tester-a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-a2dp.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-a2dp.Tpo -c -o android/android_tester-tester-a2dp.obj `if test -f 'android/tester-a2dp.c'; then $(CYGPATH_W) 'android/tester-a2dp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-a2dp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-a2dp.Tpo android/$(DEPDIR)/android_tester-tester-a2dp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-a2dp.c' object='android/android_tester-tester-a2dp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-a2dp.obj `if test -f 'android/tester-a2dp.c'; then $(CYGPATH_W) 'android/tester-a2dp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-a2dp.c'; fi`
+
+android/android_tester-tester-avrcp.o: android/tester-avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-avrcp.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-avrcp.Tpo -c -o android/android_tester-tester-avrcp.o `test -f 'android/tester-avrcp.c' || echo '$(srcdir)/'`android/tester-avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-avrcp.Tpo android/$(DEPDIR)/android_tester-tester-avrcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-avrcp.c' object='android/android_tester-tester-avrcp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-avrcp.o `test -f 'android/tester-avrcp.c' || echo '$(srcdir)/'`android/tester-avrcp.c
+
+android/android_tester-tester-avrcp.obj: android/tester-avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-avrcp.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-avrcp.Tpo -c -o android/android_tester-tester-avrcp.obj `if test -f 'android/tester-avrcp.c'; then $(CYGPATH_W) 'android/tester-avrcp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-avrcp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-avrcp.Tpo android/$(DEPDIR)/android_tester-tester-avrcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-avrcp.c' object='android/android_tester-tester-avrcp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-avrcp.obj `if test -f 'android/tester-avrcp.c'; then $(CYGPATH_W) 'android/tester-avrcp.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-avrcp.c'; fi`
+
+android/android_tester-tester-gatt.o: android/tester-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-gatt.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-gatt.Tpo -c -o android/android_tester-tester-gatt.o `test -f 'android/tester-gatt.c' || echo '$(srcdir)/'`android/tester-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-gatt.Tpo android/$(DEPDIR)/android_tester-tester-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-gatt.c' object='android/android_tester-tester-gatt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-gatt.o `test -f 'android/tester-gatt.c' || echo '$(srcdir)/'`android/tester-gatt.c
+
+android/android_tester-tester-gatt.obj: android/tester-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-gatt.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-gatt.Tpo -c -o android/android_tester-tester-gatt.obj `if test -f 'android/tester-gatt.c'; then $(CYGPATH_W) 'android/tester-gatt.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-gatt.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-gatt.Tpo android/$(DEPDIR)/android_tester-tester-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-gatt.c' object='android/android_tester-tester-gatt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-gatt.obj `if test -f 'android/tester-gatt.c'; then $(CYGPATH_W) 'android/tester-gatt.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-gatt.c'; fi`
+
+android/android_tester-tester-map-client.o: android/tester-map-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-map-client.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-map-client.Tpo -c -o android/android_tester-tester-map-client.o `test -f 'android/tester-map-client.c' || echo '$(srcdir)/'`android/tester-map-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-map-client.Tpo android/$(DEPDIR)/android_tester-tester-map-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-map-client.c' object='android/android_tester-tester-map-client.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-map-client.o `test -f 'android/tester-map-client.c' || echo '$(srcdir)/'`android/tester-map-client.c
+
+android/android_tester-tester-map-client.obj: android/tester-map-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-map-client.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-map-client.Tpo -c -o android/android_tester-tester-map-client.obj `if test -f 'android/tester-map-client.c'; then $(CYGPATH_W) 'android/tester-map-client.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-map-client.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-map-client.Tpo android/$(DEPDIR)/android_tester-tester-map-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-map-client.c' object='android/android_tester-tester-map-client.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-map-client.obj `if test -f 'android/tester-map-client.c'; then $(CYGPATH_W) 'android/tester-map-client.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-map-client.c'; fi`
+
+android/android_tester-tester-main.o: android/tester-main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-main.o -MD -MP -MF android/$(DEPDIR)/android_tester-tester-main.Tpo -c -o android/android_tester-tester-main.o `test -f 'android/tester-main.c' || echo '$(srcdir)/'`android/tester-main.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-main.Tpo android/$(DEPDIR)/android_tester-tester-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-main.c' object='android/android_tester-tester-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-main.o `test -f 'android/tester-main.c' || echo '$(srcdir)/'`android/tester-main.c
+
+android/android_tester-tester-main.obj: android/tester-main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/android_tester-tester-main.obj -MD -MP -MF android/$(DEPDIR)/android_tester-tester-main.Tpo -c -o android/android_tester-tester-main.obj `if test -f 'android/tester-main.c'; then $(CYGPATH_W) 'android/tester-main.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-main.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/android_tester-tester-main.Tpo android/$(DEPDIR)/android_tester-tester-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/tester-main.c' object='android/android_tester-tester-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_android_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/android_tester-tester-main.obj `if test -f 'android/tester-main.c'; then $(CYGPATH_W) 'android/tester-main.c'; else $(CYGPATH_W) '$(srcdir)/android/tester-main.c'; fi`
+
+android/avdtptest-avdtptest.o: android/avdtptest.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT android/avdtptest-avdtptest.o -MD -MP -MF android/$(DEPDIR)/avdtptest-avdtptest.Tpo -c -o android/avdtptest-avdtptest.o `test -f 'android/avdtptest.c' || echo '$(srcdir)/'`android/avdtptest.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/avdtptest-avdtptest.Tpo android/$(DEPDIR)/avdtptest-avdtptest.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/avdtptest.c' object='android/avdtptest-avdtptest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o android/avdtptest-avdtptest.o `test -f 'android/avdtptest.c' || echo '$(srcdir)/'`android/avdtptest.c
+
+android/avdtptest-avdtptest.obj: android/avdtptest.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT android/avdtptest-avdtptest.obj -MD -MP -MF android/$(DEPDIR)/avdtptest-avdtptest.Tpo -c -o android/avdtptest-avdtptest.obj `if test -f 'android/avdtptest.c'; then $(CYGPATH_W) 'android/avdtptest.c'; else $(CYGPATH_W) '$(srcdir)/android/avdtptest.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/avdtptest-avdtptest.Tpo android/$(DEPDIR)/avdtptest-avdtptest.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/avdtptest.c' object='android/avdtptest-avdtptest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o android/avdtptest-avdtptest.obj `if test -f 'android/avdtptest.c'; then $(CYGPATH_W) 'android/avdtptest.c'; else $(CYGPATH_W) '$(srcdir)/android/avdtptest.c'; fi`
+
+src/android_avdtptest-log.o: src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/android_avdtptest-log.o -MD -MP -MF src/$(DEPDIR)/android_avdtptest-log.Tpo -c -o src/android_avdtptest-log.o `test -f 'src/log.c' || echo '$(srcdir)/'`src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/android_avdtptest-log.Tpo src/$(DEPDIR)/android_avdtptest-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/log.c' object='src/android_avdtptest-log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/android_avdtptest-log.o `test -f 'src/log.c' || echo '$(srcdir)/'`src/log.c
+
+src/android_avdtptest-log.obj: src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/android_avdtptest-log.obj -MD -MP -MF src/$(DEPDIR)/android_avdtptest-log.Tpo -c -o src/android_avdtptest-log.obj `if test -f 'src/log.c'; then $(CYGPATH_W) 'src/log.c'; else $(CYGPATH_W) '$(srcdir)/src/log.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/android_avdtptest-log.Tpo src/$(DEPDIR)/android_avdtptest-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/log.c' object='src/android_avdtptest-log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/android_avdtptest-log.obj `if test -f 'src/log.c'; then $(CYGPATH_W) 'src/log.c'; else $(CYGPATH_W) '$(srcdir)/src/log.c'; fi`
+
+btio/android_avdtptest-btio.o: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT btio/android_avdtptest-btio.o -MD -MP -MF btio/$(DEPDIR)/android_avdtptest-btio.Tpo -c -o btio/android_avdtptest-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/android_avdtptest-btio.Tpo btio/$(DEPDIR)/android_avdtptest-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/android_avdtptest-btio.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o btio/android_avdtptest-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+
+btio/android_avdtptest-btio.obj: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT btio/android_avdtptest-btio.obj -MD -MP -MF btio/$(DEPDIR)/android_avdtptest-btio.Tpo -c -o btio/android_avdtptest-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/android_avdtptest-btio.Tpo btio/$(DEPDIR)/android_avdtptest-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/android_avdtptest-btio.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o btio/android_avdtptest-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+
+src/shared/android_avdtptest-util.o: src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-util.o -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-util.Tpo -c -o src/shared/android_avdtptest-util.o `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-util.Tpo src/shared/$(DEPDIR)/android_avdtptest-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/util.c' object='src/shared/android_avdtptest-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-util.o `test -f 'src/shared/util.c' || echo '$(srcdir)/'`src/shared/util.c
+
+src/shared/android_avdtptest-util.obj: src/shared/util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-util.obj -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-util.Tpo -c -o src/shared/android_avdtptest-util.obj `if test -f 'src/shared/util.c'; then $(CYGPATH_W) 'src/shared/util.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/util.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-util.Tpo src/shared/$(DEPDIR)/android_avdtptest-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/util.c' object='src/shared/android_avdtptest-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-util.obj `if test -f 'src/shared/util.c'; then $(CYGPATH_W) 'src/shared/util.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/util.c'; fi`
+
+src/shared/android_avdtptest-queue.o: src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-queue.o -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-queue.Tpo -c -o src/shared/android_avdtptest-queue.o `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-queue.Tpo src/shared/$(DEPDIR)/android_avdtptest-queue.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/queue.c' object='src/shared/android_avdtptest-queue.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-queue.o `test -f 'src/shared/queue.c' || echo '$(srcdir)/'`src/shared/queue.c
+
+src/shared/android_avdtptest-queue.obj: src/shared/queue.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-queue.obj -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-queue.Tpo -c -o src/shared/android_avdtptest-queue.obj `if test -f 'src/shared/queue.c'; then $(CYGPATH_W) 'src/shared/queue.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/queue.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-queue.Tpo src/shared/$(DEPDIR)/android_avdtptest-queue.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/queue.c' object='src/shared/android_avdtptest-queue.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-queue.obj `if test -f 'src/shared/queue.c'; then $(CYGPATH_W) 'src/shared/queue.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/queue.c'; fi`
+
+src/shared/android_avdtptest-log.o: src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-log.o -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-log.Tpo -c -o src/shared/android_avdtptest-log.o `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-log.Tpo src/shared/$(DEPDIR)/android_avdtptest-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/log.c' object='src/shared/android_avdtptest-log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-log.o `test -f 'src/shared/log.c' || echo '$(srcdir)/'`src/shared/log.c
+
+src/shared/android_avdtptest-log.obj: src/shared/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT src/shared/android_avdtptest-log.obj -MD -MP -MF src/shared/$(DEPDIR)/android_avdtptest-log.Tpo -c -o src/shared/android_avdtptest-log.obj `if test -f 'src/shared/log.c'; then $(CYGPATH_W) 'src/shared/log.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/log.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/shared/$(DEPDIR)/android_avdtptest-log.Tpo src/shared/$(DEPDIR)/android_avdtptest-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/shared/log.c' object='src/shared/android_avdtptest-log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o src/shared/android_avdtptest-log.obj `if test -f 'src/shared/log.c'; then $(CYGPATH_W) 'src/shared/log.c'; else $(CYGPATH_W) '$(srcdir)/src/shared/log.c'; fi`
+
+android/avdtptest-avdtp.o: android/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT android/avdtptest-avdtp.o -MD -MP -MF android/$(DEPDIR)/avdtptest-avdtp.Tpo -c -o android/avdtptest-avdtp.o `test -f 'android/avdtp.c' || echo '$(srcdir)/'`android/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/avdtptest-avdtp.Tpo android/$(DEPDIR)/avdtptest-avdtp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/avdtp.c' object='android/avdtptest-avdtp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o android/avdtptest-avdtp.o `test -f 'android/avdtp.c' || echo '$(srcdir)/'`android/avdtp.c
+
+android/avdtptest-avdtp.obj: android/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -MT android/avdtptest-avdtp.obj -MD -MP -MF android/$(DEPDIR)/avdtptest-avdtp.Tpo -c -o android/avdtptest-avdtp.obj `if test -f 'android/avdtp.c'; then $(CYGPATH_W) 'android/avdtp.c'; else $(CYGPATH_W) '$(srcdir)/android/avdtp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/avdtptest-avdtp.Tpo android/$(DEPDIR)/avdtptest-avdtp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/avdtp.c' object='android/avdtptest-avdtp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(android_avdtptest_CFLAGS) $(CFLAGS) -c -o android/avdtptest-avdtp.obj `if test -f 'android/avdtp.c'; then $(CYGPATH_W) 'android/avdtp.c'; else $(CYGPATH_W) '$(srcdir)/android/avdtp.c'; fi`
+
+android/client/haltest-haltest.o: android/client/haltest.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-haltest.o -MD -MP -MF android/client/$(DEPDIR)/haltest-haltest.Tpo -c -o android/client/haltest-haltest.o `test -f 'android/client/haltest.c' || echo '$(srcdir)/'`android/client/haltest.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-haltest.Tpo android/client/$(DEPDIR)/haltest-haltest.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/haltest.c' object='android/client/haltest-haltest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-haltest.o `test -f 'android/client/haltest.c' || echo '$(srcdir)/'`android/client/haltest.c
+
+android/client/haltest-haltest.obj: android/client/haltest.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-haltest.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-haltest.Tpo -c -o android/client/haltest-haltest.obj `if test -f 'android/client/haltest.c'; then $(CYGPATH_W) 'android/client/haltest.c'; else $(CYGPATH_W) '$(srcdir)/android/client/haltest.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-haltest.Tpo android/client/$(DEPDIR)/haltest-haltest.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/haltest.c' object='android/client/haltest-haltest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-haltest.obj `if test -f 'android/client/haltest.c'; then $(CYGPATH_W) 'android/client/haltest.c'; else $(CYGPATH_W) '$(srcdir)/android/client/haltest.c'; fi`
+
+android/client/haltest-pollhandler.o: android/client/pollhandler.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-pollhandler.o -MD -MP -MF android/client/$(DEPDIR)/haltest-pollhandler.Tpo -c -o android/client/haltest-pollhandler.o `test -f 'android/client/pollhandler.c' || echo '$(srcdir)/'`android/client/pollhandler.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-pollhandler.Tpo android/client/$(DEPDIR)/haltest-pollhandler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/pollhandler.c' object='android/client/haltest-pollhandler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-pollhandler.o `test -f 'android/client/pollhandler.c' || echo '$(srcdir)/'`android/client/pollhandler.c
+
+android/client/haltest-pollhandler.obj: android/client/pollhandler.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-pollhandler.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-pollhandler.Tpo -c -o android/client/haltest-pollhandler.obj `if test -f 'android/client/pollhandler.c'; then $(CYGPATH_W) 'android/client/pollhandler.c'; else $(CYGPATH_W) '$(srcdir)/android/client/pollhandler.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-pollhandler.Tpo android/client/$(DEPDIR)/haltest-pollhandler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/pollhandler.c' object='android/client/haltest-pollhandler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-pollhandler.obj `if test -f 'android/client/pollhandler.c'; then $(CYGPATH_W) 'android/client/pollhandler.c'; else $(CYGPATH_W) '$(srcdir)/android/client/pollhandler.c'; fi`
+
+android/client/haltest-terminal.o: android/client/terminal.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-terminal.o -MD -MP -MF android/client/$(DEPDIR)/haltest-terminal.Tpo -c -o android/client/haltest-terminal.o `test -f 'android/client/terminal.c' || echo '$(srcdir)/'`android/client/terminal.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-terminal.Tpo android/client/$(DEPDIR)/haltest-terminal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/terminal.c' object='android/client/haltest-terminal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-terminal.o `test -f 'android/client/terminal.c' || echo '$(srcdir)/'`android/client/terminal.c
+
+android/client/haltest-terminal.obj: android/client/terminal.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-terminal.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-terminal.Tpo -c -o android/client/haltest-terminal.obj `if test -f 'android/client/terminal.c'; then $(CYGPATH_W) 'android/client/terminal.c'; else $(CYGPATH_W) '$(srcdir)/android/client/terminal.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-terminal.Tpo android/client/$(DEPDIR)/haltest-terminal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/terminal.c' object='android/client/haltest-terminal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-terminal.obj `if test -f 'android/client/terminal.c'; then $(CYGPATH_W) 'android/client/terminal.c'; else $(CYGPATH_W) '$(srcdir)/android/client/terminal.c'; fi`
+
+android/client/haltest-history.o: android/client/history.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-history.o -MD -MP -MF android/client/$(DEPDIR)/haltest-history.Tpo -c -o android/client/haltest-history.o `test -f 'android/client/history.c' || echo '$(srcdir)/'`android/client/history.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-history.Tpo android/client/$(DEPDIR)/haltest-history.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/history.c' object='android/client/haltest-history.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-history.o `test -f 'android/client/history.c' || echo '$(srcdir)/'`android/client/history.c
+
+android/client/haltest-history.obj: android/client/history.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-history.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-history.Tpo -c -o android/client/haltest-history.obj `if test -f 'android/client/history.c'; then $(CYGPATH_W) 'android/client/history.c'; else $(CYGPATH_W) '$(srcdir)/android/client/history.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-history.Tpo android/client/$(DEPDIR)/haltest-history.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/history.c' object='android/client/haltest-history.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-history.obj `if test -f 'android/client/history.c'; then $(CYGPATH_W) 'android/client/history.c'; else $(CYGPATH_W) '$(srcdir)/android/client/history.c'; fi`
+
+android/client/haltest-tabcompletion.o: android/client/tabcompletion.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-tabcompletion.o -MD -MP -MF android/client/$(DEPDIR)/haltest-tabcompletion.Tpo -c -o android/client/haltest-tabcompletion.o `test -f 'android/client/tabcompletion.c' || echo '$(srcdir)/'`android/client/tabcompletion.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-tabcompletion.Tpo android/client/$(DEPDIR)/haltest-tabcompletion.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/tabcompletion.c' object='android/client/haltest-tabcompletion.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-tabcompletion.o `test -f 'android/client/tabcompletion.c' || echo '$(srcdir)/'`android/client/tabcompletion.c
+
+android/client/haltest-tabcompletion.obj: android/client/tabcompletion.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-tabcompletion.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-tabcompletion.Tpo -c -o android/client/haltest-tabcompletion.obj `if test -f 'android/client/tabcompletion.c'; then $(CYGPATH_W) 'android/client/tabcompletion.c'; else $(CYGPATH_W) '$(srcdir)/android/client/tabcompletion.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-tabcompletion.Tpo android/client/$(DEPDIR)/haltest-tabcompletion.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/tabcompletion.c' object='android/client/haltest-tabcompletion.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-tabcompletion.obj `if test -f 'android/client/tabcompletion.c'; then $(CYGPATH_W) 'android/client/tabcompletion.c'; else $(CYGPATH_W) '$(srcdir)/android/client/tabcompletion.c'; fi`
+
+android/client/haltest-if-av.o: android/client/if-av.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-av.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-av.Tpo -c -o android/client/haltest-if-av.o `test -f 'android/client/if-av.c' || echo '$(srcdir)/'`android/client/if-av.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-av.Tpo android/client/$(DEPDIR)/haltest-if-av.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-av.c' object='android/client/haltest-if-av.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-av.o `test -f 'android/client/if-av.c' || echo '$(srcdir)/'`android/client/if-av.c
+
+android/client/haltest-if-av.obj: android/client/if-av.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-av.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-av.Tpo -c -o android/client/haltest-if-av.obj `if test -f 'android/client/if-av.c'; then $(CYGPATH_W) 'android/client/if-av.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-av.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-av.Tpo android/client/$(DEPDIR)/haltest-if-av.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-av.c' object='android/client/haltest-if-av.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-av.obj `if test -f 'android/client/if-av.c'; then $(CYGPATH_W) 'android/client/if-av.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-av.c'; fi`
+
+android/client/haltest-if-av-sink.o: android/client/if-av-sink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-av-sink.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-av-sink.Tpo -c -o android/client/haltest-if-av-sink.o `test -f 'android/client/if-av-sink.c' || echo '$(srcdir)/'`android/client/if-av-sink.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-av-sink.Tpo android/client/$(DEPDIR)/haltest-if-av-sink.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-av-sink.c' object='android/client/haltest-if-av-sink.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-av-sink.o `test -f 'android/client/if-av-sink.c' || echo '$(srcdir)/'`android/client/if-av-sink.c
+
+android/client/haltest-if-av-sink.obj: android/client/if-av-sink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-av-sink.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-av-sink.Tpo -c -o android/client/haltest-if-av-sink.obj `if test -f 'android/client/if-av-sink.c'; then $(CYGPATH_W) 'android/client/if-av-sink.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-av-sink.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-av-sink.Tpo android/client/$(DEPDIR)/haltest-if-av-sink.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-av-sink.c' object='android/client/haltest-if-av-sink.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-av-sink.obj `if test -f 'android/client/if-av-sink.c'; then $(CYGPATH_W) 'android/client/if-av-sink.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-av-sink.c'; fi`
+
+android/client/haltest-if-rc.o: android/client/if-rc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-rc.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-rc.Tpo -c -o android/client/haltest-if-rc.o `test -f 'android/client/if-rc.c' || echo '$(srcdir)/'`android/client/if-rc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-rc.Tpo android/client/$(DEPDIR)/haltest-if-rc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-rc.c' object='android/client/haltest-if-rc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-rc.o `test -f 'android/client/if-rc.c' || echo '$(srcdir)/'`android/client/if-rc.c
+
+android/client/haltest-if-rc.obj: android/client/if-rc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-rc.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-rc.Tpo -c -o android/client/haltest-if-rc.obj `if test -f 'android/client/if-rc.c'; then $(CYGPATH_W) 'android/client/if-rc.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-rc.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-rc.Tpo android/client/$(DEPDIR)/haltest-if-rc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-rc.c' object='android/client/haltest-if-rc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-rc.obj `if test -f 'android/client/if-rc.c'; then $(CYGPATH_W) 'android/client/if-rc.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-rc.c'; fi`
+
+android/client/haltest-if-rc-ctrl.o: android/client/if-rc-ctrl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-rc-ctrl.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-rc-ctrl.Tpo -c -o android/client/haltest-if-rc-ctrl.o `test -f 'android/client/if-rc-ctrl.c' || echo '$(srcdir)/'`android/client/if-rc-ctrl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-rc-ctrl.Tpo android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-rc-ctrl.c' object='android/client/haltest-if-rc-ctrl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-rc-ctrl.o `test -f 'android/client/if-rc-ctrl.c' || echo '$(srcdir)/'`android/client/if-rc-ctrl.c
+
+android/client/haltest-if-rc-ctrl.obj: android/client/if-rc-ctrl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-rc-ctrl.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-rc-ctrl.Tpo -c -o android/client/haltest-if-rc-ctrl.obj `if test -f 'android/client/if-rc-ctrl.c'; then $(CYGPATH_W) 'android/client/if-rc-ctrl.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-rc-ctrl.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-rc-ctrl.Tpo android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-rc-ctrl.c' object='android/client/haltest-if-rc-ctrl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-rc-ctrl.obj `if test -f 'android/client/if-rc-ctrl.c'; then $(CYGPATH_W) 'android/client/if-rc-ctrl.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-rc-ctrl.c'; fi`
+
+android/client/haltest-if-bt.o: android/client/if-bt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-bt.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-bt.Tpo -c -o android/client/haltest-if-bt.o `test -f 'android/client/if-bt.c' || echo '$(srcdir)/'`android/client/if-bt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-bt.Tpo android/client/$(DEPDIR)/haltest-if-bt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-bt.c' object='android/client/haltest-if-bt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-bt.o `test -f 'android/client/if-bt.c' || echo '$(srcdir)/'`android/client/if-bt.c
+
+android/client/haltest-if-bt.obj: android/client/if-bt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-bt.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-bt.Tpo -c -o android/client/haltest-if-bt.obj `if test -f 'android/client/if-bt.c'; then $(CYGPATH_W) 'android/client/if-bt.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-bt.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-bt.Tpo android/client/$(DEPDIR)/haltest-if-bt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-bt.c' object='android/client/haltest-if-bt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-bt.obj `if test -f 'android/client/if-bt.c'; then $(CYGPATH_W) 'android/client/if-bt.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-bt.c'; fi`
+
+android/client/haltest-if-gatt.o: android/client/if-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-gatt.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-gatt.Tpo -c -o android/client/haltest-if-gatt.o `test -f 'android/client/if-gatt.c' || echo '$(srcdir)/'`android/client/if-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-gatt.Tpo android/client/$(DEPDIR)/haltest-if-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-gatt.c' object='android/client/haltest-if-gatt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-gatt.o `test -f 'android/client/if-gatt.c' || echo '$(srcdir)/'`android/client/if-gatt.c
+
+android/client/haltest-if-gatt.obj: android/client/if-gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-gatt.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-gatt.Tpo -c -o android/client/haltest-if-gatt.obj `if test -f 'android/client/if-gatt.c'; then $(CYGPATH_W) 'android/client/if-gatt.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-gatt.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-gatt.Tpo android/client/$(DEPDIR)/haltest-if-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-gatt.c' object='android/client/haltest-if-gatt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-gatt.obj `if test -f 'android/client/if-gatt.c'; then $(CYGPATH_W) 'android/client/if-gatt.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-gatt.c'; fi`
+
+android/client/haltest-if-hf.o: android/client/if-hf.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hf.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hf.Tpo -c -o android/client/haltest-if-hf.o `test -f 'android/client/if-hf.c' || echo '$(srcdir)/'`android/client/if-hf.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hf.Tpo android/client/$(DEPDIR)/haltest-if-hf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hf.c' object='android/client/haltest-if-hf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hf.o `test -f 'android/client/if-hf.c' || echo '$(srcdir)/'`android/client/if-hf.c
+
+android/client/haltest-if-hf.obj: android/client/if-hf.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hf.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hf.Tpo -c -o android/client/haltest-if-hf.obj `if test -f 'android/client/if-hf.c'; then $(CYGPATH_W) 'android/client/if-hf.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hf.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hf.Tpo android/client/$(DEPDIR)/haltest-if-hf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hf.c' object='android/client/haltest-if-hf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hf.obj `if test -f 'android/client/if-hf.c'; then $(CYGPATH_W) 'android/client/if-hf.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hf.c'; fi`
+
+android/client/haltest-if-hf-client.o: android/client/if-hf-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hf-client.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hf-client.Tpo -c -o android/client/haltest-if-hf-client.o `test -f 'android/client/if-hf-client.c' || echo '$(srcdir)/'`android/client/if-hf-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hf-client.Tpo android/client/$(DEPDIR)/haltest-if-hf-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hf-client.c' object='android/client/haltest-if-hf-client.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hf-client.o `test -f 'android/client/if-hf-client.c' || echo '$(srcdir)/'`android/client/if-hf-client.c
+
+android/client/haltest-if-hf-client.obj: android/client/if-hf-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hf-client.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hf-client.Tpo -c -o android/client/haltest-if-hf-client.obj `if test -f 'android/client/if-hf-client.c'; then $(CYGPATH_W) 'android/client/if-hf-client.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hf-client.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hf-client.Tpo android/client/$(DEPDIR)/haltest-if-hf-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hf-client.c' object='android/client/haltest-if-hf-client.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hf-client.obj `if test -f 'android/client/if-hf-client.c'; then $(CYGPATH_W) 'android/client/if-hf-client.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hf-client.c'; fi`
+
+android/client/haltest-if-hh.o: android/client/if-hh.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hh.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hh.Tpo -c -o android/client/haltest-if-hh.o `test -f 'android/client/if-hh.c' || echo '$(srcdir)/'`android/client/if-hh.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hh.Tpo android/client/$(DEPDIR)/haltest-if-hh.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hh.c' object='android/client/haltest-if-hh.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hh.o `test -f 'android/client/if-hh.c' || echo '$(srcdir)/'`android/client/if-hh.c
+
+android/client/haltest-if-hh.obj: android/client/if-hh.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hh.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hh.Tpo -c -o android/client/haltest-if-hh.obj `if test -f 'android/client/if-hh.c'; then $(CYGPATH_W) 'android/client/if-hh.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hh.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hh.Tpo android/client/$(DEPDIR)/haltest-if-hh.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hh.c' object='android/client/haltest-if-hh.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hh.obj `if test -f 'android/client/if-hh.c'; then $(CYGPATH_W) 'android/client/if-hh.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hh.c'; fi`
+
+android/client/haltest-if-pan.o: android/client/if-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-pan.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-pan.Tpo -c -o android/client/haltest-if-pan.o `test -f 'android/client/if-pan.c' || echo '$(srcdir)/'`android/client/if-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-pan.Tpo android/client/$(DEPDIR)/haltest-if-pan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-pan.c' object='android/client/haltest-if-pan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-pan.o `test -f 'android/client/if-pan.c' || echo '$(srcdir)/'`android/client/if-pan.c
+
+android/client/haltest-if-pan.obj: android/client/if-pan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-pan.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-pan.Tpo -c -o android/client/haltest-if-pan.obj `if test -f 'android/client/if-pan.c'; then $(CYGPATH_W) 'android/client/if-pan.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-pan.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-pan.Tpo android/client/$(DEPDIR)/haltest-if-pan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-pan.c' object='android/client/haltest-if-pan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-pan.obj `if test -f 'android/client/if-pan.c'; then $(CYGPATH_W) 'android/client/if-pan.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-pan.c'; fi`
+
+android/client/haltest-if-hl.o: android/client/if-hl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hl.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hl.Tpo -c -o android/client/haltest-if-hl.o `test -f 'android/client/if-hl.c' || echo '$(srcdir)/'`android/client/if-hl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hl.Tpo android/client/$(DEPDIR)/haltest-if-hl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hl.c' object='android/client/haltest-if-hl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hl.o `test -f 'android/client/if-hl.c' || echo '$(srcdir)/'`android/client/if-hl.c
+
+android/client/haltest-if-hl.obj: android/client/if-hl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-hl.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-hl.Tpo -c -o android/client/haltest-if-hl.obj `if test -f 'android/client/if-hl.c'; then $(CYGPATH_W) 'android/client/if-hl.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hl.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-hl.Tpo android/client/$(DEPDIR)/haltest-if-hl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-hl.c' object='android/client/haltest-if-hl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-hl.obj `if test -f 'android/client/if-hl.c'; then $(CYGPATH_W) 'android/client/if-hl.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-hl.c'; fi`
+
+android/client/haltest-if-sock.o: android/client/if-sock.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-sock.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-sock.Tpo -c -o android/client/haltest-if-sock.o `test -f 'android/client/if-sock.c' || echo '$(srcdir)/'`android/client/if-sock.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-sock.Tpo android/client/$(DEPDIR)/haltest-if-sock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-sock.c' object='android/client/haltest-if-sock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-sock.o `test -f 'android/client/if-sock.c' || echo '$(srcdir)/'`android/client/if-sock.c
+
+android/client/haltest-if-sock.obj: android/client/if-sock.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-sock.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-sock.Tpo -c -o android/client/haltest-if-sock.obj `if test -f 'android/client/if-sock.c'; then $(CYGPATH_W) 'android/client/if-sock.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-sock.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-sock.Tpo android/client/$(DEPDIR)/haltest-if-sock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-sock.c' object='android/client/haltest-if-sock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-sock.obj `if test -f 'android/client/if-sock.c'; then $(CYGPATH_W) 'android/client/if-sock.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-sock.c'; fi`
+
+android/client/haltest-if-audio.o: android/client/if-audio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-audio.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-audio.Tpo -c -o android/client/haltest-if-audio.o `test -f 'android/client/if-audio.c' || echo '$(srcdir)/'`android/client/if-audio.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-audio.Tpo android/client/$(DEPDIR)/haltest-if-audio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-audio.c' object='android/client/haltest-if-audio.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-audio.o `test -f 'android/client/if-audio.c' || echo '$(srcdir)/'`android/client/if-audio.c
+
+android/client/haltest-if-audio.obj: android/client/if-audio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-audio.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-audio.Tpo -c -o android/client/haltest-if-audio.obj `if test -f 'android/client/if-audio.c'; then $(CYGPATH_W) 'android/client/if-audio.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-audio.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-audio.Tpo android/client/$(DEPDIR)/haltest-if-audio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-audio.c' object='android/client/haltest-if-audio.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-audio.obj `if test -f 'android/client/if-audio.c'; then $(CYGPATH_W) 'android/client/if-audio.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-audio.c'; fi`
+
+android/client/haltest-if-sco.o: android/client/if-sco.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-sco.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-sco.Tpo -c -o android/client/haltest-if-sco.o `test -f 'android/client/if-sco.c' || echo '$(srcdir)/'`android/client/if-sco.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-sco.Tpo android/client/$(DEPDIR)/haltest-if-sco.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-sco.c' object='android/client/haltest-if-sco.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-sco.o `test -f 'android/client/if-sco.c' || echo '$(srcdir)/'`android/client/if-sco.c
+
+android/client/haltest-if-sco.obj: android/client/if-sco.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-sco.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-sco.Tpo -c -o android/client/haltest-if-sco.obj `if test -f 'android/client/if-sco.c'; then $(CYGPATH_W) 'android/client/if-sco.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-sco.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-sco.Tpo android/client/$(DEPDIR)/haltest-if-sco.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-sco.c' object='android/client/haltest-if-sco.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-sco.obj `if test -f 'android/client/if-sco.c'; then $(CYGPATH_W) 'android/client/if-sco.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-sco.c'; fi`
+
+android/client/haltest-if-mce.o: android/client/if-mce.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-mce.o -MD -MP -MF android/client/$(DEPDIR)/haltest-if-mce.Tpo -c -o android/client/haltest-if-mce.o `test -f 'android/client/if-mce.c' || echo '$(srcdir)/'`android/client/if-mce.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-mce.Tpo android/client/$(DEPDIR)/haltest-if-mce.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-mce.c' object='android/client/haltest-if-mce.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-mce.o `test -f 'android/client/if-mce.c' || echo '$(srcdir)/'`android/client/if-mce.c
+
+android/client/haltest-if-mce.obj: android/client/if-mce.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/client/haltest-if-mce.obj -MD -MP -MF android/client/$(DEPDIR)/haltest-if-mce.Tpo -c -o android/client/haltest-if-mce.obj `if test -f 'android/client/if-mce.c'; then $(CYGPATH_W) 'android/client/if-mce.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-mce.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/client/$(DEPDIR)/haltest-if-mce.Tpo android/client/$(DEPDIR)/haltest-if-mce.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/client/if-mce.c' object='android/client/haltest-if-mce.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/client/haltest-if-mce.obj `if test -f 'android/client/if-mce.c'; then $(CYGPATH_W) 'android/client/if-mce.c'; else $(CYGPATH_W) '$(srcdir)/android/client/if-mce.c'; fi`
+
+android/hardware/haltest-hardware.o: android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/hardware/haltest-hardware.o -MD -MP -MF android/hardware/$(DEPDIR)/haltest-hardware.Tpo -c -o android/hardware/haltest-hardware.o `test -f 'android/hardware/hardware.c' || echo '$(srcdir)/'`android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/hardware/$(DEPDIR)/haltest-hardware.Tpo android/hardware/$(DEPDIR)/haltest-hardware.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hardware/hardware.c' object='android/hardware/haltest-hardware.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/hardware/haltest-hardware.o `test -f 'android/hardware/hardware.c' || echo '$(srcdir)/'`android/hardware/hardware.c
+
+android/hardware/haltest-hardware.obj: android/hardware/hardware.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/hardware/haltest-hardware.obj -MD -MP -MF android/hardware/$(DEPDIR)/haltest-hardware.Tpo -c -o android/hardware/haltest-hardware.obj `if test -f 'android/hardware/hardware.c'; then $(CYGPATH_W) 'android/hardware/hardware.c'; else $(CYGPATH_W) '$(srcdir)/android/hardware/hardware.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/hardware/$(DEPDIR)/haltest-hardware.Tpo android/hardware/$(DEPDIR)/haltest-hardware.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hardware/hardware.c' object='android/hardware/haltest-hardware.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/hardware/haltest-hardware.obj `if test -f 'android/hardware/hardware.c'; then $(CYGPATH_W) 'android/hardware/hardware.c'; else $(CYGPATH_W) '$(srcdir)/android/hardware/hardware.c'; fi`
+
+android/haltest-hal-utils.o: android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/haltest-hal-utils.o -MD -MP -MF android/$(DEPDIR)/haltest-hal-utils.Tpo -c -o android/haltest-hal-utils.o `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/haltest-hal-utils.Tpo android/$(DEPDIR)/haltest-hal-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-utils.c' object='android/haltest-hal-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/haltest-hal-utils.o `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+
+android/haltest-hal-utils.obj: android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/haltest-hal-utils.obj -MD -MP -MF android/$(DEPDIR)/haltest-hal-utils.Tpo -c -o android/haltest-hal-utils.obj `if test -f 'android/hal-utils.c'; then $(CYGPATH_W) 'android/hal-utils.c'; else $(CYGPATH_W) '$(srcdir)/android/hal-utils.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/haltest-hal-utils.Tpo android/$(DEPDIR)/haltest-hal-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-utils.c' object='android/haltest-hal-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_haltest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/haltest-hal-utils.obj `if test -f 'android/hal-utils.c'; then $(CYGPATH_W) 'android/hal-utils.c'; else $(CYGPATH_W) '$(srcdir)/android/hal-utils.c'; fi`
+
+emulator/android_ipc_tester-hciemu.o: emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-hciemu.o -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-hciemu.Tpo -c -o emulator/android_ipc_tester-hciemu.o `test -f 'emulator/hciemu.c' || echo '$(srcdir)/'`emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-hciemu.Tpo emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/hciemu.c' object='emulator/android_ipc_tester-hciemu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-hciemu.o `test -f 'emulator/hciemu.c' || echo '$(srcdir)/'`emulator/hciemu.c
+
+emulator/android_ipc_tester-hciemu.obj: emulator/hciemu.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-hciemu.obj -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-hciemu.Tpo -c -o emulator/android_ipc_tester-hciemu.obj `if test -f 'emulator/hciemu.c'; then $(CYGPATH_W) 'emulator/hciemu.c'; else $(CYGPATH_W) '$(srcdir)/emulator/hciemu.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-hciemu.Tpo emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/hciemu.c' object='emulator/android_ipc_tester-hciemu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-hciemu.obj `if test -f 'emulator/hciemu.c'; then $(CYGPATH_W) 'emulator/hciemu.c'; else $(CYGPATH_W) '$(srcdir)/emulator/hciemu.c'; fi`
+
+emulator/android_ipc_tester-vhci.o: emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-vhci.o -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-vhci.Tpo -c -o emulator/android_ipc_tester-vhci.o `test -f 'emulator/vhci.c' || echo '$(srcdir)/'`emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-vhci.Tpo emulator/$(DEPDIR)/android_ipc_tester-vhci.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/vhci.c' object='emulator/android_ipc_tester-vhci.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-vhci.o `test -f 'emulator/vhci.c' || echo '$(srcdir)/'`emulator/vhci.c
+
+emulator/android_ipc_tester-vhci.obj: emulator/vhci.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-vhci.obj -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-vhci.Tpo -c -o emulator/android_ipc_tester-vhci.obj `if test -f 'emulator/vhci.c'; then $(CYGPATH_W) 'emulator/vhci.c'; else $(CYGPATH_W) '$(srcdir)/emulator/vhci.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-vhci.Tpo emulator/$(DEPDIR)/android_ipc_tester-vhci.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/vhci.c' object='emulator/android_ipc_tester-vhci.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-vhci.obj `if test -f 'emulator/vhci.c'; then $(CYGPATH_W) 'emulator/vhci.c'; else $(CYGPATH_W) '$(srcdir)/emulator/vhci.c'; fi`
+
+emulator/android_ipc_tester-btdev.o: emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-btdev.o -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-btdev.Tpo -c -o emulator/android_ipc_tester-btdev.o `test -f 'emulator/btdev.c' || echo '$(srcdir)/'`emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-btdev.Tpo emulator/$(DEPDIR)/android_ipc_tester-btdev.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/btdev.c' object='emulator/android_ipc_tester-btdev.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-btdev.o `test -f 'emulator/btdev.c' || echo '$(srcdir)/'`emulator/btdev.c
+
+emulator/android_ipc_tester-btdev.obj: emulator/btdev.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-btdev.obj -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-btdev.Tpo -c -o emulator/android_ipc_tester-btdev.obj `if test -f 'emulator/btdev.c'; then $(CYGPATH_W) 'emulator/btdev.c'; else $(CYGPATH_W) '$(srcdir)/emulator/btdev.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-btdev.Tpo emulator/$(DEPDIR)/android_ipc_tester-btdev.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/btdev.c' object='emulator/android_ipc_tester-btdev.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-btdev.obj `if test -f 'emulator/btdev.c'; then $(CYGPATH_W) 'emulator/btdev.c'; else $(CYGPATH_W) '$(srcdir)/emulator/btdev.c'; fi`
+
+emulator/android_ipc_tester-bthost.o: emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-bthost.o -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-bthost.Tpo -c -o emulator/android_ipc_tester-bthost.o `test -f 'emulator/bthost.c' || echo '$(srcdir)/'`emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-bthost.Tpo emulator/$(DEPDIR)/android_ipc_tester-bthost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/bthost.c' object='emulator/android_ipc_tester-bthost.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-bthost.o `test -f 'emulator/bthost.c' || echo '$(srcdir)/'`emulator/bthost.c
+
+emulator/android_ipc_tester-bthost.obj: emulator/bthost.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-bthost.obj -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-bthost.Tpo -c -o emulator/android_ipc_tester-bthost.obj `if test -f 'emulator/bthost.c'; then $(CYGPATH_W) 'emulator/bthost.c'; else $(CYGPATH_W) '$(srcdir)/emulator/bthost.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-bthost.Tpo emulator/$(DEPDIR)/android_ipc_tester-bthost.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/bthost.c' object='emulator/android_ipc_tester-bthost.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-bthost.obj `if test -f 'emulator/bthost.c'; then $(CYGPATH_W) 'emulator/bthost.c'; else $(CYGPATH_W) '$(srcdir)/emulator/bthost.c'; fi`
+
+emulator/android_ipc_tester-smp.o: emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-smp.o -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-smp.Tpo -c -o emulator/android_ipc_tester-smp.o `test -f 'emulator/smp.c' || echo '$(srcdir)/'`emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-smp.Tpo emulator/$(DEPDIR)/android_ipc_tester-smp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/smp.c' object='emulator/android_ipc_tester-smp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-smp.o `test -f 'emulator/smp.c' || echo '$(srcdir)/'`emulator/smp.c
+
+emulator/android_ipc_tester-smp.obj: emulator/smp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT emulator/android_ipc_tester-smp.obj -MD -MP -MF emulator/$(DEPDIR)/android_ipc_tester-smp.Tpo -c -o emulator/android_ipc_tester-smp.obj `if test -f 'emulator/smp.c'; then $(CYGPATH_W) 'emulator/smp.c'; else $(CYGPATH_W) '$(srcdir)/emulator/smp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) emulator/$(DEPDIR)/android_ipc_tester-smp.Tpo emulator/$(DEPDIR)/android_ipc_tester-smp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='emulator/smp.c' object='emulator/android_ipc_tester-smp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o emulator/android_ipc_tester-smp.obj `if test -f 'emulator/smp.c'; then $(CYGPATH_W) 'emulator/smp.c'; else $(CYGPATH_W) '$(srcdir)/emulator/smp.c'; fi`
+
+android/ipc_tester-hal-utils.o: android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/ipc_tester-hal-utils.o -MD -MP -MF android/$(DEPDIR)/ipc_tester-hal-utils.Tpo -c -o android/ipc_tester-hal-utils.o `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/ipc_tester-hal-utils.Tpo android/$(DEPDIR)/ipc_tester-hal-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-utils.c' object='android/ipc_tester-hal-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/ipc_tester-hal-utils.o `test -f 'android/hal-utils.c' || echo '$(srcdir)/'`android/hal-utils.c
+
+android/ipc_tester-hal-utils.obj: android/hal-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/ipc_tester-hal-utils.obj -MD -MP -MF android/$(DEPDIR)/ipc_tester-hal-utils.Tpo -c -o android/ipc_tester-hal-utils.obj `if test -f 'android/hal-utils.c'; then $(CYGPATH_W) 'android/hal-utils.c'; else $(CYGPATH_W) '$(srcdir)/android/hal-utils.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/ipc_tester-hal-utils.Tpo android/$(DEPDIR)/ipc_tester-hal-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/hal-utils.c' object='android/ipc_tester-hal-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/ipc_tester-hal-utils.obj `if test -f 'android/hal-utils.c'; then $(CYGPATH_W) 'android/hal-utils.c'; else $(CYGPATH_W) '$(srcdir)/android/hal-utils.c'; fi`
+
+android/ipc_tester-ipc-tester.o: android/ipc-tester.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/ipc_tester-ipc-tester.o -MD -MP -MF android/$(DEPDIR)/ipc_tester-ipc-tester.Tpo -c -o android/ipc_tester-ipc-tester.o `test -f 'android/ipc-tester.c' || echo '$(srcdir)/'`android/ipc-tester.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/ipc_tester-ipc-tester.Tpo android/$(DEPDIR)/ipc_tester-ipc-tester.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/ipc-tester.c' object='android/ipc_tester-ipc-tester.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/ipc_tester-ipc-tester.o `test -f 'android/ipc-tester.c' || echo '$(srcdir)/'`android/ipc-tester.c
+
+android/ipc_tester-ipc-tester.obj: android/ipc-tester.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT android/ipc_tester-ipc-tester.obj -MD -MP -MF android/$(DEPDIR)/ipc_tester-ipc-tester.Tpo -c -o android/ipc_tester-ipc-tester.obj `if test -f 'android/ipc-tester.c'; then $(CYGPATH_W) 'android/ipc-tester.c'; else $(CYGPATH_W) '$(srcdir)/android/ipc-tester.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) android/$(DEPDIR)/ipc_tester-ipc-tester.Tpo android/$(DEPDIR)/ipc_tester-ipc-tester.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='android/ipc-tester.c' object='android/ipc_tester-ipc-tester.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(android_ipc_tester_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o android/ipc_tester-ipc-tester.obj `if test -f 'android/ipc-tester.c'; then $(CYGPATH_W) 'android/ipc-tester.c'; else $(CYGPATH_W) '$(srcdir)/android/ipc-tester.c'; fi`
+
+btio/obexd-btio.o: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT btio/obexd-btio.o -MD -MP -MF btio/$(DEPDIR)/obexd-btio.Tpo -c -o btio/obexd-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/obexd-btio.Tpo btio/$(DEPDIR)/obexd-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/obexd-btio.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o btio/obexd-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+
+btio/obexd-btio.obj: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT btio/obexd-btio.obj -MD -MP -MF btio/$(DEPDIR)/obexd-btio.Tpo -c -o btio/obexd-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/obexd-btio.Tpo btio/$(DEPDIR)/obexd-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/obexd-btio.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o btio/obexd-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+
+gobex/obexd-gobex.o: gobex/gobex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex.Tpo -c -o gobex/obexd-gobex.o `test -f 'gobex/gobex.c' || echo '$(srcdir)/'`gobex/gobex.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex.Tpo gobex/$(DEPDIR)/obexd-gobex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex.c' object='gobex/obexd-gobex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex.o `test -f 'gobex/gobex.c' || echo '$(srcdir)/'`gobex/gobex.c
+
+gobex/obexd-gobex.obj: gobex/gobex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex.Tpo -c -o gobex/obexd-gobex.obj `if test -f 'gobex/gobex.c'; then $(CYGPATH_W) 'gobex/gobex.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex.Tpo gobex/$(DEPDIR)/obexd-gobex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex.c' object='gobex/obexd-gobex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex.obj `if test -f 'gobex/gobex.c'; then $(CYGPATH_W) 'gobex/gobex.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex.c'; fi`
+
+gobex/obexd-gobex-defs.o: gobex/gobex-defs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-defs.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-defs.Tpo -c -o gobex/obexd-gobex-defs.o `test -f 'gobex/gobex-defs.c' || echo '$(srcdir)/'`gobex/gobex-defs.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-defs.Tpo gobex/$(DEPDIR)/obexd-gobex-defs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-defs.c' object='gobex/obexd-gobex-defs.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-defs.o `test -f 'gobex/gobex-defs.c' || echo '$(srcdir)/'`gobex/gobex-defs.c
+
+gobex/obexd-gobex-defs.obj: gobex/gobex-defs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-defs.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-defs.Tpo -c -o gobex/obexd-gobex-defs.obj `if test -f 'gobex/gobex-defs.c'; then $(CYGPATH_W) 'gobex/gobex-defs.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-defs.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-defs.Tpo gobex/$(DEPDIR)/obexd-gobex-defs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-defs.c' object='gobex/obexd-gobex-defs.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-defs.obj `if test -f 'gobex/gobex-defs.c'; then $(CYGPATH_W) 'gobex/gobex-defs.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-defs.c'; fi`
+
+gobex/obexd-gobex-packet.o: gobex/gobex-packet.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-packet.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-packet.Tpo -c -o gobex/obexd-gobex-packet.o `test -f 'gobex/gobex-packet.c' || echo '$(srcdir)/'`gobex/gobex-packet.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-packet.Tpo gobex/$(DEPDIR)/obexd-gobex-packet.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-packet.c' object='gobex/obexd-gobex-packet.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-packet.o `test -f 'gobex/gobex-packet.c' || echo '$(srcdir)/'`gobex/gobex-packet.c
+
+gobex/obexd-gobex-packet.obj: gobex/gobex-packet.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-packet.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-packet.Tpo -c -o gobex/obexd-gobex-packet.obj `if test -f 'gobex/gobex-packet.c'; then $(CYGPATH_W) 'gobex/gobex-packet.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-packet.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-packet.Tpo gobex/$(DEPDIR)/obexd-gobex-packet.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-packet.c' object='gobex/obexd-gobex-packet.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-packet.obj `if test -f 'gobex/gobex-packet.c'; then $(CYGPATH_W) 'gobex/gobex-packet.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-packet.c'; fi`
+
+gobex/obexd-gobex-header.o: gobex/gobex-header.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-header.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-header.Tpo -c -o gobex/obexd-gobex-header.o `test -f 'gobex/gobex-header.c' || echo '$(srcdir)/'`gobex/gobex-header.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-header.Tpo gobex/$(DEPDIR)/obexd-gobex-header.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-header.c' object='gobex/obexd-gobex-header.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-header.o `test -f 'gobex/gobex-header.c' || echo '$(srcdir)/'`gobex/gobex-header.c
+
+gobex/obexd-gobex-header.obj: gobex/gobex-header.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-header.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-header.Tpo -c -o gobex/obexd-gobex-header.obj `if test -f 'gobex/gobex-header.c'; then $(CYGPATH_W) 'gobex/gobex-header.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-header.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-header.Tpo gobex/$(DEPDIR)/obexd-gobex-header.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-header.c' object='gobex/obexd-gobex-header.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-header.obj `if test -f 'gobex/gobex-header.c'; then $(CYGPATH_W) 'gobex/gobex-header.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-header.c'; fi`
+
+gobex/obexd-gobex-transfer.o: gobex/gobex-transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-transfer.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-transfer.Tpo -c -o gobex/obexd-gobex-transfer.o `test -f 'gobex/gobex-transfer.c' || echo '$(srcdir)/'`gobex/gobex-transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-transfer.Tpo gobex/$(DEPDIR)/obexd-gobex-transfer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-transfer.c' object='gobex/obexd-gobex-transfer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-transfer.o `test -f 'gobex/gobex-transfer.c' || echo '$(srcdir)/'`gobex/gobex-transfer.c
+
+gobex/obexd-gobex-transfer.obj: gobex/gobex-transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-transfer.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-transfer.Tpo -c -o gobex/obexd-gobex-transfer.obj `if test -f 'gobex/gobex-transfer.c'; then $(CYGPATH_W) 'gobex/gobex-transfer.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-transfer.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-transfer.Tpo gobex/$(DEPDIR)/obexd-gobex-transfer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-transfer.c' object='gobex/obexd-gobex-transfer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-transfer.obj `if test -f 'gobex/gobex-transfer.c'; then $(CYGPATH_W) 'gobex/gobex-transfer.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-transfer.c'; fi`
+
+gobex/obexd-gobex-apparam.o: gobex/gobex-apparam.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-apparam.o -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-apparam.Tpo -c -o gobex/obexd-gobex-apparam.o `test -f 'gobex/gobex-apparam.c' || echo '$(srcdir)/'`gobex/gobex-apparam.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-apparam.Tpo gobex/$(DEPDIR)/obexd-gobex-apparam.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-apparam.c' object='gobex/obexd-gobex-apparam.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-apparam.o `test -f 'gobex/gobex-apparam.c' || echo '$(srcdir)/'`gobex/gobex-apparam.c
+
+gobex/obexd-gobex-apparam.obj: gobex/gobex-apparam.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gobex/obexd-gobex-apparam.obj -MD -MP -MF gobex/$(DEPDIR)/obexd-gobex-apparam.Tpo -c -o gobex/obexd-gobex-apparam.obj `if test -f 'gobex/gobex-apparam.c'; then $(CYGPATH_W) 'gobex/gobex-apparam.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-apparam.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) gobex/$(DEPDIR)/obexd-gobex-apparam.Tpo gobex/$(DEPDIR)/obexd-gobex-apparam.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gobex/gobex-apparam.c' object='gobex/obexd-gobex-apparam.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gobex/obexd-gobex-apparam.obj `if test -f 'gobex/gobex-apparam.c'; then $(CYGPATH_W) 'gobex/gobex-apparam.c'; else $(CYGPATH_W) '$(srcdir)/gobex/gobex-apparam.c'; fi`
+
+obexd/plugins/obexd-filesystem.o: obexd/plugins/filesystem.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-filesystem.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-filesystem.Tpo -c -o obexd/plugins/obexd-filesystem.o `test -f 'obexd/plugins/filesystem.c' || echo '$(srcdir)/'`obexd/plugins/filesystem.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-filesystem.Tpo obexd/plugins/$(DEPDIR)/obexd-filesystem.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/filesystem.c' object='obexd/plugins/obexd-filesystem.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-filesystem.o `test -f 'obexd/plugins/filesystem.c' || echo '$(srcdir)/'`obexd/plugins/filesystem.c
+
+obexd/plugins/obexd-filesystem.obj: obexd/plugins/filesystem.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-filesystem.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-filesystem.Tpo -c -o obexd/plugins/obexd-filesystem.obj `if test -f 'obexd/plugins/filesystem.c'; then $(CYGPATH_W) 'obexd/plugins/filesystem.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/filesystem.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-filesystem.Tpo obexd/plugins/$(DEPDIR)/obexd-filesystem.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/filesystem.c' object='obexd/plugins/obexd-filesystem.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-filesystem.obj `if test -f 'obexd/plugins/filesystem.c'; then $(CYGPATH_W) 'obexd/plugins/filesystem.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/filesystem.c'; fi`
+
+obexd/plugins/obexd-bluetooth.o: obexd/plugins/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-bluetooth.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-bluetooth.Tpo -c -o obexd/plugins/obexd-bluetooth.o `test -f 'obexd/plugins/bluetooth.c' || echo '$(srcdir)/'`obexd/plugins/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-bluetooth.Tpo obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/bluetooth.c' object='obexd/plugins/obexd-bluetooth.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-bluetooth.o `test -f 'obexd/plugins/bluetooth.c' || echo '$(srcdir)/'`obexd/plugins/bluetooth.c
+
+obexd/plugins/obexd-bluetooth.obj: obexd/plugins/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-bluetooth.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-bluetooth.Tpo -c -o obexd/plugins/obexd-bluetooth.obj `if test -f 'obexd/plugins/bluetooth.c'; then $(CYGPATH_W) 'obexd/plugins/bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/bluetooth.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-bluetooth.Tpo obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/bluetooth.c' object='obexd/plugins/obexd-bluetooth.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-bluetooth.obj `if test -f 'obexd/plugins/bluetooth.c'; then $(CYGPATH_W) 'obexd/plugins/bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/bluetooth.c'; fi`
+
+obexd/plugins/obexd-pcsuite.o: obexd/plugins/pcsuite.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-pcsuite.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-pcsuite.Tpo -c -o obexd/plugins/obexd-pcsuite.o `test -f 'obexd/plugins/pcsuite.c' || echo '$(srcdir)/'`obexd/plugins/pcsuite.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-pcsuite.Tpo obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/pcsuite.c' object='obexd/plugins/obexd-pcsuite.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-pcsuite.o `test -f 'obexd/plugins/pcsuite.c' || echo '$(srcdir)/'`obexd/plugins/pcsuite.c
+
+obexd/plugins/obexd-pcsuite.obj: obexd/plugins/pcsuite.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-pcsuite.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-pcsuite.Tpo -c -o obexd/plugins/obexd-pcsuite.obj `if test -f 'obexd/plugins/pcsuite.c'; then $(CYGPATH_W) 'obexd/plugins/pcsuite.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/pcsuite.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-pcsuite.Tpo obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/pcsuite.c' object='obexd/plugins/obexd-pcsuite.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-pcsuite.obj `if test -f 'obexd/plugins/pcsuite.c'; then $(CYGPATH_W) 'obexd/plugins/pcsuite.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/pcsuite.c'; fi`
+
+obexd/plugins/obexd-opp.o: obexd/plugins/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-opp.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-opp.Tpo -c -o obexd/plugins/obexd-opp.o `test -f 'obexd/plugins/opp.c' || echo '$(srcdir)/'`obexd/plugins/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-opp.Tpo obexd/plugins/$(DEPDIR)/obexd-opp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/opp.c' object='obexd/plugins/obexd-opp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-opp.o `test -f 'obexd/plugins/opp.c' || echo '$(srcdir)/'`obexd/plugins/opp.c
+
+obexd/plugins/obexd-opp.obj: obexd/plugins/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-opp.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-opp.Tpo -c -o obexd/plugins/obexd-opp.obj `if test -f 'obexd/plugins/opp.c'; then $(CYGPATH_W) 'obexd/plugins/opp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/opp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-opp.Tpo obexd/plugins/$(DEPDIR)/obexd-opp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/opp.c' object='obexd/plugins/obexd-opp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-opp.obj `if test -f 'obexd/plugins/opp.c'; then $(CYGPATH_W) 'obexd/plugins/opp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/opp.c'; fi`
+
+obexd/plugins/obexd-ftp.o: obexd/plugins/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-ftp.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-ftp.Tpo -c -o obexd/plugins/obexd-ftp.o `test -f 'obexd/plugins/ftp.c' || echo '$(srcdir)/'`obexd/plugins/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-ftp.Tpo obexd/plugins/$(DEPDIR)/obexd-ftp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/ftp.c' object='obexd/plugins/obexd-ftp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-ftp.o `test -f 'obexd/plugins/ftp.c' || echo '$(srcdir)/'`obexd/plugins/ftp.c
+
+obexd/plugins/obexd-ftp.obj: obexd/plugins/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-ftp.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-ftp.Tpo -c -o obexd/plugins/obexd-ftp.obj `if test -f 'obexd/plugins/ftp.c'; then $(CYGPATH_W) 'obexd/plugins/ftp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/ftp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-ftp.Tpo obexd/plugins/$(DEPDIR)/obexd-ftp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/ftp.c' object='obexd/plugins/obexd-ftp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-ftp.obj `if test -f 'obexd/plugins/ftp.c'; then $(CYGPATH_W) 'obexd/plugins/ftp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/ftp.c'; fi`
+
+obexd/plugins/obexd-irmc.o: obexd/plugins/irmc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-irmc.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-irmc.Tpo -c -o obexd/plugins/obexd-irmc.o `test -f 'obexd/plugins/irmc.c' || echo '$(srcdir)/'`obexd/plugins/irmc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-irmc.Tpo obexd/plugins/$(DEPDIR)/obexd-irmc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/irmc.c' object='obexd/plugins/obexd-irmc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-irmc.o `test -f 'obexd/plugins/irmc.c' || echo '$(srcdir)/'`obexd/plugins/irmc.c
+
+obexd/plugins/obexd-irmc.obj: obexd/plugins/irmc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-irmc.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-irmc.Tpo -c -o obexd/plugins/obexd-irmc.obj `if test -f 'obexd/plugins/irmc.c'; then $(CYGPATH_W) 'obexd/plugins/irmc.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/irmc.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-irmc.Tpo obexd/plugins/$(DEPDIR)/obexd-irmc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/irmc.c' object='obexd/plugins/obexd-irmc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-irmc.obj `if test -f 'obexd/plugins/irmc.c'; then $(CYGPATH_W) 'obexd/plugins/irmc.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/irmc.c'; fi`
+
+obexd/plugins/obexd-pbap.o: obexd/plugins/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-pbap.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-pbap.Tpo -c -o obexd/plugins/obexd-pbap.o `test -f 'obexd/plugins/pbap.c' || echo '$(srcdir)/'`obexd/plugins/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-pbap.Tpo obexd/plugins/$(DEPDIR)/obexd-pbap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/pbap.c' object='obexd/plugins/obexd-pbap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-pbap.o `test -f 'obexd/plugins/pbap.c' || echo '$(srcdir)/'`obexd/plugins/pbap.c
+
+obexd/plugins/obexd-pbap.obj: obexd/plugins/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-pbap.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-pbap.Tpo -c -o obexd/plugins/obexd-pbap.obj `if test -f 'obexd/plugins/pbap.c'; then $(CYGPATH_W) 'obexd/plugins/pbap.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/pbap.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-pbap.Tpo obexd/plugins/$(DEPDIR)/obexd-pbap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/pbap.c' object='obexd/plugins/obexd-pbap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-pbap.obj `if test -f 'obexd/plugins/pbap.c'; then $(CYGPATH_W) 'obexd/plugins/pbap.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/pbap.c'; fi`
+
+obexd/plugins/obexd-vcard.o: obexd/plugins/vcard.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-vcard.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-vcard.Tpo -c -o obexd/plugins/obexd-vcard.o `test -f 'obexd/plugins/vcard.c' || echo '$(srcdir)/'`obexd/plugins/vcard.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-vcard.Tpo obexd/plugins/$(DEPDIR)/obexd-vcard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/vcard.c' object='obexd/plugins/obexd-vcard.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-vcard.o `test -f 'obexd/plugins/vcard.c' || echo '$(srcdir)/'`obexd/plugins/vcard.c
+
+obexd/plugins/obexd-vcard.obj: obexd/plugins/vcard.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-vcard.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-vcard.Tpo -c -o obexd/plugins/obexd-vcard.obj `if test -f 'obexd/plugins/vcard.c'; then $(CYGPATH_W) 'obexd/plugins/vcard.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/vcard.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-vcard.Tpo obexd/plugins/$(DEPDIR)/obexd-vcard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/vcard.c' object='obexd/plugins/obexd-vcard.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-vcard.obj `if test -f 'obexd/plugins/vcard.c'; then $(CYGPATH_W) 'obexd/plugins/vcard.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/vcard.c'; fi`
+
+obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.o: obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Tpo -c -o obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.o `test -f 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c' || echo '$(srcdir)/'`obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Tpo obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c' object='obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.o `test -f 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c' || echo '$(srcdir)/'`obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
+
+obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.obj: obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Tpo -c -o obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.obj `if test -f 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; then $(CYGPATH_W) 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Tpo obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c' object='obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-phonebook-@PLUGIN_PHONEBOOK@.obj `if test -f 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; then $(CYGPATH_W) 'obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c'; fi`
+
+obexd/plugins/obexd-mas.o: obexd/plugins/mas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-mas.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-mas.Tpo -c -o obexd/plugins/obexd-mas.o `test -f 'obexd/plugins/mas.c' || echo '$(srcdir)/'`obexd/plugins/mas.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-mas.Tpo obexd/plugins/$(DEPDIR)/obexd-mas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/mas.c' object='obexd/plugins/obexd-mas.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-mas.o `test -f 'obexd/plugins/mas.c' || echo '$(srcdir)/'`obexd/plugins/mas.c
+
+obexd/plugins/obexd-mas.obj: obexd/plugins/mas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-mas.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-mas.Tpo -c -o obexd/plugins/obexd-mas.obj `if test -f 'obexd/plugins/mas.c'; then $(CYGPATH_W) 'obexd/plugins/mas.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/mas.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-mas.Tpo obexd/plugins/$(DEPDIR)/obexd-mas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/mas.c' object='obexd/plugins/obexd-mas.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-mas.obj `if test -f 'obexd/plugins/mas.c'; then $(CYGPATH_W) 'obexd/plugins/mas.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/mas.c'; fi`
+
+obexd/plugins/obexd-messages-dummy.o: obexd/plugins/messages-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-messages-dummy.o -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Tpo -c -o obexd/plugins/obexd-messages-dummy.o `test -f 'obexd/plugins/messages-dummy.c' || echo '$(srcdir)/'`obexd/plugins/messages-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Tpo obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/messages-dummy.c' object='obexd/plugins/obexd-messages-dummy.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-messages-dummy.o `test -f 'obexd/plugins/messages-dummy.c' || echo '$(srcdir)/'`obexd/plugins/messages-dummy.c
+
+obexd/plugins/obexd-messages-dummy.obj: obexd/plugins/messages-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/plugins/obexd-messages-dummy.obj -MD -MP -MF obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Tpo -c -o obexd/plugins/obexd-messages-dummy.obj `if test -f 'obexd/plugins/messages-dummy.c'; then $(CYGPATH_W) 'obexd/plugins/messages-dummy.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/messages-dummy.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Tpo obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/plugins/messages-dummy.c' object='obexd/plugins/obexd-messages-dummy.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/plugins/obexd-messages-dummy.obj `if test -f 'obexd/plugins/messages-dummy.c'; then $(CYGPATH_W) 'obexd/plugins/messages-dummy.c'; else $(CYGPATH_W) '$(srcdir)/obexd/plugins/messages-dummy.c'; fi`
+
+obexd/client/obexd-mns.o: obexd/client/mns.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-mns.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-mns.Tpo -c -o obexd/client/obexd-mns.o `test -f 'obexd/client/mns.c' || echo '$(srcdir)/'`obexd/client/mns.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-mns.Tpo obexd/client/$(DEPDIR)/obexd-mns.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/mns.c' object='obexd/client/obexd-mns.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-mns.o `test -f 'obexd/client/mns.c' || echo '$(srcdir)/'`obexd/client/mns.c
+
+obexd/client/obexd-mns.obj: obexd/client/mns.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-mns.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-mns.Tpo -c -o obexd/client/obexd-mns.obj `if test -f 'obexd/client/mns.c'; then $(CYGPATH_W) 'obexd/client/mns.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/mns.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-mns.Tpo obexd/client/$(DEPDIR)/obexd-mns.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/mns.c' object='obexd/client/obexd-mns.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-mns.obj `if test -f 'obexd/client/mns.c'; then $(CYGPATH_W) 'obexd/client/mns.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/mns.c'; fi`
+
+obexd/src/obexd-main.o: obexd/src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-main.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-main.Tpo -c -o obexd/src/obexd-main.o `test -f 'obexd/src/main.c' || echo '$(srcdir)/'`obexd/src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-main.Tpo obexd/src/$(DEPDIR)/obexd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/main.c' object='obexd/src/obexd-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-main.o `test -f 'obexd/src/main.c' || echo '$(srcdir)/'`obexd/src/main.c
+
+obexd/src/obexd-main.obj: obexd/src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-main.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-main.Tpo -c -o obexd/src/obexd-main.obj `if test -f 'obexd/src/main.c'; then $(CYGPATH_W) 'obexd/src/main.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/main.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-main.Tpo obexd/src/$(DEPDIR)/obexd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/main.c' object='obexd/src/obexd-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-main.obj `if test -f 'obexd/src/main.c'; then $(CYGPATH_W) 'obexd/src/main.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/main.c'; fi`
+
+obexd/src/obexd-plugin.o: obexd/src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-plugin.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-plugin.Tpo -c -o obexd/src/obexd-plugin.o `test -f 'obexd/src/plugin.c' || echo '$(srcdir)/'`obexd/src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-plugin.Tpo obexd/src/$(DEPDIR)/obexd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/plugin.c' object='obexd/src/obexd-plugin.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-plugin.o `test -f 'obexd/src/plugin.c' || echo '$(srcdir)/'`obexd/src/plugin.c
+
+obexd/src/obexd-plugin.obj: obexd/src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-plugin.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-plugin.Tpo -c -o obexd/src/obexd-plugin.obj `if test -f 'obexd/src/plugin.c'; then $(CYGPATH_W) 'obexd/src/plugin.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/plugin.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-plugin.Tpo obexd/src/$(DEPDIR)/obexd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/plugin.c' object='obexd/src/obexd-plugin.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-plugin.obj `if test -f 'obexd/src/plugin.c'; then $(CYGPATH_W) 'obexd/src/plugin.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/plugin.c'; fi`
+
+obexd/src/obexd-log.o: obexd/src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-log.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-log.Tpo -c -o obexd/src/obexd-log.o `test -f 'obexd/src/log.c' || echo '$(srcdir)/'`obexd/src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-log.Tpo obexd/src/$(DEPDIR)/obexd-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/log.c' object='obexd/src/obexd-log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-log.o `test -f 'obexd/src/log.c' || echo '$(srcdir)/'`obexd/src/log.c
+
+obexd/src/obexd-log.obj: obexd/src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-log.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-log.Tpo -c -o obexd/src/obexd-log.obj `if test -f 'obexd/src/log.c'; then $(CYGPATH_W) 'obexd/src/log.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/log.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-log.Tpo obexd/src/$(DEPDIR)/obexd-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/log.c' object='obexd/src/obexd-log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-log.obj `if test -f 'obexd/src/log.c'; then $(CYGPATH_W) 'obexd/src/log.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/log.c'; fi`
+
+obexd/src/obexd-manager.o: obexd/src/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-manager.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-manager.Tpo -c -o obexd/src/obexd-manager.o `test -f 'obexd/src/manager.c' || echo '$(srcdir)/'`obexd/src/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-manager.Tpo obexd/src/$(DEPDIR)/obexd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/manager.c' object='obexd/src/obexd-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-manager.o `test -f 'obexd/src/manager.c' || echo '$(srcdir)/'`obexd/src/manager.c
+
+obexd/src/obexd-manager.obj: obexd/src/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-manager.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-manager.Tpo -c -o obexd/src/obexd-manager.obj `if test -f 'obexd/src/manager.c'; then $(CYGPATH_W) 'obexd/src/manager.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-manager.Tpo obexd/src/$(DEPDIR)/obexd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/manager.c' object='obexd/src/obexd-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-manager.obj `if test -f 'obexd/src/manager.c'; then $(CYGPATH_W) 'obexd/src/manager.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/manager.c'; fi`
+
+obexd/src/obexd-obex.o: obexd/src/obex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-obex.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-obex.Tpo -c -o obexd/src/obexd-obex.o `test -f 'obexd/src/obex.c' || echo '$(srcdir)/'`obexd/src/obex.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-obex.Tpo obexd/src/$(DEPDIR)/obexd-obex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/obex.c' object='obexd/src/obexd-obex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-obex.o `test -f 'obexd/src/obex.c' || echo '$(srcdir)/'`obexd/src/obex.c
+
+obexd/src/obexd-obex.obj: obexd/src/obex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-obex.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-obex.Tpo -c -o obexd/src/obexd-obex.obj `if test -f 'obexd/src/obex.c'; then $(CYGPATH_W) 'obexd/src/obex.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/obex.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-obex.Tpo obexd/src/$(DEPDIR)/obexd-obex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/obex.c' object='obexd/src/obexd-obex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-obex.obj `if test -f 'obexd/src/obex.c'; then $(CYGPATH_W) 'obexd/src/obex.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/obex.c'; fi`
+
+obexd/src/obexd-mimetype.o: obexd/src/mimetype.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-mimetype.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-mimetype.Tpo -c -o obexd/src/obexd-mimetype.o `test -f 'obexd/src/mimetype.c' || echo '$(srcdir)/'`obexd/src/mimetype.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-mimetype.Tpo obexd/src/$(DEPDIR)/obexd-mimetype.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/mimetype.c' object='obexd/src/obexd-mimetype.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-mimetype.o `test -f 'obexd/src/mimetype.c' || echo '$(srcdir)/'`obexd/src/mimetype.c
+
+obexd/src/obexd-mimetype.obj: obexd/src/mimetype.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-mimetype.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-mimetype.Tpo -c -o obexd/src/obexd-mimetype.obj `if test -f 'obexd/src/mimetype.c'; then $(CYGPATH_W) 'obexd/src/mimetype.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/mimetype.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-mimetype.Tpo obexd/src/$(DEPDIR)/obexd-mimetype.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/mimetype.c' object='obexd/src/obexd-mimetype.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-mimetype.obj `if test -f 'obexd/src/mimetype.c'; then $(CYGPATH_W) 'obexd/src/mimetype.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/mimetype.c'; fi`
+
+obexd/src/obexd-service.o: obexd/src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-service.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-service.Tpo -c -o obexd/src/obexd-service.o `test -f 'obexd/src/service.c' || echo '$(srcdir)/'`obexd/src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-service.Tpo obexd/src/$(DEPDIR)/obexd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/service.c' object='obexd/src/obexd-service.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-service.o `test -f 'obexd/src/service.c' || echo '$(srcdir)/'`obexd/src/service.c
+
+obexd/src/obexd-service.obj: obexd/src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-service.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-service.Tpo -c -o obexd/src/obexd-service.obj `if test -f 'obexd/src/service.c'; then $(CYGPATH_W) 'obexd/src/service.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/service.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-service.Tpo obexd/src/$(DEPDIR)/obexd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/service.c' object='obexd/src/obexd-service.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-service.obj `if test -f 'obexd/src/service.c'; then $(CYGPATH_W) 'obexd/src/service.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/service.c'; fi`
+
+obexd/src/obexd-transport.o: obexd/src/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-transport.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-transport.Tpo -c -o obexd/src/obexd-transport.o `test -f 'obexd/src/transport.c' || echo '$(srcdir)/'`obexd/src/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-transport.Tpo obexd/src/$(DEPDIR)/obexd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/transport.c' object='obexd/src/obexd-transport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-transport.o `test -f 'obexd/src/transport.c' || echo '$(srcdir)/'`obexd/src/transport.c
+
+obexd/src/obexd-transport.obj: obexd/src/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-transport.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-transport.Tpo -c -o obexd/src/obexd-transport.obj `if test -f 'obexd/src/transport.c'; then $(CYGPATH_W) 'obexd/src/transport.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/transport.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-transport.Tpo obexd/src/$(DEPDIR)/obexd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/transport.c' object='obexd/src/obexd-transport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-transport.obj `if test -f 'obexd/src/transport.c'; then $(CYGPATH_W) 'obexd/src/transport.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/transport.c'; fi`
+
+obexd/src/obexd-server.o: obexd/src/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-server.o -MD -MP -MF obexd/src/$(DEPDIR)/obexd-server.Tpo -c -o obexd/src/obexd-server.o `test -f 'obexd/src/server.c' || echo '$(srcdir)/'`obexd/src/server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-server.Tpo obexd/src/$(DEPDIR)/obexd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/server.c' object='obexd/src/obexd-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-server.o `test -f 'obexd/src/server.c' || echo '$(srcdir)/'`obexd/src/server.c
+
+obexd/src/obexd-server.obj: obexd/src/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/src/obexd-server.obj -MD -MP -MF obexd/src/$(DEPDIR)/obexd-server.Tpo -c -o obexd/src/obexd-server.obj `if test -f 'obexd/src/server.c'; then $(CYGPATH_W) 'obexd/src/server.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/server.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/src/$(DEPDIR)/obexd-server.Tpo obexd/src/$(DEPDIR)/obexd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/src/server.c' object='obexd/src/obexd-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/src/obexd-server.obj `if test -f 'obexd/src/server.c'; then $(CYGPATH_W) 'obexd/src/server.c'; else $(CYGPATH_W) '$(srcdir)/obexd/src/server.c'; fi`
+
+obexd/client/obexd-manager.o: obexd/client/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-manager.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-manager.Tpo -c -o obexd/client/obexd-manager.o `test -f 'obexd/client/manager.c' || echo '$(srcdir)/'`obexd/client/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-manager.Tpo obexd/client/$(DEPDIR)/obexd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/manager.c' object='obexd/client/obexd-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-manager.o `test -f 'obexd/client/manager.c' || echo '$(srcdir)/'`obexd/client/manager.c
+
+obexd/client/obexd-manager.obj: obexd/client/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-manager.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-manager.Tpo -c -o obexd/client/obexd-manager.obj `if test -f 'obexd/client/manager.c'; then $(CYGPATH_W) 'obexd/client/manager.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-manager.Tpo obexd/client/$(DEPDIR)/obexd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/manager.c' object='obexd/client/obexd-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-manager.obj `if test -f 'obexd/client/manager.c'; then $(CYGPATH_W) 'obexd/client/manager.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/manager.c'; fi`
+
+obexd/client/obexd-session.o: obexd/client/session.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-session.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-session.Tpo -c -o obexd/client/obexd-session.o `test -f 'obexd/client/session.c' || echo '$(srcdir)/'`obexd/client/session.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-session.Tpo obexd/client/$(DEPDIR)/obexd-session.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/session.c' object='obexd/client/obexd-session.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-session.o `test -f 'obexd/client/session.c' || echo '$(srcdir)/'`obexd/client/session.c
+
+obexd/client/obexd-session.obj: obexd/client/session.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-session.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-session.Tpo -c -o obexd/client/obexd-session.obj `if test -f 'obexd/client/session.c'; then $(CYGPATH_W) 'obexd/client/session.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/session.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-session.Tpo obexd/client/$(DEPDIR)/obexd-session.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/session.c' object='obexd/client/obexd-session.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-session.obj `if test -f 'obexd/client/session.c'; then $(CYGPATH_W) 'obexd/client/session.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/session.c'; fi`
+
+obexd/client/obexd-bluetooth.o: obexd/client/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bluetooth.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bluetooth.Tpo -c -o obexd/client/obexd-bluetooth.o `test -f 'obexd/client/bluetooth.c' || echo '$(srcdir)/'`obexd/client/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bluetooth.Tpo obexd/client/$(DEPDIR)/obexd-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bluetooth.c' object='obexd/client/obexd-bluetooth.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bluetooth.o `test -f 'obexd/client/bluetooth.c' || echo '$(srcdir)/'`obexd/client/bluetooth.c
+
+obexd/client/obexd-bluetooth.obj: obexd/client/bluetooth.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bluetooth.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bluetooth.Tpo -c -o obexd/client/obexd-bluetooth.obj `if test -f 'obexd/client/bluetooth.c'; then $(CYGPATH_W) 'obexd/client/bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bluetooth.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bluetooth.Tpo obexd/client/$(DEPDIR)/obexd-bluetooth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bluetooth.c' object='obexd/client/obexd-bluetooth.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bluetooth.obj `if test -f 'obexd/client/bluetooth.c'; then $(CYGPATH_W) 'obexd/client/bluetooth.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bluetooth.c'; fi`
+
+obexd/client/obexd-sync.o: obexd/client/sync.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-sync.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-sync.Tpo -c -o obexd/client/obexd-sync.o `test -f 'obexd/client/sync.c' || echo '$(srcdir)/'`obexd/client/sync.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-sync.Tpo obexd/client/$(DEPDIR)/obexd-sync.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/sync.c' object='obexd/client/obexd-sync.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-sync.o `test -f 'obexd/client/sync.c' || echo '$(srcdir)/'`obexd/client/sync.c
+
+obexd/client/obexd-sync.obj: obexd/client/sync.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-sync.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-sync.Tpo -c -o obexd/client/obexd-sync.obj `if test -f 'obexd/client/sync.c'; then $(CYGPATH_W) 'obexd/client/sync.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/sync.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-sync.Tpo obexd/client/$(DEPDIR)/obexd-sync.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/sync.c' object='obexd/client/obexd-sync.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-sync.obj `if test -f 'obexd/client/sync.c'; then $(CYGPATH_W) 'obexd/client/sync.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/sync.c'; fi`
+
+obexd/client/obexd-pbap.o: obexd/client/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-pbap.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-pbap.Tpo -c -o obexd/client/obexd-pbap.o `test -f 'obexd/client/pbap.c' || echo '$(srcdir)/'`obexd/client/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-pbap.Tpo obexd/client/$(DEPDIR)/obexd-pbap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/pbap.c' object='obexd/client/obexd-pbap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-pbap.o `test -f 'obexd/client/pbap.c' || echo '$(srcdir)/'`obexd/client/pbap.c
+
+obexd/client/obexd-pbap.obj: obexd/client/pbap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-pbap.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-pbap.Tpo -c -o obexd/client/obexd-pbap.obj `if test -f 'obexd/client/pbap.c'; then $(CYGPATH_W) 'obexd/client/pbap.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/pbap.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-pbap.Tpo obexd/client/$(DEPDIR)/obexd-pbap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/pbap.c' object='obexd/client/obexd-pbap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-pbap.obj `if test -f 'obexd/client/pbap.c'; then $(CYGPATH_W) 'obexd/client/pbap.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/pbap.c'; fi`
+
+obexd/client/obexd-ftp.o: obexd/client/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-ftp.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-ftp.Tpo -c -o obexd/client/obexd-ftp.o `test -f 'obexd/client/ftp.c' || echo '$(srcdir)/'`obexd/client/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-ftp.Tpo obexd/client/$(DEPDIR)/obexd-ftp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/ftp.c' object='obexd/client/obexd-ftp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-ftp.o `test -f 'obexd/client/ftp.c' || echo '$(srcdir)/'`obexd/client/ftp.c
+
+obexd/client/obexd-ftp.obj: obexd/client/ftp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-ftp.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-ftp.Tpo -c -o obexd/client/obexd-ftp.obj `if test -f 'obexd/client/ftp.c'; then $(CYGPATH_W) 'obexd/client/ftp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/ftp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-ftp.Tpo obexd/client/$(DEPDIR)/obexd-ftp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/ftp.c' object='obexd/client/obexd-ftp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-ftp.obj `if test -f 'obexd/client/ftp.c'; then $(CYGPATH_W) 'obexd/client/ftp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/ftp.c'; fi`
+
+obexd/client/obexd-opp.o: obexd/client/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-opp.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-opp.Tpo -c -o obexd/client/obexd-opp.o `test -f 'obexd/client/opp.c' || echo '$(srcdir)/'`obexd/client/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-opp.Tpo obexd/client/$(DEPDIR)/obexd-opp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/opp.c' object='obexd/client/obexd-opp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-opp.o `test -f 'obexd/client/opp.c' || echo '$(srcdir)/'`obexd/client/opp.c
+
+obexd/client/obexd-opp.obj: obexd/client/opp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-opp.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-opp.Tpo -c -o obexd/client/obexd-opp.obj `if test -f 'obexd/client/opp.c'; then $(CYGPATH_W) 'obexd/client/opp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/opp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-opp.Tpo obexd/client/$(DEPDIR)/obexd-opp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/opp.c' object='obexd/client/obexd-opp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-opp.obj `if test -f 'obexd/client/opp.c'; then $(CYGPATH_W) 'obexd/client/opp.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/opp.c'; fi`
+
+obexd/client/obexd-map.o: obexd/client/map.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-map.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-map.Tpo -c -o obexd/client/obexd-map.o `test -f 'obexd/client/map.c' || echo '$(srcdir)/'`obexd/client/map.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-map.Tpo obexd/client/$(DEPDIR)/obexd-map.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/map.c' object='obexd/client/obexd-map.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-map.o `test -f 'obexd/client/map.c' || echo '$(srcdir)/'`obexd/client/map.c
+
+obexd/client/obexd-map.obj: obexd/client/map.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-map.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-map.Tpo -c -o obexd/client/obexd-map.obj `if test -f 'obexd/client/map.c'; then $(CYGPATH_W) 'obexd/client/map.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/map.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-map.Tpo obexd/client/$(DEPDIR)/obexd-map.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/map.c' object='obexd/client/obexd-map.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-map.obj `if test -f 'obexd/client/map.c'; then $(CYGPATH_W) 'obexd/client/map.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/map.c'; fi`
+
+obexd/client/obexd-bip.o: obexd/client/bip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bip.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bip.Tpo -c -o obexd/client/obexd-bip.o `test -f 'obexd/client/bip.c' || echo '$(srcdir)/'`obexd/client/bip.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bip.Tpo obexd/client/$(DEPDIR)/obexd-bip.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bip.c' object='obexd/client/obexd-bip.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bip.o `test -f 'obexd/client/bip.c' || echo '$(srcdir)/'`obexd/client/bip.c
+
+obexd/client/obexd-bip.obj: obexd/client/bip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bip.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bip.Tpo -c -o obexd/client/obexd-bip.obj `if test -f 'obexd/client/bip.c'; then $(CYGPATH_W) 'obexd/client/bip.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bip.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bip.Tpo obexd/client/$(DEPDIR)/obexd-bip.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bip.c' object='obexd/client/obexd-bip.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bip.obj `if test -f 'obexd/client/bip.c'; then $(CYGPATH_W) 'obexd/client/bip.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bip.c'; fi`
+
+obexd/client/obexd-bip-common.o: obexd/client/bip-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bip-common.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bip-common.Tpo -c -o obexd/client/obexd-bip-common.o `test -f 'obexd/client/bip-common.c' || echo '$(srcdir)/'`obexd/client/bip-common.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bip-common.Tpo obexd/client/$(DEPDIR)/obexd-bip-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bip-common.c' object='obexd/client/obexd-bip-common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bip-common.o `test -f 'obexd/client/bip-common.c' || echo '$(srcdir)/'`obexd/client/bip-common.c
+
+obexd/client/obexd-bip-common.obj: obexd/client/bip-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-bip-common.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-bip-common.Tpo -c -o obexd/client/obexd-bip-common.obj `if test -f 'obexd/client/bip-common.c'; then $(CYGPATH_W) 'obexd/client/bip-common.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bip-common.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-bip-common.Tpo obexd/client/$(DEPDIR)/obexd-bip-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/bip-common.c' object='obexd/client/obexd-bip-common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-bip-common.obj `if test -f 'obexd/client/bip-common.c'; then $(CYGPATH_W) 'obexd/client/bip-common.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/bip-common.c'; fi`
+
+obexd/client/obexd-map-event.o: obexd/client/map-event.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-map-event.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-map-event.Tpo -c -o obexd/client/obexd-map-event.o `test -f 'obexd/client/map-event.c' || echo '$(srcdir)/'`obexd/client/map-event.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-map-event.Tpo obexd/client/$(DEPDIR)/obexd-map-event.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/map-event.c' object='obexd/client/obexd-map-event.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-map-event.o `test -f 'obexd/client/map-event.c' || echo '$(srcdir)/'`obexd/client/map-event.c
+
+obexd/client/obexd-map-event.obj: obexd/client/map-event.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-map-event.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-map-event.Tpo -c -o obexd/client/obexd-map-event.obj `if test -f 'obexd/client/map-event.c'; then $(CYGPATH_W) 'obexd/client/map-event.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/map-event.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-map-event.Tpo obexd/client/$(DEPDIR)/obexd-map-event.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/map-event.c' object='obexd/client/obexd-map-event.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-map-event.obj `if test -f 'obexd/client/map-event.c'; then $(CYGPATH_W) 'obexd/client/map-event.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/map-event.c'; fi`
+
+obexd/client/obexd-transfer.o: obexd/client/transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-transfer.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-transfer.Tpo -c -o obexd/client/obexd-transfer.o `test -f 'obexd/client/transfer.c' || echo '$(srcdir)/'`obexd/client/transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-transfer.Tpo obexd/client/$(DEPDIR)/obexd-transfer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/transfer.c' object='obexd/client/obexd-transfer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-transfer.o `test -f 'obexd/client/transfer.c' || echo '$(srcdir)/'`obexd/client/transfer.c
+
+obexd/client/obexd-transfer.obj: obexd/client/transfer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-transfer.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-transfer.Tpo -c -o obexd/client/obexd-transfer.obj `if test -f 'obexd/client/transfer.c'; then $(CYGPATH_W) 'obexd/client/transfer.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/transfer.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-transfer.Tpo obexd/client/$(DEPDIR)/obexd-transfer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/transfer.c' object='obexd/client/obexd-transfer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-transfer.obj `if test -f 'obexd/client/transfer.c'; then $(CYGPATH_W) 'obexd/client/transfer.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/transfer.c'; fi`
+
+obexd/client/obexd-transport.o: obexd/client/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-transport.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-transport.Tpo -c -o obexd/client/obexd-transport.o `test -f 'obexd/client/transport.c' || echo '$(srcdir)/'`obexd/client/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-transport.Tpo obexd/client/$(DEPDIR)/obexd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/transport.c' object='obexd/client/obexd-transport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-transport.o `test -f 'obexd/client/transport.c' || echo '$(srcdir)/'`obexd/client/transport.c
+
+obexd/client/obexd-transport.obj: obexd/client/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-transport.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-transport.Tpo -c -o obexd/client/obexd-transport.obj `if test -f 'obexd/client/transport.c'; then $(CYGPATH_W) 'obexd/client/transport.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/transport.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-transport.Tpo obexd/client/$(DEPDIR)/obexd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/transport.c' object='obexd/client/obexd-transport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-transport.obj `if test -f 'obexd/client/transport.c'; then $(CYGPATH_W) 'obexd/client/transport.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/transport.c'; fi`
+
+obexd/client/obexd-driver.o: obexd/client/driver.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-driver.o -MD -MP -MF obexd/client/$(DEPDIR)/obexd-driver.Tpo -c -o obexd/client/obexd-driver.o `test -f 'obexd/client/driver.c' || echo '$(srcdir)/'`obexd/client/driver.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-driver.Tpo obexd/client/$(DEPDIR)/obexd-driver.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/driver.c' object='obexd/client/obexd-driver.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-driver.o `test -f 'obexd/client/driver.c' || echo '$(srcdir)/'`obexd/client/driver.c
+
+obexd/client/obexd-driver.obj: obexd/client/driver.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obexd/client/obexd-driver.obj -MD -MP -MF obexd/client/$(DEPDIR)/obexd-driver.Tpo -c -o obexd/client/obexd-driver.obj `if test -f 'obexd/client/driver.c'; then $(CYGPATH_W) 'obexd/client/driver.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/driver.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) obexd/client/$(DEPDIR)/obexd-driver.Tpo obexd/client/$(DEPDIR)/obexd-driver.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='obexd/client/driver.c' object='obexd/client/obexd-driver.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(obexd_src_obexd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o obexd/client/obexd-driver.obj `if test -f 'obexd/client/driver.c'; then $(CYGPATH_W) 'obexd/client/driver.c'; else $(CYGPATH_W) '$(srcdir)/obexd/client/driver.c'; fi`
+
+plugins/bluetoothd-hostname.o: plugins/hostname.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-hostname.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-hostname.Tpo -c -o plugins/bluetoothd-hostname.o `test -f 'plugins/hostname.c' || echo '$(srcdir)/'`plugins/hostname.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-hostname.Tpo plugins/$(DEPDIR)/bluetoothd-hostname.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/hostname.c' object='plugins/bluetoothd-hostname.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-hostname.o `test -f 'plugins/hostname.c' || echo '$(srcdir)/'`plugins/hostname.c
+
+plugins/bluetoothd-hostname.obj: plugins/hostname.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-hostname.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-hostname.Tpo -c -o plugins/bluetoothd-hostname.obj `if test -f 'plugins/hostname.c'; then $(CYGPATH_W) 'plugins/hostname.c'; else $(CYGPATH_W) '$(srcdir)/plugins/hostname.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-hostname.Tpo plugins/$(DEPDIR)/bluetoothd-hostname.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/hostname.c' object='plugins/bluetoothd-hostname.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-hostname.obj `if test -f 'plugins/hostname.c'; then $(CYGPATH_W) 'plugins/hostname.c'; else $(CYGPATH_W) '$(srcdir)/plugins/hostname.c'; fi`
+
+plugins/bluetoothd-wiimote.o: plugins/wiimote.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-wiimote.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-wiimote.Tpo -c -o plugins/bluetoothd-wiimote.o `test -f 'plugins/wiimote.c' || echo '$(srcdir)/'`plugins/wiimote.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-wiimote.Tpo plugins/$(DEPDIR)/bluetoothd-wiimote.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/wiimote.c' object='plugins/bluetoothd-wiimote.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-wiimote.o `test -f 'plugins/wiimote.c' || echo '$(srcdir)/'`plugins/wiimote.c
+
+plugins/bluetoothd-wiimote.obj: plugins/wiimote.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-wiimote.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-wiimote.Tpo -c -o plugins/bluetoothd-wiimote.obj `if test -f 'plugins/wiimote.c'; then $(CYGPATH_W) 'plugins/wiimote.c'; else $(CYGPATH_W) '$(srcdir)/plugins/wiimote.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-wiimote.Tpo plugins/$(DEPDIR)/bluetoothd-wiimote.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/wiimote.c' object='plugins/bluetoothd-wiimote.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-wiimote.obj `if test -f 'plugins/wiimote.c'; then $(CYGPATH_W) 'plugins/wiimote.c'; else $(CYGPATH_W) '$(srcdir)/plugins/wiimote.c'; fi`
+
+plugins/bluetoothd-autopair.o: plugins/autopair.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-autopair.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-autopair.Tpo -c -o plugins/bluetoothd-autopair.o `test -f 'plugins/autopair.c' || echo '$(srcdir)/'`plugins/autopair.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-autopair.Tpo plugins/$(DEPDIR)/bluetoothd-autopair.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/autopair.c' object='plugins/bluetoothd-autopair.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-autopair.o `test -f 'plugins/autopair.c' || echo '$(srcdir)/'`plugins/autopair.c
+
+plugins/bluetoothd-autopair.obj: plugins/autopair.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-autopair.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-autopair.Tpo -c -o plugins/bluetoothd-autopair.obj `if test -f 'plugins/autopair.c'; then $(CYGPATH_W) 'plugins/autopair.c'; else $(CYGPATH_W) '$(srcdir)/plugins/autopair.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-autopair.Tpo plugins/$(DEPDIR)/bluetoothd-autopair.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/autopair.c' object='plugins/bluetoothd-autopair.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-autopair.obj `if test -f 'plugins/autopair.c'; then $(CYGPATH_W) 'plugins/autopair.c'; else $(CYGPATH_W) '$(srcdir)/plugins/autopair.c'; fi`
+
+plugins/bluetoothd-policy.o: plugins/policy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-policy.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-policy.Tpo -c -o plugins/bluetoothd-policy.o `test -f 'plugins/policy.c' || echo '$(srcdir)/'`plugins/policy.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-policy.Tpo plugins/$(DEPDIR)/bluetoothd-policy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/policy.c' object='plugins/bluetoothd-policy.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-policy.o `test -f 'plugins/policy.c' || echo '$(srcdir)/'`plugins/policy.c
+
+plugins/bluetoothd-policy.obj: plugins/policy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-policy.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-policy.Tpo -c -o plugins/bluetoothd-policy.obj `if test -f 'plugins/policy.c'; then $(CYGPATH_W) 'plugins/policy.c'; else $(CYGPATH_W) '$(srcdir)/plugins/policy.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-policy.Tpo plugins/$(DEPDIR)/bluetoothd-policy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/policy.c' object='plugins/bluetoothd-policy.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-policy.obj `if test -f 'plugins/policy.c'; then $(CYGPATH_W) 'plugins/policy.c'; else $(CYGPATH_W) '$(srcdir)/plugins/policy.c'; fi`
+
+plugins/bluetoothd-admin.o: plugins/admin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-admin.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-admin.Tpo -c -o plugins/bluetoothd-admin.o `test -f 'plugins/admin.c' || echo '$(srcdir)/'`plugins/admin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-admin.Tpo plugins/$(DEPDIR)/bluetoothd-admin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/admin.c' object='plugins/bluetoothd-admin.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-admin.o `test -f 'plugins/admin.c' || echo '$(srcdir)/'`plugins/admin.c
+
+plugins/bluetoothd-admin.obj: plugins/admin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-admin.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-admin.Tpo -c -o plugins/bluetoothd-admin.obj `if test -f 'plugins/admin.c'; then $(CYGPATH_W) 'plugins/admin.c'; else $(CYGPATH_W) '$(srcdir)/plugins/admin.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-admin.Tpo plugins/$(DEPDIR)/bluetoothd-admin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/admin.c' object='plugins/bluetoothd-admin.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-admin.obj `if test -f 'plugins/admin.c'; then $(CYGPATH_W) 'plugins/admin.c'; else $(CYGPATH_W) '$(srcdir)/plugins/admin.c'; fi`
+
+plugins/bluetoothd-neard.o: plugins/neard.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-neard.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-neard.Tpo -c -o plugins/bluetoothd-neard.o `test -f 'plugins/neard.c' || echo '$(srcdir)/'`plugins/neard.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-neard.Tpo plugins/$(DEPDIR)/bluetoothd-neard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/neard.c' object='plugins/bluetoothd-neard.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-neard.o `test -f 'plugins/neard.c' || echo '$(srcdir)/'`plugins/neard.c
+
+plugins/bluetoothd-neard.obj: plugins/neard.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-neard.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-neard.Tpo -c -o plugins/bluetoothd-neard.obj `if test -f 'plugins/neard.c'; then $(CYGPATH_W) 'plugins/neard.c'; else $(CYGPATH_W) '$(srcdir)/plugins/neard.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-neard.Tpo plugins/$(DEPDIR)/bluetoothd-neard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/neard.c' object='plugins/bluetoothd-neard.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-neard.obj `if test -f 'plugins/neard.c'; then $(CYGPATH_W) 'plugins/neard.c'; else $(CYGPATH_W) '$(srcdir)/plugins/neard.c'; fi`
+
+profiles/sap/bluetoothd-main.o: profiles/sap/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-main.o -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-main.Tpo -c -o profiles/sap/bluetoothd-main.o `test -f 'profiles/sap/main.c' || echo '$(srcdir)/'`profiles/sap/main.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-main.Tpo profiles/sap/$(DEPDIR)/bluetoothd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/main.c' object='profiles/sap/bluetoothd-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-main.o `test -f 'profiles/sap/main.c' || echo '$(srcdir)/'`profiles/sap/main.c
+
+profiles/sap/bluetoothd-main.obj: profiles/sap/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-main.obj -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-main.Tpo -c -o profiles/sap/bluetoothd-main.obj `if test -f 'profiles/sap/main.c'; then $(CYGPATH_W) 'profiles/sap/main.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/main.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-main.Tpo profiles/sap/$(DEPDIR)/bluetoothd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/main.c' object='profiles/sap/bluetoothd-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-main.obj `if test -f 'profiles/sap/main.c'; then $(CYGPATH_W) 'profiles/sap/main.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/main.c'; fi`
+
+profiles/sap/bluetoothd-manager.o: profiles/sap/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-manager.o -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/sap/bluetoothd-manager.o `test -f 'profiles/sap/manager.c' || echo '$(srcdir)/'`profiles/sap/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-manager.Tpo profiles/sap/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/manager.c' object='profiles/sap/bluetoothd-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-manager.o `test -f 'profiles/sap/manager.c' || echo '$(srcdir)/'`profiles/sap/manager.c
+
+profiles/sap/bluetoothd-manager.obj: profiles/sap/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-manager.obj -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/sap/bluetoothd-manager.obj `if test -f 'profiles/sap/manager.c'; then $(CYGPATH_W) 'profiles/sap/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-manager.Tpo profiles/sap/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/manager.c' object='profiles/sap/bluetoothd-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-manager.obj `if test -f 'profiles/sap/manager.c'; then $(CYGPATH_W) 'profiles/sap/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/manager.c'; fi`
+
+profiles/sap/bluetoothd-server.o: profiles/sap/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-server.o -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/sap/bluetoothd-server.o `test -f 'profiles/sap/server.c' || echo '$(srcdir)/'`profiles/sap/server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-server.Tpo profiles/sap/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/server.c' object='profiles/sap/bluetoothd-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-server.o `test -f 'profiles/sap/server.c' || echo '$(srcdir)/'`profiles/sap/server.c
+
+profiles/sap/bluetoothd-server.obj: profiles/sap/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-server.obj -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/sap/bluetoothd-server.obj `if test -f 'profiles/sap/server.c'; then $(CYGPATH_W) 'profiles/sap/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/server.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-server.Tpo profiles/sap/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/server.c' object='profiles/sap/bluetoothd-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-server.obj `if test -f 'profiles/sap/server.c'; then $(CYGPATH_W) 'profiles/sap/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/server.c'; fi`
+
+profiles/sap/bluetoothd-sap-dummy.o: profiles/sap/sap-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-sap-dummy.o -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Tpo -c -o profiles/sap/bluetoothd-sap-dummy.o `test -f 'profiles/sap/sap-dummy.c' || echo '$(srcdir)/'`profiles/sap/sap-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Tpo profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/sap-dummy.c' object='profiles/sap/bluetoothd-sap-dummy.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-sap-dummy.o `test -f 'profiles/sap/sap-dummy.c' || echo '$(srcdir)/'`profiles/sap/sap-dummy.c
+
+profiles/sap/bluetoothd-sap-dummy.obj: profiles/sap/sap-dummy.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/sap/bluetoothd-sap-dummy.obj -MD -MP -MF profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Tpo -c -o profiles/sap/bluetoothd-sap-dummy.obj `if test -f 'profiles/sap/sap-dummy.c'; then $(CYGPATH_W) 'profiles/sap/sap-dummy.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/sap-dummy.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Tpo profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/sap/sap-dummy.c' object='profiles/sap/bluetoothd-sap-dummy.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/sap/bluetoothd-sap-dummy.obj `if test -f 'profiles/sap/sap-dummy.c'; then $(CYGPATH_W) 'profiles/sap/sap-dummy.c'; else $(CYGPATH_W) '$(srcdir)/profiles/sap/sap-dummy.c'; fi`
+
+profiles/audio/bluetoothd-source.o: profiles/audio/source.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-source.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-source.Tpo -c -o profiles/audio/bluetoothd-source.o `test -f 'profiles/audio/source.c' || echo '$(srcdir)/'`profiles/audio/source.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-source.Tpo profiles/audio/$(DEPDIR)/bluetoothd-source.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/source.c' object='profiles/audio/bluetoothd-source.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-source.o `test -f 'profiles/audio/source.c' || echo '$(srcdir)/'`profiles/audio/source.c
+
+profiles/audio/bluetoothd-source.obj: profiles/audio/source.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-source.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-source.Tpo -c -o profiles/audio/bluetoothd-source.obj `if test -f 'profiles/audio/source.c'; then $(CYGPATH_W) 'profiles/audio/source.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/source.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-source.Tpo profiles/audio/$(DEPDIR)/bluetoothd-source.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/source.c' object='profiles/audio/bluetoothd-source.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-source.obj `if test -f 'profiles/audio/source.c'; then $(CYGPATH_W) 'profiles/audio/source.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/source.c'; fi`
+
+profiles/audio/bluetoothd-sink.o: profiles/audio/sink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-sink.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-sink.Tpo -c -o profiles/audio/bluetoothd-sink.o `test -f 'profiles/audio/sink.c' || echo '$(srcdir)/'`profiles/audio/sink.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-sink.Tpo profiles/audio/$(DEPDIR)/bluetoothd-sink.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/sink.c' object='profiles/audio/bluetoothd-sink.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-sink.o `test -f 'profiles/audio/sink.c' || echo '$(srcdir)/'`profiles/audio/sink.c
+
+profiles/audio/bluetoothd-sink.obj: profiles/audio/sink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-sink.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-sink.Tpo -c -o profiles/audio/bluetoothd-sink.obj `if test -f 'profiles/audio/sink.c'; then $(CYGPATH_W) 'profiles/audio/sink.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/sink.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-sink.Tpo profiles/audio/$(DEPDIR)/bluetoothd-sink.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/sink.c' object='profiles/audio/bluetoothd-sink.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-sink.obj `if test -f 'profiles/audio/sink.c'; then $(CYGPATH_W) 'profiles/audio/sink.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/sink.c'; fi`
+
+profiles/audio/bluetoothd-a2dp.o: profiles/audio/a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-a2dp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Tpo -c -o profiles/audio/bluetoothd-a2dp.o `test -f 'profiles/audio/a2dp.c' || echo '$(srcdir)/'`profiles/audio/a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/a2dp.c' object='profiles/audio/bluetoothd-a2dp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-a2dp.o `test -f 'profiles/audio/a2dp.c' || echo '$(srcdir)/'`profiles/audio/a2dp.c
+
+profiles/audio/bluetoothd-a2dp.obj: profiles/audio/a2dp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-a2dp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Tpo -c -o profiles/audio/bluetoothd-a2dp.obj `if test -f 'profiles/audio/a2dp.c'; then $(CYGPATH_W) 'profiles/audio/a2dp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/a2dp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/a2dp.c' object='profiles/audio/bluetoothd-a2dp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-a2dp.obj `if test -f 'profiles/audio/a2dp.c'; then $(CYGPATH_W) 'profiles/audio/a2dp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/a2dp.c'; fi`
+
+profiles/audio/bluetoothd-avdtp.o: profiles/audio/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avdtp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Tpo -c -o profiles/audio/bluetoothd-avdtp.o `test -f 'profiles/audio/avdtp.c' || echo '$(srcdir)/'`profiles/audio/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avdtp.c' object='profiles/audio/bluetoothd-avdtp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avdtp.o `test -f 'profiles/audio/avdtp.c' || echo '$(srcdir)/'`profiles/audio/avdtp.c
+
+profiles/audio/bluetoothd-avdtp.obj: profiles/audio/avdtp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avdtp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Tpo -c -o profiles/audio/bluetoothd-avdtp.obj `if test -f 'profiles/audio/avdtp.c'; then $(CYGPATH_W) 'profiles/audio/avdtp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avdtp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avdtp.c' object='profiles/audio/bluetoothd-avdtp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avdtp.obj `if test -f 'profiles/audio/avdtp.c'; then $(CYGPATH_W) 'profiles/audio/avdtp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avdtp.c'; fi`
+
+profiles/audio/bluetoothd-media.o: profiles/audio/media.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-media.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-media.Tpo -c -o profiles/audio/bluetoothd-media.o `test -f 'profiles/audio/media.c' || echo '$(srcdir)/'`profiles/audio/media.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-media.Tpo profiles/audio/$(DEPDIR)/bluetoothd-media.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/media.c' object='profiles/audio/bluetoothd-media.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-media.o `test -f 'profiles/audio/media.c' || echo '$(srcdir)/'`profiles/audio/media.c
+
+profiles/audio/bluetoothd-media.obj: profiles/audio/media.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-media.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-media.Tpo -c -o profiles/audio/bluetoothd-media.obj `if test -f 'profiles/audio/media.c'; then $(CYGPATH_W) 'profiles/audio/media.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/media.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-media.Tpo profiles/audio/$(DEPDIR)/bluetoothd-media.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/media.c' object='profiles/audio/bluetoothd-media.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-media.obj `if test -f 'profiles/audio/media.c'; then $(CYGPATH_W) 'profiles/audio/media.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/media.c'; fi`
+
+profiles/audio/bluetoothd-transport.o: profiles/audio/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-transport.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-transport.Tpo -c -o profiles/audio/bluetoothd-transport.o `test -f 'profiles/audio/transport.c' || echo '$(srcdir)/'`profiles/audio/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-transport.Tpo profiles/audio/$(DEPDIR)/bluetoothd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/transport.c' object='profiles/audio/bluetoothd-transport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-transport.o `test -f 'profiles/audio/transport.c' || echo '$(srcdir)/'`profiles/audio/transport.c
+
+profiles/audio/bluetoothd-transport.obj: profiles/audio/transport.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-transport.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-transport.Tpo -c -o profiles/audio/bluetoothd-transport.obj `if test -f 'profiles/audio/transport.c'; then $(CYGPATH_W) 'profiles/audio/transport.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/transport.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-transport.Tpo profiles/audio/$(DEPDIR)/bluetoothd-transport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/transport.c' object='profiles/audio/bluetoothd-transport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-transport.obj `if test -f 'profiles/audio/transport.c'; then $(CYGPATH_W) 'profiles/audio/transport.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/transport.c'; fi`
+
+profiles/audio/bluetoothd-control.o: profiles/audio/control.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-control.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-control.Tpo -c -o profiles/audio/bluetoothd-control.o `test -f 'profiles/audio/control.c' || echo '$(srcdir)/'`profiles/audio/control.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-control.Tpo profiles/audio/$(DEPDIR)/bluetoothd-control.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/control.c' object='profiles/audio/bluetoothd-control.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-control.o `test -f 'profiles/audio/control.c' || echo '$(srcdir)/'`profiles/audio/control.c
+
+profiles/audio/bluetoothd-control.obj: profiles/audio/control.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-control.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-control.Tpo -c -o profiles/audio/bluetoothd-control.obj `if test -f 'profiles/audio/control.c'; then $(CYGPATH_W) 'profiles/audio/control.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/control.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-control.Tpo profiles/audio/$(DEPDIR)/bluetoothd-control.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/control.c' object='profiles/audio/bluetoothd-control.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-control.obj `if test -f 'profiles/audio/control.c'; then $(CYGPATH_W) 'profiles/audio/control.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/control.c'; fi`
+
+profiles/audio/bluetoothd-avctp.o: profiles/audio/avctp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avctp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avctp.Tpo -c -o profiles/audio/bluetoothd-avctp.o `test -f 'profiles/audio/avctp.c' || echo '$(srcdir)/'`profiles/audio/avctp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avctp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avctp.c' object='profiles/audio/bluetoothd-avctp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avctp.o `test -f 'profiles/audio/avctp.c' || echo '$(srcdir)/'`profiles/audio/avctp.c
+
+profiles/audio/bluetoothd-avctp.obj: profiles/audio/avctp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avctp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avctp.Tpo -c -o profiles/audio/bluetoothd-avctp.obj `if test -f 'profiles/audio/avctp.c'; then $(CYGPATH_W) 'profiles/audio/avctp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avctp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avctp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avctp.c' object='profiles/audio/bluetoothd-avctp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avctp.obj `if test -f 'profiles/audio/avctp.c'; then $(CYGPATH_W) 'profiles/audio/avctp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avctp.c'; fi`
+
+profiles/audio/bluetoothd-avrcp.o: profiles/audio/avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avrcp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Tpo -c -o profiles/audio/bluetoothd-avrcp.o `test -f 'profiles/audio/avrcp.c' || echo '$(srcdir)/'`profiles/audio/avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avrcp.c' object='profiles/audio/bluetoothd-avrcp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avrcp.o `test -f 'profiles/audio/avrcp.c' || echo '$(srcdir)/'`profiles/audio/avrcp.c
+
+profiles/audio/bluetoothd-avrcp.obj: profiles/audio/avrcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-avrcp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Tpo -c -o profiles/audio/bluetoothd-avrcp.obj `if test -f 'profiles/audio/avrcp.c'; then $(CYGPATH_W) 'profiles/audio/avrcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avrcp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/avrcp.c' object='profiles/audio/bluetoothd-avrcp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-avrcp.obj `if test -f 'profiles/audio/avrcp.c'; then $(CYGPATH_W) 'profiles/audio/avrcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/avrcp.c'; fi`
+
+profiles/audio/bluetoothd-player.o: profiles/audio/player.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-player.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-player.Tpo -c -o profiles/audio/bluetoothd-player.o `test -f 'profiles/audio/player.c' || echo '$(srcdir)/'`profiles/audio/player.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-player.Tpo profiles/audio/$(DEPDIR)/bluetoothd-player.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/player.c' object='profiles/audio/bluetoothd-player.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-player.o `test -f 'profiles/audio/player.c' || echo '$(srcdir)/'`profiles/audio/player.c
+
+profiles/audio/bluetoothd-player.obj: profiles/audio/player.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-player.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-player.Tpo -c -o profiles/audio/bluetoothd-player.obj `if test -f 'profiles/audio/player.c'; then $(CYGPATH_W) 'profiles/audio/player.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/player.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-player.Tpo profiles/audio/$(DEPDIR)/bluetoothd-player.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/player.c' object='profiles/audio/bluetoothd-player.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-player.obj `if test -f 'profiles/audio/player.c'; then $(CYGPATH_W) 'profiles/audio/player.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/player.c'; fi`
+
+profiles/network/bluetoothd-manager.o: profiles/network/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-manager.o -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/network/bluetoothd-manager.o `test -f 'profiles/network/manager.c' || echo '$(srcdir)/'`profiles/network/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-manager.Tpo profiles/network/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/manager.c' object='profiles/network/bluetoothd-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-manager.o `test -f 'profiles/network/manager.c' || echo '$(srcdir)/'`profiles/network/manager.c
+
+profiles/network/bluetoothd-manager.obj: profiles/network/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-manager.obj -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/network/bluetoothd-manager.obj `if test -f 'profiles/network/manager.c'; then $(CYGPATH_W) 'profiles/network/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-manager.Tpo profiles/network/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/manager.c' object='profiles/network/bluetoothd-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-manager.obj `if test -f 'profiles/network/manager.c'; then $(CYGPATH_W) 'profiles/network/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/manager.c'; fi`
+
+profiles/network/bluetoothd-bnep.o: profiles/network/bnep.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-bnep.o -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-bnep.Tpo -c -o profiles/network/bluetoothd-bnep.o `test -f 'profiles/network/bnep.c' || echo '$(srcdir)/'`profiles/network/bnep.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-bnep.Tpo profiles/network/$(DEPDIR)/bluetoothd-bnep.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/bnep.c' object='profiles/network/bluetoothd-bnep.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-bnep.o `test -f 'profiles/network/bnep.c' || echo '$(srcdir)/'`profiles/network/bnep.c
+
+profiles/network/bluetoothd-bnep.obj: profiles/network/bnep.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-bnep.obj -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-bnep.Tpo -c -o profiles/network/bluetoothd-bnep.obj `if test -f 'profiles/network/bnep.c'; then $(CYGPATH_W) 'profiles/network/bnep.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/bnep.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-bnep.Tpo profiles/network/$(DEPDIR)/bluetoothd-bnep.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/bnep.c' object='profiles/network/bluetoothd-bnep.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-bnep.obj `if test -f 'profiles/network/bnep.c'; then $(CYGPATH_W) 'profiles/network/bnep.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/bnep.c'; fi`
+
+profiles/network/bluetoothd-server.o: profiles/network/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-server.o -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/network/bluetoothd-server.o `test -f 'profiles/network/server.c' || echo '$(srcdir)/'`profiles/network/server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-server.Tpo profiles/network/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/server.c' object='profiles/network/bluetoothd-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-server.o `test -f 'profiles/network/server.c' || echo '$(srcdir)/'`profiles/network/server.c
+
+profiles/network/bluetoothd-server.obj: profiles/network/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-server.obj -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/network/bluetoothd-server.obj `if test -f 'profiles/network/server.c'; then $(CYGPATH_W) 'profiles/network/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/server.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-server.Tpo profiles/network/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/server.c' object='profiles/network/bluetoothd-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-server.obj `if test -f 'profiles/network/server.c'; then $(CYGPATH_W) 'profiles/network/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/server.c'; fi`
+
+profiles/network/bluetoothd-connection.o: profiles/network/connection.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-connection.o -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-connection.Tpo -c -o profiles/network/bluetoothd-connection.o `test -f 'profiles/network/connection.c' || echo '$(srcdir)/'`profiles/network/connection.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-connection.Tpo profiles/network/$(DEPDIR)/bluetoothd-connection.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/connection.c' object='profiles/network/bluetoothd-connection.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-connection.o `test -f 'profiles/network/connection.c' || echo '$(srcdir)/'`profiles/network/connection.c
+
+profiles/network/bluetoothd-connection.obj: profiles/network/connection.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/network/bluetoothd-connection.obj -MD -MP -MF profiles/network/$(DEPDIR)/bluetoothd-connection.Tpo -c -o profiles/network/bluetoothd-connection.obj `if test -f 'profiles/network/connection.c'; then $(CYGPATH_W) 'profiles/network/connection.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/connection.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/network/$(DEPDIR)/bluetoothd-connection.Tpo profiles/network/$(DEPDIR)/bluetoothd-connection.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/network/connection.c' object='profiles/network/bluetoothd-connection.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/network/bluetoothd-connection.obj `if test -f 'profiles/network/connection.c'; then $(CYGPATH_W) 'profiles/network/connection.c'; else $(CYGPATH_W) '$(srcdir)/profiles/network/connection.c'; fi`
+
+profiles/input/bluetoothd-manager.o: profiles/input/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-manager.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/input/bluetoothd-manager.o `test -f 'profiles/input/manager.c' || echo '$(srcdir)/'`profiles/input/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-manager.Tpo profiles/input/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/manager.c' object='profiles/input/bluetoothd-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-manager.o `test -f 'profiles/input/manager.c' || echo '$(srcdir)/'`profiles/input/manager.c
+
+profiles/input/bluetoothd-manager.obj: profiles/input/manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-manager.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-manager.Tpo -c -o profiles/input/bluetoothd-manager.obj `if test -f 'profiles/input/manager.c'; then $(CYGPATH_W) 'profiles/input/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-manager.Tpo profiles/input/$(DEPDIR)/bluetoothd-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/manager.c' object='profiles/input/bluetoothd-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-manager.obj `if test -f 'profiles/input/manager.c'; then $(CYGPATH_W) 'profiles/input/manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/manager.c'; fi`
+
+profiles/input/bluetoothd-server.o: profiles/input/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-server.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/input/bluetoothd-server.o `test -f 'profiles/input/server.c' || echo '$(srcdir)/'`profiles/input/server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-server.Tpo profiles/input/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/server.c' object='profiles/input/bluetoothd-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-server.o `test -f 'profiles/input/server.c' || echo '$(srcdir)/'`profiles/input/server.c
+
+profiles/input/bluetoothd-server.obj: profiles/input/server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-server.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-server.Tpo -c -o profiles/input/bluetoothd-server.obj `if test -f 'profiles/input/server.c'; then $(CYGPATH_W) 'profiles/input/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/server.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-server.Tpo profiles/input/$(DEPDIR)/bluetoothd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/server.c' object='profiles/input/bluetoothd-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-server.obj `if test -f 'profiles/input/server.c'; then $(CYGPATH_W) 'profiles/input/server.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/server.c'; fi`
+
+profiles/input/bluetoothd-device.o: profiles/input/device.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-device.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-device.Tpo -c -o profiles/input/bluetoothd-device.o `test -f 'profiles/input/device.c' || echo '$(srcdir)/'`profiles/input/device.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-device.Tpo profiles/input/$(DEPDIR)/bluetoothd-device.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/device.c' object='profiles/input/bluetoothd-device.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-device.o `test -f 'profiles/input/device.c' || echo '$(srcdir)/'`profiles/input/device.c
+
+profiles/input/bluetoothd-device.obj: profiles/input/device.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-device.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-device.Tpo -c -o profiles/input/bluetoothd-device.obj `if test -f 'profiles/input/device.c'; then $(CYGPATH_W) 'profiles/input/device.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/device.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-device.Tpo profiles/input/$(DEPDIR)/bluetoothd-device.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/device.c' object='profiles/input/bluetoothd-device.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-device.obj `if test -f 'profiles/input/device.c'; then $(CYGPATH_W) 'profiles/input/device.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/device.c'; fi`
+
+profiles/input/bluetoothd-hog.o: profiles/input/hog.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-hog.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-hog.Tpo -c -o profiles/input/bluetoothd-hog.o `test -f 'profiles/input/hog.c' || echo '$(srcdir)/'`profiles/input/hog.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-hog.Tpo profiles/input/$(DEPDIR)/bluetoothd-hog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/hog.c' object='profiles/input/bluetoothd-hog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-hog.o `test -f 'profiles/input/hog.c' || echo '$(srcdir)/'`profiles/input/hog.c
+
+profiles/input/bluetoothd-hog.obj: profiles/input/hog.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-hog.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-hog.Tpo -c -o profiles/input/bluetoothd-hog.obj `if test -f 'profiles/input/hog.c'; then $(CYGPATH_W) 'profiles/input/hog.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/hog.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-hog.Tpo profiles/input/$(DEPDIR)/bluetoothd-hog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/hog.c' object='profiles/input/bluetoothd-hog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-hog.obj `if test -f 'profiles/input/hog.c'; then $(CYGPATH_W) 'profiles/input/hog.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/hog.c'; fi`
+
+profiles/input/bluetoothd-hog-lib.o: profiles/input/hog-lib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-hog-lib.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Tpo -c -o profiles/input/bluetoothd-hog-lib.o `test -f 'profiles/input/hog-lib.c' || echo '$(srcdir)/'`profiles/input/hog-lib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Tpo profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/hog-lib.c' object='profiles/input/bluetoothd-hog-lib.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-hog-lib.o `test -f 'profiles/input/hog-lib.c' || echo '$(srcdir)/'`profiles/input/hog-lib.c
+
+profiles/input/bluetoothd-hog-lib.obj: profiles/input/hog-lib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-hog-lib.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Tpo -c -o profiles/input/bluetoothd-hog-lib.obj `if test -f 'profiles/input/hog-lib.c'; then $(CYGPATH_W) 'profiles/input/hog-lib.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/hog-lib.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Tpo profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/hog-lib.c' object='profiles/input/bluetoothd-hog-lib.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-hog-lib.obj `if test -f 'profiles/input/hog-lib.c'; then $(CYGPATH_W) 'profiles/input/hog-lib.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/hog-lib.c'; fi`
+
+profiles/deviceinfo/bluetoothd-dis.o: profiles/deviceinfo/dis.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/deviceinfo/bluetoothd-dis.o -MD -MP -MF profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Tpo -c -o profiles/deviceinfo/bluetoothd-dis.o `test -f 'profiles/deviceinfo/dis.c' || echo '$(srcdir)/'`profiles/deviceinfo/dis.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Tpo profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/deviceinfo/dis.c' object='profiles/deviceinfo/bluetoothd-dis.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/deviceinfo/bluetoothd-dis.o `test -f 'profiles/deviceinfo/dis.c' || echo '$(srcdir)/'`profiles/deviceinfo/dis.c
+
+profiles/deviceinfo/bluetoothd-dis.obj: profiles/deviceinfo/dis.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/deviceinfo/bluetoothd-dis.obj -MD -MP -MF profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Tpo -c -o profiles/deviceinfo/bluetoothd-dis.obj `if test -f 'profiles/deviceinfo/dis.c'; then $(CYGPATH_W) 'profiles/deviceinfo/dis.c'; else $(CYGPATH_W) '$(srcdir)/profiles/deviceinfo/dis.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Tpo profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/deviceinfo/dis.c' object='profiles/deviceinfo/bluetoothd-dis.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/deviceinfo/bluetoothd-dis.obj `if test -f 'profiles/deviceinfo/dis.c'; then $(CYGPATH_W) 'profiles/deviceinfo/dis.c'; else $(CYGPATH_W) '$(srcdir)/profiles/deviceinfo/dis.c'; fi`
+
+profiles/battery/bluetoothd-bas.o: profiles/battery/bas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/battery/bluetoothd-bas.o -MD -MP -MF profiles/battery/$(DEPDIR)/bluetoothd-bas.Tpo -c -o profiles/battery/bluetoothd-bas.o `test -f 'profiles/battery/bas.c' || echo '$(srcdir)/'`profiles/battery/bas.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/battery/$(DEPDIR)/bluetoothd-bas.Tpo profiles/battery/$(DEPDIR)/bluetoothd-bas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/battery/bas.c' object='profiles/battery/bluetoothd-bas.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/battery/bluetoothd-bas.o `test -f 'profiles/battery/bas.c' || echo '$(srcdir)/'`profiles/battery/bas.c
+
+profiles/battery/bluetoothd-bas.obj: profiles/battery/bas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/battery/bluetoothd-bas.obj -MD -MP -MF profiles/battery/$(DEPDIR)/bluetoothd-bas.Tpo -c -o profiles/battery/bluetoothd-bas.obj `if test -f 'profiles/battery/bas.c'; then $(CYGPATH_W) 'profiles/battery/bas.c'; else $(CYGPATH_W) '$(srcdir)/profiles/battery/bas.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/battery/$(DEPDIR)/bluetoothd-bas.Tpo profiles/battery/$(DEPDIR)/bluetoothd-bas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/battery/bas.c' object='profiles/battery/bluetoothd-bas.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/battery/bluetoothd-bas.obj `if test -f 'profiles/battery/bas.c'; then $(CYGPATH_W) 'profiles/battery/bas.c'; else $(CYGPATH_W) '$(srcdir)/profiles/battery/bas.c'; fi`
+
+profiles/scanparam/bluetoothd-scpp.o: profiles/scanparam/scpp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/scanparam/bluetoothd-scpp.o -MD -MP -MF profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Tpo -c -o profiles/scanparam/bluetoothd-scpp.o `test -f 'profiles/scanparam/scpp.c' || echo '$(srcdir)/'`profiles/scanparam/scpp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Tpo profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/scanparam/scpp.c' object='profiles/scanparam/bluetoothd-scpp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/scanparam/bluetoothd-scpp.o `test -f 'profiles/scanparam/scpp.c' || echo '$(srcdir)/'`profiles/scanparam/scpp.c
+
+profiles/scanparam/bluetoothd-scpp.obj: profiles/scanparam/scpp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/scanparam/bluetoothd-scpp.obj -MD -MP -MF profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Tpo -c -o profiles/scanparam/bluetoothd-scpp.obj `if test -f 'profiles/scanparam/scpp.c'; then $(CYGPATH_W) 'profiles/scanparam/scpp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/scanparam/scpp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Tpo profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/scanparam/scpp.c' object='profiles/scanparam/bluetoothd-scpp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/scanparam/bluetoothd-scpp.obj `if test -f 'profiles/scanparam/scpp.c'; then $(CYGPATH_W) 'profiles/scanparam/scpp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/scanparam/scpp.c'; fi`
+
+profiles/input/bluetoothd-suspend-none.o: profiles/input/suspend-none.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-suspend-none.o -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Tpo -c -o profiles/input/bluetoothd-suspend-none.o `test -f 'profiles/input/suspend-none.c' || echo '$(srcdir)/'`profiles/input/suspend-none.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Tpo profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/suspend-none.c' object='profiles/input/bluetoothd-suspend-none.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-suspend-none.o `test -f 'profiles/input/suspend-none.c' || echo '$(srcdir)/'`profiles/input/suspend-none.c
+
+profiles/input/bluetoothd-suspend-none.obj: profiles/input/suspend-none.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/input/bluetoothd-suspend-none.obj -MD -MP -MF profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Tpo -c -o profiles/input/bluetoothd-suspend-none.obj `if test -f 'profiles/input/suspend-none.c'; then $(CYGPATH_W) 'profiles/input/suspend-none.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/suspend-none.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Tpo profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/input/suspend-none.c' object='profiles/input/bluetoothd-suspend-none.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/input/bluetoothd-suspend-none.obj `if test -f 'profiles/input/suspend-none.c'; then $(CYGPATH_W) 'profiles/input/suspend-none.c'; else $(CYGPATH_W) '$(srcdir)/profiles/input/suspend-none.c'; fi`
+
+profiles/health/bluetoothd-mcap.o: profiles/health/mcap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-mcap.o -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-mcap.Tpo -c -o profiles/health/bluetoothd-mcap.o `test -f 'profiles/health/mcap.c' || echo '$(srcdir)/'`profiles/health/mcap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-mcap.Tpo profiles/health/$(DEPDIR)/bluetoothd-mcap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/mcap.c' object='profiles/health/bluetoothd-mcap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-mcap.o `test -f 'profiles/health/mcap.c' || echo '$(srcdir)/'`profiles/health/mcap.c
+
+profiles/health/bluetoothd-mcap.obj: profiles/health/mcap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-mcap.obj -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-mcap.Tpo -c -o profiles/health/bluetoothd-mcap.obj `if test -f 'profiles/health/mcap.c'; then $(CYGPATH_W) 'profiles/health/mcap.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/mcap.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-mcap.Tpo profiles/health/$(DEPDIR)/bluetoothd-mcap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/mcap.c' object='profiles/health/bluetoothd-mcap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-mcap.obj `if test -f 'profiles/health/mcap.c'; then $(CYGPATH_W) 'profiles/health/mcap.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/mcap.c'; fi`
+
+profiles/health/bluetoothd-hdp_main.o: profiles/health/hdp_main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_main.o -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Tpo -c -o profiles/health/bluetoothd-hdp_main.o `test -f 'profiles/health/hdp_main.c' || echo '$(srcdir)/'`profiles/health/hdp_main.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_main.c' object='profiles/health/bluetoothd-hdp_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_main.o `test -f 'profiles/health/hdp_main.c' || echo '$(srcdir)/'`profiles/health/hdp_main.c
+
+profiles/health/bluetoothd-hdp_main.obj: profiles/health/hdp_main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_main.obj -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Tpo -c -o profiles/health/bluetoothd-hdp_main.obj `if test -f 'profiles/health/hdp_main.c'; then $(CYGPATH_W) 'profiles/health/hdp_main.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_main.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_main.c' object='profiles/health/bluetoothd-hdp_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_main.obj `if test -f 'profiles/health/hdp_main.c'; then $(CYGPATH_W) 'profiles/health/hdp_main.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_main.c'; fi`
+
+profiles/health/bluetoothd-hdp_manager.o: profiles/health/hdp_manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_manager.o -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Tpo -c -o profiles/health/bluetoothd-hdp_manager.o `test -f 'profiles/health/hdp_manager.c' || echo '$(srcdir)/'`profiles/health/hdp_manager.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_manager.c' object='profiles/health/bluetoothd-hdp_manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_manager.o `test -f 'profiles/health/hdp_manager.c' || echo '$(srcdir)/'`profiles/health/hdp_manager.c
+
+profiles/health/bluetoothd-hdp_manager.obj: profiles/health/hdp_manager.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_manager.obj -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Tpo -c -o profiles/health/bluetoothd-hdp_manager.obj `if test -f 'profiles/health/hdp_manager.c'; then $(CYGPATH_W) 'profiles/health/hdp_manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_manager.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_manager.c' object='profiles/health/bluetoothd-hdp_manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_manager.obj `if test -f 'profiles/health/hdp_manager.c'; then $(CYGPATH_W) 'profiles/health/hdp_manager.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_manager.c'; fi`
+
+profiles/health/bluetoothd-hdp.o: profiles/health/hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp.o -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp.Tpo -c -o profiles/health/bluetoothd-hdp.o `test -f 'profiles/health/hdp.c' || echo '$(srcdir)/'`profiles/health/hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp.c' object='profiles/health/bluetoothd-hdp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp.o `test -f 'profiles/health/hdp.c' || echo '$(srcdir)/'`profiles/health/hdp.c
+
+profiles/health/bluetoothd-hdp.obj: profiles/health/hdp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp.obj -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp.Tpo -c -o profiles/health/bluetoothd-hdp.obj `if test -f 'profiles/health/hdp.c'; then $(CYGPATH_W) 'profiles/health/hdp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp.c' object='profiles/health/bluetoothd-hdp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp.obj `if test -f 'profiles/health/hdp.c'; then $(CYGPATH_W) 'profiles/health/hdp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp.c'; fi`
+
+profiles/health/bluetoothd-hdp_util.o: profiles/health/hdp_util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_util.o -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Tpo -c -o profiles/health/bluetoothd-hdp_util.o `test -f 'profiles/health/hdp_util.c' || echo '$(srcdir)/'`profiles/health/hdp_util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_util.c' object='profiles/health/bluetoothd-hdp_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_util.o `test -f 'profiles/health/hdp_util.c' || echo '$(srcdir)/'`profiles/health/hdp_util.c
+
+profiles/health/bluetoothd-hdp_util.obj: profiles/health/hdp_util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/health/bluetoothd-hdp_util.obj -MD -MP -MF profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Tpo -c -o profiles/health/bluetoothd-hdp_util.obj `if test -f 'profiles/health/hdp_util.c'; then $(CYGPATH_W) 'profiles/health/hdp_util.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_util.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Tpo profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/health/hdp_util.c' object='profiles/health/bluetoothd-hdp_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/health/bluetoothd-hdp_util.obj `if test -f 'profiles/health/hdp_util.c'; then $(CYGPATH_W) 'profiles/health/hdp_util.c'; else $(CYGPATH_W) '$(srcdir)/profiles/health/hdp_util.c'; fi`
+
+profiles/gap/bluetoothd-gas.o: profiles/gap/gas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/gap/bluetoothd-gas.o -MD -MP -MF profiles/gap/$(DEPDIR)/bluetoothd-gas.Tpo -c -o profiles/gap/bluetoothd-gas.o `test -f 'profiles/gap/gas.c' || echo '$(srcdir)/'`profiles/gap/gas.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/gap/$(DEPDIR)/bluetoothd-gas.Tpo profiles/gap/$(DEPDIR)/bluetoothd-gas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/gap/gas.c' object='profiles/gap/bluetoothd-gas.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/gap/bluetoothd-gas.o `test -f 'profiles/gap/gas.c' || echo '$(srcdir)/'`profiles/gap/gas.c
+
+profiles/gap/bluetoothd-gas.obj: profiles/gap/gas.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/gap/bluetoothd-gas.obj -MD -MP -MF profiles/gap/$(DEPDIR)/bluetoothd-gas.Tpo -c -o profiles/gap/bluetoothd-gas.obj `if test -f 'profiles/gap/gas.c'; then $(CYGPATH_W) 'profiles/gap/gas.c'; else $(CYGPATH_W) '$(srcdir)/profiles/gap/gas.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/gap/$(DEPDIR)/bluetoothd-gas.Tpo profiles/gap/$(DEPDIR)/bluetoothd-gas.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/gap/gas.c' object='profiles/gap/bluetoothd-gas.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/gap/bluetoothd-gas.obj `if test -f 'profiles/gap/gas.c'; then $(CYGPATH_W) 'profiles/gap/gas.c'; else $(CYGPATH_W) '$(srcdir)/profiles/gap/gas.c'; fi`
+
+profiles/scanparam/bluetoothd-scan.o: profiles/scanparam/scan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/scanparam/bluetoothd-scan.o -MD -MP -MF profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Tpo -c -o profiles/scanparam/bluetoothd-scan.o `test -f 'profiles/scanparam/scan.c' || echo '$(srcdir)/'`profiles/scanparam/scan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Tpo profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/scanparam/scan.c' object='profiles/scanparam/bluetoothd-scan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/scanparam/bluetoothd-scan.o `test -f 'profiles/scanparam/scan.c' || echo '$(srcdir)/'`profiles/scanparam/scan.c
+
+profiles/scanparam/bluetoothd-scan.obj: profiles/scanparam/scan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/scanparam/bluetoothd-scan.obj -MD -MP -MF profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Tpo -c -o profiles/scanparam/bluetoothd-scan.obj `if test -f 'profiles/scanparam/scan.c'; then $(CYGPATH_W) 'profiles/scanparam/scan.c'; else $(CYGPATH_W) '$(srcdir)/profiles/scanparam/scan.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Tpo profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/scanparam/scan.c' object='profiles/scanparam/bluetoothd-scan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/scanparam/bluetoothd-scan.obj `if test -f 'profiles/scanparam/scan.c'; then $(CYGPATH_W) 'profiles/scanparam/scan.c'; else $(CYGPATH_W) '$(srcdir)/profiles/scanparam/scan.c'; fi`
+
+profiles/deviceinfo/bluetoothd-deviceinfo.o: profiles/deviceinfo/deviceinfo.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/deviceinfo/bluetoothd-deviceinfo.o -MD -MP -MF profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Tpo -c -o profiles/deviceinfo/bluetoothd-deviceinfo.o `test -f 'profiles/deviceinfo/deviceinfo.c' || echo '$(srcdir)/'`profiles/deviceinfo/deviceinfo.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Tpo profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/deviceinfo/deviceinfo.c' object='profiles/deviceinfo/bluetoothd-deviceinfo.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/deviceinfo/bluetoothd-deviceinfo.o `test -f 'profiles/deviceinfo/deviceinfo.c' || echo '$(srcdir)/'`profiles/deviceinfo/deviceinfo.c
+
+profiles/deviceinfo/bluetoothd-deviceinfo.obj: profiles/deviceinfo/deviceinfo.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/deviceinfo/bluetoothd-deviceinfo.obj -MD -MP -MF profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Tpo -c -o profiles/deviceinfo/bluetoothd-deviceinfo.obj `if test -f 'profiles/deviceinfo/deviceinfo.c'; then $(CYGPATH_W) 'profiles/deviceinfo/deviceinfo.c'; else $(CYGPATH_W) '$(srcdir)/profiles/deviceinfo/deviceinfo.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Tpo profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/deviceinfo/deviceinfo.c' object='profiles/deviceinfo/bluetoothd-deviceinfo.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/deviceinfo/bluetoothd-deviceinfo.obj `if test -f 'profiles/deviceinfo/deviceinfo.c'; then $(CYGPATH_W) 'profiles/deviceinfo/deviceinfo.c'; else $(CYGPATH_W) '$(srcdir)/profiles/deviceinfo/deviceinfo.c'; fi`
+
+profiles/midi/bluetoothd-midi.o: profiles/midi/midi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/bluetoothd-midi.o -MD -MP -MF profiles/midi/$(DEPDIR)/bluetoothd-midi.Tpo -c -o profiles/midi/bluetoothd-midi.o `test -f 'profiles/midi/midi.c' || echo '$(srcdir)/'`profiles/midi/midi.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/bluetoothd-midi.Tpo profiles/midi/$(DEPDIR)/bluetoothd-midi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/midi.c' object='profiles/midi/bluetoothd-midi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/bluetoothd-midi.o `test -f 'profiles/midi/midi.c' || echo '$(srcdir)/'`profiles/midi/midi.c
+
+profiles/midi/bluetoothd-midi.obj: profiles/midi/midi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/bluetoothd-midi.obj -MD -MP -MF profiles/midi/$(DEPDIR)/bluetoothd-midi.Tpo -c -o profiles/midi/bluetoothd-midi.obj `if test -f 'profiles/midi/midi.c'; then $(CYGPATH_W) 'profiles/midi/midi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/midi.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/bluetoothd-midi.Tpo profiles/midi/$(DEPDIR)/bluetoothd-midi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/midi.c' object='profiles/midi/bluetoothd-midi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/bluetoothd-midi.obj `if test -f 'profiles/midi/midi.c'; then $(CYGPATH_W) 'profiles/midi/midi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/midi.c'; fi`
+
+profiles/midi/bluetoothd-libmidi.o: profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/bluetoothd-libmidi.o -MD -MP -MF profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Tpo -c -o profiles/midi/bluetoothd-libmidi.o `test -f 'profiles/midi/libmidi.c' || echo '$(srcdir)/'`profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Tpo profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/libmidi.c' object='profiles/midi/bluetoothd-libmidi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/bluetoothd-libmidi.o `test -f 'profiles/midi/libmidi.c' || echo '$(srcdir)/'`profiles/midi/libmidi.c
+
+profiles/midi/bluetoothd-libmidi.obj: profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/bluetoothd-libmidi.obj -MD -MP -MF profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Tpo -c -o profiles/midi/bluetoothd-libmidi.obj `if test -f 'profiles/midi/libmidi.c'; then $(CYGPATH_W) 'profiles/midi/libmidi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/libmidi.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Tpo profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/libmidi.c' object='profiles/midi/bluetoothd-libmidi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/bluetoothd-libmidi.obj `if test -f 'profiles/midi/libmidi.c'; then $(CYGPATH_W) 'profiles/midi/libmidi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/libmidi.c'; fi`
+
+profiles/battery/bluetoothd-battery.o: profiles/battery/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/battery/bluetoothd-battery.o -MD -MP -MF profiles/battery/$(DEPDIR)/bluetoothd-battery.Tpo -c -o profiles/battery/bluetoothd-battery.o `test -f 'profiles/battery/battery.c' || echo '$(srcdir)/'`profiles/battery/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/battery/$(DEPDIR)/bluetoothd-battery.Tpo profiles/battery/$(DEPDIR)/bluetoothd-battery.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/battery/battery.c' object='profiles/battery/bluetoothd-battery.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/battery/bluetoothd-battery.o `test -f 'profiles/battery/battery.c' || echo '$(srcdir)/'`profiles/battery/battery.c
+
+profiles/battery/bluetoothd-battery.obj: profiles/battery/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/battery/bluetoothd-battery.obj -MD -MP -MF profiles/battery/$(DEPDIR)/bluetoothd-battery.Tpo -c -o profiles/battery/bluetoothd-battery.obj `if test -f 'profiles/battery/battery.c'; then $(CYGPATH_W) 'profiles/battery/battery.c'; else $(CYGPATH_W) '$(srcdir)/profiles/battery/battery.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/battery/$(DEPDIR)/bluetoothd-battery.Tpo profiles/battery/$(DEPDIR)/bluetoothd-battery.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/battery/battery.c' object='profiles/battery/bluetoothd-battery.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/battery/bluetoothd-battery.obj `if test -f 'profiles/battery/battery.c'; then $(CYGPATH_W) 'profiles/battery/battery.c'; else $(CYGPATH_W) '$(srcdir)/profiles/battery/battery.c'; fi`
+
+plugins/bluetoothd-sixaxis.o: plugins/sixaxis.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-sixaxis.o -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-sixaxis.Tpo -c -o plugins/bluetoothd-sixaxis.o `test -f 'plugins/sixaxis.c' || echo '$(srcdir)/'`plugins/sixaxis.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-sixaxis.Tpo plugins/$(DEPDIR)/bluetoothd-sixaxis.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/sixaxis.c' object='plugins/bluetoothd-sixaxis.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-sixaxis.o `test -f 'plugins/sixaxis.c' || echo '$(srcdir)/'`plugins/sixaxis.c
+
+plugins/bluetoothd-sixaxis.obj: plugins/sixaxis.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins/bluetoothd-sixaxis.obj -MD -MP -MF plugins/$(DEPDIR)/bluetoothd-sixaxis.Tpo -c -o plugins/bluetoothd-sixaxis.obj `if test -f 'plugins/sixaxis.c'; then $(CYGPATH_W) 'plugins/sixaxis.c'; else $(CYGPATH_W) '$(srcdir)/plugins/sixaxis.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) plugins/$(DEPDIR)/bluetoothd-sixaxis.Tpo plugins/$(DEPDIR)/bluetoothd-sixaxis.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='plugins/sixaxis.c' object='plugins/bluetoothd-sixaxis.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins/bluetoothd-sixaxis.obj `if test -f 'plugins/sixaxis.c'; then $(CYGPATH_W) 'plugins/sixaxis.c'; else $(CYGPATH_W) '$(srcdir)/plugins/sixaxis.c'; fi`
+
+profiles/audio/bluetoothd-bap.o: profiles/audio/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-bap.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-bap.Tpo -c -o profiles/audio/bluetoothd-bap.o `test -f 'profiles/audio/bap.c' || echo '$(srcdir)/'`profiles/audio/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-bap.Tpo profiles/audio/$(DEPDIR)/bluetoothd-bap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/bap.c' object='profiles/audio/bluetoothd-bap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-bap.o `test -f 'profiles/audio/bap.c' || echo '$(srcdir)/'`profiles/audio/bap.c
+
+profiles/audio/bluetoothd-bap.obj: profiles/audio/bap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-bap.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-bap.Tpo -c -o profiles/audio/bluetoothd-bap.obj `if test -f 'profiles/audio/bap.c'; then $(CYGPATH_W) 'profiles/audio/bap.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/bap.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-bap.Tpo profiles/audio/$(DEPDIR)/bluetoothd-bap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/bap.c' object='profiles/audio/bluetoothd-bap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-bap.obj `if test -f 'profiles/audio/bap.c'; then $(CYGPATH_W) 'profiles/audio/bap.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/bap.c'; fi`
+
+profiles/audio/bluetoothd-bass.o: profiles/audio/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-bass.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-bass.Tpo -c -o profiles/audio/bluetoothd-bass.o `test -f 'profiles/audio/bass.c' || echo '$(srcdir)/'`profiles/audio/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-bass.Tpo profiles/audio/$(DEPDIR)/bluetoothd-bass.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/bass.c' object='profiles/audio/bluetoothd-bass.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-bass.o `test -f 'profiles/audio/bass.c' || echo '$(srcdir)/'`profiles/audio/bass.c
+
+profiles/audio/bluetoothd-bass.obj: profiles/audio/bass.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-bass.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-bass.Tpo -c -o profiles/audio/bluetoothd-bass.obj `if test -f 'profiles/audio/bass.c'; then $(CYGPATH_W) 'profiles/audio/bass.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/bass.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-bass.Tpo profiles/audio/$(DEPDIR)/bluetoothd-bass.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/bass.c' object='profiles/audio/bluetoothd-bass.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-bass.obj `if test -f 'profiles/audio/bass.c'; then $(CYGPATH_W) 'profiles/audio/bass.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/bass.c'; fi`
+
+profiles/audio/bluetoothd-mcp.o: profiles/audio/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-mcp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-mcp.Tpo -c -o profiles/audio/bluetoothd-mcp.o `test -f 'profiles/audio/mcp.c' || echo '$(srcdir)/'`profiles/audio/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-mcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/mcp.c' object='profiles/audio/bluetoothd-mcp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-mcp.o `test -f 'profiles/audio/mcp.c' || echo '$(srcdir)/'`profiles/audio/mcp.c
+
+profiles/audio/bluetoothd-mcp.obj: profiles/audio/mcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-mcp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-mcp.Tpo -c -o profiles/audio/bluetoothd-mcp.obj `if test -f 'profiles/audio/mcp.c'; then $(CYGPATH_W) 'profiles/audio/mcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/mcp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-mcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/mcp.c' object='profiles/audio/bluetoothd-mcp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-mcp.obj `if test -f 'profiles/audio/mcp.c'; then $(CYGPATH_W) 'profiles/audio/mcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/mcp.c'; fi`
+
+profiles/audio/bluetoothd-vcp.o: profiles/audio/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-vcp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-vcp.Tpo -c -o profiles/audio/bluetoothd-vcp.o `test -f 'profiles/audio/vcp.c' || echo '$(srcdir)/'`profiles/audio/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-vcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/vcp.c' object='profiles/audio/bluetoothd-vcp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-vcp.o `test -f 'profiles/audio/vcp.c' || echo '$(srcdir)/'`profiles/audio/vcp.c
+
+profiles/audio/bluetoothd-vcp.obj: profiles/audio/vcp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-vcp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-vcp.Tpo -c -o profiles/audio/bluetoothd-vcp.obj `if test -f 'profiles/audio/vcp.c'; then $(CYGPATH_W) 'profiles/audio/vcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/vcp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-vcp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/vcp.c' object='profiles/audio/bluetoothd-vcp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-vcp.obj `if test -f 'profiles/audio/vcp.c'; then $(CYGPATH_W) 'profiles/audio/vcp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/vcp.c'; fi`
+
+profiles/audio/bluetoothd-micp.o: profiles/audio/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-micp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-micp.Tpo -c -o profiles/audio/bluetoothd-micp.o `test -f 'profiles/audio/micp.c' || echo '$(srcdir)/'`profiles/audio/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-micp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-micp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/micp.c' object='profiles/audio/bluetoothd-micp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-micp.o `test -f 'profiles/audio/micp.c' || echo '$(srcdir)/'`profiles/audio/micp.c
+
+profiles/audio/bluetoothd-micp.obj: profiles/audio/micp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-micp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-micp.Tpo -c -o profiles/audio/bluetoothd-micp.obj `if test -f 'profiles/audio/micp.c'; then $(CYGPATH_W) 'profiles/audio/micp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/micp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-micp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-micp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/micp.c' object='profiles/audio/bluetoothd-micp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-micp.obj `if test -f 'profiles/audio/micp.c'; then $(CYGPATH_W) 'profiles/audio/micp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/micp.c'; fi`
+
+profiles/audio/bluetoothd-ccp.o: profiles/audio/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-ccp.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-ccp.Tpo -c -o profiles/audio/bluetoothd-ccp.o `test -f 'profiles/audio/ccp.c' || echo '$(srcdir)/'`profiles/audio/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-ccp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/ccp.c' object='profiles/audio/bluetoothd-ccp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-ccp.o `test -f 'profiles/audio/ccp.c' || echo '$(srcdir)/'`profiles/audio/ccp.c
+
+profiles/audio/bluetoothd-ccp.obj: profiles/audio/ccp.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-ccp.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-ccp.Tpo -c -o profiles/audio/bluetoothd-ccp.obj `if test -f 'profiles/audio/ccp.c'; then $(CYGPATH_W) 'profiles/audio/ccp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/ccp.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-ccp.Tpo profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/ccp.c' object='profiles/audio/bluetoothd-ccp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-ccp.obj `if test -f 'profiles/audio/ccp.c'; then $(CYGPATH_W) 'profiles/audio/ccp.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/ccp.c'; fi`
+
+profiles/audio/bluetoothd-csip.o: profiles/audio/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-csip.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-csip.Tpo -c -o profiles/audio/bluetoothd-csip.o `test -f 'profiles/audio/csip.c' || echo '$(srcdir)/'`profiles/audio/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-csip.Tpo profiles/audio/$(DEPDIR)/bluetoothd-csip.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/csip.c' object='profiles/audio/bluetoothd-csip.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-csip.o `test -f 'profiles/audio/csip.c' || echo '$(srcdir)/'`profiles/audio/csip.c
+
+profiles/audio/bluetoothd-csip.obj: profiles/audio/csip.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-csip.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-csip.Tpo -c -o profiles/audio/bluetoothd-csip.obj `if test -f 'profiles/audio/csip.c'; then $(CYGPATH_W) 'profiles/audio/csip.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/csip.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-csip.Tpo profiles/audio/$(DEPDIR)/bluetoothd-csip.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/csip.c' object='profiles/audio/bluetoothd-csip.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-csip.obj `if test -f 'profiles/audio/csip.c'; then $(CYGPATH_W) 'profiles/audio/csip.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/csip.c'; fi`
+
+profiles/audio/bluetoothd-asha.o: profiles/audio/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-asha.o -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-asha.Tpo -c -o profiles/audio/bluetoothd-asha.o `test -f 'profiles/audio/asha.c' || echo '$(srcdir)/'`profiles/audio/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-asha.Tpo profiles/audio/$(DEPDIR)/bluetoothd-asha.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/asha.c' object='profiles/audio/bluetoothd-asha.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-asha.o `test -f 'profiles/audio/asha.c' || echo '$(srcdir)/'`profiles/audio/asha.c
+
+profiles/audio/bluetoothd-asha.obj: profiles/audio/asha.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/audio/bluetoothd-asha.obj -MD -MP -MF profiles/audio/$(DEPDIR)/bluetoothd-asha.Tpo -c -o profiles/audio/bluetoothd-asha.obj `if test -f 'profiles/audio/asha.c'; then $(CYGPATH_W) 'profiles/audio/asha.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/asha.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/audio/$(DEPDIR)/bluetoothd-asha.Tpo profiles/audio/$(DEPDIR)/bluetoothd-asha.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/audio/asha.c' object='profiles/audio/bluetoothd-asha.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/audio/bluetoothd-asha.obj `if test -f 'profiles/audio/asha.c'; then $(CYGPATH_W) 'profiles/audio/asha.c'; else $(CYGPATH_W) '$(srcdir)/profiles/audio/asha.c'; fi`
+
+attrib/bluetoothd-att.o: attrib/att.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-att.o -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-att.Tpo -c -o attrib/bluetoothd-att.o `test -f 'attrib/att.c' || echo '$(srcdir)/'`attrib/att.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-att.Tpo attrib/$(DEPDIR)/bluetoothd-att.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/att.c' object='attrib/bluetoothd-att.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-att.o `test -f 'attrib/att.c' || echo '$(srcdir)/'`attrib/att.c
+
+attrib/bluetoothd-att.obj: attrib/att.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-att.obj -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-att.Tpo -c -o attrib/bluetoothd-att.obj `if test -f 'attrib/att.c'; then $(CYGPATH_W) 'attrib/att.c'; else $(CYGPATH_W) '$(srcdir)/attrib/att.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-att.Tpo attrib/$(DEPDIR)/bluetoothd-att.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/att.c' object='attrib/bluetoothd-att.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-att.obj `if test -f 'attrib/att.c'; then $(CYGPATH_W) 'attrib/att.c'; else $(CYGPATH_W) '$(srcdir)/attrib/att.c'; fi`
+
+attrib/bluetoothd-gatt.o: attrib/gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-gatt.o -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-gatt.Tpo -c -o attrib/bluetoothd-gatt.o `test -f 'attrib/gatt.c' || echo '$(srcdir)/'`attrib/gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-gatt.Tpo attrib/$(DEPDIR)/bluetoothd-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/gatt.c' object='attrib/bluetoothd-gatt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-gatt.o `test -f 'attrib/gatt.c' || echo '$(srcdir)/'`attrib/gatt.c
+
+attrib/bluetoothd-gatt.obj: attrib/gatt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-gatt.obj -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-gatt.Tpo -c -o attrib/bluetoothd-gatt.obj `if test -f 'attrib/gatt.c'; then $(CYGPATH_W) 'attrib/gatt.c'; else $(CYGPATH_W) '$(srcdir)/attrib/gatt.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-gatt.Tpo attrib/$(DEPDIR)/bluetoothd-gatt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/gatt.c' object='attrib/bluetoothd-gatt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-gatt.obj `if test -f 'attrib/gatt.c'; then $(CYGPATH_W) 'attrib/gatt.c'; else $(CYGPATH_W) '$(srcdir)/attrib/gatt.c'; fi`
+
+attrib/bluetoothd-gattrib.o: attrib/gattrib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-gattrib.o -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-gattrib.Tpo -c -o attrib/bluetoothd-gattrib.o `test -f 'attrib/gattrib.c' || echo '$(srcdir)/'`attrib/gattrib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-gattrib.Tpo attrib/$(DEPDIR)/bluetoothd-gattrib.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/gattrib.c' object='attrib/bluetoothd-gattrib.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-gattrib.o `test -f 'attrib/gattrib.c' || echo '$(srcdir)/'`attrib/gattrib.c
+
+attrib/bluetoothd-gattrib.obj: attrib/gattrib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attrib/bluetoothd-gattrib.obj -MD -MP -MF attrib/$(DEPDIR)/bluetoothd-gattrib.Tpo -c -o attrib/bluetoothd-gattrib.obj `if test -f 'attrib/gattrib.c'; then $(CYGPATH_W) 'attrib/gattrib.c'; else $(CYGPATH_W) '$(srcdir)/attrib/gattrib.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) attrib/$(DEPDIR)/bluetoothd-gattrib.Tpo attrib/$(DEPDIR)/bluetoothd-gattrib.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib/gattrib.c' object='attrib/bluetoothd-gattrib.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attrib/bluetoothd-gattrib.obj `if test -f 'attrib/gattrib.c'; then $(CYGPATH_W) 'attrib/gattrib.c'; else $(CYGPATH_W) '$(srcdir)/attrib/gattrib.c'; fi`
+
+btio/bluetoothd-btio.o: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT btio/bluetoothd-btio.o -MD -MP -MF btio/$(DEPDIR)/bluetoothd-btio.Tpo -c -o btio/bluetoothd-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/bluetoothd-btio.Tpo btio/$(DEPDIR)/bluetoothd-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/bluetoothd-btio.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o btio/bluetoothd-btio.o `test -f 'btio/btio.c' || echo '$(srcdir)/'`btio/btio.c
+
+btio/bluetoothd-btio.obj: btio/btio.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT btio/bluetoothd-btio.obj -MD -MP -MF btio/$(DEPDIR)/bluetoothd-btio.Tpo -c -o btio/bluetoothd-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) btio/$(DEPDIR)/bluetoothd-btio.Tpo btio/$(DEPDIR)/bluetoothd-btio.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='btio/btio.c' object='btio/bluetoothd-btio.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o btio/bluetoothd-btio.obj `if test -f 'btio/btio.c'; then $(CYGPATH_W) 'btio/btio.c'; else $(CYGPATH_W) '$(srcdir)/btio/btio.c'; fi`
+
+src/bluetoothd-main.o: src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-main.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-main.Tpo -c -o src/bluetoothd-main.o `test -f 'src/main.c' || echo '$(srcdir)/'`src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-main.Tpo src/$(DEPDIR)/bluetoothd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/main.c' object='src/bluetoothd-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-main.o `test -f 'src/main.c' || echo '$(srcdir)/'`src/main.c
+
+src/bluetoothd-main.obj: src/main.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-main.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-main.Tpo -c -o src/bluetoothd-main.obj `if test -f 'src/main.c'; then $(CYGPATH_W) 'src/main.c'; else $(CYGPATH_W) '$(srcdir)/src/main.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-main.Tpo src/$(DEPDIR)/bluetoothd-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/main.c' object='src/bluetoothd-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-main.obj `if test -f 'src/main.c'; then $(CYGPATH_W) 'src/main.c'; else $(CYGPATH_W) '$(srcdir)/src/main.c'; fi`
+
+src/bluetoothd-log.o: src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-log.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-log.Tpo -c -o src/bluetoothd-log.o `test -f 'src/log.c' || echo '$(srcdir)/'`src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-log.Tpo src/$(DEPDIR)/bluetoothd-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/log.c' object='src/bluetoothd-log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-log.o `test -f 'src/log.c' || echo '$(srcdir)/'`src/log.c
+
+src/bluetoothd-log.obj: src/log.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-log.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-log.Tpo -c -o src/bluetoothd-log.obj `if test -f 'src/log.c'; then $(CYGPATH_W) 'src/log.c'; else $(CYGPATH_W) '$(srcdir)/src/log.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-log.Tpo src/$(DEPDIR)/bluetoothd-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/log.c' object='src/bluetoothd-log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-log.obj `if test -f 'src/log.c'; then $(CYGPATH_W) 'src/log.c'; else $(CYGPATH_W) '$(srcdir)/src/log.c'; fi`
+
+src/bluetoothd-backtrace.o: src/backtrace.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-backtrace.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-backtrace.Tpo -c -o src/bluetoothd-backtrace.o `test -f 'src/backtrace.c' || echo '$(srcdir)/'`src/backtrace.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-backtrace.Tpo src/$(DEPDIR)/bluetoothd-backtrace.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/backtrace.c' object='src/bluetoothd-backtrace.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-backtrace.o `test -f 'src/backtrace.c' || echo '$(srcdir)/'`src/backtrace.c
+
+src/bluetoothd-backtrace.obj: src/backtrace.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-backtrace.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-backtrace.Tpo -c -o src/bluetoothd-backtrace.obj `if test -f 'src/backtrace.c'; then $(CYGPATH_W) 'src/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/src/backtrace.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-backtrace.Tpo src/$(DEPDIR)/bluetoothd-backtrace.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/backtrace.c' object='src/bluetoothd-backtrace.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-backtrace.obj `if test -f 'src/backtrace.c'; then $(CYGPATH_W) 'src/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/src/backtrace.c'; fi`
+
+src/bluetoothd-rfkill.o: src/rfkill.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-rfkill.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-rfkill.Tpo -c -o src/bluetoothd-rfkill.o `test -f 'src/rfkill.c' || echo '$(srcdir)/'`src/rfkill.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-rfkill.Tpo src/$(DEPDIR)/bluetoothd-rfkill.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/rfkill.c' object='src/bluetoothd-rfkill.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-rfkill.o `test -f 'src/rfkill.c' || echo '$(srcdir)/'`src/rfkill.c
+
+src/bluetoothd-rfkill.obj: src/rfkill.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-rfkill.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-rfkill.Tpo -c -o src/bluetoothd-rfkill.obj `if test -f 'src/rfkill.c'; then $(CYGPATH_W) 'src/rfkill.c'; else $(CYGPATH_W) '$(srcdir)/src/rfkill.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-rfkill.Tpo src/$(DEPDIR)/bluetoothd-rfkill.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/rfkill.c' object='src/bluetoothd-rfkill.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-rfkill.obj `if test -f 'src/rfkill.c'; then $(CYGPATH_W) 'src/rfkill.c'; else $(CYGPATH_W) '$(srcdir)/src/rfkill.c'; fi`
+
+src/bluetoothd-sdpd-server.o: src/sdpd-server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-server.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-server.Tpo -c -o src/bluetoothd-sdpd-server.o `test -f 'src/sdpd-server.c' || echo '$(srcdir)/'`src/sdpd-server.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-server.Tpo src/$(DEPDIR)/bluetoothd-sdpd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-server.c' object='src/bluetoothd-sdpd-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-server.o `test -f 'src/sdpd-server.c' || echo '$(srcdir)/'`src/sdpd-server.c
+
+src/bluetoothd-sdpd-server.obj: src/sdpd-server.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-server.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-server.Tpo -c -o src/bluetoothd-sdpd-server.obj `if test -f 'src/sdpd-server.c'; then $(CYGPATH_W) 'src/sdpd-server.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-server.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-server.Tpo src/$(DEPDIR)/bluetoothd-sdpd-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-server.c' object='src/bluetoothd-sdpd-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-server.obj `if test -f 'src/sdpd-server.c'; then $(CYGPATH_W) 'src/sdpd-server.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-server.c'; fi`
+
+src/bluetoothd-sdpd-request.o: src/sdpd-request.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-request.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-request.Tpo -c -o src/bluetoothd-sdpd-request.o `test -f 'src/sdpd-request.c' || echo '$(srcdir)/'`src/sdpd-request.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-request.Tpo src/$(DEPDIR)/bluetoothd-sdpd-request.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-request.c' object='src/bluetoothd-sdpd-request.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-request.o `test -f 'src/sdpd-request.c' || echo '$(srcdir)/'`src/sdpd-request.c
+
+src/bluetoothd-sdpd-request.obj: src/sdpd-request.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-request.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-request.Tpo -c -o src/bluetoothd-sdpd-request.obj `if test -f 'src/sdpd-request.c'; then $(CYGPATH_W) 'src/sdpd-request.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-request.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-request.Tpo src/$(DEPDIR)/bluetoothd-sdpd-request.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-request.c' object='src/bluetoothd-sdpd-request.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-request.obj `if test -f 'src/sdpd-request.c'; then $(CYGPATH_W) 'src/sdpd-request.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-request.c'; fi`
+
+src/bluetoothd-sdpd-service.o: src/sdpd-service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-service.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-service.Tpo -c -o src/bluetoothd-sdpd-service.o `test -f 'src/sdpd-service.c' || echo '$(srcdir)/'`src/sdpd-service.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-service.Tpo src/$(DEPDIR)/bluetoothd-sdpd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-service.c' object='src/bluetoothd-sdpd-service.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-service.o `test -f 'src/sdpd-service.c' || echo '$(srcdir)/'`src/sdpd-service.c
+
+src/bluetoothd-sdpd-service.obj: src/sdpd-service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-service.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-service.Tpo -c -o src/bluetoothd-sdpd-service.obj `if test -f 'src/sdpd-service.c'; then $(CYGPATH_W) 'src/sdpd-service.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-service.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-service.Tpo src/$(DEPDIR)/bluetoothd-sdpd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-service.c' object='src/bluetoothd-sdpd-service.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-service.obj `if test -f 'src/sdpd-service.c'; then $(CYGPATH_W) 'src/sdpd-service.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-service.c'; fi`
+
+src/bluetoothd-sdpd-database.o: src/sdpd-database.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-database.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-database.Tpo -c -o src/bluetoothd-sdpd-database.o `test -f 'src/sdpd-database.c' || echo '$(srcdir)/'`src/sdpd-database.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-database.Tpo src/$(DEPDIR)/bluetoothd-sdpd-database.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-database.c' object='src/bluetoothd-sdpd-database.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-database.o `test -f 'src/sdpd-database.c' || echo '$(srcdir)/'`src/sdpd-database.c
+
+src/bluetoothd-sdpd-database.obj: src/sdpd-database.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdpd-database.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdpd-database.Tpo -c -o src/bluetoothd-sdpd-database.obj `if test -f 'src/sdpd-database.c'; then $(CYGPATH_W) 'src/sdpd-database.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-database.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdpd-database.Tpo src/$(DEPDIR)/bluetoothd-sdpd-database.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdpd-database.c' object='src/bluetoothd-sdpd-database.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdpd-database.obj `if test -f 'src/sdpd-database.c'; then $(CYGPATH_W) 'src/sdpd-database.c'; else $(CYGPATH_W) '$(srcdir)/src/sdpd-database.c'; fi`
+
+src/bluetoothd-gatt-database.o: src/gatt-database.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-gatt-database.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-gatt-database.Tpo -c -o src/bluetoothd-gatt-database.o `test -f 'src/gatt-database.c' || echo '$(srcdir)/'`src/gatt-database.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-gatt-database.Tpo src/$(DEPDIR)/bluetoothd-gatt-database.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/gatt-database.c' object='src/bluetoothd-gatt-database.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-gatt-database.o `test -f 'src/gatt-database.c' || echo '$(srcdir)/'`src/gatt-database.c
+
+src/bluetoothd-gatt-database.obj: src/gatt-database.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-gatt-database.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-gatt-database.Tpo -c -o src/bluetoothd-gatt-database.obj `if test -f 'src/gatt-database.c'; then $(CYGPATH_W) 'src/gatt-database.c'; else $(CYGPATH_W) '$(srcdir)/src/gatt-database.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-gatt-database.Tpo src/$(DEPDIR)/bluetoothd-gatt-database.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/gatt-database.c' object='src/bluetoothd-gatt-database.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-gatt-database.obj `if test -f 'src/gatt-database.c'; then $(CYGPATH_W) 'src/gatt-database.c'; else $(CYGPATH_W) '$(srcdir)/src/gatt-database.c'; fi`
+
+src/bluetoothd-sdp-xml.o: src/sdp-xml.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdp-xml.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdp-xml.Tpo -c -o src/bluetoothd-sdp-xml.o `test -f 'src/sdp-xml.c' || echo '$(srcdir)/'`src/sdp-xml.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdp-xml.Tpo src/$(DEPDIR)/bluetoothd-sdp-xml.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdp-xml.c' object='src/bluetoothd-sdp-xml.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdp-xml.o `test -f 'src/sdp-xml.c' || echo '$(srcdir)/'`src/sdp-xml.c
+
+src/bluetoothd-sdp-xml.obj: src/sdp-xml.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdp-xml.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdp-xml.Tpo -c -o src/bluetoothd-sdp-xml.obj `if test -f 'src/sdp-xml.c'; then $(CYGPATH_W) 'src/sdp-xml.c'; else $(CYGPATH_W) '$(srcdir)/src/sdp-xml.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdp-xml.Tpo src/$(DEPDIR)/bluetoothd-sdp-xml.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdp-xml.c' object='src/bluetoothd-sdp-xml.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdp-xml.obj `if test -f 'src/sdp-xml.c'; then $(CYGPATH_W) 'src/sdp-xml.c'; else $(CYGPATH_W) '$(srcdir)/src/sdp-xml.c'; fi`
+
+src/bluetoothd-sdp-client.o: src/sdp-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdp-client.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdp-client.Tpo -c -o src/bluetoothd-sdp-client.o `test -f 'src/sdp-client.c' || echo '$(srcdir)/'`src/sdp-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdp-client.Tpo src/$(DEPDIR)/bluetoothd-sdp-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdp-client.c' object='src/bluetoothd-sdp-client.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdp-client.o `test -f 'src/sdp-client.c' || echo '$(srcdir)/'`src/sdp-client.c
+
+src/bluetoothd-sdp-client.obj: src/sdp-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-sdp-client.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-sdp-client.Tpo -c -o src/bluetoothd-sdp-client.obj `if test -f 'src/sdp-client.c'; then $(CYGPATH_W) 'src/sdp-client.c'; else $(CYGPATH_W) '$(srcdir)/src/sdp-client.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-sdp-client.Tpo src/$(DEPDIR)/bluetoothd-sdp-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/sdp-client.c' object='src/bluetoothd-sdp-client.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-sdp-client.obj `if test -f 'src/sdp-client.c'; then $(CYGPATH_W) 'src/sdp-client.c'; else $(CYGPATH_W) '$(srcdir)/src/sdp-client.c'; fi`
+
+src/bluetoothd-textfile.o: src/textfile.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-textfile.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-textfile.Tpo -c -o src/bluetoothd-textfile.o `test -f 'src/textfile.c' || echo '$(srcdir)/'`src/textfile.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-textfile.Tpo src/$(DEPDIR)/bluetoothd-textfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/textfile.c' object='src/bluetoothd-textfile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-textfile.o `test -f 'src/textfile.c' || echo '$(srcdir)/'`src/textfile.c
+
+src/bluetoothd-textfile.obj: src/textfile.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-textfile.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-textfile.Tpo -c -o src/bluetoothd-textfile.obj `if test -f 'src/textfile.c'; then $(CYGPATH_W) 'src/textfile.c'; else $(CYGPATH_W) '$(srcdir)/src/textfile.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-textfile.Tpo src/$(DEPDIR)/bluetoothd-textfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/textfile.c' object='src/bluetoothd-textfile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-textfile.obj `if test -f 'src/textfile.c'; then $(CYGPATH_W) 'src/textfile.c'; else $(CYGPATH_W) '$(srcdir)/src/textfile.c'; fi`
+
+src/bluetoothd-uuid-helper.o: src/uuid-helper.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-uuid-helper.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-uuid-helper.Tpo -c -o src/bluetoothd-uuid-helper.o `test -f 'src/uuid-helper.c' || echo '$(srcdir)/'`src/uuid-helper.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-uuid-helper.Tpo src/$(DEPDIR)/bluetoothd-uuid-helper.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/uuid-helper.c' object='src/bluetoothd-uuid-helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-uuid-helper.o `test -f 'src/uuid-helper.c' || echo '$(srcdir)/'`src/uuid-helper.c
+
+src/bluetoothd-uuid-helper.obj: src/uuid-helper.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-uuid-helper.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-uuid-helper.Tpo -c -o src/bluetoothd-uuid-helper.obj `if test -f 'src/uuid-helper.c'; then $(CYGPATH_W) 'src/uuid-helper.c'; else $(CYGPATH_W) '$(srcdir)/src/uuid-helper.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-uuid-helper.Tpo src/$(DEPDIR)/bluetoothd-uuid-helper.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/uuid-helper.c' object='src/bluetoothd-uuid-helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-uuid-helper.obj `if test -f 'src/uuid-helper.c'; then $(CYGPATH_W) 'src/uuid-helper.c'; else $(CYGPATH_W) '$(srcdir)/src/uuid-helper.c'; fi`
+
+src/bluetoothd-plugin.o: src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-plugin.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-plugin.Tpo -c -o src/bluetoothd-plugin.o `test -f 'src/plugin.c' || echo '$(srcdir)/'`src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-plugin.Tpo src/$(DEPDIR)/bluetoothd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/plugin.c' object='src/bluetoothd-plugin.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-plugin.o `test -f 'src/plugin.c' || echo '$(srcdir)/'`src/plugin.c
+
+src/bluetoothd-plugin.obj: src/plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-plugin.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-plugin.Tpo -c -o src/bluetoothd-plugin.obj `if test -f 'src/plugin.c'; then $(CYGPATH_W) 'src/plugin.c'; else $(CYGPATH_W) '$(srcdir)/src/plugin.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-plugin.Tpo src/$(DEPDIR)/bluetoothd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/plugin.c' object='src/bluetoothd-plugin.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-plugin.obj `if test -f 'src/plugin.c'; then $(CYGPATH_W) 'src/plugin.c'; else $(CYGPATH_W) '$(srcdir)/src/plugin.c'; fi`
+
+src/bluetoothd-storage.o: src/storage.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-storage.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-storage.Tpo -c -o src/bluetoothd-storage.o `test -f 'src/storage.c' || echo '$(srcdir)/'`src/storage.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-storage.Tpo src/$(DEPDIR)/bluetoothd-storage.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/storage.c' object='src/bluetoothd-storage.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-storage.o `test -f 'src/storage.c' || echo '$(srcdir)/'`src/storage.c
+
+src/bluetoothd-storage.obj: src/storage.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-storage.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-storage.Tpo -c -o src/bluetoothd-storage.obj `if test -f 'src/storage.c'; then $(CYGPATH_W) 'src/storage.c'; else $(CYGPATH_W) '$(srcdir)/src/storage.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-storage.Tpo src/$(DEPDIR)/bluetoothd-storage.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/storage.c' object='src/bluetoothd-storage.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-storage.obj `if test -f 'src/storage.c'; then $(CYGPATH_W) 'src/storage.c'; else $(CYGPATH_W) '$(srcdir)/src/storage.c'; fi`
+
+src/bluetoothd-advertising.o: src/advertising.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-advertising.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-advertising.Tpo -c -o src/bluetoothd-advertising.o `test -f 'src/advertising.c' || echo '$(srcdir)/'`src/advertising.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-advertising.Tpo src/$(DEPDIR)/bluetoothd-advertising.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/advertising.c' object='src/bluetoothd-advertising.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-advertising.o `test -f 'src/advertising.c' || echo '$(srcdir)/'`src/advertising.c
+
+src/bluetoothd-advertising.obj: src/advertising.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-advertising.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-advertising.Tpo -c -o src/bluetoothd-advertising.obj `if test -f 'src/advertising.c'; then $(CYGPATH_W) 'src/advertising.c'; else $(CYGPATH_W) '$(srcdir)/src/advertising.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-advertising.Tpo src/$(DEPDIR)/bluetoothd-advertising.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/advertising.c' object='src/bluetoothd-advertising.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-advertising.obj `if test -f 'src/advertising.c'; then $(CYGPATH_W) 'src/advertising.c'; else $(CYGPATH_W) '$(srcdir)/src/advertising.c'; fi`
+
+src/bluetoothd-agent.o: src/agent.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-agent.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-agent.Tpo -c -o src/bluetoothd-agent.o `test -f 'src/agent.c' || echo '$(srcdir)/'`src/agent.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-agent.Tpo src/$(DEPDIR)/bluetoothd-agent.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/agent.c' object='src/bluetoothd-agent.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-agent.o `test -f 'src/agent.c' || echo '$(srcdir)/'`src/agent.c
+
+src/bluetoothd-agent.obj: src/agent.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-agent.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-agent.Tpo -c -o src/bluetoothd-agent.obj `if test -f 'src/agent.c'; then $(CYGPATH_W) 'src/agent.c'; else $(CYGPATH_W) '$(srcdir)/src/agent.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-agent.Tpo src/$(DEPDIR)/bluetoothd-agent.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/agent.c' object='src/bluetoothd-agent.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-agent.obj `if test -f 'src/agent.c'; then $(CYGPATH_W) 'src/agent.c'; else $(CYGPATH_W) '$(srcdir)/src/agent.c'; fi`
+
+src/bluetoothd-error.o: src/error.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-error.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-error.Tpo -c -o src/bluetoothd-error.o `test -f 'src/error.c' || echo '$(srcdir)/'`src/error.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-error.Tpo src/$(DEPDIR)/bluetoothd-error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/error.c' object='src/bluetoothd-error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-error.o `test -f 'src/error.c' || echo '$(srcdir)/'`src/error.c
+
+src/bluetoothd-error.obj: src/error.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-error.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-error.Tpo -c -o src/bluetoothd-error.obj `if test -f 'src/error.c'; then $(CYGPATH_W) 'src/error.c'; else $(CYGPATH_W) '$(srcdir)/src/error.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-error.Tpo src/$(DEPDIR)/bluetoothd-error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/error.c' object='src/bluetoothd-error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-error.obj `if test -f 'src/error.c'; then $(CYGPATH_W) 'src/error.c'; else $(CYGPATH_W) '$(srcdir)/src/error.c'; fi`
+
+src/bluetoothd-adapter.o: src/adapter.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-adapter.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-adapter.Tpo -c -o src/bluetoothd-adapter.o `test -f 'src/adapter.c' || echo '$(srcdir)/'`src/adapter.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-adapter.Tpo src/$(DEPDIR)/bluetoothd-adapter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/adapter.c' object='src/bluetoothd-adapter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-adapter.o `test -f 'src/adapter.c' || echo '$(srcdir)/'`src/adapter.c
+
+src/bluetoothd-adapter.obj: src/adapter.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-adapter.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-adapter.Tpo -c -o src/bluetoothd-adapter.obj `if test -f 'src/adapter.c'; then $(CYGPATH_W) 'src/adapter.c'; else $(CYGPATH_W) '$(srcdir)/src/adapter.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-adapter.Tpo src/$(DEPDIR)/bluetoothd-adapter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/adapter.c' object='src/bluetoothd-adapter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-adapter.obj `if test -f 'src/adapter.c'; then $(CYGPATH_W) 'src/adapter.c'; else $(CYGPATH_W) '$(srcdir)/src/adapter.c'; fi`
+
+src/bluetoothd-profile.o: src/profile.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-profile.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-profile.Tpo -c -o src/bluetoothd-profile.o `test -f 'src/profile.c' || echo '$(srcdir)/'`src/profile.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-profile.Tpo src/$(DEPDIR)/bluetoothd-profile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/profile.c' object='src/bluetoothd-profile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-profile.o `test -f 'src/profile.c' || echo '$(srcdir)/'`src/profile.c
+
+src/bluetoothd-profile.obj: src/profile.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-profile.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-profile.Tpo -c -o src/bluetoothd-profile.obj `if test -f 'src/profile.c'; then $(CYGPATH_W) 'src/profile.c'; else $(CYGPATH_W) '$(srcdir)/src/profile.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-profile.Tpo src/$(DEPDIR)/bluetoothd-profile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/profile.c' object='src/bluetoothd-profile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-profile.obj `if test -f 'src/profile.c'; then $(CYGPATH_W) 'src/profile.c'; else $(CYGPATH_W) '$(srcdir)/src/profile.c'; fi`
+
+src/bluetoothd-service.o: src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-service.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-service.Tpo -c -o src/bluetoothd-service.o `test -f 'src/service.c' || echo '$(srcdir)/'`src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-service.Tpo src/$(DEPDIR)/bluetoothd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/service.c' object='src/bluetoothd-service.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-service.o `test -f 'src/service.c' || echo '$(srcdir)/'`src/service.c
+
+src/bluetoothd-service.obj: src/service.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-service.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-service.Tpo -c -o src/bluetoothd-service.obj `if test -f 'src/service.c'; then $(CYGPATH_W) 'src/service.c'; else $(CYGPATH_W) '$(srcdir)/src/service.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-service.Tpo src/$(DEPDIR)/bluetoothd-service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/service.c' object='src/bluetoothd-service.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-service.obj `if test -f 'src/service.c'; then $(CYGPATH_W) 'src/service.c'; else $(CYGPATH_W) '$(srcdir)/src/service.c'; fi`
+
+src/bluetoothd-gatt-client.o: src/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-gatt-client.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-gatt-client.Tpo -c -o src/bluetoothd-gatt-client.o `test -f 'src/gatt-client.c' || echo '$(srcdir)/'`src/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-gatt-client.Tpo src/$(DEPDIR)/bluetoothd-gatt-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/gatt-client.c' object='src/bluetoothd-gatt-client.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-gatt-client.o `test -f 'src/gatt-client.c' || echo '$(srcdir)/'`src/gatt-client.c
+
+src/bluetoothd-gatt-client.obj: src/gatt-client.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-gatt-client.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-gatt-client.Tpo -c -o src/bluetoothd-gatt-client.obj `if test -f 'src/gatt-client.c'; then $(CYGPATH_W) 'src/gatt-client.c'; else $(CYGPATH_W) '$(srcdir)/src/gatt-client.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-gatt-client.Tpo src/$(DEPDIR)/bluetoothd-gatt-client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/gatt-client.c' object='src/bluetoothd-gatt-client.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-gatt-client.obj `if test -f 'src/gatt-client.c'; then $(CYGPATH_W) 'src/gatt-client.c'; else $(CYGPATH_W) '$(srcdir)/src/gatt-client.c'; fi`
+
+src/bluetoothd-device.o: src/device.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-device.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-device.Tpo -c -o src/bluetoothd-device.o `test -f 'src/device.c' || echo '$(srcdir)/'`src/device.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-device.Tpo src/$(DEPDIR)/bluetoothd-device.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/device.c' object='src/bluetoothd-device.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-device.o `test -f 'src/device.c' || echo '$(srcdir)/'`src/device.c
+
+src/bluetoothd-device.obj: src/device.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-device.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-device.Tpo -c -o src/bluetoothd-device.obj `if test -f 'src/device.c'; then $(CYGPATH_W) 'src/device.c'; else $(CYGPATH_W) '$(srcdir)/src/device.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-device.Tpo src/$(DEPDIR)/bluetoothd-device.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/device.c' object='src/bluetoothd-device.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-device.obj `if test -f 'src/device.c'; then $(CYGPATH_W) 'src/device.c'; else $(CYGPATH_W) '$(srcdir)/src/device.c'; fi`
+
+src/bluetoothd-dbus-common.o: src/dbus-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-dbus-common.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-dbus-common.Tpo -c -o src/bluetoothd-dbus-common.o `test -f 'src/dbus-common.c' || echo '$(srcdir)/'`src/dbus-common.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-dbus-common.Tpo src/$(DEPDIR)/bluetoothd-dbus-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/dbus-common.c' object='src/bluetoothd-dbus-common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-dbus-common.o `test -f 'src/dbus-common.c' || echo '$(srcdir)/'`src/dbus-common.c
+
+src/bluetoothd-dbus-common.obj: src/dbus-common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-dbus-common.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-dbus-common.Tpo -c -o src/bluetoothd-dbus-common.obj `if test -f 'src/dbus-common.c'; then $(CYGPATH_W) 'src/dbus-common.c'; else $(CYGPATH_W) '$(srcdir)/src/dbus-common.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-dbus-common.Tpo src/$(DEPDIR)/bluetoothd-dbus-common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/dbus-common.c' object='src/bluetoothd-dbus-common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-dbus-common.obj `if test -f 'src/dbus-common.c'; then $(CYGPATH_W) 'src/dbus-common.c'; else $(CYGPATH_W) '$(srcdir)/src/dbus-common.c'; fi`
+
+src/bluetoothd-eir.o: src/eir.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-eir.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-eir.Tpo -c -o src/bluetoothd-eir.o `test -f 'src/eir.c' || echo '$(srcdir)/'`src/eir.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-eir.Tpo src/$(DEPDIR)/bluetoothd-eir.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/eir.c' object='src/bluetoothd-eir.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-eir.o `test -f 'src/eir.c' || echo '$(srcdir)/'`src/eir.c
+
+src/bluetoothd-eir.obj: src/eir.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-eir.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-eir.Tpo -c -o src/bluetoothd-eir.obj `if test -f 'src/eir.c'; then $(CYGPATH_W) 'src/eir.c'; else $(CYGPATH_W) '$(srcdir)/src/eir.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-eir.Tpo src/$(DEPDIR)/bluetoothd-eir.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/eir.c' object='src/bluetoothd-eir.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-eir.obj `if test -f 'src/eir.c'; then $(CYGPATH_W) 'src/eir.c'; else $(CYGPATH_W) '$(srcdir)/src/eir.c'; fi`
+
+src/bluetoothd-adv_monitor.o: src/adv_monitor.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-adv_monitor.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-adv_monitor.Tpo -c -o src/bluetoothd-adv_monitor.o `test -f 'src/adv_monitor.c' || echo '$(srcdir)/'`src/adv_monitor.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-adv_monitor.Tpo src/$(DEPDIR)/bluetoothd-adv_monitor.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/adv_monitor.c' object='src/bluetoothd-adv_monitor.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-adv_monitor.o `test -f 'src/adv_monitor.c' || echo '$(srcdir)/'`src/adv_monitor.c
+
+src/bluetoothd-adv_monitor.obj: src/adv_monitor.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-adv_monitor.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-adv_monitor.Tpo -c -o src/bluetoothd-adv_monitor.obj `if test -f 'src/adv_monitor.c'; then $(CYGPATH_W) 'src/adv_monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/adv_monitor.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-adv_monitor.Tpo src/$(DEPDIR)/bluetoothd-adv_monitor.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/adv_monitor.c' object='src/bluetoothd-adv_monitor.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-adv_monitor.obj `if test -f 'src/adv_monitor.c'; then $(CYGPATH_W) 'src/adv_monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/adv_monitor.c'; fi`
+
+src/bluetoothd-battery.o: src/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-battery.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-battery.Tpo -c -o src/bluetoothd-battery.o `test -f 'src/battery.c' || echo '$(srcdir)/'`src/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-battery.Tpo src/$(DEPDIR)/bluetoothd-battery.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/battery.c' object='src/bluetoothd-battery.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-battery.o `test -f 'src/battery.c' || echo '$(srcdir)/'`src/battery.c
+
+src/bluetoothd-battery.obj: src/battery.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-battery.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-battery.Tpo -c -o src/bluetoothd-battery.obj `if test -f 'src/battery.c'; then $(CYGPATH_W) 'src/battery.c'; else $(CYGPATH_W) '$(srcdir)/src/battery.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-battery.Tpo src/$(DEPDIR)/bluetoothd-battery.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/battery.c' object='src/bluetoothd-battery.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-battery.obj `if test -f 'src/battery.c'; then $(CYGPATH_W) 'src/battery.c'; else $(CYGPATH_W) '$(srcdir)/src/battery.c'; fi`
+
+src/bluetoothd-settings.o: src/settings.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-settings.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-settings.Tpo -c -o src/bluetoothd-settings.o `test -f 'src/settings.c' || echo '$(srcdir)/'`src/settings.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-settings.Tpo src/$(DEPDIR)/bluetoothd-settings.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/settings.c' object='src/bluetoothd-settings.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-settings.o `test -f 'src/settings.c' || echo '$(srcdir)/'`src/settings.c
+
+src/bluetoothd-settings.obj: src/settings.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-settings.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-settings.Tpo -c -o src/bluetoothd-settings.obj `if test -f 'src/settings.c'; then $(CYGPATH_W) 'src/settings.c'; else $(CYGPATH_W) '$(srcdir)/src/settings.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-settings.Tpo src/$(DEPDIR)/bluetoothd-settings.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/settings.c' object='src/bluetoothd-settings.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-settings.obj `if test -f 'src/settings.c'; then $(CYGPATH_W) 'src/settings.c'; else $(CYGPATH_W) '$(srcdir)/src/settings.c'; fi`
+
+src/bluetoothd-set.o: src/set.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-set.o -MD -MP -MF src/$(DEPDIR)/bluetoothd-set.Tpo -c -o src/bluetoothd-set.o `test -f 'src/set.c' || echo '$(srcdir)/'`src/set.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-set.Tpo src/$(DEPDIR)/bluetoothd-set.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/set.c' object='src/bluetoothd-set.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-set.o `test -f 'src/set.c' || echo '$(srcdir)/'`src/set.c
+
+src/bluetoothd-set.obj: src/set.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/bluetoothd-set.obj -MD -MP -MF src/$(DEPDIR)/bluetoothd-set.Tpo -c -o src/bluetoothd-set.obj `if test -f 'src/set.c'; then $(CYGPATH_W) 'src/set.c'; else $(CYGPATH_W) '$(srcdir)/src/set.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/bluetoothd-set.Tpo src/$(DEPDIR)/bluetoothd-set.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/set.c' object='src/bluetoothd-set.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bluetoothd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/bluetoothd-set.obj `if test -f 'src/set.c'; then $(CYGPATH_W) 'src/set.c'; else $(CYGPATH_W) '$(srcdir)/src/set.c'; fi`
+
+unit/test_mesh_crypto-test-mesh-crypto.o: unit/test-mesh-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_mesh_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unit/test_mesh_crypto-test-mesh-crypto.o -MD -MP -MF unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Tpo -c -o unit/test_mesh_crypto-test-mesh-crypto.o `test -f 'unit/test-mesh-crypto.c' || echo '$(srcdir)/'`unit/test-mesh-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Tpo unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unit/test-mesh-crypto.c' object='unit/test_mesh_crypto-test-mesh-crypto.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_mesh_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unit/test_mesh_crypto-test-mesh-crypto.o `test -f 'unit/test-mesh-crypto.c' || echo '$(srcdir)/'`unit/test-mesh-crypto.c
+
+unit/test_mesh_crypto-test-mesh-crypto.obj: unit/test-mesh-crypto.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_mesh_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unit/test_mesh_crypto-test-mesh-crypto.obj -MD -MP -MF unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Tpo -c -o unit/test_mesh_crypto-test-mesh-crypto.obj `if test -f 'unit/test-mesh-crypto.c'; then $(CYGPATH_W) 'unit/test-mesh-crypto.c'; else $(CYGPATH_W) '$(srcdir)/unit/test-mesh-crypto.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Tpo unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unit/test-mesh-crypto.c' object='unit/test_mesh_crypto-test-mesh-crypto.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_mesh_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unit/test_mesh_crypto-test-mesh-crypto.obj `if test -f 'unit/test-mesh-crypto.c'; then $(CYGPATH_W) 'unit/test-mesh-crypto.c'; else $(CYGPATH_W) '$(srcdir)/unit/test-mesh-crypto.c'; fi`
+
+unit/test_midi-test-midi.o: unit/test-midi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unit/test_midi-test-midi.o -MD -MP -MF unit/$(DEPDIR)/test_midi-test-midi.Tpo -c -o unit/test_midi-test-midi.o `test -f 'unit/test-midi.c' || echo '$(srcdir)/'`unit/test-midi.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) unit/$(DEPDIR)/test_midi-test-midi.Tpo unit/$(DEPDIR)/test_midi-test-midi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unit/test-midi.c' object='unit/test_midi-test-midi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unit/test_midi-test-midi.o `test -f 'unit/test-midi.c' || echo '$(srcdir)/'`unit/test-midi.c
+
+unit/test_midi-test-midi.obj: unit/test-midi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unit/test_midi-test-midi.obj -MD -MP -MF unit/$(DEPDIR)/test_midi-test-midi.Tpo -c -o unit/test_midi-test-midi.obj `if test -f 'unit/test-midi.c'; then $(CYGPATH_W) 'unit/test-midi.c'; else $(CYGPATH_W) '$(srcdir)/unit/test-midi.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) unit/$(DEPDIR)/test_midi-test-midi.Tpo unit/$(DEPDIR)/test_midi-test-midi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unit/test-midi.c' object='unit/test_midi-test-midi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unit/test_midi-test-midi.obj `if test -f 'unit/test-midi.c'; then $(CYGPATH_W) 'unit/test-midi.c'; else $(CYGPATH_W) '$(srcdir)/unit/test-midi.c'; fi`
+
+profiles/midi/unit_test_midi-libmidi.o: profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/unit_test_midi-libmidi.o -MD -MP -MF profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Tpo -c -o profiles/midi/unit_test_midi-libmidi.o `test -f 'profiles/midi/libmidi.c' || echo '$(srcdir)/'`profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Tpo profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/libmidi.c' object='profiles/midi/unit_test_midi-libmidi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/unit_test_midi-libmidi.o `test -f 'profiles/midi/libmidi.c' || echo '$(srcdir)/'`profiles/midi/libmidi.c
+
+profiles/midi/unit_test_midi-libmidi.obj: profiles/midi/libmidi.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT profiles/midi/unit_test_midi-libmidi.obj -MD -MP -MF profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Tpo -c -o profiles/midi/unit_test_midi-libmidi.obj `if test -f 'profiles/midi/libmidi.c'; then $(CYGPATH_W) 'profiles/midi/libmidi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/libmidi.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Tpo profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='profiles/midi/libmidi.c' object='profiles/midi/unit_test_midi-libmidi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(unit_test_midi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o profiles/midi/unit_test_midi-libmidi.obj `if test -f 'profiles/midi/libmidi.c'; then $(CYGPATH_W) 'profiles/midi/libmidi.c'; else $(CYGPATH_W) '$(srcdir)/profiles/midi/libmidi.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+	-rm -rf android/.libs android/_libs
+	-rm -rf android/audio_utils/.libs android/audio_utils/_libs
+	-rm -rf attrib/.libs attrib/_libs
+	-rm -rf client/.libs client/_libs
+	-rm -rf ell/.libs ell/_libs
+	-rm -rf emulator/.libs emulator/_libs
+	-rm -rf gdbus/.libs gdbus/_libs
+	-rm -rf lib/.libs lib/_libs
+	-rm -rf mesh/.libs mesh/_libs
+	-rm -rf monitor/.libs monitor/_libs
+	-rm -rf obexd/src/.libs obexd/src/_libs
+	-rm -rf peripheral/.libs peripheral/_libs
+	-rm -rf profiles/cups/.libs profiles/cups/_libs
+	-rm -rf profiles/iap/.libs profiles/iap/_libs
+	-rm -rf src/.libs src/_libs
+	-rm -rf src/shared/.libs src/shared/_libs
+	-rm -rf tools/.libs tools/_libs
+	-rm -rf unit/.libs unit/_libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+install-man1: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man1dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.1[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man1:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man1dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.1[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+install-man5: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man5dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.5[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man5:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man5dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.5[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man7: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man7dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.7[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man7:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man7dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.7[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man8dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.8[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man8dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.8[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+install-confDATA: $(conf_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(conf_DATA)'; test -n "$(confdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(confdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(confdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(confdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(confdir)" || exit $$?; \
+	done
+
+uninstall-confDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(conf_DATA)'; test -n "$(confdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(confdir)'; $(am__uninstall_files_from_dir)
+install-dbusDATA: $(dbus_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(dbus_DATA)'; test -n "$(dbusdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(dbusdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(dbusdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusdir)" || exit $$?; \
+	done
+
+uninstall-dbusDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(dbus_DATA)'; test -n "$(dbusdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(dbusdir)'; $(am__uninstall_files_from_dir)
+install-dbussessionbusDATA: $(dbussessionbus_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(dbussessionbus_DATA)'; test -n "$(dbussessionbusdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(dbussessionbusdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(dbussessionbusdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbussessionbusdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(dbussessionbusdir)" || exit $$?; \
+	done
+
+uninstall-dbussessionbusDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(dbussessionbus_DATA)'; test -n "$(dbussessionbusdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(dbussessionbusdir)'; $(am__uninstall_files_from_dir)
+install-dbussystembusDATA: $(dbussystembus_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(dbussystembus_DATA)'; test -n "$(dbussystembusdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(dbussystembusdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(dbussystembusdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbussystembusdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(dbussystembusdir)" || exit $$?; \
+	done
+
+uninstall-dbussystembusDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(dbussystembus_DATA)'; test -n "$(dbussystembusdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(dbussystembusdir)'; $(am__uninstall_files_from_dir)
+install-dist_zshcompletionDATA: $(dist_zshcompletion_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(dist_zshcompletion_DATA)'; test -n "$(zshcompletiondir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(zshcompletiondir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(zshcompletiondir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(zshcompletiondir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(zshcompletiondir)" || exit $$?; \
+	done
+
+uninstall-dist_zshcompletionDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(dist_zshcompletion_DATA)'; test -n "$(zshcompletiondir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(zshcompletiondir)'; $(am__uninstall_files_from_dir)
+install-pkgconfigDATA: $(pkgconfig_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+	done
+
+uninstall-pkgconfigDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+install-rulesDATA: $(rules_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(rules_DATA)'; test -n "$(rulesdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(rulesdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(rulesdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rulesdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(rulesdir)" || exit $$?; \
+	done
+
+uninstall-rulesDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(rules_DATA)'; test -n "$(rulesdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(rulesdir)'; $(am__uninstall_files_from_dir)
+install-stateDATA: $(state_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(state_DATA)'; test -n "$(statedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(statedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(statedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(statedir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(statedir)" || exit $$?; \
+	done
+
+uninstall-stateDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(state_DATA)'; test -n "$(statedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(statedir)'; $(am__uninstall_files_from_dir)
+install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(systemdsystemunitdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(systemdsystemunitdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemdsystemunitdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(systemdsystemunitdir)" || exit $$?; \
+	done
+
+uninstall-systemdsystemunitDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir)
+install-systemduserunitDATA: $(systemduserunit_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(systemduserunit_DATA)'; test -n "$(systemduserunitdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(systemduserunitdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(systemduserunitdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemduserunitdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(systemduserunitdir)" || exit $$?; \
+	done
+
+uninstall-systemduserunitDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(systemduserunit_DATA)'; test -n "$(systemduserunitdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(systemduserunitdir)'; $(am__uninstall_files_from_dir)
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+	done
+
+uninstall-pkgincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+	test ! -s cscope.files \
+	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+	rm -f $< $@
+	$(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+	@:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+	@$(am__set_TESTS_bases); \
+	am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+	redo_bases=`for i in $$bases; do \
+	              am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+	            done`; \
+	if test -n "$$redo_bases"; then \
+	  redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+	  redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+	  if $(am__make_dryrun); then :; else \
+	    rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+	  fi; \
+	fi; \
+	if test -n "$$am__remaking_logs"; then \
+	  echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+	       "recursion detected" >&2; \
+	elif test -n "$$redo_logs"; then \
+	  am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+	fi; \
+	if $(am__make_dryrun); then :; else \
+	  st=0;  \
+	  errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+	  for i in $$redo_bases; do \
+	    test -f $$i.trs && test -r $$i.trs \
+	      || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+	    test -f $$i.log && test -r $$i.log \
+	      || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+	  done; \
+	  test $$st -eq 0 || exit 1; \
+	fi
+	@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+	ws='[ 	]'; \
+	results=`for b in $$bases; do echo $$b.trs; done`; \
+	test -n "$$results" || results=/dev/null; \
+	all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+	pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+	fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+	skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+	xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+	xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+	error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+	if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+	  success=true; \
+	else \
+	  success=false; \
+	fi; \
+	br='==================='; br=$$br$$br$$br$$br; \
+	result_count () \
+	{ \
+	    if test x"$$1" = x"--maybe-color"; then \
+	      maybe_colorize=yes; \
+	    elif test x"$$1" = x"--no-color"; then \
+	      maybe_colorize=no; \
+	    else \
+	      echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+	    fi; \
+	    shift; \
+	    desc=$$1 count=$$2; \
+	    if test $$maybe_colorize = yes && test $$count -gt 0; then \
+	      color_start=$$3 color_end=$$std; \
+	    else \
+	      color_start= color_end=; \
+	    fi; \
+	    echo "$${color_start}# $$desc $$count$${color_end}"; \
+	}; \
+	create_testsuite_report () \
+	{ \
+	  result_count $$1 "TOTAL:" $$all   "$$brg"; \
+	  result_count $$1 "PASS: " $$pass  "$$grn"; \
+	  result_count $$1 "SKIP: " $$skip  "$$blu"; \
+	  result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+	  result_count $$1 "FAIL: " $$fail  "$$red"; \
+	  result_count $$1 "XPASS:" $$xpass "$$red"; \
+	  result_count $$1 "ERROR:" $$error "$$mgn"; \
+	}; \
+	{								\
+	  echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |	\
+	    $(am__rst_title);						\
+	  create_testsuite_report --no-color;				\
+	  echo;								\
+	  echo ".. contents:: :depth: 2";				\
+	  echo;								\
+	  for b in $$bases; do echo $$b; done				\
+	    | $(am__create_global_log);					\
+	} >$(TEST_SUITE_LOG).tmp || exit 1;				\
+	mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);			\
+	if $$success; then						\
+	  col="$$grn";							\
+	 else								\
+	  col="$$red";							\
+	  test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);		\
+	fi;								\
+	echo "$${col}$$br$${std}"; 					\
+	echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}";	\
+	echo "$${col}$$br$${std}"; 					\
+	create_testsuite_report --maybe-color;				\
+	echo "$$col$$br$$std";						\
+	if $$success; then :; else					\
+	  echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";		\
+	  if test -n "$(PACKAGE_BUGREPORT)"; then			\
+	    echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}";	\
+	  fi;								\
+	  echo "$$col$$br$$std";					\
+	fi;								\
+	$$success || exit 1
+
+check-TESTS: 
+	@list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+	@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+	log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+	exit $$?;
+recheck: all 
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	bases=`for i in $$bases; do echo $$i; done \
+	         | $(am__list_recheck_tests)` || exit 1; \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	log_list=`echo $$log_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+	        am__force_recheck=am--force-recheck \
+	        TEST_LOGS="$$log_list"; \
+	exit $$?
+android/test-ipc.log: android/test-ipc$(EXEEXT)
+	@p='android/test-ipc$(EXEEXT)'; \
+	b='android/test-ipc'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-tester.log: unit/test-tester$(EXEEXT)
+	@p='unit/test-tester$(EXEEXT)'; \
+	b='unit/test-tester'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-eir.log: unit/test-eir$(EXEEXT)
+	@p='unit/test-eir$(EXEEXT)'; \
+	b='unit/test-eir'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-uuid.log: unit/test-uuid$(EXEEXT)
+	@p='unit/test-uuid$(EXEEXT)'; \
+	b='unit/test-uuid'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-textfile.log: unit/test-textfile$(EXEEXT)
+	@p='unit/test-textfile$(EXEEXT)'; \
+	b='unit/test-textfile'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-crc.log: unit/test-crc$(EXEEXT)
+	@p='unit/test-crc$(EXEEXT)'; \
+	b='unit/test-crc'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-crypto.log: unit/test-crypto$(EXEEXT)
+	@p='unit/test-crypto$(EXEEXT)'; \
+	b='unit/test-crypto'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-ecc.log: unit/test-ecc$(EXEEXT)
+	@p='unit/test-ecc$(EXEEXT)'; \
+	b='unit/test-ecc'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-ringbuf.log: unit/test-ringbuf$(EXEEXT)
+	@p='unit/test-ringbuf$(EXEEXT)'; \
+	b='unit/test-ringbuf'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-queue.log: unit/test-queue$(EXEEXT)
+	@p='unit/test-queue$(EXEEXT)'; \
+	b='unit/test-queue'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-mgmt.log: unit/test-mgmt$(EXEEXT)
+	@p='unit/test-mgmt$(EXEEXT)'; \
+	b='unit/test-mgmt'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-uhid.log: unit/test-uhid$(EXEEXT)
+	@p='unit/test-uhid$(EXEEXT)'; \
+	b='unit/test-uhid'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-sdp.log: unit/test-sdp$(EXEEXT)
+	@p='unit/test-sdp$(EXEEXT)'; \
+	b='unit/test-sdp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-avdtp.log: unit/test-avdtp$(EXEEXT)
+	@p='unit/test-avdtp$(EXEEXT)'; \
+	b='unit/test-avdtp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-avctp.log: unit/test-avctp$(EXEEXT)
+	@p='unit/test-avctp$(EXEEXT)'; \
+	b='unit/test-avctp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-avrcp.log: unit/test-avrcp$(EXEEXT)
+	@p='unit/test-avrcp$(EXEEXT)'; \
+	b='unit/test-avrcp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-hfp.log: unit/test-hfp$(EXEEXT)
+	@p='unit/test-hfp$(EXEEXT)'; \
+	b='unit/test-hfp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gdbus-client.log: unit/test-gdbus-client$(EXEEXT)
+	@p='unit/test-gdbus-client$(EXEEXT)'; \
+	b='unit/test-gdbus-client'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gobex-header.log: unit/test-gobex-header$(EXEEXT)
+	@p='unit/test-gobex-header$(EXEEXT)'; \
+	b='unit/test-gobex-header'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gobex-packet.log: unit/test-gobex-packet$(EXEEXT)
+	@p='unit/test-gobex-packet$(EXEEXT)'; \
+	b='unit/test-gobex-packet'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gobex.log: unit/test-gobex$(EXEEXT)
+	@p='unit/test-gobex$(EXEEXT)'; \
+	b='unit/test-gobex'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gobex-transfer.log: unit/test-gobex-transfer$(EXEEXT)
+	@p='unit/test-gobex-transfer$(EXEEXT)'; \
+	b='unit/test-gobex-transfer'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gobex-apparam.log: unit/test-gobex-apparam$(EXEEXT)
+	@p='unit/test-gobex-apparam$(EXEEXT)'; \
+	b='unit/test-gobex-apparam'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-lib.log: unit/test-lib$(EXEEXT)
+	@p='unit/test-lib$(EXEEXT)'; \
+	b='unit/test-lib'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gatt.log: unit/test-gatt$(EXEEXT)
+	@p='unit/test-gatt$(EXEEXT)'; \
+	b='unit/test-gatt'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-hog.log: unit/test-hog$(EXEEXT)
+	@p='unit/test-hog$(EXEEXT)'; \
+	b='unit/test-hog'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-gattrib.log: unit/test-gattrib$(EXEEXT)
+	@p='unit/test-gattrib$(EXEEXT)'; \
+	b='unit/test-gattrib'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-bap.log: unit/test-bap$(EXEEXT)
+	@p='unit/test-bap$(EXEEXT)'; \
+	b='unit/test-bap'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-micp.log: unit/test-micp$(EXEEXT)
+	@p='unit/test-micp$(EXEEXT)'; \
+	b='unit/test-micp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-bass.log: unit/test-bass$(EXEEXT)
+	@p='unit/test-bass$(EXEEXT)'; \
+	b='unit/test-bass'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-vcp.log: unit/test-vcp$(EXEEXT)
+	@p='unit/test-vcp$(EXEEXT)'; \
+	b='unit/test-vcp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-midi.log: unit/test-midi$(EXEEXT)
+	@p='unit/test-midi$(EXEEXT)'; \
+	b='unit/test-midi'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+unit/test-mesh-crypto.log: unit/test-mesh-crypto$(EXEEXT)
+	@p='unit/test-mesh-crypto$(EXEEXT)'; \
+	b='unit/test-mesh-crypto'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+	@p='$<'; \
+	$(am__set_b); \
+	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@	@p='$<'; \
+@am__EXEEXT_TRUE@	$(am__set_b); \
+@am__EXEEXT_TRUE@	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@	--log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@	"$$tst" $(AM_TESTS_FD_REDIRECT)
+distdir: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d "$(distdir)" || mkdir "$(distdir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	-test -n "$(am__skip_mode_fix)" \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+	$(am__post_remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+	$(am__post_remove_distdir)
+
+dist-lzip: distdir
+	tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+	$(am__post_remove_distdir)
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+	$(am__post_remove_distdir)
+
+dist-zstd: distdir
+	tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+	$(am__post_remove_distdir)
+
+dist-tarZ: distdir
+	@echo WARNING: "Support for distribution archives compressed with" \
+		       "legacy program 'compress' is deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__post_remove_distdir)
+
+dist-shar: distdir
+	@echo WARNING: "Support for shar distribution archives is" \
+	               "deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
+	$(am__post_remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__post_remove_distdir)
+
+dist dist-all:
+	$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+	$(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lz*) \
+	  lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	*.tar.zst*) \
+	  zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
+	esac
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+	chmod a-w $(distdir)
+	test -d $(distdir)/_build || exit 0; \
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && am__cwd=`pwd` \
+	  && $(am__cd) $(distdir)/_build/sub \
+	  && ../../configure \
+	    $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	    --srcdir=../.. --prefix="$$dc_install_base" \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+	  && cd "$$am__cwd" \
+	  || exit 1
+	$(am__post_remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@test -n '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: trying to run $@ with an empty' \
+	       '$$(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	$(am__cd) '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(LIBRARIES) $(LTLIBRARIES) $(SCRIPTS) \
+		$(MANS) $(DATA) $(HEADERS) config.h
+install-binPROGRAMS: install-libLTLIBRARIES
+
+install-cupsPROGRAMS: install-libLTLIBRARIES
+
+install-pkglibexecPROGRAMS: install-libLTLIBRARIES
+
+install-udevPROGRAMS: install-libLTLIBRARIES
+
+install-pluginLTLIBRARIES: install-libLTLIBRARIES
+
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cupsdir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(udevdir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(testdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(confdir)" "$(DESTDIR)$(dbusdir)" "$(DESTDIR)$(dbussessionbusdir)" "$(DESTDIR)$(dbussystembusdir)" "$(DESTDIR)$(zshcompletiondir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(rulesdir)" "$(DESTDIR)$(statedir)" "$(DESTDIR)$(systemdsystemunitdir)" "$(DESTDIR)$(systemduserunitdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+	-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+	-test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+	-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f android/$(DEPDIR)/$(am__dirstamp)
+	-rm -f android/$(am__dirstamp)
+	-rm -f android/audio_utils/$(DEPDIR)/$(am__dirstamp)
+	-rm -f android/audio_utils/$(am__dirstamp)
+	-rm -f android/client/$(DEPDIR)/$(am__dirstamp)
+	-rm -f android/client/$(am__dirstamp)
+	-rm -f android/hardware/$(DEPDIR)/$(am__dirstamp)
+	-rm -f android/hardware/$(am__dirstamp)
+	-rm -f attrib/$(DEPDIR)/$(am__dirstamp)
+	-rm -f attrib/$(am__dirstamp)
+	-rm -f btio/$(DEPDIR)/$(am__dirstamp)
+	-rm -f btio/$(am__dirstamp)
+	-rm -f client/$(DEPDIR)/$(am__dirstamp)
+	-rm -f client/$(am__dirstamp)
+	-rm -f ell/$(DEPDIR)/$(am__dirstamp)
+	-rm -f ell/$(am__dirstamp)
+	-rm -f emulator/$(DEPDIR)/$(am__dirstamp)
+	-rm -f emulator/$(am__dirstamp)
+	-rm -f gdbus/$(DEPDIR)/$(am__dirstamp)
+	-rm -f gdbus/$(am__dirstamp)
+	-rm -f gobex/$(DEPDIR)/$(am__dirstamp)
+	-rm -f gobex/$(am__dirstamp)
+	-rm -f lib/$(DEPDIR)/$(am__dirstamp)
+	-rm -f lib/$(am__dirstamp)
+	-rm -f mesh/$(DEPDIR)/$(am__dirstamp)
+	-rm -f mesh/$(am__dirstamp)
+	-rm -f monitor/$(DEPDIR)/$(am__dirstamp)
+	-rm -f monitor/$(am__dirstamp)
+	-rm -f obexd/client/$(DEPDIR)/$(am__dirstamp)
+	-rm -f obexd/client/$(am__dirstamp)
+	-rm -f obexd/plugins/$(DEPDIR)/$(am__dirstamp)
+	-rm -f obexd/plugins/$(am__dirstamp)
+	-rm -f obexd/src/$(DEPDIR)/$(am__dirstamp)
+	-rm -f obexd/src/$(am__dirstamp)
+	-rm -f peripheral/$(DEPDIR)/$(am__dirstamp)
+	-rm -f peripheral/$(am__dirstamp)
+	-rm -f plugins/$(DEPDIR)/$(am__dirstamp)
+	-rm -f plugins/$(am__dirstamp)
+	-rm -f profiles/audio/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/audio/$(am__dirstamp)
+	-rm -f profiles/battery/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/battery/$(am__dirstamp)
+	-rm -f profiles/cups/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/cups/$(am__dirstamp)
+	-rm -f profiles/deviceinfo/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/deviceinfo/$(am__dirstamp)
+	-rm -f profiles/gap/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/gap/$(am__dirstamp)
+	-rm -f profiles/health/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/health/$(am__dirstamp)
+	-rm -f profiles/iap/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/iap/$(am__dirstamp)
+	-rm -f profiles/input/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/input/$(am__dirstamp)
+	-rm -f profiles/midi/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/midi/$(am__dirstamp)
+	-rm -f profiles/network/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/network/$(am__dirstamp)
+	-rm -f profiles/sap/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/sap/$(am__dirstamp)
+	-rm -f profiles/scanparam/$(DEPDIR)/$(am__dirstamp)
+	-rm -f profiles/scanparam/$(am__dirstamp)
+	-rm -f src/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/$(am__dirstamp)
+	-rm -f src/shared/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/shared/$(am__dirstamp)
+	-rm -f tools/$(DEPDIR)/$(am__dirstamp)
+	-rm -f tools/$(am__dirstamp)
+	-rm -f tools/mesh-gatt/$(DEPDIR)/$(am__dirstamp)
+	-rm -f tools/mesh-gatt/$(am__dirstamp)
+	-rm -f tools/mesh/$(DEPDIR)/$(am__dirstamp)
+	-rm -f tools/mesh/$(am__dirstamp)
+	-rm -f tools/parser/$(DEPDIR)/$(am__dirstamp)
+	-rm -f tools/parser/$(am__dirstamp)
+	-rm -f unit/$(DEPDIR)/$(am__dirstamp)
+	-rm -f unit/$(am__dirstamp)
+	-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-cupsPROGRAMS clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-local \
+	clean-noinstLIBRARIES clean-noinstLTLIBRARIES \
+	clean-noinstPROGRAMS clean-pkglibexecPROGRAMS \
+	clean-pluginLTLIBRARIES clean-udevPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+		-rm -f android/$(DEPDIR)/a2dp-sink.Po
+	-rm -f android/$(DEPDIR)/a2dp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-a2dp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-avrcp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-bluetooth.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-gatt.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-hdp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-hidhost.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-main.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-map-client.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-pan.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-socket.Po
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Plo
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Plo
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Plo
+	-rm -f android/$(DEPDIR)/audio_sco_default_la-hal-sco.Plo
+	-rm -f android/$(DEPDIR)/avctp.Po
+	-rm -f android/$(DEPDIR)/avdtp.Po
+	-rm -f android/$(DEPDIR)/avdtptest-avdtp.Po
+	-rm -f android/$(DEPDIR)/avdtptest-avdtptest.Po
+	-rm -f android/$(DEPDIR)/avrcp-lib.Po
+	-rm -f android/$(DEPDIR)/avrcp.Po
+	-rm -f android/$(DEPDIR)/bluetooth.Po
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-health.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-pan.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-socket.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-utils.Plo
+	-rm -f android/$(DEPDIR)/bluetoothd-snoop.Po
+	-rm -f android/$(DEPDIR)/gatt.Po
+	-rm -f android/$(DEPDIR)/haltest-hal-utils.Po
+	-rm -f android/$(DEPDIR)/handsfree-client.Po
+	-rm -f android/$(DEPDIR)/handsfree.Po
+	-rm -f android/$(DEPDIR)/health.Po
+	-rm -f android/$(DEPDIR)/hidhost.Po
+	-rm -f android/$(DEPDIR)/ipc.Po
+	-rm -f android/$(DEPDIR)/ipc_tester-hal-utils.Po
+	-rm -f android/$(DEPDIR)/ipc_tester-ipc-tester.Po
+	-rm -f android/$(DEPDIR)/main.Po
+	-rm -f android/$(DEPDIR)/map-client.Po
+	-rm -f android/$(DEPDIR)/pan.Po
+	-rm -f android/$(DEPDIR)/sco.Po
+	-rm -f android/$(DEPDIR)/socket.Po
+	-rm -f android/$(DEPDIR)/system-emulator.Po
+	-rm -f android/$(DEPDIR)/test-ipc.Po
+	-rm -f android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Plo
+	-rm -f android/client/$(DEPDIR)/haltest-haltest.Po
+	-rm -f android/client/$(DEPDIR)/haltest-history.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-audio.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-av-sink.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-av.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-bt.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-gatt.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hf-client.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hf.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hh.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hl.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-mce.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-pan.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-rc.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-sco.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-sock.Po
+	-rm -f android/client/$(DEPDIR)/haltest-pollhandler.Po
+	-rm -f android/client/$(DEPDIR)/haltest-tabcompletion.Po
+	-rm -f android/client/$(DEPDIR)/haltest-terminal.Po
+	-rm -f android/hardware/$(DEPDIR)/android_tester-hardware.Po
+	-rm -f android/hardware/$(DEPDIR)/haltest-hardware.Po
+	-rm -f attrib/$(DEPDIR)/att.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-att.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-gatt.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-gattrib.Po
+	-rm -f attrib/$(DEPDIR)/gatt.Po
+	-rm -f attrib/$(DEPDIR)/gattrib.Po
+	-rm -f attrib/$(DEPDIR)/gatttool.Po
+	-rm -f attrib/$(DEPDIR)/interactive.Po
+	-rm -f attrib/$(DEPDIR)/utils.Po
+	-rm -f btio/$(DEPDIR)/android_avdtptest-btio.Po
+	-rm -f btio/$(DEPDIR)/bluetoothd-btio.Po
+	-rm -f btio/$(DEPDIR)/btio.Po
+	-rm -f btio/$(DEPDIR)/obexd-btio.Po
+	-rm -f client/$(DEPDIR)/admin.Po
+	-rm -f client/$(DEPDIR)/adv_monitor.Po
+	-rm -f client/$(DEPDIR)/advertising.Po
+	-rm -f client/$(DEPDIR)/agent.Po
+	-rm -f client/$(DEPDIR)/assistant.Po
+	-rm -f client/$(DEPDIR)/display.Po
+	-rm -f client/$(DEPDIR)/gatt.Po
+	-rm -f client/$(DEPDIR)/main.Po
+	-rm -f client/$(DEPDIR)/mgmt.Po
+	-rm -f client/$(DEPDIR)/player.Po
+	-rm -f client/$(DEPDIR)/print.Po
+	-rm -f ell/$(DEPDIR)/base64.Plo
+	-rm -f ell/$(DEPDIR)/cert-crypto.Plo
+	-rm -f ell/$(DEPDIR)/cert.Plo
+	-rm -f ell/$(DEPDIR)/checksum.Plo
+	-rm -f ell/$(DEPDIR)/cipher.Plo
+	-rm -f ell/$(DEPDIR)/dbus-client.Plo
+	-rm -f ell/$(DEPDIR)/dbus-filter.Plo
+	-rm -f ell/$(DEPDIR)/dbus-message.Plo
+	-rm -f ell/$(DEPDIR)/dbus-name-cache.Plo
+	-rm -f ell/$(DEPDIR)/dbus-service.Plo
+	-rm -f ell/$(DEPDIR)/dbus-util.Plo
+	-rm -f ell/$(DEPDIR)/dbus.Plo
+	-rm -f ell/$(DEPDIR)/ecc-external.Plo
+	-rm -f ell/$(DEPDIR)/ecc.Plo
+	-rm -f ell/$(DEPDIR)/ecdh.Plo
+	-rm -f ell/$(DEPDIR)/gvariant-util.Plo
+	-rm -f ell/$(DEPDIR)/hashmap.Plo
+	-rm -f ell/$(DEPDIR)/idle.Plo
+	-rm -f ell/$(DEPDIR)/io.Plo
+	-rm -f ell/$(DEPDIR)/key.Plo
+	-rm -f ell/$(DEPDIR)/log.Plo
+	-rm -f ell/$(DEPDIR)/main.Plo
+	-rm -f ell/$(DEPDIR)/pem.Plo
+	-rm -f ell/$(DEPDIR)/queue.Plo
+	-rm -f ell/$(DEPDIR)/random.Plo
+	-rm -f ell/$(DEPDIR)/settings.Plo
+	-rm -f ell/$(DEPDIR)/signal.Plo
+	-rm -f ell/$(DEPDIR)/siphash.Plo
+	-rm -f ell/$(DEPDIR)/string.Plo
+	-rm -f ell/$(DEPDIR)/strv.Plo
+	-rm -f ell/$(DEPDIR)/tester.Plo
+	-rm -f ell/$(DEPDIR)/time.Plo
+	-rm -f ell/$(DEPDIR)/timeout.Plo
+	-rm -f ell/$(DEPDIR)/tls-extensions.Plo
+	-rm -f ell/$(DEPDIR)/tls-record.Plo
+	-rm -f ell/$(DEPDIR)/tls-suites.Plo
+	-rm -f ell/$(DEPDIR)/tls.Plo
+	-rm -f ell/$(DEPDIR)/utf8.Plo
+	-rm -f ell/$(DEPDIR)/util.Plo
+	-rm -f ell/$(DEPDIR)/uuid.Plo
+	-rm -f emulator/$(DEPDIR)/amp.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-btdev.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-bthost.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-hciemu.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-smp.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-vhci.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-btdev.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-bthost.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-smp.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-vhci.Po
+	-rm -f emulator/$(DEPDIR)/b1ee.Po
+	-rm -f emulator/$(DEPDIR)/btdev.Po
+	-rm -f emulator/$(DEPDIR)/bthost.Po
+	-rm -f emulator/$(DEPDIR)/hciemu.Po
+	-rm -f emulator/$(DEPDIR)/hfp.Po
+	-rm -f emulator/$(DEPDIR)/le.Po
+	-rm -f emulator/$(DEPDIR)/main.Po
+	-rm -f emulator/$(DEPDIR)/phy.Po
+	-rm -f emulator/$(DEPDIR)/serial.Po
+	-rm -f emulator/$(DEPDIR)/server.Po
+	-rm -f emulator/$(DEPDIR)/smp.Po
+	-rm -f emulator/$(DEPDIR)/vhci.Po
+	-rm -f gdbus/$(DEPDIR)/client.Plo
+	-rm -f gdbus/$(DEPDIR)/mainloop.Plo
+	-rm -f gdbus/$(DEPDIR)/object.Plo
+	-rm -f gdbus/$(DEPDIR)/polkit.Plo
+	-rm -f gdbus/$(DEPDIR)/watch.Plo
+	-rm -f gobex/$(DEPDIR)/gobex-apparam.Po
+	-rm -f gobex/$(DEPDIR)/gobex-defs.Po
+	-rm -f gobex/$(DEPDIR)/gobex-header.Po
+	-rm -f gobex/$(DEPDIR)/gobex-packet.Po
+	-rm -f gobex/$(DEPDIR)/gobex-transfer.Po
+	-rm -f gobex/$(DEPDIR)/gobex.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-apparam.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-defs.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-header.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-packet.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-transfer.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex.Po
+	-rm -f lib/$(DEPDIR)/bluetooth.Plo
+	-rm -f lib/$(DEPDIR)/hci.Plo
+	-rm -f lib/$(DEPDIR)/sdp.Plo
+	-rm -f lib/$(DEPDIR)/uuid.Plo
+	-rm -f mesh/$(DEPDIR)/agent.Po
+	-rm -f mesh/$(DEPDIR)/appkey.Po
+	-rm -f mesh/$(DEPDIR)/cfgmod-server.Po
+	-rm -f mesh/$(DEPDIR)/crypto.Po
+	-rm -f mesh/$(DEPDIR)/dbus.Po
+	-rm -f mesh/$(DEPDIR)/friend.Po
+	-rm -f mesh/$(DEPDIR)/keyring.Po
+	-rm -f mesh/$(DEPDIR)/main.Po
+	-rm -f mesh/$(DEPDIR)/manager.Po
+	-rm -f mesh/$(DEPDIR)/mesh-config-json.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-generic.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-mgmt.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-unit.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io.Po
+	-rm -f mesh/$(DEPDIR)/mesh-mgmt.Po
+	-rm -f mesh/$(DEPDIR)/mesh.Po
+	-rm -f mesh/$(DEPDIR)/model.Po
+	-rm -f mesh/$(DEPDIR)/net-keys.Po
+	-rm -f mesh/$(DEPDIR)/net.Po
+	-rm -f mesh/$(DEPDIR)/node.Po
+	-rm -f mesh/$(DEPDIR)/pb-adv.Po
+	-rm -f mesh/$(DEPDIR)/prov-acceptor.Po
+	-rm -f mesh/$(DEPDIR)/prov-initiator.Po
+	-rm -f mesh/$(DEPDIR)/prvbeac-server.Po
+	-rm -f mesh/$(DEPDIR)/remprv-server.Po
+	-rm -f mesh/$(DEPDIR)/rpl.Po
+	-rm -f mesh/$(DEPDIR)/util.Po
+	-rm -f monitor/$(DEPDIR)/a2dp.Po
+	-rm -f monitor/$(DEPDIR)/analyze.Po
+	-rm -f monitor/$(DEPDIR)/att.Po
+	-rm -f monitor/$(DEPDIR)/avctp.Po
+	-rm -f monitor/$(DEPDIR)/avdtp.Po
+	-rm -f monitor/$(DEPDIR)/bnep.Po
+	-rm -f monitor/$(DEPDIR)/broadcom.Po
+	-rm -f monitor/$(DEPDIR)/control.Po
+	-rm -f monitor/$(DEPDIR)/crc.Po
+	-rm -f monitor/$(DEPDIR)/display.Po
+	-rm -f monitor/$(DEPDIR)/ellisys.Po
+	-rm -f monitor/$(DEPDIR)/hcidump.Po
+	-rm -f monitor/$(DEPDIR)/hwdb.Po
+	-rm -f monitor/$(DEPDIR)/intel.Po
+	-rm -f monitor/$(DEPDIR)/jlink.Po
+	-rm -f monitor/$(DEPDIR)/keys.Po
+	-rm -f monitor/$(DEPDIR)/l2cap.Po
+	-rm -f monitor/$(DEPDIR)/ll.Po
+	-rm -f monitor/$(DEPDIR)/lmp.Po
+	-rm -f monitor/$(DEPDIR)/main.Po
+	-rm -f monitor/$(DEPDIR)/msft.Po
+	-rm -f monitor/$(DEPDIR)/packet.Po
+	-rm -f monitor/$(DEPDIR)/rfcomm.Po
+	-rm -f monitor/$(DEPDIR)/sdp.Po
+	-rm -f monitor/$(DEPDIR)/vendor.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bip-common.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bip.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bluetooth.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-driver.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-ftp.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-manager.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-map-event.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-map.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-mns.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-opp.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-pbap.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-session.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-sync.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-transfer.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-transport.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-filesystem.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-ftp.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-irmc.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-mas.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-opp.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-pbap.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-vcard.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-log.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-main.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-manager.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-mimetype.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-obex.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-plugin.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-server.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-service.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-transport.Po
+	-rm -f peripheral/$(DEPDIR)/attach.Po
+	-rm -f peripheral/$(DEPDIR)/efivars.Po
+	-rm -f peripheral/$(DEPDIR)/gap.Po
+	-rm -f peripheral/$(DEPDIR)/gatt.Po
+	-rm -f peripheral/$(DEPDIR)/log.Po
+	-rm -f peripheral/$(DEPDIR)/main.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-admin.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-autopair.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-hostname.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-neard.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-policy.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-sixaxis.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-wiimote.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-asha.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-bap.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-bass.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-control.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-csip.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-media.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-micp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-player.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-sink.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-source.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-transport.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po
+	-rm -f profiles/battery/$(DEPDIR)/bas.Po
+	-rm -f profiles/battery/$(DEPDIR)/bluetoothd-bas.Po
+	-rm -f profiles/battery/$(DEPDIR)/bluetoothd-battery.Po
+	-rm -f profiles/cups/$(DEPDIR)/hcrp.Po
+	-rm -f profiles/cups/$(DEPDIR)/main.Po
+	-rm -f profiles/cups/$(DEPDIR)/sdp.Po
+	-rm -f profiles/cups/$(DEPDIR)/spp.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/dis.Po
+	-rm -f profiles/gap/$(DEPDIR)/bluetoothd-gas.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-mcap.Po
+	-rm -f profiles/health/$(DEPDIR)/mcap.Po
+	-rm -f profiles/iap/$(DEPDIR)/main.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-device.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-hog.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po
+	-rm -f profiles/input/$(DEPDIR)/hog-lib.Po
+	-rm -f profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po
+	-rm -f profiles/midi/$(DEPDIR)/bluetoothd-midi.Po
+	-rm -f profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-bnep.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-connection.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/network/$(DEPDIR)/bnep.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-main.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/scpp.Po
+	-rm -f src/$(DEPDIR)/android_avdtptest-log.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-adapter.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-adv_monitor.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-advertising.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-agent.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-backtrace.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-battery.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-dbus-common.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-device.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-eir.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-error.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-gatt-client.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-gatt-database.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-log.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-main.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-plugin.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-profile.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-rfkill.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdp-client.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdp-xml.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-database.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-request.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-server.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-service.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-service.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-set.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-settings.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-storage.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-textfile.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-uuid-helper.Po
+	-rm -f src/$(DEPDIR)/eir.Po
+	-rm -f src/$(DEPDIR)/log.Po
+	-rm -f src/$(DEPDIR)/oui.Po
+	-rm -f src/$(DEPDIR)/sdp-client.Po
+	-rm -f src/$(DEPDIR)/sdp-xml.Po
+	-rm -f src/$(DEPDIR)/sdpd-database.Po
+	-rm -f src/$(DEPDIR)/sdpd-request.Po
+	-rm -f src/$(DEPDIR)/sdpd-server.Po
+	-rm -f src/$(DEPDIR)/sdpd-service.Po
+	-rm -f src/$(DEPDIR)/settings.Po
+	-rm -f src/$(DEPDIR)/textfile.Po
+	-rm -f src/$(DEPDIR)/uuid-helper.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-log.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-queue.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-util.Po
+	-rm -f src/shared/$(DEPDIR)/btp.Po
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-vcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-tester.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-vcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Plo
+	-rm -f tools/$(DEPDIR)/3dsp.Po
+	-rm -f tools/$(DEPDIR)/advtest.Po
+	-rm -f tools/$(DEPDIR)/amptest.Po
+	-rm -f tools/$(DEPDIR)/avinfo.Po
+	-rm -f tools/$(DEPDIR)/avtest.Po
+	-rm -f tools/$(DEPDIR)/bcmfw.Po
+	-rm -f tools/$(DEPDIR)/bdaddr.Po
+	-rm -f tools/$(DEPDIR)/bluemoon.Po
+	-rm -f tools/$(DEPDIR)/bluetooth-player.Po
+	-rm -f tools/$(DEPDIR)/bnep-tester.Po
+	-rm -f tools/$(DEPDIR)/bneptest.Po
+	-rm -f tools/$(DEPDIR)/btattach.Po
+	-rm -f tools/$(DEPDIR)/btconfig.Po
+	-rm -f tools/$(DEPDIR)/btgatt-client.Po
+	-rm -f tools/$(DEPDIR)/btgatt-server.Po
+	-rm -f tools/$(DEPDIR)/btinfo.Po
+	-rm -f tools/$(DEPDIR)/btiotest.Po
+	-rm -f tools/$(DEPDIR)/btmgmt.Po
+	-rm -f tools/$(DEPDIR)/btmon-logger.Po
+	-rm -f tools/$(DEPDIR)/btpclient.Po
+	-rm -f tools/$(DEPDIR)/btpclientctl.Po
+	-rm -f tools/$(DEPDIR)/btproxy.Po
+	-rm -f tools/$(DEPDIR)/btsnoop.Po
+	-rm -f tools/$(DEPDIR)/check-selftest.Po
+	-rm -f tools/$(DEPDIR)/ciptool.Po
+	-rm -f tools/$(DEPDIR)/cltest.Po
+	-rm -f tools/$(DEPDIR)/create-image.Po
+	-rm -f tools/$(DEPDIR)/eddystone.Po
+	-rm -f tools/$(DEPDIR)/gap-tester.Po
+	-rm -f tools/$(DEPDIR)/gatt-service.Po
+	-rm -f tools/$(DEPDIR)/hci-tester.Po
+	-rm -f tools/$(DEPDIR)/hciattach.Po
+	-rm -f tools/$(DEPDIR)/hciattach_ath3k.Po
+	-rm -f tools/$(DEPDIR)/hciattach_bcm43xx.Po
+	-rm -f tools/$(DEPDIR)/hciattach_intel.Po
+	-rm -f tools/$(DEPDIR)/hciattach_qualcomm.Po
+	-rm -f tools/$(DEPDIR)/hciattach_st.Po
+	-rm -f tools/$(DEPDIR)/hciattach_ti.Po
+	-rm -f tools/$(DEPDIR)/hciattach_tialt.Po
+	-rm -f tools/$(DEPDIR)/hciconfig.Po
+	-rm -f tools/$(DEPDIR)/hcidump.Po
+	-rm -f tools/$(DEPDIR)/hcieventmask.Po
+	-rm -f tools/$(DEPDIR)/hcisecfilter.Po
+	-rm -f tools/$(DEPDIR)/hcitool.Po
+	-rm -f tools/$(DEPDIR)/hex2hcd.Po
+	-rm -f tools/$(DEPDIR)/hid2hci.Po
+	-rm -f tools/$(DEPDIR)/hwdb.Po
+	-rm -f tools/$(DEPDIR)/ibeacon.Po
+	-rm -f tools/$(DEPDIR)/ioctl-tester.Po
+	-rm -f tools/$(DEPDIR)/iso-tester.Po
+	-rm -f tools/$(DEPDIR)/isotest.Po
+	-rm -f tools/$(DEPDIR)/l2cap-tester.Po
+	-rm -f tools/$(DEPDIR)/l2ping.Po
+	-rm -f tools/$(DEPDIR)/l2test.Po
+	-rm -f tools/$(DEPDIR)/mcaptest.Po
+	-rm -f tools/$(DEPDIR)/mesh-cfgclient.Po
+	-rm -f tools/$(DEPDIR)/mesh-cfgtest.Po
+	-rm -f tools/$(DEPDIR)/mesh-tester.Po
+	-rm -f tools/$(DEPDIR)/meshctl.Po
+	-rm -f tools/$(DEPDIR)/mgmt-tester.Po
+	-rm -f tools/$(DEPDIR)/mpris-proxy.Po
+	-rm -f tools/$(DEPDIR)/nokfw.Po
+	-rm -f tools/$(DEPDIR)/obex-client-tool.Po
+	-rm -f tools/$(DEPDIR)/obex-server-tool.Po
+	-rm -f tools/$(DEPDIR)/obexctl.Po
+	-rm -f tools/$(DEPDIR)/oobtest.Po
+	-rm -f tools/$(DEPDIR)/rctest.Po
+	-rm -f tools/$(DEPDIR)/rfcomm-tester.Po
+	-rm -f tools/$(DEPDIR)/rfcomm.Po
+	-rm -f tools/$(DEPDIR)/rtlfw.Po
+	-rm -f tools/$(DEPDIR)/sco-tester.Po
+	-rm -f tools/$(DEPDIR)/scotest.Po
+	-rm -f tools/$(DEPDIR)/sdptool.Po
+	-rm -f tools/$(DEPDIR)/seq2bseq.Po
+	-rm -f tools/$(DEPDIR)/smp-tester.Po
+	-rm -f tools/$(DEPDIR)/test-runner.Po
+	-rm -f tools/$(DEPDIR)/userchan-tester.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/config-client.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/config-server.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/crypto.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/gatt.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/net.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/node.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/onoff-model.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/prov-db.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/prov.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/util.Po
+	-rm -f tools/mesh/$(DEPDIR)/agent.Po
+	-rm -f tools/mesh/$(DEPDIR)/cfgcli.Po
+	-rm -f tools/mesh/$(DEPDIR)/keys.Po
+	-rm -f tools/mesh/$(DEPDIR)/mesh-db.Po
+	-rm -f tools/mesh/$(DEPDIR)/remote.Po
+	-rm -f tools/mesh/$(DEPDIR)/util.Po
+	-rm -f tools/parser/$(DEPDIR)/amp.Po
+	-rm -f tools/parser/$(DEPDIR)/att.Po
+	-rm -f tools/parser/$(DEPDIR)/avctp.Po
+	-rm -f tools/parser/$(DEPDIR)/avdtp.Po
+	-rm -f tools/parser/$(DEPDIR)/avrcp.Po
+	-rm -f tools/parser/$(DEPDIR)/bnep.Po
+	-rm -f tools/parser/$(DEPDIR)/bpa.Po
+	-rm -f tools/parser/$(DEPDIR)/capi.Po
+	-rm -f tools/parser/$(DEPDIR)/cmtp.Po
+	-rm -f tools/parser/$(DEPDIR)/csr.Po
+	-rm -f tools/parser/$(DEPDIR)/ericsson.Po
+	-rm -f tools/parser/$(DEPDIR)/hci.Po
+	-rm -f tools/parser/$(DEPDIR)/hcrp.Po
+	-rm -f tools/parser/$(DEPDIR)/hidp.Po
+	-rm -f tools/parser/$(DEPDIR)/l2cap.Po
+	-rm -f tools/parser/$(DEPDIR)/lmp.Po
+	-rm -f tools/parser/$(DEPDIR)/obex.Po
+	-rm -f tools/parser/$(DEPDIR)/parser.Po
+	-rm -f tools/parser/$(DEPDIR)/ppp.Po
+	-rm -f tools/parser/$(DEPDIR)/rfcomm.Po
+	-rm -f tools/parser/$(DEPDIR)/sap.Po
+	-rm -f tools/parser/$(DEPDIR)/sdp.Po
+	-rm -f tools/parser/$(DEPDIR)/smp.Po
+	-rm -f tools/parser/$(DEPDIR)/tcpip.Po
+	-rm -f unit/$(DEPDIR)/test-avctp.Po
+	-rm -f unit/$(DEPDIR)/test-avdtp.Po
+	-rm -f unit/$(DEPDIR)/test-avrcp.Po
+	-rm -f unit/$(DEPDIR)/test-bap.Po
+	-rm -f unit/$(DEPDIR)/test-bass.Po
+	-rm -f unit/$(DEPDIR)/test-crc.Po
+	-rm -f unit/$(DEPDIR)/test-crypto.Po
+	-rm -f unit/$(DEPDIR)/test-ecc.Po
+	-rm -f unit/$(DEPDIR)/test-eir.Po
+	-rm -f unit/$(DEPDIR)/test-gatt.Po
+	-rm -f unit/$(DEPDIR)/test-gattrib.Po
+	-rm -f unit/$(DEPDIR)/test-gdbus-client.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-apparam.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-header.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-packet.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-transfer.Po
+	-rm -f unit/$(DEPDIR)/test-gobex.Po
+	-rm -f unit/$(DEPDIR)/test-hfp.Po
+	-rm -f unit/$(DEPDIR)/test-hog.Po
+	-rm -f unit/$(DEPDIR)/test-lib.Po
+	-rm -f unit/$(DEPDIR)/test-mgmt.Po
+	-rm -f unit/$(DEPDIR)/test-micp.Po
+	-rm -f unit/$(DEPDIR)/test-queue.Po
+	-rm -f unit/$(DEPDIR)/test-ringbuf.Po
+	-rm -f unit/$(DEPDIR)/test-sdp.Po
+	-rm -f unit/$(DEPDIR)/test-tester.Po
+	-rm -f unit/$(DEPDIR)/test-textfile.Po
+	-rm -f unit/$(DEPDIR)/test-uhid.Po
+	-rm -f unit/$(DEPDIR)/test-uuid.Po
+	-rm -f unit/$(DEPDIR)/test-vcp.Po
+	-rm -f unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po
+	-rm -f unit/$(DEPDIR)/test_midi-test-midi.Po
+	-rm -f unit/$(DEPDIR)/util.Po
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-confDATA install-cupsPROGRAMS \
+	install-dbusDATA install-dbussessionbusDATA \
+	install-dbussystembusDATA install-dist_zshcompletionDATA \
+	install-man install-pkgconfigDATA install-pkgincludeHEADERS \
+	install-pluginLTLIBRARIES install-rulesDATA install-stateDATA \
+	install-systemdsystemunitDATA install-systemduserunitDATA \
+	install-testSCRIPTS install-udevPROGRAMS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \
+	install-pkglibexecPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1 install-man5 install-man7 install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+		-rm -f android/$(DEPDIR)/a2dp-sink.Po
+	-rm -f android/$(DEPDIR)/a2dp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-a2dp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-avrcp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-bluetooth.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-gatt.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-hdp.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-hidhost.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-main.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-map-client.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-pan.Po
+	-rm -f android/$(DEPDIR)/android_tester-tester-socket.Po
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-aptx.Plo
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio-sbc.Plo
+	-rm -f android/$(DEPDIR)/audio_a2dp_default_la-hal-audio.Plo
+	-rm -f android/$(DEPDIR)/audio_sco_default_la-hal-sco.Plo
+	-rm -f android/$(DEPDIR)/avctp.Po
+	-rm -f android/$(DEPDIR)/avdtp.Po
+	-rm -f android/$(DEPDIR)/avdtptest-avdtp.Po
+	-rm -f android/$(DEPDIR)/avdtptest-avdtptest.Po
+	-rm -f android/$(DEPDIR)/avrcp-lib.Po
+	-rm -f android/$(DEPDIR)/avrcp.Po
+	-rm -f android/$(DEPDIR)/bluetooth.Po
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-a2dp-sink.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-a2dp.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-avrcp-ctrl.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-avrcp.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-bluetooth.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-gatt.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-handsfree-client.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-handsfree.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-health.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-hidhost.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-ipc.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-map-client.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-pan.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-socket.Plo
+	-rm -f android/$(DEPDIR)/bluetooth_default_la-hal-utils.Plo
+	-rm -f android/$(DEPDIR)/bluetoothd-snoop.Po
+	-rm -f android/$(DEPDIR)/gatt.Po
+	-rm -f android/$(DEPDIR)/haltest-hal-utils.Po
+	-rm -f android/$(DEPDIR)/handsfree-client.Po
+	-rm -f android/$(DEPDIR)/handsfree.Po
+	-rm -f android/$(DEPDIR)/health.Po
+	-rm -f android/$(DEPDIR)/hidhost.Po
+	-rm -f android/$(DEPDIR)/ipc.Po
+	-rm -f android/$(DEPDIR)/ipc_tester-hal-utils.Po
+	-rm -f android/$(DEPDIR)/ipc_tester-ipc-tester.Po
+	-rm -f android/$(DEPDIR)/main.Po
+	-rm -f android/$(DEPDIR)/map-client.Po
+	-rm -f android/$(DEPDIR)/pan.Po
+	-rm -f android/$(DEPDIR)/sco.Po
+	-rm -f android/$(DEPDIR)/socket.Po
+	-rm -f android/$(DEPDIR)/system-emulator.Po
+	-rm -f android/$(DEPDIR)/test-ipc.Po
+	-rm -f android/audio_utils/$(DEPDIR)/audio_sco_default_la-resampler.Plo
+	-rm -f android/client/$(DEPDIR)/haltest-haltest.Po
+	-rm -f android/client/$(DEPDIR)/haltest-history.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-audio.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-av-sink.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-av.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-bt.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-gatt.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hf-client.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hf.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hh.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-hl.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-mce.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-pan.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-rc-ctrl.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-rc.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-sco.Po
+	-rm -f android/client/$(DEPDIR)/haltest-if-sock.Po
+	-rm -f android/client/$(DEPDIR)/haltest-pollhandler.Po
+	-rm -f android/client/$(DEPDIR)/haltest-tabcompletion.Po
+	-rm -f android/client/$(DEPDIR)/haltest-terminal.Po
+	-rm -f android/hardware/$(DEPDIR)/android_tester-hardware.Po
+	-rm -f android/hardware/$(DEPDIR)/haltest-hardware.Po
+	-rm -f attrib/$(DEPDIR)/att.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-att.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-gatt.Po
+	-rm -f attrib/$(DEPDIR)/bluetoothd-gattrib.Po
+	-rm -f attrib/$(DEPDIR)/gatt.Po
+	-rm -f attrib/$(DEPDIR)/gattrib.Po
+	-rm -f attrib/$(DEPDIR)/gatttool.Po
+	-rm -f attrib/$(DEPDIR)/interactive.Po
+	-rm -f attrib/$(DEPDIR)/utils.Po
+	-rm -f btio/$(DEPDIR)/android_avdtptest-btio.Po
+	-rm -f btio/$(DEPDIR)/bluetoothd-btio.Po
+	-rm -f btio/$(DEPDIR)/btio.Po
+	-rm -f btio/$(DEPDIR)/obexd-btio.Po
+	-rm -f client/$(DEPDIR)/admin.Po
+	-rm -f client/$(DEPDIR)/adv_monitor.Po
+	-rm -f client/$(DEPDIR)/advertising.Po
+	-rm -f client/$(DEPDIR)/agent.Po
+	-rm -f client/$(DEPDIR)/assistant.Po
+	-rm -f client/$(DEPDIR)/display.Po
+	-rm -f client/$(DEPDIR)/gatt.Po
+	-rm -f client/$(DEPDIR)/main.Po
+	-rm -f client/$(DEPDIR)/mgmt.Po
+	-rm -f client/$(DEPDIR)/player.Po
+	-rm -f client/$(DEPDIR)/print.Po
+	-rm -f ell/$(DEPDIR)/base64.Plo
+	-rm -f ell/$(DEPDIR)/cert-crypto.Plo
+	-rm -f ell/$(DEPDIR)/cert.Plo
+	-rm -f ell/$(DEPDIR)/checksum.Plo
+	-rm -f ell/$(DEPDIR)/cipher.Plo
+	-rm -f ell/$(DEPDIR)/dbus-client.Plo
+	-rm -f ell/$(DEPDIR)/dbus-filter.Plo
+	-rm -f ell/$(DEPDIR)/dbus-message.Plo
+	-rm -f ell/$(DEPDIR)/dbus-name-cache.Plo
+	-rm -f ell/$(DEPDIR)/dbus-service.Plo
+	-rm -f ell/$(DEPDIR)/dbus-util.Plo
+	-rm -f ell/$(DEPDIR)/dbus.Plo
+	-rm -f ell/$(DEPDIR)/ecc-external.Plo
+	-rm -f ell/$(DEPDIR)/ecc.Plo
+	-rm -f ell/$(DEPDIR)/ecdh.Plo
+	-rm -f ell/$(DEPDIR)/gvariant-util.Plo
+	-rm -f ell/$(DEPDIR)/hashmap.Plo
+	-rm -f ell/$(DEPDIR)/idle.Plo
+	-rm -f ell/$(DEPDIR)/io.Plo
+	-rm -f ell/$(DEPDIR)/key.Plo
+	-rm -f ell/$(DEPDIR)/log.Plo
+	-rm -f ell/$(DEPDIR)/main.Plo
+	-rm -f ell/$(DEPDIR)/pem.Plo
+	-rm -f ell/$(DEPDIR)/queue.Plo
+	-rm -f ell/$(DEPDIR)/random.Plo
+	-rm -f ell/$(DEPDIR)/settings.Plo
+	-rm -f ell/$(DEPDIR)/signal.Plo
+	-rm -f ell/$(DEPDIR)/siphash.Plo
+	-rm -f ell/$(DEPDIR)/string.Plo
+	-rm -f ell/$(DEPDIR)/strv.Plo
+	-rm -f ell/$(DEPDIR)/tester.Plo
+	-rm -f ell/$(DEPDIR)/time.Plo
+	-rm -f ell/$(DEPDIR)/timeout.Plo
+	-rm -f ell/$(DEPDIR)/tls-extensions.Plo
+	-rm -f ell/$(DEPDIR)/tls-record.Plo
+	-rm -f ell/$(DEPDIR)/tls-suites.Plo
+	-rm -f ell/$(DEPDIR)/tls.Plo
+	-rm -f ell/$(DEPDIR)/utf8.Plo
+	-rm -f ell/$(DEPDIR)/util.Plo
+	-rm -f ell/$(DEPDIR)/uuid.Plo
+	-rm -f emulator/$(DEPDIR)/amp.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-btdev.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-bthost.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-hciemu.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-smp.Po
+	-rm -f emulator/$(DEPDIR)/android_android_tester-vhci.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-btdev.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-bthost.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-hciemu.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-smp.Po
+	-rm -f emulator/$(DEPDIR)/android_ipc_tester-vhci.Po
+	-rm -f emulator/$(DEPDIR)/b1ee.Po
+	-rm -f emulator/$(DEPDIR)/btdev.Po
+	-rm -f emulator/$(DEPDIR)/bthost.Po
+	-rm -f emulator/$(DEPDIR)/hciemu.Po
+	-rm -f emulator/$(DEPDIR)/hfp.Po
+	-rm -f emulator/$(DEPDIR)/le.Po
+	-rm -f emulator/$(DEPDIR)/main.Po
+	-rm -f emulator/$(DEPDIR)/phy.Po
+	-rm -f emulator/$(DEPDIR)/serial.Po
+	-rm -f emulator/$(DEPDIR)/server.Po
+	-rm -f emulator/$(DEPDIR)/smp.Po
+	-rm -f emulator/$(DEPDIR)/vhci.Po
+	-rm -f gdbus/$(DEPDIR)/client.Plo
+	-rm -f gdbus/$(DEPDIR)/mainloop.Plo
+	-rm -f gdbus/$(DEPDIR)/object.Plo
+	-rm -f gdbus/$(DEPDIR)/polkit.Plo
+	-rm -f gdbus/$(DEPDIR)/watch.Plo
+	-rm -f gobex/$(DEPDIR)/gobex-apparam.Po
+	-rm -f gobex/$(DEPDIR)/gobex-defs.Po
+	-rm -f gobex/$(DEPDIR)/gobex-header.Po
+	-rm -f gobex/$(DEPDIR)/gobex-packet.Po
+	-rm -f gobex/$(DEPDIR)/gobex-transfer.Po
+	-rm -f gobex/$(DEPDIR)/gobex.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-apparam.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-defs.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-header.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-packet.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex-transfer.Po
+	-rm -f gobex/$(DEPDIR)/obexd-gobex.Po
+	-rm -f lib/$(DEPDIR)/bluetooth.Plo
+	-rm -f lib/$(DEPDIR)/hci.Plo
+	-rm -f lib/$(DEPDIR)/sdp.Plo
+	-rm -f lib/$(DEPDIR)/uuid.Plo
+	-rm -f mesh/$(DEPDIR)/agent.Po
+	-rm -f mesh/$(DEPDIR)/appkey.Po
+	-rm -f mesh/$(DEPDIR)/cfgmod-server.Po
+	-rm -f mesh/$(DEPDIR)/crypto.Po
+	-rm -f mesh/$(DEPDIR)/dbus.Po
+	-rm -f mesh/$(DEPDIR)/friend.Po
+	-rm -f mesh/$(DEPDIR)/keyring.Po
+	-rm -f mesh/$(DEPDIR)/main.Po
+	-rm -f mesh/$(DEPDIR)/manager.Po
+	-rm -f mesh/$(DEPDIR)/mesh-config-json.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-generic.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-mgmt.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io-unit.Po
+	-rm -f mesh/$(DEPDIR)/mesh-io.Po
+	-rm -f mesh/$(DEPDIR)/mesh-mgmt.Po
+	-rm -f mesh/$(DEPDIR)/mesh.Po
+	-rm -f mesh/$(DEPDIR)/model.Po
+	-rm -f mesh/$(DEPDIR)/net-keys.Po
+	-rm -f mesh/$(DEPDIR)/net.Po
+	-rm -f mesh/$(DEPDIR)/node.Po
+	-rm -f mesh/$(DEPDIR)/pb-adv.Po
+	-rm -f mesh/$(DEPDIR)/prov-acceptor.Po
+	-rm -f mesh/$(DEPDIR)/prov-initiator.Po
+	-rm -f mesh/$(DEPDIR)/prvbeac-server.Po
+	-rm -f mesh/$(DEPDIR)/remprv-server.Po
+	-rm -f mesh/$(DEPDIR)/rpl.Po
+	-rm -f mesh/$(DEPDIR)/util.Po
+	-rm -f monitor/$(DEPDIR)/a2dp.Po
+	-rm -f monitor/$(DEPDIR)/analyze.Po
+	-rm -f monitor/$(DEPDIR)/att.Po
+	-rm -f monitor/$(DEPDIR)/avctp.Po
+	-rm -f monitor/$(DEPDIR)/avdtp.Po
+	-rm -f monitor/$(DEPDIR)/bnep.Po
+	-rm -f monitor/$(DEPDIR)/broadcom.Po
+	-rm -f monitor/$(DEPDIR)/control.Po
+	-rm -f monitor/$(DEPDIR)/crc.Po
+	-rm -f monitor/$(DEPDIR)/display.Po
+	-rm -f monitor/$(DEPDIR)/ellisys.Po
+	-rm -f monitor/$(DEPDIR)/hcidump.Po
+	-rm -f monitor/$(DEPDIR)/hwdb.Po
+	-rm -f monitor/$(DEPDIR)/intel.Po
+	-rm -f monitor/$(DEPDIR)/jlink.Po
+	-rm -f monitor/$(DEPDIR)/keys.Po
+	-rm -f monitor/$(DEPDIR)/l2cap.Po
+	-rm -f monitor/$(DEPDIR)/ll.Po
+	-rm -f monitor/$(DEPDIR)/lmp.Po
+	-rm -f monitor/$(DEPDIR)/main.Po
+	-rm -f monitor/$(DEPDIR)/msft.Po
+	-rm -f monitor/$(DEPDIR)/packet.Po
+	-rm -f monitor/$(DEPDIR)/rfcomm.Po
+	-rm -f monitor/$(DEPDIR)/sdp.Po
+	-rm -f monitor/$(DEPDIR)/vendor.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bip-common.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bip.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-bluetooth.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-driver.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-ftp.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-manager.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-map-event.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-map.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-mns.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-opp.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-pbap.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-session.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-sync.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-transfer.Po
+	-rm -f obexd/client/$(DEPDIR)/obexd-transport.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-bluetooth.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-filesystem.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-ftp.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-irmc.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-mas.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-messages-dummy.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-opp.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-pbap.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-pcsuite.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-phonebook-@PLUGIN_PHONEBOOK@.Po
+	-rm -f obexd/plugins/$(DEPDIR)/obexd-vcard.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-log.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-main.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-manager.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-mimetype.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-obex.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-plugin.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-server.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-service.Po
+	-rm -f obexd/src/$(DEPDIR)/obexd-transport.Po
+	-rm -f peripheral/$(DEPDIR)/attach.Po
+	-rm -f peripheral/$(DEPDIR)/efivars.Po
+	-rm -f peripheral/$(DEPDIR)/gap.Po
+	-rm -f peripheral/$(DEPDIR)/gatt.Po
+	-rm -f peripheral/$(DEPDIR)/log.Po
+	-rm -f peripheral/$(DEPDIR)/main.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-admin.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-autopair.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-hostname.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-neard.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-policy.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-sixaxis.Po
+	-rm -f plugins/$(DEPDIR)/bluetoothd-wiimote.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-a2dp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-asha.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avctp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avdtp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-avrcp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-bap.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-bass.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-ccp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-control.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-csip.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-mcp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-media.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-micp.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-player.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-sink.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-source.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-transport.Po
+	-rm -f profiles/audio/$(DEPDIR)/bluetoothd-vcp.Po
+	-rm -f profiles/battery/$(DEPDIR)/bas.Po
+	-rm -f profiles/battery/$(DEPDIR)/bluetoothd-bas.Po
+	-rm -f profiles/battery/$(DEPDIR)/bluetoothd-battery.Po
+	-rm -f profiles/cups/$(DEPDIR)/hcrp.Po
+	-rm -f profiles/cups/$(DEPDIR)/main.Po
+	-rm -f profiles/cups/$(DEPDIR)/sdp.Po
+	-rm -f profiles/cups/$(DEPDIR)/spp.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/bluetoothd-deviceinfo.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/bluetoothd-dis.Po
+	-rm -f profiles/deviceinfo/$(DEPDIR)/dis.Po
+	-rm -f profiles/gap/$(DEPDIR)/bluetoothd-gas.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_main.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_manager.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-hdp_util.Po
+	-rm -f profiles/health/$(DEPDIR)/bluetoothd-mcap.Po
+	-rm -f profiles/health/$(DEPDIR)/mcap.Po
+	-rm -f profiles/iap/$(DEPDIR)/main.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-device.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-hog-lib.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-hog.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/input/$(DEPDIR)/bluetoothd-suspend-none.Po
+	-rm -f profiles/input/$(DEPDIR)/hog-lib.Po
+	-rm -f profiles/midi/$(DEPDIR)/bluetoothd-libmidi.Po
+	-rm -f profiles/midi/$(DEPDIR)/bluetoothd-midi.Po
+	-rm -f profiles/midi/$(DEPDIR)/unit_test_midi-libmidi.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-bnep.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-connection.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/network/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/network/$(DEPDIR)/bnep.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-main.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-manager.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-sap-dummy.Po
+	-rm -f profiles/sap/$(DEPDIR)/bluetoothd-server.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/bluetoothd-scan.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/bluetoothd-scpp.Po
+	-rm -f profiles/scanparam/$(DEPDIR)/scpp.Po
+	-rm -f src/$(DEPDIR)/android_avdtptest-log.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-adapter.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-adv_monitor.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-advertising.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-agent.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-backtrace.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-battery.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-dbus-common.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-device.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-eir.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-error.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-gatt-client.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-gatt-database.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-log.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-main.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-plugin.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-profile.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-rfkill.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdp-client.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdp-xml.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-database.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-request.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-server.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-sdpd-service.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-service.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-set.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-settings.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-storage.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-textfile.Po
+	-rm -f src/$(DEPDIR)/bluetoothd-uuid-helper.Po
+	-rm -f src/$(DEPDIR)/eir.Po
+	-rm -f src/$(DEPDIR)/log.Po
+	-rm -f src/$(DEPDIR)/oui.Po
+	-rm -f src/$(DEPDIR)/sdp-client.Po
+	-rm -f src/$(DEPDIR)/sdp-xml.Po
+	-rm -f src/$(DEPDIR)/sdpd-database.Po
+	-rm -f src/$(DEPDIR)/sdpd-request.Po
+	-rm -f src/$(DEPDIR)/sdpd-server.Po
+	-rm -f src/$(DEPDIR)/sdpd-service.Po
+	-rm -f src/$(DEPDIR)/settings.Po
+	-rm -f src/$(DEPDIR)/textfile.Po
+	-rm -f src/$(DEPDIR)/uuid-helper.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-log.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-queue.Po
+	-rm -f src/shared/$(DEPDIR)/android_avdtptest-util.Po
+	-rm -f src/shared/$(DEPDIR)/btp.Po
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-io-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mainloop-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-timeout-ell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_ell_la-vcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-io-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mainloop-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mainloop-notify.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-tester.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-timeout-glib.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_glib_la-vcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ad.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-asha.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-att.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bap-debug.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-bass.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-btsnoop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ccp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-csip.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ecc.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-client.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-db.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-helpers.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-gatt-server.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hci-crypto.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hci.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-hfp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-io-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-log.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop-notify.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mcp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-mgmt.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-micp.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-pcap.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-queue.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-ringbuf.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-shell.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-timeout-mainloop.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-uhid.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-util.Plo
+	-rm -f src/shared/$(DEPDIR)/libshared_mainloop_la-vcp.Plo
+	-rm -f tools/$(DEPDIR)/3dsp.Po
+	-rm -f tools/$(DEPDIR)/advtest.Po
+	-rm -f tools/$(DEPDIR)/amptest.Po
+	-rm -f tools/$(DEPDIR)/avinfo.Po
+	-rm -f tools/$(DEPDIR)/avtest.Po
+	-rm -f tools/$(DEPDIR)/bcmfw.Po
+	-rm -f tools/$(DEPDIR)/bdaddr.Po
+	-rm -f tools/$(DEPDIR)/bluemoon.Po
+	-rm -f tools/$(DEPDIR)/bluetooth-player.Po
+	-rm -f tools/$(DEPDIR)/bnep-tester.Po
+	-rm -f tools/$(DEPDIR)/bneptest.Po
+	-rm -f tools/$(DEPDIR)/btattach.Po
+	-rm -f tools/$(DEPDIR)/btconfig.Po
+	-rm -f tools/$(DEPDIR)/btgatt-client.Po
+	-rm -f tools/$(DEPDIR)/btgatt-server.Po
+	-rm -f tools/$(DEPDIR)/btinfo.Po
+	-rm -f tools/$(DEPDIR)/btiotest.Po
+	-rm -f tools/$(DEPDIR)/btmgmt.Po
+	-rm -f tools/$(DEPDIR)/btmon-logger.Po
+	-rm -f tools/$(DEPDIR)/btpclient.Po
+	-rm -f tools/$(DEPDIR)/btpclientctl.Po
+	-rm -f tools/$(DEPDIR)/btproxy.Po
+	-rm -f tools/$(DEPDIR)/btsnoop.Po
+	-rm -f tools/$(DEPDIR)/check-selftest.Po
+	-rm -f tools/$(DEPDIR)/ciptool.Po
+	-rm -f tools/$(DEPDIR)/cltest.Po
+	-rm -f tools/$(DEPDIR)/create-image.Po
+	-rm -f tools/$(DEPDIR)/eddystone.Po
+	-rm -f tools/$(DEPDIR)/gap-tester.Po
+	-rm -f tools/$(DEPDIR)/gatt-service.Po
+	-rm -f tools/$(DEPDIR)/hci-tester.Po
+	-rm -f tools/$(DEPDIR)/hciattach.Po
+	-rm -f tools/$(DEPDIR)/hciattach_ath3k.Po
+	-rm -f tools/$(DEPDIR)/hciattach_bcm43xx.Po
+	-rm -f tools/$(DEPDIR)/hciattach_intel.Po
+	-rm -f tools/$(DEPDIR)/hciattach_qualcomm.Po
+	-rm -f tools/$(DEPDIR)/hciattach_st.Po
+	-rm -f tools/$(DEPDIR)/hciattach_ti.Po
+	-rm -f tools/$(DEPDIR)/hciattach_tialt.Po
+	-rm -f tools/$(DEPDIR)/hciconfig.Po
+	-rm -f tools/$(DEPDIR)/hcidump.Po
+	-rm -f tools/$(DEPDIR)/hcieventmask.Po
+	-rm -f tools/$(DEPDIR)/hcisecfilter.Po
+	-rm -f tools/$(DEPDIR)/hcitool.Po
+	-rm -f tools/$(DEPDIR)/hex2hcd.Po
+	-rm -f tools/$(DEPDIR)/hid2hci.Po
+	-rm -f tools/$(DEPDIR)/hwdb.Po
+	-rm -f tools/$(DEPDIR)/ibeacon.Po
+	-rm -f tools/$(DEPDIR)/ioctl-tester.Po
+	-rm -f tools/$(DEPDIR)/iso-tester.Po
+	-rm -f tools/$(DEPDIR)/isotest.Po
+	-rm -f tools/$(DEPDIR)/l2cap-tester.Po
+	-rm -f tools/$(DEPDIR)/l2ping.Po
+	-rm -f tools/$(DEPDIR)/l2test.Po
+	-rm -f tools/$(DEPDIR)/mcaptest.Po
+	-rm -f tools/$(DEPDIR)/mesh-cfgclient.Po
+	-rm -f tools/$(DEPDIR)/mesh-cfgtest.Po
+	-rm -f tools/$(DEPDIR)/mesh-tester.Po
+	-rm -f tools/$(DEPDIR)/meshctl.Po
+	-rm -f tools/$(DEPDIR)/mgmt-tester.Po
+	-rm -f tools/$(DEPDIR)/mpris-proxy.Po
+	-rm -f tools/$(DEPDIR)/nokfw.Po
+	-rm -f tools/$(DEPDIR)/obex-client-tool.Po
+	-rm -f tools/$(DEPDIR)/obex-server-tool.Po
+	-rm -f tools/$(DEPDIR)/obexctl.Po
+	-rm -f tools/$(DEPDIR)/oobtest.Po
+	-rm -f tools/$(DEPDIR)/rctest.Po
+	-rm -f tools/$(DEPDIR)/rfcomm-tester.Po
+	-rm -f tools/$(DEPDIR)/rfcomm.Po
+	-rm -f tools/$(DEPDIR)/rtlfw.Po
+	-rm -f tools/$(DEPDIR)/sco-tester.Po
+	-rm -f tools/$(DEPDIR)/scotest.Po
+	-rm -f tools/$(DEPDIR)/sdptool.Po
+	-rm -f tools/$(DEPDIR)/seq2bseq.Po
+	-rm -f tools/$(DEPDIR)/smp-tester.Po
+	-rm -f tools/$(DEPDIR)/test-runner.Po
+	-rm -f tools/$(DEPDIR)/userchan-tester.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/config-client.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/config-server.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/crypto.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/gatt.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/net.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/node.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/onoff-model.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/prov-db.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/prov.Po
+	-rm -f tools/mesh-gatt/$(DEPDIR)/util.Po
+	-rm -f tools/mesh/$(DEPDIR)/agent.Po
+	-rm -f tools/mesh/$(DEPDIR)/cfgcli.Po
+	-rm -f tools/mesh/$(DEPDIR)/keys.Po
+	-rm -f tools/mesh/$(DEPDIR)/mesh-db.Po
+	-rm -f tools/mesh/$(DEPDIR)/remote.Po
+	-rm -f tools/mesh/$(DEPDIR)/util.Po
+	-rm -f tools/parser/$(DEPDIR)/amp.Po
+	-rm -f tools/parser/$(DEPDIR)/att.Po
+	-rm -f tools/parser/$(DEPDIR)/avctp.Po
+	-rm -f tools/parser/$(DEPDIR)/avdtp.Po
+	-rm -f tools/parser/$(DEPDIR)/avrcp.Po
+	-rm -f tools/parser/$(DEPDIR)/bnep.Po
+	-rm -f tools/parser/$(DEPDIR)/bpa.Po
+	-rm -f tools/parser/$(DEPDIR)/capi.Po
+	-rm -f tools/parser/$(DEPDIR)/cmtp.Po
+	-rm -f tools/parser/$(DEPDIR)/csr.Po
+	-rm -f tools/parser/$(DEPDIR)/ericsson.Po
+	-rm -f tools/parser/$(DEPDIR)/hci.Po
+	-rm -f tools/parser/$(DEPDIR)/hcrp.Po
+	-rm -f tools/parser/$(DEPDIR)/hidp.Po
+	-rm -f tools/parser/$(DEPDIR)/l2cap.Po
+	-rm -f tools/parser/$(DEPDIR)/lmp.Po
+	-rm -f tools/parser/$(DEPDIR)/obex.Po
+	-rm -f tools/parser/$(DEPDIR)/parser.Po
+	-rm -f tools/parser/$(DEPDIR)/ppp.Po
+	-rm -f tools/parser/$(DEPDIR)/rfcomm.Po
+	-rm -f tools/parser/$(DEPDIR)/sap.Po
+	-rm -f tools/parser/$(DEPDIR)/sdp.Po
+	-rm -f tools/parser/$(DEPDIR)/smp.Po
+	-rm -f tools/parser/$(DEPDIR)/tcpip.Po
+	-rm -f unit/$(DEPDIR)/test-avctp.Po
+	-rm -f unit/$(DEPDIR)/test-avdtp.Po
+	-rm -f unit/$(DEPDIR)/test-avrcp.Po
+	-rm -f unit/$(DEPDIR)/test-bap.Po
+	-rm -f unit/$(DEPDIR)/test-bass.Po
+	-rm -f unit/$(DEPDIR)/test-crc.Po
+	-rm -f unit/$(DEPDIR)/test-crypto.Po
+	-rm -f unit/$(DEPDIR)/test-ecc.Po
+	-rm -f unit/$(DEPDIR)/test-eir.Po
+	-rm -f unit/$(DEPDIR)/test-gatt.Po
+	-rm -f unit/$(DEPDIR)/test-gattrib.Po
+	-rm -f unit/$(DEPDIR)/test-gdbus-client.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-apparam.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-header.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-packet.Po
+	-rm -f unit/$(DEPDIR)/test-gobex-transfer.Po
+	-rm -f unit/$(DEPDIR)/test-gobex.Po
+	-rm -f unit/$(DEPDIR)/test-hfp.Po
+	-rm -f unit/$(DEPDIR)/test-hog.Po
+	-rm -f unit/$(DEPDIR)/test-lib.Po
+	-rm -f unit/$(DEPDIR)/test-mgmt.Po
+	-rm -f unit/$(DEPDIR)/test-micp.Po
+	-rm -f unit/$(DEPDIR)/test-queue.Po
+	-rm -f unit/$(DEPDIR)/test-ringbuf.Po
+	-rm -f unit/$(DEPDIR)/test-sdp.Po
+	-rm -f unit/$(DEPDIR)/test-tester.Po
+	-rm -f unit/$(DEPDIR)/test-textfile.Po
+	-rm -f unit/$(DEPDIR)/test-uhid.Po
+	-rm -f unit/$(DEPDIR)/test-uuid.Po
+	-rm -f unit/$(DEPDIR)/test-vcp.Po
+	-rm -f unit/$(DEPDIR)/test_mesh_crypto-test-mesh-crypto.Po
+	-rm -f unit/$(DEPDIR)/test_midi-test-midi.Po
+	-rm -f unit/$(DEPDIR)/util.Po
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-confDATA \
+	uninstall-cupsPROGRAMS uninstall-dbusDATA \
+	uninstall-dbussessionbusDATA uninstall-dbussystembusDATA \
+	uninstall-dist_zshcompletionDATA uninstall-libLTLIBRARIES \
+	uninstall-man uninstall-pkgconfigDATA \
+	uninstall-pkgincludeHEADERS uninstall-pkglibexecPROGRAMS \
+	uninstall-pluginLTLIBRARIES uninstall-rulesDATA \
+	uninstall-stateDATA uninstall-systemdsystemunitDATA \
+	uninstall-systemduserunitDATA uninstall-testSCRIPTS \
+	uninstall-udevPROGRAMS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+uninstall-man: uninstall-man1 uninstall-man5 uninstall-man7 \
+	uninstall-man8
+
+.MAKE: all check check-am install install-am install-data-am \
+	install-exec install-strip uninstall-am
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \
+	check-TESTS check-am clean clean-binPROGRAMS clean-cscope \
+	clean-cupsPROGRAMS clean-generic clean-libLTLIBRARIES \
+	clean-libtool clean-local clean-noinstLIBRARIES \
+	clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+	clean-pkglibexecPROGRAMS clean-pluginLTLIBRARIES \
+	clean-udevPROGRAMS cscope cscopelist-am ctags ctags-am dist \
+	dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
+	dist-xz dist-zip dist-zstd distcheck distclean \
+	distclean-compile distclean-generic distclean-hdr \
+	distclean-libtool distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-binPROGRAMS install-confDATA \
+	install-cupsPROGRAMS install-data install-data-am \
+	install-data-hook install-dbusDATA install-dbussessionbusDATA \
+	install-dbussystembusDATA install-dist_zshcompletionDATA \
+	install-dvi install-dvi-am install-exec install-exec-am \
+	install-html install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-man install-man1 install-man5 \
+	install-man7 install-man8 install-pdf install-pdf-am \
+	install-pkgconfigDATA install-pkgincludeHEADERS \
+	install-pkglibexecPROGRAMS install-pluginLTLIBRARIES \
+	install-ps install-ps-am install-rulesDATA install-stateDATA \
+	install-strip install-systemdsystemunitDATA \
+	install-systemduserunitDATA install-testSCRIPTS \
+	install-udevPROGRAMS installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic \
+	maintainer-clean-local mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	recheck tags tags-am uninstall uninstall-am \
+	uninstall-binPROGRAMS uninstall-confDATA \
+	uninstall-cupsPROGRAMS uninstall-dbusDATA \
+	uninstall-dbussessionbusDATA uninstall-dbussystembusDATA \
+	uninstall-dist_zshcompletionDATA uninstall-hook \
+	uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \
+	uninstall-man5 uninstall-man7 uninstall-man8 \
+	uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS \
+	uninstall-pkglibexecPROGRAMS uninstall-pluginLTLIBRARIES \
+	uninstall-rulesDATA uninstall-stateDATA \
+	uninstall-systemdsystemunitDATA uninstall-systemduserunitDATA \
+	uninstall-testSCRIPTS uninstall-udevPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+bluetoothd-fix-permissions:
+	install -dm555 $(DESTDIR)$(confdir)
+	install -dm700 $(DESTDIR)$(statedir)
+@BTPCLIENT_TRUE@tools/btpclient.$(OBJEXT): src/libshared-ell.la ell/internal
+
+@OBEX_TRUE@@SYSTEMD_TRUE@obexd-add-service-symlink:
+@OBEX_TRUE@@SYSTEMD_TRUE@	$(LN_S) -f obex.service $(DESTDIR)$(SYSTEMD_USERUNITDIR)/dbus-org.bluez.obex.service
+
+@OBEX_TRUE@@SYSTEMD_TRUE@obexd-remove-service-symlink:
+@OBEX_TRUE@@SYSTEMD_TRUE@	rm -f $(DESTDIR)$(SYSTEMD_USERUNITDIR)/dbus-org.bluez.obex.service
+@OBEX_TRUE@@SYSTEMD_FALSE@obexd-add-service-symlink:
+@OBEX_TRUE@@SYSTEMD_FALSE@obexd-remove-service-symlink:
+
+@OBEX_FALSE@obexd-add-service-symlink:
+@OBEX_FALSE@obexd-remove-service-symlink:
+
+obexd/src/plugin.$(OBJEXT): obexd/src/builtin.h
+
+obexd/src/builtin.h: obexd/src/genbuiltin $(obexd_builtin_sources)
+	$(AM_V_at)$(MKDIR_P) $(dir $@)
+	$(AM_V_GEN)$(srcdir)/obexd/src/genbuiltin $(obexd_builtin_modules) > $@
+
+@MESH_TRUE@mesh/mesh.$(OBJEXT): ell/internal
+@MESH_TRUE@mesh/main.$(OBJEXT): src/builtin.h lib/bluetooth/bluetooth.h
+
+@SYSTEMD_TRUE@install-data-hook: obexd-add-service-symlink
+@SYSTEMD_FALSE@install-data-hook: bluetoothd-fix-permissions obexd-add-service-symlink
+
+uninstall-hook: obexd-remove-service-symlink
+
+%.1: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
+%.5: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
+%.7: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
+%.8: %.rst Makefile
+	$(RST2MAN_PROCESS)
+
+src/builtin.h: src/genbuiltin $(builtin_sources)
+	$(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@
+
+tools/%.rules:
+	$(AM_V_at)$(MKDIR_P) tools
+	$(AM_V_GEN)cp $(srcdir)/$(subst 97-,,$@) $@
+
+$(lib_libbluetooth_la_OBJECTS): $(local_headers)
+
+lib/bluetooth/%.h: lib/%.h
+	$(AM_V_at)$(MKDIR_P) lib/bluetooth
+	$(AM_V_GEN)$(LN_S) -f $(abspath $<) $@
+
+ell/shared: Makefile
+	$(AM_V_at)$(MKDIR_P) ell
+	$(AM_V_GEN)for f in $(ell_shared) ; do \
+		if [ ! -f $$f ] ; then \
+			$(LN_S) -t ell -f $(abs_srcdir)/../ell/$$f ; \
+		fi \
+	done > $@
+
+ell/internal: Makefile
+	$(AM_V_at)$(MKDIR_P) ell
+	$(AM_V_GEN)for f in $(ell_headers) $(ell_sources) ; do \
+		if [ ! -f $$f ] ; then \
+			$(LN_S) -t ell -f $(abs_srcdir)/../ell/$$f ; \
+		fi \
+	done > $@
+
+ell/ell.h: Makefile
+	$(AM_V_at)echo -n > $@
+	$(AM_V_GEN)for f in $(ell_headers) ; do \
+		echo "#include <$$f>" >> $@ ; \
+	done
+
+maintainer-clean-local:
+	-rm -rf ell
+
+clean-coverage:
+@COVERAGE_TRUE@	@lcov --directory $(top_builddir) --zerocounters
+@COVERAGE_TRUE@	$(RM) -r coverage $(top_builddir)/coverage.info
+
+@COVERAGE_TRUE@coverage: check
+@COVERAGE_TRUE@	@lcov --compat-libtool --directory $(top_builddir) --capture \
+@COVERAGE_TRUE@				--output-file $(top_builddir)/coverage.info
+@COVERAGE_TRUE@	$(AM_V_at)$(MKDIR_P) coverage
+@COVERAGE_TRUE@	@genhtml -o coverage/ $(top_builddir)/coverage.info
+
+clean-local: clean-coverage
+	-find $(top_builddir) -name "*.gcno" -delete
+	-find $(top_builddir) -name "*.gcda" -delete
+	$(RM) -r lib/bluetooth
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Makefile.mesh b/Makefile.mesh
index 3047f36..e4c9fa6 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -3,6 +3,7 @@ if MESH
 
 if DATAFILES
 dbus_DATA += mesh/bluetooth-mesh.conf
+conf_DATA += mesh/mesh-main.conf
 endif
 
 if SYSTEMD
@@ -26,6 +27,7 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \
 				mesh/provision.h mesh/prov.h \
 				mesh/model.h mesh/model.c \
 				mesh/cfgmod.h mesh/cfgmod-server.c \
+				mesh/remprv.h mesh/remprv-server.c \
 				mesh/mesh-config.h mesh/mesh-config-json.c \
 				mesh/util.h mesh/util.c \
 				mesh/dbus.h mesh/dbus.c \
@@ -35,6 +37,7 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \
 				mesh/pb-adv.h mesh/pb-adv.c \
 				mesh/keyring.h mesh/keyring.c \
 				mesh/rpl.h mesh/rpl.c \
+				mesh/prv-beacon.h mesh/prvbeac-server.c \
 				mesh/mesh-defs.h
 pkglibexec_PROGRAMS += mesh/bluetooth-meshd
 
@@ -43,17 +46,12 @@ mesh/main.$(OBJEXT): src/builtin.h lib/bluetooth/bluetooth.h
 
 mesh_bluetooth_meshd_SOURCES = $(mesh_sources) mesh/main.c
 mesh_bluetooth_meshd_LDADD = src/libshared-ell.la $(ell_ldadd) -ljson-c
-mesh_bluetooth_meshd_DEPENDENCIES = $(ell_dependencies) src/libshared-ell.la \
-				mesh/bluetooth-mesh.service
 
 if MANPAGES
 man_MANS += mesh/bluetooth-meshd.8
 endif
 manual_pages += mesh/bluetooth-meshd.8
 
-CLEANFILES += mesh/bluetooth-mesh.service
-
 endif
 
-EXTRA_DIST += mesh/bluetooth-mesh.conf mesh/bluetooth-mesh.service.in \
-		mesh/org.bluez.mesh.service mesh/mesh-main.conf
+EXTRA_DIST += mesh/bluetooth-mesh.conf mesh/org.bluez.mesh.service mesh/mesh-main.conf
diff --git a/Makefile.obexd b/Makefile.obexd
index 5d1a4ff..74dd977 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -1,15 +1,21 @@
 # SPDX-License-Identifier: GPL-2.0
+if OBEX
+
 if SYSTEMD
-systemduserunitdir = $(SYSTEMD_USERUNITDIR)
-systemduserunit_DATA = obexd/src/obex.service
+systemduserunit_DATA += obexd/src/obex.service
 
 dbussessionbusdir = $(DBUS_SESSIONBUSDIR)
 dbussessionbus_DATA = obexd/src/org.bluez.obex.service
-endif
 
-EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service
+obexd-add-service-symlink:
+	$(LN_S) -f obex.service $(DESTDIR)$(SYSTEMD_USERUNITDIR)/dbus-org.bluez.obex.service
 
-if OBEX
+obexd-remove-service-symlink:
+	rm -f $(DESTDIR)$(SYSTEMD_USERUNITDIR)/dbus-org.bluez.obex.service
+else
+obexd-add-service-symlink:
+obexd-remove-service-symlink:
+endif
 
 obex_plugindir = $(libdir)/obex/plugins
 
@@ -75,6 +81,8 @@ obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \
 			obexd/client/ftp.h obexd/client/ftp.c \
 			obexd/client/opp.h obexd/client/opp.c \
 			obexd/client/map.h obexd/client/map.c \
+			obexd/client/bip.h obexd/client/bip.c \
+			obexd/client/bip-common.h obexd/client/bip-common.c \
 			obexd/client/map-event.h obexd/client/map-event.c \
 			obexd/client/transfer.h obexd/client/transfer.c \
 			obexd/client/transport.h obexd/client/transport.c \
@@ -86,16 +94,19 @@ obexd_src_obexd_LDADD = lib/libbluetooth-internal.la \
 			$(ICAL_LIBS) $(DBUS_LIBS) $(LIBEBOOK_LIBS) \
 			$(LIBEDATASERVER_LIBS) $(GLIB_LIBS) -ldl
 
+if EXTERNAL_PLUGINS
 obexd_src_obexd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic
+endif
 
 obexd_src_obexd_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
 				$(ICAL_CFLAGS) -DOBEX_PLUGIN_BUILTIN \
 				-DPLUGINDIR=\""$(obex_plugindir)"\" \
 				-D_FILE_OFFSET_BITS=64 \
-				-I$(builddir)/lib -I$(builddir)/obexd/src
-
-obexd_src_obexd_CFLAGS = $(AM_CFLAGS) -fPIC
+				-I$(builddir)/obexd/src
 
+else
+obexd-add-service-symlink:
+obexd-remove-service-symlink:
 endif
 
 obexd_src_obexd_SHORTNAME = obexd
@@ -112,6 +123,6 @@ obexd/src/builtin.h: obexd/src/genbuiltin $(obexd_builtin_sources)
 	$(AM_V_at)$(MKDIR_P) $(dir $@)
 	$(AM_V_GEN)$(srcdir)/obexd/src/genbuiltin $(obexd_builtin_modules) > $@
 
-CLEANFILES += obexd/src/builtin.h $(builtin_files) obexd/src/obex.service
+CLEANFILES += obexd/src/builtin.h
 
 EXTRA_DIST += obexd/src/genbuiltin
diff --git a/Makefile.plugins b/Makefile.plugins
index 20cac38..9da29a3 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -74,8 +74,6 @@ builtin_sources += profiles/input/hog.c \
 			profiles/battery/bas.c profiles/battery/bas.h \
 			profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
 			profiles/input/suspend.h profiles/input/suspend-none.c
-
-EXTRA_DIST += profiles/input/suspend-dummy.c
 endif
 
 if HEALTH
@@ -110,16 +108,19 @@ builtin_modules += battery
 builtin_sources += profiles/battery/battery.c
 
 if SIXAXIS
-plugin_LTLIBRARIES += plugins/sixaxis.la
-plugins_sixaxis_la_SOURCES = plugins/sixaxis.c
-plugins_sixaxis_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version
-plugins_sixaxis_la_LIBADD = $(UDEV_LIBS)
-plugins_sixaxis_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+builtin_modules += sixaxis
+builtin_sources += plugins/sixaxis.c
+builtin_ldadd += $(UDEV_LIBS)
 endif
 
 if BAP
 builtin_modules += bap
-builtin_sources += profiles/audio/bap.c
+builtin_sources += profiles/audio/bap.h profiles/audio/bap.c
+endif
+
+if BASS
+builtin_modules += bass
+builtin_sources += profiles/audio/bass.h profiles/audio/bass.c
 endif
 
 if MCP
@@ -131,3 +132,23 @@ if VCP
 builtin_modules += vcp
 builtin_sources += profiles/audio/vcp.c
 endif
+
+if MICP
+builtin_modules += micp
+builtin_sources += profiles/audio/micp.c
+endif
+
+if CCP
+builtin_modules += ccp
+builtin_sources += profiles/audio/ccp.c
+endif
+
+if CSIP
+builtin_modules += csip
+builtin_sources += profiles/audio/csip.c
+endif
+
+if ASHA
+builtin_modules += asha
+builtin_sources += profiles/audio/asha.h profiles/audio/asha.c
+endif
diff --git a/Makefile.tools b/Makefile.tools
index 4bc355c..71033d6 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -3,6 +3,7 @@ if CLIENT
 bin_PROGRAMS += client/bluetoothctl
 
 client_bluetoothctl_SOURCES = client/main.c \
+					client/print.h client/print.c \
 					client/display.h client/display.c \
 					client/agent.h client/agent.c \
 					client/advertising.h \
@@ -11,9 +12,12 @@ client_bluetoothctl_SOURCES = client/main.c \
 					client/adv_monitor.c \
 					client/gatt.h client/gatt.c \
 					client/admin.h client/admin.c \
-					client/player.h client/player.c
-client_bluetoothctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
-				$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
+					client/player.h client/player.c \
+					client/mgmt.h client/mgmt.c \
+					client/assistant.h client/assistant.c
+client_bluetoothctl_LDADD = lib/libbluetooth-internal.la \
+			gdbus/libgdbus-internal.la src/libshared-glib.la \
+			$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
 endif
 
 if ZSH_COMPLETIONS
@@ -68,17 +72,12 @@ pkglibexec_PROGRAMS += tools/btmon-logger
 
 tools_btmon_logger_SOURCES = tools/btmon-logger.c
 tools_btmon_logger_LDADD = src/libshared-mainloop.la
-tools_btmon_logger_DEPENDENCIES = src/libshared-mainloop.la \
-					tools/bluetooth-logger.service
 
 if SYSTEMD
 systemdsystemunit_DATA += tools/bluetooth-logger.service
 endif
 endif
 
-CLEANFILES += tools/bluetooth-logger.service
-EXTRA_DIST += tools/bluetooth-logger.service.in
-
 if TESTING
 noinst_PROGRAMS += emulator/btvirt emulator/b1ee emulator/hfp \
 					peripheral/btsensor tools/3dsp \
@@ -137,7 +136,7 @@ tools_mesh_tester_SOURCES = tools/mesh-tester.c monitor/bt.h \
 tools_mesh_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
-tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
+tools_l2cap_tester_SOURCES = tools/l2cap-tester.c tools/tester.h monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu.c \
 				emulator/vhci.h emulator/vhci.c \
 				emulator/btdev.h emulator/btdev.c \
@@ -184,7 +183,7 @@ tools_gap_tester_LDADD =  lib/libbluetooth-internal.la \
 				src/libshared-glib.la \
 				$(GLIB_LIBS) $(DBUS_LIBS)
 
-tools_sco_tester_SOURCES = tools/sco-tester.c monitor/bt.h \
+tools_sco_tester_SOURCES = tools/sco-tester.c tools/tester.h monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu.c \
 				emulator/vhci.h emulator/vhci.c \
 				emulator/btdev.h emulator/btdev.c \
@@ -205,7 +204,7 @@ tools_userchan_tester_SOURCES = tools/userchan-tester.c monitor/bt.h \
 tools_userchan_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
-tools_iso_tester_SOURCES = tools/iso-tester.c monitor/bt.h \
+tools_iso_tester_SOURCES = tools/iso-tester.c tools/tester.h monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu.c \
 				emulator/vhci.h emulator/vhci.c \
 				emulator/btdev.h emulator/btdev.c \
@@ -329,10 +328,13 @@ tools_l2ping_LDADD = lib/libbluetooth-internal.la
 tools_bluemoon_SOURCES = tools/bluemoon.c monitor/bt.h
 tools_bluemoon_LDADD = src/libshared-mainloop.la
 
-tools_hex2hcd_SOURCES = tools/hex2hcd.c
+tools_hex2hcd_SOURCES = tools/hex2hcd.c tools/missing.h
 
 tools_mpris_proxy_SOURCES = tools/mpris-proxy.c
 tools_mpris_proxy_LDADD = gdbus/libgdbus-internal.la $(GLIB_LIBS) $(DBUS_LIBS)
+if SYSTEMD
+systemduserunit_DATA += tools/mpris-proxy.service
+endif
 
 tools_gatt_service_SOURCES = tools/gatt-service.c
 tools_gatt_service_LDADD = gdbus/libgdbus-internal.la \
@@ -344,7 +346,15 @@ profiles_iap_iapd_SOURCES = profiles/iap/main.c
 profiles_iap_iapd_LDADD = gdbus/libgdbus-internal.la $(GLIB_LIBS) $(DBUS_LIBS)
 
 if MANPAGES
-man_MANS += tools/rctest.1 tools/l2ping.1 tools/btattach.1 tools/isotest.1
+man_MANS += tools/rctest.1 tools/l2ping.1 tools/btattach.1 tools/isotest.1 \
+		tools/btmgmt.1 client/bluetoothctl.1 \
+		client/bluetoothctl-mgmt.1 \
+		client/bluetoothctl-monitor.1 client/bluetoothctl-admin.1 \
+		client/bluetoothctl-advertise.1 client/bluetoothctl-endpoint.1 \
+		client/bluetoothctl-gatt.1 client/bluetoothctl-player.1 \
+		client/bluetoothctl-scan.1 client/bluetoothctl-transport.1 \
+		client/bluetoothctl-assistant.1
+
 endif
 
 if MESH
@@ -465,7 +475,18 @@ manual_pages += tools/hciattach.1 tools/hciconfig.1 \
 			tools/hcitool.1 tools/hcidump.1 \
 			tools/rfcomm.1 tools/sdptool.1 tools/ciptool.1 \
 			tools/rctest.1 tools/l2ping.1 tools/btattach.1 \
-			tools/bdaddr.1 tools/isotest.1
+			tools/bdaddr.1 tools/isotest.1 tools/btmgmt.1 \
+			client/bluetoothctl.1 \
+			client/bluetoothctl-mgmt.1 \
+			client/bluetoothctl-monitor.1 \
+			client/bluetoothctl-admin.1 \
+			client/bluetoothctl-advertise.1 \
+			client/bluetoothctl-endpoint.1 \
+			client/bluetoothctl-gatt.1 \
+			client/bluetoothctl-player.1 \
+			client/bluetoothctl-scan.1 \
+			client/bluetoothctl-transport.1 \
+			client/bluetoothctl-assistant.1
 
 if HID2HCI
 udevdir = $(UDEV_DIR)
@@ -494,7 +515,8 @@ tools_obex_server_tool_SOURCES = $(gobex_sources) $(btio_sources) \
 tools_obex_server_tool_LDADD = lib/libbluetooth-internal.la \
 			       src/libshared-glib.la $(GLIB_LIBS)
 
-tools_bluetooth_player_SOURCES = tools/bluetooth-player.c client/player.c
+tools_bluetooth_player_SOURCES = tools/bluetooth-player.c client/print.c \
+				client/player.c
 tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \
 				src/libshared-glib.la \
 				$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
@@ -503,7 +525,8 @@ tools_obexctl_SOURCES = tools/obexctl.c
 tools_obexctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
 			$(GLIB_LIBS) $(DBUS_LIBS) -lreadline
 
-tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c client/display.c
+tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c client/display.c \
+			client/mgmt.c
 tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la \
 				-lreadline
 if DEPRECATED
@@ -521,7 +544,12 @@ endif
 endif
 
 if CUPS
+
+if CUPS_SERVERBIN
+cupsdir = $(CUPS_SERVERBIN)/backend
+else
 cupsdir = $(libdir)/cups/backend
+endif
 
 cups_PROGRAMS = profiles/cups/bluetooth
 
@@ -556,7 +584,6 @@ noinst_PROGRAMS += tools/btpclient tools/btpclientctl
 tools_btpclient_SOURCES = tools/btpclient.c src/shared/btp.c src/shared/btp.h
 tools_btpclient_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-ell.la $(ell_ldadd)
-tools_btpclient_DEPENDENCIES = lib/libbluetooth-internal.la $(ell_dependencies)
 tools/btpclient.$(OBJEXT): src/libshared-ell.la ell/internal
 
 tools_btpclientctl_SOURCES = tools/btpclientctl.c client/display.c
diff --git a/README b/README
index 7de7045..6c07770 100644
--- a/README
+++ b/README
@@ -249,6 +249,19 @@ For a working system, certain configuration options need to be enabled:
 		systems. The behavior of the deprecated tools may be unstable
 		or simply don't work anymore.
 
+	--enable-external-plugins
+
+		Enable support for external plugins
+
+		By default external plugins for bluetoothd and obexd are not
+		supported and thus disabled.
+
+		External plugins require access to internal, undocumented and
+		unversioned API in said daemons. As such they can break at any
+		time. If you have such plugins, enable this option and work
+		actively with the community to make said plugin part of the
+		upstream bluez project.
+
 	--enable-nfc
 
 		This option enable NFC pairing support.
diff --git a/acinclude.m4 b/acinclude.m4
index c5d6de7..4b73a5b 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -134,6 +134,8 @@ AC_DEFUN([MISC_FLAGS], [
 		misc_cflags="$misc_cflags --coverage"
 		misc_ldflags="$misc_ldflags --coverage"
 	fi
+	misc_cflags="$misc_cflags -ffunction-sections -fdata-sections"
+	misc_ldflags="$misc_ldflags -Wl,--gc-sections"
 	AC_SUBST([MISC_CFLAGS], $misc_cflags)
 	AC_SUBST([MISC_LDFLAGS], $misc_ldflags)
 ])
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..cfb9291
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,10619 @@
+# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],,
+[m4_warning([this file was generated for autoconf 2.72.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+#   Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool 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 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the  same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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, see <http://www.gnu.org/licenses/>.
+])
+
+# serial 59 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+		   [m4_fatal([Libtool version $1 or higher is required],
+		             63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\	*)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in @S|@*""; do
+      case $cc_temp in
+        compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+        distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_DECL_FILECMD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test set != "${COLLECT_NAMES+set}"; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from 'configure', and 'config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain=$ac_aux_dir/ltmain.sh
+])# _LT_PROG_LTMAIN
+
+
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the 'libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+	[m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+	[tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+	   m4_quote(lt_decl_varnames),
+	m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to 'config.status' so that its
+# declaration there will have the same value as in 'configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags='_LT_TAGS'dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+					   [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into 'config.status', and then the shell code to quote escape them in
+# for loops in 'config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+	dnl If the libtool generation code has been placed in $CONFIG_LT,
+	dnl instead of duplicating it all over again into config.status,
+	dnl then we will have config.status run $CONFIG_LT later, so it
+	dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# '#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $[#]
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try '$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try '$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options that allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}"; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile=${ofile}T
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+    cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  $SED '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],			[_LT_LANG(C)],
+  [C++],		[_LT_LANG(CXX)],
+  [Go],			[_LT_LANG(GO)],
+  [Java],		[_LT_LANG(GCJ)],
+  [Fortran 77],		[_LT_LANG(F77)],
+  [Fortran],		[_LT_LANG(FC)],
+  [Windows Resource],	[_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC],     [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+  fi
+fi
+if test -z "$GOC"; then
+  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+  [LT_LANG(GO)],
+  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "$LT_MULTI_MODULE"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	# If there is a non-empty error log, and "single_module"
+	# appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	# Otherwise, if the output was created with a 0 exit code from
+	# the compiler, it worked.
+	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi])
+
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+	[lt_cv_ld_exported_symbols_list=yes],
+	[lt_cv_ld_exported_symbols_list=no])
+	LDFLAGS=$save_LDFLAGS
+    ])
+
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+	cat conftest.err >&AS_MESSAGE_LOG_FD
+      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+    darwin*)
+      case $MACOSX_DEPLOYMENT_TARGET,$host in
+        10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+        *)
+          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test yes = "$lt_cv_apple_cc_single_mod"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+    fi
+    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  if test yes = "$lt_cv_ld_force_load"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+  case $cc_basename in
+     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test yes = "$_lt_dar_can_shared"; then
+    output_verbose_link_cmd=func_echo_all
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+    m4_if([$1], [CXX],
+[   if test yes != "$lt_cv_apple_cc_single_mod"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+  lt_aix_libpath_sed='[
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }]'
+  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi],[])
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+  fi
+  ])
+  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script that will find a shell with a builtin
+# printf (that we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+case $ECHO in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+  [Search for dependent libraries within DIR (or the compiler's sysroot
+   if not specified).])],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted.  We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+   if test yes = "$GCC"; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   AC_MSG_RESULT([$with_sysroot])
+   AC_MSG_ERROR([The sysroot must be an absolute path.])
+   ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and where our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out what ABI is being produced by ac_compile, and set mode
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `$FILECMD conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE=32
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE=64
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test yes = "$lt_cv_prog_gnu_ld"; then
+      case `$FILECMD conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `$FILECMD conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+mips64*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    emul=elf
+    case `$FILECMD conftest.$ac_objext` in
+      *32-bit*)
+	emul="${emul}32"
+	;;
+      *64-bit*)
+	emul="${emul}64"
+	;;
+    esac
+    case `$FILECMD conftest.$ac_objext` in
+      *MSB*)
+	emul="${emul}btsmip"
+	;;
+      *LSB*)
+	emul="${emul}ltsmip"
+	;;
+    esac
+    case `$FILECMD conftest.$ac_objext` in
+      *N32*)
+	emul="${emul}n32"
+	;;
+    esac
+    LD="${LD-ld} -m $emul"
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.  Note that the listed cases only cover the
+  # situations where additional linker options are needed (such as when
+  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+  # vice versa); the common cases where no linker options are needed do
+  # not appear in the list.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `$FILECMD conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `$FILECMD conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test yes != "$lt_cv_cc_needs_belf"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS=$SAVE_CFLAGS
+  fi
+  ;;
+*-*solaris*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `$FILECMD conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*|x86_64-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD=${LD-ld}_sol2
+        fi
+        ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks=$enable_libtool_lock
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+_LT_DECL([], [AR], [1], [The archiver])
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+         [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+  [lt_cv_ar_at_file=no
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+     [echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([lt_ar_try])
+      if test 0 -eq "$ac_status"; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	AC_TRY_EVAL([lt_ar_try])
+	if test 0 -ne "$ac_status"; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+     ])
+  ])
+
+if test no = "$lt_cv_ar_at_file"; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+  [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  bitrig* | openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test yes = "[$]$2"; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+])
+
+if test yes = "[$]$2"; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring=ABCD
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[	 ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test 17 != "$i" # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n "$lt_cv_sys_max_cmd_len"; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes = "$cross_compiling"; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes != "$enable_dlopen"; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen=load_add_on
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen=LoadLibrary
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+    # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+    lt_cv_dlopen=dyld
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  tpf*)
+    # Don't try to run any link tests for TPF.  We know it's impossible
+    # because TPF is a cross-compiler, and we know how we open DSOs.
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=no
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+	  [lt_cv_dlopen=shl_load],
+      [AC_CHECK_LIB([dld], [shl_load],
+	    [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen=dlopen],
+	  [AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+	    [AC_CHECK_LIB([svld], [dlopen],
+		  [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+	      [AC_CHECK_LIB([dld], [dld_link],
+		    [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test no = "$lt_cv_dlopen"; then
+    enable_dlopen=no
+  else
+    enable_dlopen=yes
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS=$CPPFLAGS
+    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS=$LDFLAGS
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS=$LIBS
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test yes = "$lt_cv_dlopen_self"; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+	  lt_cv_dlopen_self_static, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS=$save_CPPFLAGS
+    LDFLAGS=$save_LDFLAGS
+    LIBS=$save_LIBS
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+	 [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+	 [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+	 [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+	[Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links=nottested
+if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test no = "$hard_links"; then
+    AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+  [Define to the sub-directory where libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+  # We can hardcode non-existent directories.
+  if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+     test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+   test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+     test no = "$enable_shared"; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -z "$STRIP"; then
+  AC_MSG_RESULT([no])
+else
+  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+    old_striplib="$STRIP --strip-debug"
+    striplib="$STRIP --strip-unneeded"
+    AC_MSG_RESULT([yes])
+  else
+    case $host_os in
+    darwin*)
+      # FIXME - insert some real tests, host_os isn't really good enough
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+      ;;
+    freebsd*)
+      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+        old_striplib="$STRIP --strip-debug"
+        striplib="$STRIP --strip-unneeded"
+        AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+      fi
+      ;;
+    *)
+      AC_MSG_RESULT([no])
+      ;;
+    esac
+  fi
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x@S|@2 in
+    x)
+        ;;
+    *:)
+        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+        ;;
+    x:*)
+        eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+        ;;
+    *)
+        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+	[], [
+if test yes = "$GCC"; then
+  case $host_os in
+    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+    *) lt_awk_arg='/^libraries:/' ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+    *) lt_sed_strip_eq='s|=/|/|g' ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary...
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  # ...but if some path component already ends with the multilib dir we assume
+  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+  case "$lt_multi_os_dir; $lt_search_path_spec " in
+  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+    lt_multi_os_dir=
+    ;;
+  esac
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+    elif test -n "$lt_multi_os_dir"; then
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+  lt_foo = "";
+  lt_count = 0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo = "/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='$libname$release$shared_ext$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test ia64 = "$host_cpu"; then
+    # AIX 5 supports IA64
+    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line '#! .'.  This would cause the generated library to
+    # depend on '.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # Using Import Files as archive members, it is possible to support
+    # filename-based versioning of shared library archives on AIX. While
+    # this would work for both with and without runtime linking, it will
+    # prevent static linking of such archives. So we do filename-based
+    # shared library versioning with .so extension only, which is used
+    # when both runtime linking and shared linking is enabled.
+    # Unfortunately, runtime linking may impact performance, so we do
+    # not want this to be the default eventually. Also, we use the
+    # versioned .so libs for executables only if there is the -brtl
+    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+    # To allow for filename-based versioning support, we need to create
+    # libNAME.so.V as an archive file, containing:
+    # *) an Import File, referring to the versioned filename of the
+    #    archive as well as the shared archive member, telling the
+    #    bitwidth (32 or 64) of that shared object, and providing the
+    #    list of exported symbols of that shared object, eventually
+    #    decorated with the 'weak' keyword
+    # *) the shared object with the F_LOADONLY flag set, to really avoid
+    #    it being seen by the linker.
+    # At run time we better use the real file rather than another symlink,
+    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+    case $with_aix_soname,$aix_use_runtimelinking in
+    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    aix,yes) # traditional libtool
+      dynamic_linker='AIX unversionable lib.so'
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      ;;
+    aix,no) # traditional AIX only
+      dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      ;;
+    svr4,*) # full svr4 only
+      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,yes) # both, prefer svr4
+      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # unpreferred sharedlib libNAME.a needs extra handling
+      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,no) # both, prefer aix
+      dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+      ;;
+    esac
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='$libname$shared_ext'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl* | *,icl*)
+    # Native MSVC or ICC
+    libname_spec='$name'
+    soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+    library_names_spec='$libname.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec=$LIB
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC and ICC wrapper
+    library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$major$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[23]].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      soname_spec='$libname$release$shared_ext$major'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    if test 32 = "$HPUX_IA64_MODE"; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+    fi
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test yes = "$lt_cv_prog_gnu_ld"; then
+		version_type=linux # correct to gnu/linux during the next big refactor
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+linux*android*)
+  version_type=none # Android doesn't support versioned libraries.
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext'
+  soname_spec='$libname$release$shared_ext'
+  finish_cmds=
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  dynamic_linker='Android linker'
+  # Don't embed -rpath directories since the linker doesn't support them.
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+	 [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Ideally, we could use ldconfig to report *all* directores which are
+  # searched for libraries, however this is still not possible.  Aside from not
+  # being certain /sbin/ldconfig is available, command
+  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+  # even though it is searched at run-time.  Try to do the best guess by
+  # appending ld.so.conf contents (and includes) to the search path.
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd* | bitrig*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec=/usr/lib
+  need_lib_prefix=no
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    need_version=no
+  else
+    need_version=yes
+  fi
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+os2*)
+  libname_spec='$name'
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+  # OS/2 can only load a DLL with a base name of 8 characters or less.
+  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+    v=$($ECHO $release$versuffix | tr -d .-);
+    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+    $ECHO $n$v`$shared_ext'
+  library_names_spec='${libname}_dll.$libext'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=BEGINLIBPATH
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  postinstall_cmds='base_file=`basename \$file`~
+    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+    dldir=$destdir/`dirname \$dlpath`~
+    test -d \$dldir || mkdir -p \$dldir~
+    $install_prog $dir/$dlname \$dldir/$dlname~
+    chmod a+x \$dldir/$dlname~
+    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+    fi'
+  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+    dlpath=$dir/\$dldll~
+    $RM \$dlpath'
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test yes = "$with_gnu_ld"; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec; then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+    soname_spec='$libname$shared_ext.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=sco
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test yes = "$with_gnu_ld"; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+    [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+    [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$1"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac])
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program that can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test no = "$withval" || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return, which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD=$ac_prog
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test yes = "$with_gnu_ld"; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD=$ac_dir/$ac_prog
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test no != "$with_gnu_ld" && break
+	;;
+      *)
+	test yes != "$with_gnu_ld" && break
+	;;
+      esac
+    fi
+  done
+  IFS=$lt_save_ifs
+else
+  lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi])
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test yes != "$GCC"; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test yes = "$GCC"; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_PATH_DD
+# -----------
+# find a working dd
+m4_defun([_LT_PATH_DD],
+[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+  [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='$FILECMD -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=$FILECMD
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=$FILECMD
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=$FILECMD
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd* | bitrig*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+os2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+    [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM=$NM
+else
+  lt_nm_to_check=${ac_tool_prefix}nm
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS=$lt_save_ifs
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm=$ac_dir/$lt_tmp_nm
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+	case $build_os in
+	mingw*) lt_bad_file=conftest.nm/nofile ;;
+	*) lt_bad_file=/dev/null ;;
+	esac
+	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+	*$lt_bad_file* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break 2
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break 2
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS=$lt_save_ifs
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test no != "$lt_cv_path_NM"; then
+  NM=$lt_cv_path_NM
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols -headers"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+  AC_SUBST([DUMPBIN])
+  if test : != "$DUMPBIN"; then
+    NM=$DUMPBIN
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh;
+  # decide which one to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd=$ECHO
+  ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+  [lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*])
+if test yes != "$lt_cv_path_mainfest_tool"; then
+  MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+  test DEF = "`$SED -n dnl
+    -e '\''s/^[[	 ]]*//'\'' dnl Strip leading whitespace
+    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
+    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[	 ]].*\)*$/DEF/p'\'' dnl
+    -e q dnl                          Only consider the first "real" line
+    $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM=-lm)
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test yes = "$GCC"; then
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+	[Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test ia64 = "$host_cpu"; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  # Gets list of data symbols to import.
+  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+  # Adjust the below global symbol transforms to fixup imported variables.
+  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+  lt_c_name_lib_hook="\
+  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+else
+  # Disable hooks by default.
+  lt_cv_sys_global_symbol_to_import=
+  lt_cdecl_hook=
+  lt_c_name_hook=
+  lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function,
+    # D for any global variable and I for any imported variable.
+    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT@&t@_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data.  */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT@&t@_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
+	  LIBS=conftstm.$ac_objext
+	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+	    pipe_works=yes
+	  fi
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test yes = "$pipe_works"; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+    [Transform the output of nm into a list of symbols to manually relocate])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+    [The name lister interface])
+_LT_DECL([], [nm_file_list_spec], [1],
+    [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test yes = "$GXX"; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+	;;
+      esac
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+	# All AIX code is PIC.
+	if test ia64 = "$host_cpu"; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+	# This hack is so that the source file can tell whether it is being
+	# built for inclusion in a dll (and should export symbols for example).
+	m4_if([$1], [GCJ], [],
+	  [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly* | midnightbsd*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+	    if test ia64 != "$host_cpu"; then
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64, which still supported -KPIC.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | $SED 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd* | netbsdelf*-gnu)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC* | sunCC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test yes = "$GCC"; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      case $cc_basename in
+      nagfor*)
+        # NAG Fortran compiler
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      esac
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+	;;
+      esac
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64, which still supported -KPIC.
+      ecc*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # flang / f18. f95 an alias for gfortran or flang on Debian
+      flang* | f18* | f95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+	;;
+      nagfor*)
+	# NAG Fortran compiler
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	;;
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | $SED 5q` in
+	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  ;;
+	*Sun\ F* | *Sun*Fortran*)
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  ;;
+        *Intel*\ [[CF]]*Compiler*)
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	  ;;
+	*Portland\ Group*)
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms that do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+	[Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+	[Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+    # Without the "-l" option, or with the "-B" option, AIX nm treats
+    # weak defined symbols like other global defined symbols, whereas
+    # GNU nm marks them as "W".
+    # While the 'weak' keyword is ignored in the Export File, we need
+    # it in the Import File for the 'aix-soname' feature, so we have
+    # to replace the "-B" option with "-P" for AIX nm.
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+    ;;
+  cygwin* | mingw* | cegcc*)
+    case $cc_basename in
+    cl* | icl*)
+      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+      ;;
+    *)
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+      ;;
+    esac
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+    ;;
+  esac
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+  # as well as any symbol that contains 'd'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++ or Intel C++ Compiler.
+    if test yes != "$GCC"; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+    with_gnu_ld=yes
+    ;;
+  openbsd* | bitrig*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test yes = "$with_gnu_ld"; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test yes = "$lt_use_gnu_ld_interface"; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='$wl'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test ia64 != "$host_cpu"; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file, use it as
+	# is; otherwise, prepend EXPORTS...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+          cp $export_symbols $output_objdir/$soname.def;
+        else
+          echo EXPORTS > $output_objdir/$soname.def;
+          cat $export_symbols >> $output_objdir/$soname.def;
+        fi~
+        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      shrext_cmds=.dll
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test linux-dietlibc = "$host_os"; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test no = "$tmp_diet"
+      then
+	tmp_addflag=' $pic_flag'
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+	  tmp_sharedflag='--shared' ;;
+        nagfor*)                        # NAGFOR 5.3
+          tmp_sharedflag='-Wl,-shared' ;;
+	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | $SED 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+        if test yes = "$supports_anon_versioning"; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            echo "local: *; };" >> $output_objdir/$libname.ver~
+            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	tcc*)
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+	  ;;
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+	  if test yes = "$supports_anon_versioning"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              echo "local: *; };" >> $output_objdir/$libname.ver~
+              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test ia64 = "$host_cpu"; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
+	# Without the "-l" option, or with the "-B" option, AIX nm treats
+	# weak defined symbols like other global defined symbols, whereas
+	# GNU nm marks them as "W".
+	# While the 'weak' keyword is ignored in the Export File, we need
+	# it in the Import File for the 'aix-soname' feature, so we have
+	# to replace the "-B" option with "-P" for AIX nm.
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# have runtime linking enabled, and use it for executables.
+	# For shared libraries, we enable/disable runtime linking
+	# depending on the kind of the shared library created -
+	# when "with_aix_soname,aix_use_runtimelinking" is:
+	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "aix,yes"  lib.so          shared, rtl:yes, for executables
+	#            lib.a           static archive
+	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
+	#            lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a(lib.so.V) shared, rtl:no
+	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a           static archive
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
+	    # so we don't have lib.a shared libs to link our executables.
+	    # We have to force runtime linking in this case.
+	    aix_use_runtimelinking=yes
+	    LDFLAGS="$LDFLAGS -Wl,-brtl"
+	  fi
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+      case $with_aix_soname,$aix_use_runtimelinking in
+      aix,*) ;; # traditional, no import file
+      svr4,* | *,yes) # use import file
+	# The Import File defines what to hardcode.
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+	;;
+      esac
+
+      if test yes = "$GCC"; then
+	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`$CC -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test yes = "$aix_use_runtimelinking"; then
+	  shared_flag="$shared_flag "'$wl-G'
+	fi
+	# Need to ensure runtime linking is disabled for the traditional
+	# shared library, or the linker may eventually find shared libraries
+	# /with/ Import File - we do not want to mix them.
+	shared_flag_aix='-shared'
+	shared_flag_svr4='-shared $wl-G'
+      else
+	# not using gcc
+	if test ia64 = "$host_cpu"; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test yes = "$aix_use_runtimelinking"; then
+	    shared_flag='$wl-G'
+	  else
+	    shared_flag='$wl-bM:SRE'
+	  fi
+	  shared_flag_aix='$wl-bM:SRE'
+	  shared_flag_svr4='$wl-G'
+	fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+      else
+	if test ia64 = "$host_cpu"; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 _LT_SYS_MODULE_PATH_AIX([$1])
+	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+	  if test yes = "$with_gnu_ld"; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  fi
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+	  # -brtl affects multiple linker settings, -berok does not and is overridden later
+	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+	  if test svr4 != "$with_aix_soname"; then
+	    # This is similar to how AIX traditionally builds its shared libraries.
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+	  fi
+	  if test aix != "$with_aix_soname"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+	  else
+	    # used by -dlpreopen to get the symbols
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+	  fi
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++ or Intel C++ Compiler.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl* | icl*)
+	# Native MSVC or ICC
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	_LT_TAGVAR(always_export_symbols, $1)=yes
+	_LT_TAGVAR(file_list_spec, $1)='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+            cp "$export_symbols" "$output_objdir/$soname.def";
+            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+          else
+            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+          fi~
+          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+          linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+	_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+	_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+          lt_tool_outputfile="@TOOL_OUTPUT@"~
+          case $lt_outputfile in
+            *.exe|*.EXE) ;;
+            *)
+              lt_outputfile=$lt_outputfile.exe
+              lt_tool_outputfile=$lt_tool_outputfile.exe
+              ;;
+          esac~
+          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+            $RM "$lt_outputfile.manifest";
+          fi'
+	;;
+      *)
+	# Assume MSVC and ICC wrapper
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	# FIXME: Should let the user specify the lib program.
+	_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly* | midnightbsd*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+      ;;
+
+    hpux10*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test no = "$with_gnu_ld"; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	m4_if($1, [], [
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  _LT_LINKER_OPTION([if $CC understands -b],
+	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+	  ;;
+	esac
+      fi
+      if test no = "$with_gnu_ld"; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	*)
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+	# This should be the same for all languages, so no per-tag cache variable.
+	AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+	  [lt_cv_irix_exported_symbol],
+	  [save_LDFLAGS=$LDFLAGS
+	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+	   AC_LINK_IFELSE(
+	     [AC_LANG_SOURCE(
+	        [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+			      [C++], [[int foo (void) { return 0; }]],
+			      [Fortran 77], [[
+      subroutine foo
+      end]],
+			      [Fortran], [[
+      subroutine foo
+      end]])])],
+	      [lt_cv_irix_exported_symbol=yes],
+	      [lt_cv_irix_exported_symbol=no])
+           LDFLAGS=$save_LDFLAGS])
+	if test yes = "$lt_cv_irix_exported_symbol"; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+	fi
+	_LT_TAGVAR(link_all_deplibs, $1)=no
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    linux*)
+      case $cc_basename in
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	;;
+      esac
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd* | bitrig*)
+      if test -f /usr/libexec/ld.so; then
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+	else
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	fi
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      shrext_cmds=.dll
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
+      ;;
+
+    osf3*)
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test yes = "$GCC"; then
+	wlarc='$wl'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='$wl'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands '-z linker_flag'.  GCC discards it without '$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test yes = "$GCC"; then
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+	else
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test sequent = "$host_vendor"; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We CANNOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test sni = "$host_vendor"; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test yes,yes = "$GCC,$enable_shared"; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+	[$RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+	  _LT_TAGVAR(allow_undefined_flag, $1)=
+	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+	  then
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	  else
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  fi
+	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+	])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting $shlibpath_var if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+    [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC=$CC
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report what library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test no = "$can_build_shared" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test yes = "$enable_shared" && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test ia64 != "$host_cpu"; then
+      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+      yes,aix,yes) ;;			# shared object as lib.so file only
+      yes,svr4,*) ;;			# shared object as lib.so archive member only
+      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+      esac
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test yes = "$enable_shared" || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC=$lt_save_CC
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test no != "$CXX" &&
+    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+    (test g++ != "$CXX"))); then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test yes = "$GXX"; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test yes = "$GXX"; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test yes = "$with_gnu_ld"; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='$wl'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test ia64 = "$host_cpu"; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # have runtime linking enabled, and use it for executables.
+          # For shared libraries, we enable/disable runtime linking
+          # depending on the kind of the shared library created -
+          # when "with_aix_soname,aix_use_runtimelinking" is:
+          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "aix,yes"  lib.so          shared, rtl:yes, for executables
+          #            lib.a           static archive
+          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+          #            lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a(lib.so.V) shared, rtl:no
+          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a           static archive
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
+	      # so we don't have lib.a shared libs to link our executables.
+	      # We have to force runtime linking in this case.
+	      aix_use_runtimelinking=yes
+	      LDFLAGS="$LDFLAGS -Wl,-brtl"
+	    fi
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+        case $with_aix_soname,$aix_use_runtimelinking in
+        aix,*) ;;	# no import file
+        svr4,* | *,yes) # use import file
+          # The Import File defines what to hardcode.
+          _LT_TAGVAR(hardcode_direct, $1)=no
+          _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+          ;;
+        esac
+
+        if test yes = "$GXX"; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`$CC -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test yes = "$aix_use_runtimelinking"; then
+	    shared_flag=$shared_flag' $wl-G'
+	  fi
+	  # Need to ensure runtime linking is disabled for the traditional
+	  # shared library, or the linker may eventually find shared libraries
+	  # /with/ Import File - we do not want to mix them.
+	  shared_flag_aix='-shared'
+	  shared_flag_svr4='-shared $wl-G'
+        else
+          # not using gcc
+          if test ia64 = "$host_cpu"; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test yes = "$aix_use_runtimelinking"; then
+	      shared_flag='$wl-G'
+	    else
+	      shared_flag='$wl-bM:SRE'
+	    fi
+	    shared_flag_aix='$wl-bM:SRE'
+	    shared_flag_svr4='$wl-G'
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          # The "-G" linker flag allows undefined symbols.
+          _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX([$1])
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+        else
+          if test ia64 = "$host_cpu"; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    _LT_SYS_MODULE_PATH_AIX([$1])
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+	    _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+	    if test yes = "$with_gnu_ld"; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    fi
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+	    # -brtl affects multiple linker settings, -berok does not and is overridden later
+	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+	    if test svr4 != "$with_aix_soname"; then
+	      # This is similar to how AIX traditionally builds its shared
+	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+	    fi
+	    if test aix != "$with_aix_soname"; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+	    else
+	      # used by -dlpreopen to get the symbols
+	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+	    fi
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+	case $GXX,$cc_basename in
+	,cl* | no,cl* | ,icl* | no,icl*)
+	  # Native MSVC or ICC
+	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+	  # no search path for DLLs.
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  _LT_TAGVAR(always_export_symbols, $1)=yes
+	  _LT_TAGVAR(file_list_spec, $1)='@'
+	  # Tell ltmain to make .lib files, not .a files.
+	  libext=lib
+	  # Tell ltmain to make .dll files, not .so files.
+	  shrext_cmds=.dll
+	  # FIXME: Setting linknames here is a bad hack.
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+              cp "$export_symbols" "$output_objdir/$soname.def";
+              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+            else
+              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+            fi~
+            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+            linknames='
+	  # The linker will not automatically build a static lib if we build a DLL.
+	  # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	  # Don't use ranlib
+	  _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+	  _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+            lt_tool_outputfile="@TOOL_OUTPUT@"~
+            case $lt_outputfile in
+              *.exe|*.EXE) ;;
+              *)
+                lt_outputfile=$lt_outputfile.exe
+                lt_tool_outputfile=$lt_tool_outputfile.exe
+                ;;
+            esac~
+            func_to_tool_file "$lt_outputfile"~
+            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+              $RM "$lt_outputfile.manifest";
+            fi'
+	  ;;
+	*)
+	  # g++
+	  # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+	  # as there is no search path for DLLs.
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  _LT_TAGVAR(always_export_symbols, $1)=no
+	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	    # If the export-symbols file already is a .def file, use it as
+	    # is; otherwise, prepend EXPORTS...
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+              cp $export_symbols $output_objdir/$soname.def;
+            else
+              echo EXPORTS > $output_objdir/$soname.def;
+              cat $export_symbols >> $output_objdir/$soname.def;
+            fi~
+            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	  ;;
+	esac
+	;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+	;;
+
+      os2*)
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	shrext_cmds=.dll
+	_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	  emximp -o $lib $output_objdir/$libname.def'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+	  prefix_cmds="$SED"~
+	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	    prefix_cmds="$prefix_cmds -e 1d";
+	  fi~
+	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	  emximp -o $lib $output_objdir/$libname.def'
+	_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	_LT_TAGVAR(file_list_spec, $1)='@'
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly* | midnightbsd*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test yes = "$GXX"; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test no = "$with_gnu_ld"; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+          *)
+	    if test yes = "$GXX"; then
+	      if test no = "$with_gnu_ld"; then
+	        case $host_cpu in
+	          hppa*64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test yes = "$GXX"; then
+	      if test no = "$with_gnu_ld"; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	      else
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+	      fi
+	    fi
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+	    ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+                $RANLIB $oldlib'
+	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 and above use weak symbols
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+	    ;;
+	  xl* | mpixl* | bgxl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	    if test yes = "$supports_anon_versioning"; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+                echo "local: *; };" >> $output_objdir/$libname.ver~
+                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | $SED 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='func_echo_all'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+	;;
+
+      openbsd* | bitrig*)
+	if test -f /usr/libexec/ld.so; then
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=func_echo_all
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+		;;
+	      *)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+                  echo "-hidden">> $lib.exp~
+                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+                  $RM $lib.exp'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+		;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+	  *)
+	    if test yes,no = "$GXX,$with_gnu_ld"; then
+	      _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+	      case $host in
+	        osf3*)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+		  ;;
+	        *)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC* | sunCC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	    case $host_os in
+	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands '-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+	    output_verbose_link_cmd='func_echo_all'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test yes,no = "$GXX,$with_gnu_ld"; then
+	      _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	      else
+	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
+	        # platform.
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	      fi
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+	      case $host_os in
+		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+		*)
+		  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We CANNOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+	_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+	_LT_TAGVAR(link_all_deplibs, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+              '"$_LT_TAGVAR(old_archive_cmds, $1)"
+	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+              '"$_LT_TAGVAR(reload_cmds, $1)"
+	    ;;
+	  *)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)=$GXX
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+  case @S|@2 in
+  .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+  *)  func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
+  esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $prev$p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test x-L = "$p" ||
+          test x-R = "$p"; then
+	 prev=$p
+	 continue
+       fi
+
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
+       if test no = "$pre_test_object_deps_done"; then
+	 case $prev in
+	 -L | -R)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+	   else
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+	   _LT_TAGVAR(postdeps, $1)=$prev$p
+	 else
+	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+	 fi
+       fi
+       prev=
+       ;;
+
+    *.lto.$objext) ;; # Ignore GCC LTO objects
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test no = "$pre_test_object_deps_done"; then
+	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+	   _LT_TAGVAR(predep_objects, $1)=$p
+	 else
+	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+	   _LT_TAGVAR(postdep_objects, $1)=$p
+	 else
+	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test no = "$F77"; then
+  _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_F77"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${F77-"f77"}
+  CFLAGS=$FFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test no = "$can_build_shared" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test yes = "$enable_shared" && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test ia64 != "$host_cpu"; then
+	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+	  yes,aix,yes) ;;		# shared object as lib.so file only
+	  yes,svr4,*) ;;		# shared object as lib.so archive member only
+	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+	  esac
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test yes = "$enable_shared" || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)=$G77
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_F77"
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test no = "$FC"; then
+  _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_FC"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${FC-"f95"}
+  CFLAGS=$FCFLAGS
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test no = "$can_build_shared" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test yes = "$enable_shared" && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test ia64 != "$host_cpu"; then
+	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+	  yes,aix,yes) ;;		# shared object as lib.so file only
+	  yes,svr4,*) ;;		# shared object as lib.so archive member only
+	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+	  esac
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test yes = "$enable_shared" || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_FC"
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=$lt_simple_compile_test_code
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_FILECMD
+# ----------------
+# Check for a file(cmd) program that can be used to detect file type and magic
+m4_defun([_LT_DECL_FILECMD],
+[AC_CHECK_TOOL([FILECMD], [file], [:])
+_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+])# _LD_DECL_FILECMD
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f "$lt_ac_sed" && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test 10 -lt "$lt_ac_count" && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test "$lt_ac_count" -gt "$lt_ac_max"; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+         [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+         [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
+
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 8 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option '$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+		      [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+		   [_LT_ENABLE_FAST_INSTALL])
+  _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+		   [_LT_WITH_AIX_SONAME([aix])])
+  ])
+])# _LT_SET_OPTIONS
+
+
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the 'shared' and
+# 'disable-shared' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+	[Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the 'static' and
+# 'disable-static' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+	[Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the 'fast-install'
+# and 'disable-fast-install' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+	 [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'.  If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+  AC_MSG_CHECKING([which variant of shared library versioning to provide])
+  AC_ARG_WITH([aix-soname],
+    [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+      [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+    [case $withval in
+    aix|svr4|both)
+      ;;
+    *)
+      AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+      ;;
+    esac
+    lt_cv_with_aix_soname=$with_aix_soname],
+    [AC_CACHE_VAL([lt_cv_with_aix_soname],
+      [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+    with_aix_soname=$lt_cv_with_aix_soname])
+  AC_MSG_RESULT([$with_aix_soname])
+  if test aix != "$with_aix_soname"; then
+    # For the AIX way of multilib, we name the shared archive member
+    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+    if test 64 = "${OBJECT_MODE-32}"; then
+      shared_archive_member_spec=shr_64
+    else
+      shared_archive_member_spec=shr
+    fi
+  fi
+  ;;
+*)
+  with_aix_soname=aix
+  ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+    [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+# LT_INIT options.
+# MODE is either 'yes' or 'no'.  If omitted, it defaults to 'both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for lt_pkg in $withval; do
+	IFS=$lt_save_ifs
+	if test "X$lt_pkg" = "X$lt_p"; then
+	  pic_mode=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [pic_mode=m4_default([$1], [default])])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+		 [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+		 [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+		 [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+		 [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+		 [m4_define([_LTDL_TYPE], [convenience])])
+
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59, which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+	     [m4_foreach([_Lt_suffix],
+		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+		 [lt_append([$1], [$2], [$3])$4],
+		 [$5])],
+	  [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+	[$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
+
+# ltversion.m4 -- version numbers			-*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+#   Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 4245 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.7])
+m4_define([LT_PACKAGE_REVISION], [2.4.7])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.7'
+macro_revision='2.4.7'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
+
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
+
+# pkg.m4 - Macros to locate and use pkg-config.   -*- Autoconf -*-
+# serial 12 (pkg-config-0.29.2)
+
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.2])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurrence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes ],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $2])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+                $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else
+                $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+        m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+        AC_MSG_RESULT([no])
+        m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+        $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+        $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+        $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------
+dnl
+dnl Prepare a "--with-" configure option using the lowercase
+dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
+dnl PKG_CHECK_MODULES in a single macro.
+AC_DEFUN([PKG_WITH_MODULES],
+[
+m4_pushdef([with_arg], m4_tolower([$1]))
+
+m4_pushdef([description],
+           [m4_default([$5], [build with ]with_arg[ support])])
+
+m4_pushdef([def_arg], [m4_default([$6], [auto])])
+m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
+m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
+
+m4_case(def_arg,
+            [yes],[m4_pushdef([with_without], [--without-]with_arg)],
+            [m4_pushdef([with_without],[--with-]with_arg)])
+
+AC_ARG_WITH(with_arg,
+     AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
+    [AS_TR_SH([with_]with_arg)=def_arg])
+
+AS_CASE([$AS_TR_SH([with_]with_arg)],
+            [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
+            [auto],[PKG_CHECK_MODULES([$1],[$2],
+                                        [m4_n([def_action_if_found]) $3],
+                                        [m4_n([def_action_if_not_found]) $4])])
+
+m4_popdef([with_arg])
+m4_popdef([description])
+m4_popdef([def_arg])
+
+])dnl PKG_WITH_MODULES
+
+dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl -----------------------------------------------
+dnl
+dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
+dnl check._[VARIABLE-PREFIX] is exported as make variable.
+AC_DEFUN([PKG_HAVE_WITH_MODULES],
+[
+PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
+
+AM_CONDITIONAL([HAVE_][$1],
+               [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
+])dnl PKG_HAVE_WITH_MODULES
+
+dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------------------
+dnl
+dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
+dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
+dnl and preprocessor variable.
+AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
+[
+PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
+
+AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
+        [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
+])dnl PKG_HAVE_DEFINE_WITH_MODULES
+
+# Copyright (C) 2002-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.16'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.16.5], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.16.5])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  AS_CASE([$CONFIG_FILES],
+          [*\'*], [eval set x "$CONFIG_FILES"],
+          [*], [set x $CONFIG_FILES])
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`AS_DIRNAME(["$am_mf"])`
+    am_filepart=`AS_BASENAME(["$am_mf"])`
+    AM_RUN_LOG([cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles]) || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE="gmake" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).])
+  fi
+  AS_UNSET([am_dirpart])
+  AS_UNSET([am_filepart])
+  AS_UNSET([am_mf])
+  AS_UNSET([am_rc])
+  rm -f conftest-deps.mk
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+m4_ifdef([_$0_ALREADY_INIT],
+  [m4_fatal([$0 expanded multiple times
+]m4_defn([_$0_ALREADY_INIT]))],
+  [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES([CC])],
+		  [m4_define([AC_PROG_CC],
+			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES([CXX])],
+		  [m4_define([AC_PROG_CXX],
+			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES([OBJC])],
+		  [m4_define([AC_PROG_OBJC],
+			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+		  [_AM_DEPENDENCIES([OBJCXX])],
+		  [m4_define([AC_PROG_OBJCXX],
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+# Variables for tags utilities; see am/tags.am
+if test -z "$CTAGS"; then
+  CTAGS=ctags
+fi
+AC_SUBST([CTAGS])
+if test -z "$ETAGS"; then
+  ETAGS=etags
+fi
+AC_SUBST([ETAGS])
+if test -z "$CSCOPE"; then
+  CSCOPE=cscope
+fi
+AC_SUBST([CSCOPE])
+
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+      am_maintainer_other[ make rules and dependencies not useful
+      (and sometimes confusing) to the casual installer])],
+    [USE_MAINTAINER_MODE=$enableval],
+    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+      ['0:this is the am__doit target'],
+      [AS_CASE([$s],
+          [BSD], [am__include='.include' am__quote='"'],
+          [am__include='include' am__quote=''])])
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acinclude.m4])
diff --git a/android/Makefile.am b/android/Makefile.am
index 3099101..e3756e8 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -96,6 +96,7 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hal-log.h \
 					android/hal-ipc.h android/hal-ipc.c \
 					android/hal-utils.h android/hal-utils.c
+android_bluetooth_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
 android_bluetooth_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android
 android_bluetooth_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
 					-no-undefined
@@ -195,6 +196,7 @@ android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
 					android/hardware/audio_effect.h \
 					android/hardware/hardware.h \
 					android/system/audio.h
+android_audio_a2dp_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
 android_audio_a2dp_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android \
 					$(SBC_CFLAGS)
 android_audio_a2dp_default_la_LIBADD = $(SBC_LIBS) -lrt
@@ -212,6 +214,7 @@ android_audio_sco_default_la_SOURCES = android/hal-log.h \
 					android/audio_utils/resampler.c \
 					android/audio_utils/resampler.h \
 					android/system/audio.h
+android_audio_sco_default_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
 android_audio_sco_default_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/android
 android_audio_sco_default_la_LIBADD = $(SPEEXDSP_LIBS) -lrt
 android_audio_sco_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
diff --git a/android/avctp.c b/android/avctp.c
index 37b4cec..d8104a7 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -905,10 +905,8 @@ send:
 failed:
 	DBG("AVCTP Browsing: disconnected");
 
-	if (session->browsing) {
-		avctp_channel_destroy(session->browsing);
-		session->browsing = NULL;
-	}
+	avctp_channel_destroy(session->browsing);
+	session->browsing = NULL;
 
 	return FALSE;
 }
diff --git a/android/avdtp.c b/android/avdtp.c
index a261a8e..e046685 100644
--- a/android/avdtp.c
+++ b/android/avdtp.c
@@ -2130,8 +2130,10 @@ struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version,
 		return NULL;
 	}
 
-	if (set_priority(new_fd, 6) < 0)
+	if (set_priority(new_fd, 6) < 0) {
+		close(new_fd);
 		return NULL;
+	}
 
 	session = g_new0(struct avdtp, 1);
 	session->io = g_io_channel_unix_new(new_fd);
diff --git a/android/gatt.c b/android/gatt.c
index e8ba5aa..89fcdb1 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -3730,7 +3730,11 @@ static void handle_client_register_for_notification(const void *buf,
 
 	notification = new0(struct notification_data, 1);
 
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
+_Pragma("GCC diagnostic ignored \"-Wstringop-overflow\"")
 	memcpy(&notification->ch, &cmd->char_id, sizeof(notification->ch));
+_Pragma("GCC diagnostic pop")
 	memcpy(&notification->service, &cmd->srvc_id,
 						sizeof(notification->service));
 	notification->conn = conn;
diff --git a/android/hal-audio-sbc.c b/android/hal-audio-sbc.c
index 9c64d33..6f7788a 100644
--- a/android/hal-audio-sbc.c
+++ b/android/hal-audio-sbc.c
@@ -257,7 +257,7 @@ static bool sbc_codec_init(struct audio_preset *preset, uint16_t payload_len,
 		return false;
 	}
 
-	sbc_data = calloc(sizeof(struct sbc_data), 1);
+	sbc_data = calloc(1, sizeof(struct sbc_data));
 	if (!sbc_data)
 		return false;
 
diff --git a/android/hal-audio.c b/android/hal-audio.c
index d37d609..f3d9b40 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -1618,6 +1618,7 @@ static struct hw_module_methods_t hal_module_methods = {
 	.open = audio_open,
 };
 
+__attribute__ ((visibility("default")))
 struct audio_module HAL_MODULE_INFO_SYM = {
 	.common = {
 		.tag = HARDWARE_MODULE_TAG,
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index d4442e6..7d1e5ac 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -1117,6 +1117,7 @@ static struct hw_module_methods_t bluetooth_module_methods = {
 	.open = open_bluetooth,
 };
 
+__attribute__ ((visibility("default")))
 struct hw_module_t HAL_MODULE_INFO_SYM = {
 	.tag = HARDWARE_MODULE_TAG,
 	.version_major = 1,
diff --git a/android/hal-sco.c b/android/hal-sco.c
index d7c08a6..3d66ad3 100644
--- a/android/hal-sco.c
+++ b/android/hal-sco.c
@@ -1507,6 +1507,7 @@ static struct hw_module_methods_t hal_module_methods = {
 	.open = sco_open,
 };
 
+__attribute__ ((visibility("default")))
 struct audio_module HAL_MODULE_INFO_SYM = {
 	.common = {
 		.tag = HARDWARE_MODULE_TAG,
diff --git a/android/handsfree.c b/android/handsfree.c
index 2365356..7b803fa 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -1243,15 +1243,22 @@ static void at_cmd_cind(struct hfp_context *result, enum hfp_gw_cmd_type type,
 		}
 
 		buf = g_malloc(len);
-
-		ptr = buf + sprintf(buf, "+CIND:");
+		if (sprintf(buf, "+CIND:") != strlen("+CIND:")) {
+			g_free(buf);
+			break;
+		}
+		ptr = buf + strlen("+CIND:");
 
 		for (i = 0; i < IND_COUNT; i++) {
-			ptr += sprintf(ptr, "(\"%s\",(%d%c%d)),",
+			int printed;
+			printed = sprintf(ptr, "(\"%s\",(%d%c%d)),",
 					dev->inds[i].name,
 					dev->inds[i].min,
 					dev->inds[i].max == 1 ? ',' : '-',
 					dev->inds[i].max);
+			if (printed < 0)
+				goto fail;
+			ptr += printed;
 		}
 
 		ptr--;
@@ -1273,6 +1280,7 @@ static void at_cmd_cind(struct hfp_context *result, enum hfp_gw_cmd_type type,
 		break;
 	}
 
+fail:
 	hfp_gw_send_result(dev->gw, HFP_RESULT_ERROR);
 
 	if (dev->state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED)
diff --git a/android/hidhost.c b/android/hidhost.c
index b4e5c52..598bec3 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -796,7 +796,7 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
 		if (dev->hog) {
 			bt_hid_notify_state(dev,
 						HAL_HIDHOST_STATE_DISCONNECTED);
-			bt_hog_detach(dev->hog);
+			bt_hog_detach(dev->hog, true);
 			return;
 		}
 		goto fail;
@@ -808,7 +808,8 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
 	if (!dev->hog) {
 		/* TODO: Get device details and primary */
 		dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
-					dev->product, dev->version, NULL);
+					dev->product, dev->version,
+					BT_UHID_NONE, NULL);
 		if (!dev->hog) {
 			error("HoG: unable to create session");
 			goto fail;
diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 780e1dc..68e2ad1 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <poll.h>
+#include <limits.h>
 
 #include <sys/socket.h>
 #include <sys/types.h>
diff --git a/android/sco-ipc-api.txt b/android/sco-ipc-api.txt
deleted file mode 100644
index 27d5ef2..0000000
--- a/android/sco-ipc-api.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-Bluetooth SCO Audio Plugin
-==========================
-
-The SCO Audio Plugin communicate through abstract socket name
-"\0bluez_sco_socket".
-
-	.----SCO----.                             .--Android--.
-	|   Plugin  |                             |   Daemon  |
-	|           |          Command            |           |
-	|           | --------------------------> |           |
-	|           |                             |           |
-	|           | <-------------------------- |           |
-	|           |          Response           |           |
-	|           |                             |           |
-	|           |                             |           |
-	|           |                             |           |
-	'-----------'                             '-----------'
-
-
-	SCO HAL                               Daemon
-	----------------------------------------------------
-
-	call get_fd()                    --> Get SCO socket fd
-	return get_fd()                  <-- Return SCO socket fd and mtu
-
-SCO Audio Service (ID 0)
-========================
-
-	Opcode 0x00 - Error response
-
-		Response parameters: Status (1 octet)
-
-	Opcode 0x01 - Get SCO fd command
-
-		Command parameters: Remote address (6 octets)
-		Response parameters: MTU (2 octets)
-				     File descriptor (inline)
diff --git a/android/socket-api.txt b/android/socket-api.txt
deleted file mode 100644
index 9f622f9..0000000
--- a/android/socket-api.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-Android Socket protocol for Bluetooth
-=====================================
-
-Since Android switched from BlueZ (where sockets where nicely implemented) to
-Bluedroid user space stack there is a need to emulate bluetooth sockets.
-
-Android Bluetooth Socket Hardware Abstraction Layer (HAL) bt_sock.h has
-only 2 functions:
-
-static btsock_interface_t sock_if = {
-	sizeof(sock_if),
-	sock_listen,
-	sock_connect
-};
-
-with following parameters:
-
-sock_listen(btsock_type_t type, const char *service_name,
-		const uint8_t *uuid, int chan, int *sock_fd, int flags)
-sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
-		const uint8_t *uuid, int chan, int *sock_fd, int flags)
-
-socket type RFCOMM is only supported at the moment. uuid and channel used
-to decide where to connect.
-
-sockfd is used to return socket fd to Android framework. It is used to inform
-framework when remote device is connected.
-
-listen()
-========
-
-Listens on RFCOMM socket, socket channel is either found based on uuid or
-channel parameter used directly. Returns sock_fd to Android framework.
-
-Through this sock_fd channel number as (int) needs to be written right after
-listen() succeeds.
-
-When remote device is connected to this socket we shall send accept signal
-through sock_fd
-
-connect()
-=========
-
-Connects to remote device specified in bd_addr parameter. Socket channel is
-found by SDP search of remote device by supplied uuid. Returns sock_fd to
-Android framework.
-
-Through this sock_fd channel number as (int) needs to be written right after
-connects() succeeds.
-
-When remote device is connected to this socket we shall send connect signal
-through sock_fd
-
-The format of connect/accept signal is shown below:
-
-struct hal_sock_connect_signal {
-	short   size;
-	uint8_t bdaddr[6];
-	int     channel;
-	int     status;
-} __attribute__((packed));
diff --git a/android/system-emulator.c b/android/system-emulator.c
index bf1499d..50bb088 100644
--- a/android/system-emulator.c
+++ b/android/system-emulator.c
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <string.h>
+#include <limits.h>
 #include <libgen.h>
 #include <poll.h>
 #include <sys/wait.h>
diff --git a/android/tester-main.c b/android/tester-main.c
index 317c1de..361c519 100644
--- a/android/tester-main.c
+++ b/android/tester-main.c
@@ -7,6 +7,7 @@
 #define _GNU_SOURCE
 #include <stdbool.h>
 #include <unistd.h>
+#include <limits.h>
 #include <libgen.h>
 
 #include <sys/un.h>
diff --git a/attrib/gatt.c b/attrib/gatt.c
index b496dd1..3cedae9 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -1076,10 +1076,12 @@ static void desc_discovered_cb(guint8 status, const guint8 *ipdu,
 	att_data_list_free(list);
 
 	/*
-	 * If last handle is lower from previous start handle then it is smth
-	 * wrong. Let's stop search, otherwise we might enter infinite loop.
+	 * If last handle is lower from previous start handle or if iterating
+	 * to the next handle from the last possible offset would overflow, then
+	 * something is wrong. Let's stop search, otherwise we might enter
+	 * infinite loop.
 	 */
-	if (last < dd->start) {
+	if (last < dd->start || last == G_MAXUINT16) {
 		err = ATT_ECODE_UNLIKELY;
 		goto done;
 	}
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 041b9d2..1795cd3 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -21,17 +21,23 @@
 #include <glib.h>
 
 #include "lib/bluetooth.h"
+#include "lib/uuid.h"
 
 #include "btio/btio.h"
 #include "src/log.h"
 #include "src/shared/util.h"
 #include "src/shared/att.h"
+#include "src/shared/gatt-helpers.h"
 #include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "attrib/att.h"
 #include "attrib/gattrib.h"
 
 struct _GAttrib {
 	int ref_count;
 	struct bt_att *att;
+	struct bt_gatt_client *client;
 	GIOChannel *io;
 	GDestroyNotify destroy;
 	gpointer destroy_user_data;
@@ -145,6 +151,7 @@ void g_attrib_unref(GAttrib *attrib)
 	if (attrib->destroy)
 		attrib->destroy(attrib->destroy_user_data);
 
+	bt_gatt_client_unref(attrib->client);
 	bt_att_unref(attrib->att);
 
 	queue_destroy(attrib->callbacks, attrib_callbacks_destroy);
@@ -230,9 +237,9 @@ static void attrib_callback_result(uint8_t opcode, const void *pdu,
 	free(buf);
 }
 
-static void attrib_callback_notify(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void attrib_callback_notify(struct bt_att_chan *chan, uint16_t mtu,
+					uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data)
 {
 	uint8_t *buf;
 	struct attrib_callbacks *cb = user_data;
@@ -338,6 +345,20 @@ gboolean g_attrib_cancel_all(GAttrib *attrib)
 	return TRUE;
 }
 
+static void client_notify_cb(uint16_t value_handle, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	uint8_t *buf = newa(uint8_t, length + 2);
+
+	put_le16(value_handle, buf);
+
+	if (length)
+		memcpy(buf + 2, value, length);
+
+	attrib_callback_notify(NULL, 0, ATT_OP_HANDLE_NOTIFY, buf, length + 2,
+							user_data);
+}
+
 guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
 				GAttribNotifyFunc func, gpointer user_data,
 				GDestroyNotify notify)
@@ -359,6 +380,16 @@ guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
 		queue_push_head(attrib->callbacks, cb);
 	}
 
+	if (opcode == ATT_OP_HANDLE_NOTIFY && attrib->client) {
+		unsigned int id;
+
+		id = bt_gatt_client_register_notify(attrib->client, handle,
+						NULL, client_notify_cb, cb,
+						attrib_callbacks_remove);
+		if (id)
+			return id;
+	}
+
 	if (opcode == GATTRIB_ALL_REQS)
 		opcode = BT_ATT_ALL_REQUESTS;
 
@@ -410,6 +441,21 @@ gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
 	return bt_att_set_mtu(attrib->att, mtu);
 }
 
+gboolean g_attrib_attach_client(GAttrib *attrib, struct bt_gatt_client *client)
+{
+	if (!attrib || !client)
+		return FALSE;
+
+	if (attrib->client)
+		bt_gatt_client_unref(attrib->client);
+
+	attrib->client = bt_gatt_client_clone(client);
+	if (!attrib->client)
+		return FALSE;
+
+	return TRUE;
+}
+
 gboolean g_attrib_unregister(GAttrib *attrib, guint id)
 {
 	if (!attrib)
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index c2877d7..0111bfc 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -19,6 +19,7 @@ extern "C" {
 #define GATTRIB_ALL_HANDLES 0x0000
 
 struct bt_att;  /* Forward declaration for compatibility */
+struct bt_gatt_client;  /* Forward declaration for compatibility */
 struct _GAttrib;
 typedef struct _GAttrib GAttrib;
 
@@ -53,6 +54,7 @@ guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
 
 uint8_t *g_attrib_get_buffer(GAttrib *attrib, size_t *len);
 gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu);
+gboolean g_attrib_attach_client(GAttrib *attrib, struct bt_gatt_client *client);
 
 gboolean g_attrib_unregister(GAttrib *attrib, guint id);
 gboolean g_attrib_unregister_all(GAttrib *attrib);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 6a0ddfa..4309d20 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -454,26 +454,26 @@ static gboolean parse_uuid(const char *key, const char *value,
 	return TRUE;
 }
 
-static GOptionEntry primary_char_options[] = {
+static const GOptionEntry primary_char_options[] = {
 	{ "start", 's' , 0, G_OPTION_ARG_INT, &opt_start,
-		"Starting handle(optional)", "0x0001" },
+		"Starting handle (optional)", "0x0001" },
 	{ "end", 'e' , 0, G_OPTION_ARG_INT, &opt_end,
-		"Ending handle(optional)", "0xffff" },
+		"Ending handle (optional)", "0xffff" },
 	{ "uuid", 'u', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
-		parse_uuid, "UUID16 or UUID128(optional)", "0x1801"},
+		parse_uuid, "UUID16 or UUID128 (optional)", "0x1801"},
 	{ NULL },
 };
 
-static GOptionEntry char_rw_options[] = {
+static const GOptionEntry char_rw_options[] = {
 	{ "handle", 'a' , 0, G_OPTION_ARG_INT, &opt_handle,
-		"Read/Write characteristic by handle(required)", "0x0001" },
+		"Read/Write characteristic by handle (required)", "0x0001" },
 	{ "value", 'n' , 0, G_OPTION_ARG_STRING, &opt_value,
 		"Write characteristic value (required for write operation)",
 		"0x0001" },
 	{NULL},
 };
 
-static GOptionEntry gatt_options[] = {
+static const GOptionEntry gatt_options[] = {
 	{ "primary", 0, 0, G_OPTION_ARG_NONE, &opt_primary,
 		"Primary Service Discovery", NULL },
 	{ "characteristics", 0, 0, G_OPTION_ARG_NONE, &opt_characteristics,
@@ -494,7 +494,7 @@ static GOptionEntry gatt_options[] = {
 	{ NULL },
 };
 
-static GOptionEntry options[] = {
+static const GOptionEntry options[] = {
 	{ "adapter", 'i', 0, G_OPTION_ARG_STRING, &opt_src,
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 171b957..c0262e8 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -760,7 +760,7 @@ static void cmd_mtu(int argcp, char **argvp)
 	gatt_exchange_mtu(attrib, opt_mtu, exchange_mtu_cb, NULL);
 }
 
-static struct {
+static const struct {
 	const char *cmd;
 	void (*func)(int argcp, char **argvp);
 	const char *params;
diff --git a/bootstrap b/bootstrap
deleted file mode 100755
index 91756f9..0000000
--- a/bootstrap
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-aclocal && \
-    autoheader && \
-	libtoolize --automake --copy --force && \
-	    automake --add-missing --copy && \
-		autoconf
diff --git a/bootstrap-configure b/bootstrap-configure
deleted file mode 100755
index 8172840..0000000
--- a/bootstrap-configure
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-
-if [ -f config.status ]; then
-	make maintainer-clean
-fi
-
-./bootstrap && \
-    ./configure --enable-maintainer-mode \
-		--enable-debug \
-		--prefix=/usr \
-		--mandir=/usr/share/man \
-		--sysconfdir=/etc \
-		--localstatedir=/var \
-		--enable-tools \
-		--enable-manpages \
-		--enable-backtrace \
-		--enable-testing \
-		--enable-experimental \
-		--enable-deprecated \
-		--enable-nfc \
-		--enable-sap \
-		--enable-health \
-		--enable-android \
-		--enable-sixaxis \
-		--enable-hid2hci \
-		--enable-midi \
-		--enable-mesh \
-		--enable-btpclient \
-		--enable-logger \
-		--enable-pie \
-		--enable-asan \
-		--enable-lsan \
-		--enable-ubsan \
-		--enable-cups \
-		--enable-library \
-		--enable-admin \
-		--disable-datafiles $*
diff --git a/btio/btio.c b/btio/btio.c
index 1ad4272..2d277e4 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -15,6 +16,7 @@
 
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include <errno.h>
 #include <poll.h>
@@ -69,6 +71,10 @@ struct set_opts {
 	uint32_t priority;
 	uint16_t voice;
 	struct bt_iso_qos qos;
+	struct bt_iso_base base;
+	uint8_t bc_sid;
+	uint8_t bc_num_bis;
+	uint8_t bc_bis[ISO_MAX_NUM_BIS];
 };
 
 struct connect {
@@ -768,22 +774,53 @@ static int sco_bind(int sock, const bdaddr_t *src, GError **err)
 	return 0;
 }
 
-static int iso_bind(int sock, const bdaddr_t *src, uint8_t src_type,
-							GError **err)
+static int iso_bind(int sock, bool server, const bdaddr_t *src,
+					uint8_t src_type, const bdaddr_t *dst,
+					uint8_t dst_type, uint8_t bc_sid,
+					uint8_t num_bis, uint8_t *bis,
+					GError **err)
 {
-	struct sockaddr_iso addr;
+	struct sockaddr_iso *addr = NULL;
+	size_t addr_len;
+	int ret = 0;
+
+	/* If this is an ISO listener and the destination address
+	 * is not BDADDR_ANY, the listener should be bound to the
+	 * broadcaster address
+	 */
+	if (server && bacmp(dst, BDADDR_ANY))
+		addr_len = sizeof(*addr) + sizeof(*addr->iso_bc);
+	else
+		addr_len = sizeof(*addr);
 
-	memset(&addr, 0, sizeof(addr));
-	addr.iso_family = AF_BLUETOOTH;
-	bacpy(&addr.iso_bdaddr, src);
-	addr.iso_bdaddr_type = src_type;
+	addr = malloc(addr_len);
+
+	if (!addr)
+		return -ENOMEM;
 
-	if (!bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
-		return 0;
+	memset(addr, 0, addr_len);
+	addr->iso_family = AF_BLUETOOTH;
+	bacpy(&addr->iso_bdaddr, src);
+	addr->iso_bdaddr_type = src_type;
 
+	if (addr_len > sizeof(*addr)) {
+		bacpy(&addr->iso_bc->bc_bdaddr, dst);
+		addr->iso_bc->bc_bdaddr_type = dst_type;
+		addr->iso_bc->bc_sid = bc_sid;
+		addr->iso_bc->bc_num_bis = num_bis;
+		memcpy(addr->iso_bc->bc_bis, bis,
+			addr->iso_bc->bc_num_bis);
+	}
+
+	if (!bind(sock, (struct sockaddr *)addr, addr_len))
+		goto done;
+
+	ret = -errno;
 	ERROR_FAILED(err, "iso_bind", errno);
 
-	return -errno;
+done:
+	free(addr);
+	return ret;
 }
 
 static int sco_connect(int sock, const bdaddr_t *dst)
@@ -857,7 +894,7 @@ voice:
 	return TRUE;
 }
 
-static gboolean iso_set(int sock, struct bt_iso_qos *qos, GError **err)
+static gboolean iso_set_qos(int sock, struct bt_iso_qos *qos, GError **err)
 {
 	if (setsockopt(sock, SOL_BLUETOOTH, BT_ISO_QOS, qos,
 				sizeof(*qos)) < 0) {
@@ -868,6 +905,16 @@ static gboolean iso_set(int sock, struct bt_iso_qos *qos, GError **err)
 	return TRUE;
 }
 
+static gboolean iso_set_base(int sock, struct bt_iso_base *base, GError **err)
+{
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_ISO_BASE, base->base,
+			base->base_len) < 0) {
+		ERROR_FAILED(err, "setsockopt(BT_ISO_BASE)", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
 static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 						BtIOOption opt1, va_list args)
 {
@@ -965,6 +1012,19 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 		case BT_IO_OPT_QOS:
 			opts->qos = *va_arg(args, struct bt_iso_qos *);
 			break;
+		case BT_IO_OPT_BASE:
+			opts->base = *va_arg(args, struct bt_iso_base *);
+			break;
+		case BT_IO_OPT_ISO_BC_SID:
+			opts->bc_sid = va_arg(args, int);
+			break;
+		case BT_IO_OPT_ISO_BC_NUM_BIS:
+			opts->bc_num_bis = va_arg(args, int);
+			break;
+		case BT_IO_OPT_ISO_BC_BIS:
+			memcpy(opts->bc_bis, va_arg(args, uint8_t *),
+					opts->bc_num_bis);
+			break;
 		case BT_IO_OPT_INVALID:
 		case BT_IO_OPT_KEY_SIZE:
 		case BT_IO_OPT_SOURCE_CHANNEL:
@@ -1289,6 +1349,10 @@ parse_opts:
 		case BT_IO_OPT_MTU:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
+		case BT_IO_OPT_ISO_BC_SID:
+		case BT_IO_OPT_ISO_BC_NUM_BIS:
+		case BT_IO_OPT_ISO_BC_BIS:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
 					"Unknown option %d", opt);
@@ -1443,6 +1507,10 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
+		case BT_IO_OPT_ISO_BC_SID:
+		case BT_IO_OPT_ISO_BC_NUM_BIS:
+		case BT_IO_OPT_ISO_BC_BIS:
 		case BT_IO_OPT_INVALID:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1553,6 +1621,10 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
+		case BT_IO_OPT_ISO_BC_SID:
+		case BT_IO_OPT_ISO_BC_NUM_BIS:
+		case BT_IO_OPT_ISO_BC_BIS:
 		case BT_IO_OPT_INVALID:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1571,6 +1643,7 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 	BtIOOption opt = opt1;
 	struct sockaddr_iso src, dst;
 	struct bt_iso_qos qos;
+	struct bt_iso_base base;
 	socklen_t len;
 	uint32_t phy;
 
@@ -1581,6 +1654,13 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		return FALSE;
 	}
 
+	if (getsockopt(sock, SOL_BLUETOOTH, BT_ISO_BASE,
+			&base.base, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(BT_ISO_BASE)", errno);
+		return FALSE;
+	}
+	base.base_len = len;
+
 	if (!get_src(sock, &src, sizeof(src), err))
 		return FALSE;
 
@@ -1608,13 +1688,13 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 			*(va_arg(args, uint8_t *)) = dst.iso_bdaddr_type;
 			break;
 		case BT_IO_OPT_MTU:
-			*(va_arg(args, uint16_t *)) = qos.out.sdu;
+			*(va_arg(args, uint16_t *)) = qos.ucast.out.sdu;
 			break;
 		case BT_IO_OPT_IMTU:
-			*(va_arg(args, uint16_t *)) = qos.in.sdu;
+			*(va_arg(args, uint16_t *)) = qos.ucast.in.sdu;
 			break;
 		case BT_IO_OPT_OMTU:
-			*(va_arg(args, uint16_t *)) = qos.out.sdu;
+			*(va_arg(args, uint16_t *)) = qos.ucast.out.sdu;
 			break;
 		case BT_IO_OPT_PHY:
 			if (get_phy(sock, &phy) < 0) {
@@ -1626,6 +1706,9 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_QOS:
 			*(va_arg(args, struct bt_iso_qos *)) = qos;
 			break;
+		case BT_IO_OPT_BASE:
+			*(va_arg(args, struct bt_iso_base *)) = base;
+			break;
 		case BT_IO_OPT_HANDLE:
 		case BT_IO_OPT_CLASS:
 		case BT_IO_OPT_DEFER_TIMEOUT:
@@ -1641,6 +1724,9 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_FLUSHABLE:
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
+		case BT_IO_OPT_ISO_BC_SID:
+		case BT_IO_OPT_ISO_BC_NUM_BIS:
+		case BT_IO_OPT_ISO_BC_BIS:
 		case BT_IO_OPT_INVALID:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1708,6 +1794,78 @@ gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 	return TRUE;
 }
 
+gboolean bt_io_bcast_accept(GIOChannel *io, BtIOConnect connect,
+				gpointer user_data, GDestroyNotify destroy,
+				GError * *err, BtIOOption opt1, ...)
+{
+	int sock;
+	char c;
+	va_list args;
+	struct sockaddr_iso *addr = NULL;
+	uint8_t bc_num_bis = 0;
+	uint8_t bc_bis[ISO_MAX_NUM_BIS] = {0};
+	BtIOOption opt = opt1;
+
+	va_start(args, opt1);
+
+	while (opt != BT_IO_OPT_INVALID) {
+		if (opt == BT_IO_OPT_ISO_BC_NUM_BIS)  {
+			bc_num_bis = va_arg(args, int);
+		} else if (opt == BT_IO_OPT_ISO_BC_BIS) {
+			memcpy(bc_bis, va_arg(args, uint8_t *),
+					bc_num_bis);
+		} else {
+			g_set_error(err, BT_IO_ERROR, EINVAL,
+					"Invalid option %d", opt);
+			break;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	va_end(args);
+
+	if (*err)
+		return FALSE;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	if (bc_num_bis) {
+		addr = malloc(sizeof(*addr) + sizeof(*addr->iso_bc));
+
+		if (!addr) {
+			ERROR_FAILED(err, "poll", ENOMEM);
+			return FALSE;
+		}
+
+		memset(addr, 0, sizeof(*addr) + sizeof(*addr->iso_bc));
+		addr->iso_family = AF_BLUETOOTH;
+
+		addr->iso_bc->bc_num_bis = bc_num_bis;
+		memcpy(addr->iso_bc->bc_bis, bc_bis,
+			addr->iso_bc->bc_num_bis);
+
+		if (bind(sock, (struct sockaddr *)addr,
+			sizeof(*addr) + sizeof(*addr->iso_bc)) < 0) {
+			ERROR_FAILED(err, "bind", errno);
+		}
+
+		free(addr);
+
+		if (*err)
+			return FALSE;
+	}
+
+	if (read(sock, &c, 1) < 0) {
+		ERROR_FAILED(err, "read", errno);
+		return FALSE;
+	}
+
+	server_add(io, connect, NULL, user_data, destroy);
+
+	return TRUE;
+}
+
 gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...)
 {
 	va_list args;
@@ -1739,7 +1897,7 @@ gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...)
 	case BT_IO_SCO:
 		return sco_set(sock, opts.mtu, opts.voice, err);
 	case BT_IO_ISO:
-		return iso_set(sock, &opts.qos, err);
+		return iso_set_qos(sock, &opts.qos, err);
 	case BT_IO_INVALID:
 	default:
 		g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1817,10 +1975,16 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
 			ERROR_FAILED(err, "socket(SEQPACKET, ISO)", errno);
 			return NULL;
 		}
-		if (iso_bind(sock, &opts->src, opts->src_type, err) < 0)
+
+		if (iso_bind(sock, server, &opts->src, opts->src_type,
+				 &opts->dst, opts->dst_type, opts->bc_sid,
+				 opts->bc_num_bis, opts->bc_bis, err) < 0)
 			goto failed;
-		if (!iso_set(sock, &opts->qos, err))
+		if (!iso_set_qos(sock, &opts->qos, err))
 			goto failed;
+		if (opts->base.base_len)
+			if (!iso_set_base(sock, &opts->base, err))
+				goto failed;
 		break;
 	case BT_IO_INVALID:
 	default:
diff --git a/btio/btio.h b/btio/btio.h
index 9636fd4..3e69092 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -45,6 +46,10 @@ typedef enum {
 	BT_IO_OPT_VOICE,
 	BT_IO_OPT_PHY,
 	BT_IO_OPT_QOS,
+	BT_IO_OPT_BASE,
+	BT_IO_OPT_ISO_BC_SID,
+	BT_IO_OPT_ISO_BC_NUM_BIS,
+	BT_IO_OPT_ISO_BC_BIS,
 } BtIOOption;
 
 typedef enum {
@@ -70,6 +75,10 @@ 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_bcast_accept(GIOChannel *io, BtIOConnect connect,
+				gpointer user_data, GDestroyNotify destroy,
+				GError **err, BtIOOption opt1, ...);
+
 gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...);
 
 gboolean bt_io_get(GIOChannel *io, GError **err, BtIOOption opt1, ...);
diff --git a/client/adv_monitor.c b/client/adv_monitor.c
index 792379f..29e6709 100644
--- a/client/adv_monitor.c
+++ b/client/adv_monitor.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2020 Google LLC
+ *  Copyright 2024 NXP
  *
  *
  */
@@ -372,12 +373,11 @@ static void register_reply(DBusMessage *message, void *user_data)
 
 	if (!dbus_set_error_from_message(&error, message)) {
 		bt_shell_printf("AdvertisementMonitor path registered\n");
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		return;
 	}
 
 	bt_shell_printf("Failed to register path: %s\n", error.name);
 	dbus_error_free(&error);
-	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
 static void unregister_setup(DBusMessageIter *iter, void *user_data)
@@ -408,13 +408,13 @@ void adv_monitor_register_app(DBusConnection *conn)
 {
 	if (manager.app_registered) {
 		bt_shell_printf("Advertisement Monitor already registered\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		return;
 	} else if (manager.supported_types == NULL ||
 		!g_dbus_proxy_method_call(manager.proxy, "RegisterMonitor",
 					register_setup, register_reply,
 					NULL, NULL)) {
 		bt_shell_printf("Failed to register Advertisement Monitor\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		return;
 	}
 	manager.app_registered = TRUE;
 }
diff --git a/client/advertising.c b/client/advertising.c
index fb9b049..4a98121 100644
--- a/client/advertising.c
+++ b/client/advertising.c
@@ -28,7 +28,7 @@
 #define AD_IFACE "org.bluez.LEAdvertisement1"
 
 struct ad_data {
-	uint8_t data[25];
+	uint8_t data[245];
 	uint8_t len;
 };
 
@@ -43,6 +43,7 @@ struct manufacturer_data {
 };
 
 struct data {
+	bool valid;
 	uint8_t type;
 	struct ad_data data;
 };
@@ -67,9 +68,11 @@ static struct ad {
 	bool tx_power;
 	bool name;
 	bool appearance;
+	bool rsi;
 } ad = {
 	.local_appearance = UINT16_MAX,
 	.discoverable = true,
+	.rsi = true,
 };
 
 static void ad_release(DBusConnection *conn)
@@ -155,7 +158,7 @@ static void print_ad(void)
 						ad.manufacturer.data.len);
 	}
 
-	if (ad.data.data.len) {
+	if (ad.data.valid) {
 		bt_shell_printf("Data Type: 0x%02x\n", ad.data.type);
 		bt_shell_hexdump(ad.data.data.data, ad.data.data.len);
 	}
@@ -175,7 +178,8 @@ static void print_ad(void)
 		bt_shell_printf("Appearance: %s\n",
 					ad.appearance ? "on" : "off");
 
-	bt_shell_printf("Discoverable: %s\n", ad.discoverable ? "on": "off");
+	bt_shell_printf("Discoverable: %s\n", ad.discoverable ? "on" : "off");
+	bt_shell_printf("RSI: %s\n", ad.rsi ? "on" : "off");
 
 	if (ad.duration)
 		bt_shell_printf("Duration: %u sec\n", ad.duration);
@@ -295,7 +299,7 @@ static gboolean get_manufacturer_data(const GDBusPropertyTable *property,
 
 static gboolean includes_exists(const GDBusPropertyTable *property, void *data)
 {
-	return ad.tx_power || ad.name || ad.appearance;
+	return ad.tx_power || ad.name || ad.appearance || ad.rsi;
 }
 
 static gboolean get_includes(const GDBusPropertyTable *property,
@@ -323,6 +327,12 @@ static gboolean get_includes(const GDBusPropertyTable *property,
 		dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str);
 	}
 
+	if (ad.rsi) {
+		const char *str = "rsi";
+
+		dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str);
+	}
+
 	dbus_message_iter_close_container(iter, &array);
 
 
@@ -386,7 +396,7 @@ static gboolean get_timeout(const GDBusPropertyTable *property,
 
 static gboolean data_exists(const GDBusPropertyTable *property, void *data)
 {
-	return ad.data.type != 0;
+	return ad.data.valid;
 }
 
 static gboolean get_data(const GDBusPropertyTable *property,
@@ -406,12 +416,6 @@ static gboolean get_data(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
-static gboolean discoverable_exists(const GDBusPropertyTable *property,
-							void *data)
-{
-	return ad.discoverable;
-}
-
 static gboolean get_discoverable(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *user_data)
 {
@@ -488,7 +492,7 @@ static const GDBusPropertyTable ad_props[] = {
 	{ "ManufacturerData", "a{qv}", get_manufacturer_data, NULL,
 						manufacturer_data_exists },
 	{ "Data", "a{yv}", get_data, NULL, data_exists },
-	{ "Discoverable", "b", get_discoverable, NULL, discoverable_exists },
+	{ "Discoverable", "b", get_discoverable, NULL, NULL },
 	{ "DiscoverableTimeout", "q", get_discoverable_timeout, NULL,
 						discoverable_timeout_exists },
 	{ "Includes", "as", get_includes, NULL, includes_exists },
@@ -748,7 +752,7 @@ void ad_disable_manufacturer(DBusConnection *conn)
 
 static void ad_clear_data(void)
 {
-	memset(&ad.manufacturer, 0, sizeof(ad.manufacturer));
+	memset(&ad.data, 0, sizeof(ad.data));
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
@@ -778,6 +782,7 @@ void ad_advertise_data(DBusConnection *conn, int argc, char *argv[])
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 
 	ad_clear_data();
+	ad.data.valid = true;
 	ad.data.type = val;
 	ad.data.data = data;
 
@@ -1023,3 +1028,20 @@ void ad_advertise_interval(DBusConnection *conn, uint32_t *min, uint32_t *max)
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
+
+void ad_advertise_rsi(DBusConnection *conn, dbus_bool_t *value)
+{
+	if (!value) {
+		bt_shell_printf("RSI: %s\n", ad.rsi ? "on" : "off");
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	if (ad.rsi == *value)
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+
+	ad.rsi = *value;
+
+	g_dbus_emit_property_changed(conn, AD_PATH, AD_IFACE, "Includes");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
diff --git a/client/advertising.h b/client/advertising.h
index 472396e..145ac80 100644
--- a/client/advertising.h
+++ b/client/advertising.h
@@ -30,3 +30,4 @@ void ad_advertise_discoverable(DBusConnection *conn, dbus_bool_t *value);
 void ad_advertise_discoverable_timeout(DBusConnection *conn, long int *value);
 void ad_advertise_secondary(DBusConnection *conn, const char *value);
 void ad_advertise_interval(DBusConnection *conn, uint32_t *min, uint32_t *max);
+void ad_advertise_rsi(DBusConnection *conn, dbus_bool_t *value);
diff --git a/client/agent.c b/client/agent.c
index c8e1560..ff5e57f 100644
--- a/client/agent.c
+++ b/client/agent.c
@@ -77,14 +77,17 @@ static void confirm_response(const char *input, void *user_data)
 {
 	DBusConnection *conn = user_data;
 
-	if (!strcmp(input, "yes"))
-		g_dbus_send_reply(conn, pending_message, DBUS_TYPE_INVALID);
-	else if (!strcmp(input, "no"))
-		g_dbus_send_error(conn, pending_message,
+	if (pending_message != NULL) {
+		if (!strcmp(input, "yes"))
+			g_dbus_send_reply(conn, pending_message,
+					DBUS_TYPE_INVALID);
+		else if (!strcmp(input, "no"))
+			g_dbus_send_error(conn, pending_message,
 					"org.bluez.Error.Rejected", NULL);
-	else
-		g_dbus_send_error(conn, pending_message,
+		else
+			g_dbus_send_error(conn, pending_message,
 					"org.bluez.Error.Canceled", NULL);
+	}
 }
 
 static void agent_release(DBusConnection *conn)
@@ -258,7 +261,7 @@ static DBusMessage *cancel_request(DBusConnection *conn,
 	return dbus_message_new_method_return(msg);
 }
 
-static const GDBusMethodTable methods[] = {
+static const GDBusMethodTable agent_methods[] = {
 	{ GDBUS_METHOD("Release", NULL, NULL, release_agent) },
 	{ GDBUS_ASYNC_METHOD("RequestPinCode",
 			GDBUS_ARGS({ "device", "o" }),
@@ -286,6 +289,78 @@ static const GDBusMethodTable methods[] = {
 	{ }
 };
 
+static DBusMessage *auto_confirmation(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	const char *device;
+	dbus_uint32_t passkey;
+
+	bt_shell_printf("Request confirmation\n");
+
+	dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
+				DBUS_TYPE_UINT32, &passkey, DBUS_TYPE_INVALID);
+
+	bt_shell_printf("Confirm passkey %06u (auto)", passkey);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *auto_authorization(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	const char *device;
+
+	bt_shell_printf("Request authorization\n");
+
+	dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
+							DBUS_TYPE_INVALID);
+
+	bt_shell_printf("Accept pairing (auto)");
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *auto_authorize_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	const char *device, *uuid;
+
+	dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
+				DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID);
+
+	bt_shell_printf("Authorize service %s (auto)", uuid);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable auto_methods[] = {
+	{ GDBUS_METHOD("Release", NULL, NULL, release_agent) },
+	{ GDBUS_ASYNC_METHOD("RequestPinCode",
+			GDBUS_ARGS({ "device", "o" }),
+			GDBUS_ARGS({ "pincode", "s" }), request_pincode) },
+	{ GDBUS_METHOD("DisplayPinCode",
+			GDBUS_ARGS({ "device", "o" }, { "pincode", "s" }),
+			NULL, display_pincode) },
+	{ GDBUS_ASYNC_METHOD("RequestPasskey",
+			GDBUS_ARGS({ "device", "o" }),
+			GDBUS_ARGS({ "passkey", "u" }), request_passkey) },
+	{ GDBUS_METHOD("DisplayPasskey",
+			GDBUS_ARGS({ "device", "o" }, { "passkey", "u" },
+							{ "entered", "q" }),
+			NULL, display_passkey) },
+	{ GDBUS_ASYNC_METHOD("RequestConfirmation",
+			GDBUS_ARGS({ "device", "o" }, { "passkey", "u" }),
+			NULL, auto_confirmation) },
+	{ GDBUS_ASYNC_METHOD("RequestAuthorization",
+			GDBUS_ARGS({ "device", "o" }),
+			NULL, auto_authorization) },
+	{ GDBUS_ASYNC_METHOD("AuthorizeService",
+			GDBUS_ARGS({ "device", "o" }, { "uuid", "s" }),
+			NULL,  auto_authorize_service) },
+	{ GDBUS_METHOD("Cancel", NULL, NULL, cancel_request) },
+	{ }
+};
+
 static void register_agent_setup(DBusMessageIter *iter, void *user_data)
 {
 	const char *path = AGENT_PATH;
@@ -319,6 +394,8 @@ void agent_register(DBusConnection *conn, GDBusProxy *manager,
 						const char *capability)
 
 {
+	const GDBusMethodTable *methods = agent_methods;
+
 	if (agent_registered == TRUE) {
 		bt_shell_printf("Agent is already registered\n");
 		return;
@@ -326,6 +403,14 @@ void agent_register(DBusConnection *conn, GDBusProxy *manager,
 
 	agent_capability = capability;
 
+	if (!strcasecmp(agent_capability, "auto")) {
+		bt_shell_printf("Warning: setting auto response is not secure, "
+				"it bypass user confirmation/authorization, it "
+				"shall only be used for test automation.\n");
+		agent_capability = "";
+		methods = auto_methods;
+	}
+
 	if (g_dbus_register_interface(conn, AGENT_PATH,
 					AGENT_INTERFACE, methods,
 					NULL, NULL, NULL, NULL) == FALSE) {
diff --git a/client/assistant.c b/client/assistant.c
new file mode 100644
index 0000000..16e9466
--- /dev/null
+++ b/client/assistant.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2024 NXP
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/shared/util.h"
+#include "src/shared/shell.h"
+#include "src/shared/io.h"
+#include "src/shared/queue.h"
+#include "print.h"
+#include "assistant.h"
+
+/* String display constants */
+#define COLORED_NEW	COLOR_GREEN "NEW" COLOR_OFF
+#define COLORED_CHG	COLOR_YELLOW "CHG" COLOR_OFF
+#define COLORED_DEL	COLOR_RED "DEL" COLOR_OFF
+
+#define MEDIA_ASSISTANT_INTERFACE "org.bluez.MediaAssistant1"
+
+#define BCODE_LEN		16
+
+struct assistant_config {
+	GDBusProxy *proxy;	/* DBus object reference */
+	struct iovec *meta;	/* Stream metadata LTVs */
+	struct bt_iso_qos qos;	/* Stream QoS parameters */
+};
+
+static DBusConnection *dbus_conn;
+
+static GList *assistants;
+
+static char *proxy_description(GDBusProxy *proxy, const char *title,
+						const char *description)
+{
+	const char *path;
+
+	path = g_dbus_proxy_get_path(proxy);
+
+	return g_strdup_printf("%s%s%s%s %s ",
+					description ? "[" : "",
+					description ? : "",
+					description ? "] " : "",
+					title, path);
+}
+
+static void print_assistant(GDBusProxy *proxy, const char *description)
+{
+	char *str;
+
+	str = proxy_description(proxy, "Assistant", description);
+
+	bt_shell_printf("%s\n", str);
+
+	g_free(str);
+}
+
+static void assistant_added(GDBusProxy *proxy)
+{
+	assistants = g_list_append(assistants, proxy);
+
+	print_assistant(proxy, COLORED_NEW);
+}
+
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	const char *interface;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+
+	if (!strcmp(interface, MEDIA_ASSISTANT_INTERFACE))
+		assistant_added(proxy);
+}
+
+static void assistant_removed(GDBusProxy *proxy)
+{
+	assistants = g_list_remove(assistants, proxy);
+
+	print_assistant(proxy, COLORED_DEL);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	const char *interface;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+
+	if (!strcmp(interface, MEDIA_ASSISTANT_INTERFACE))
+		assistant_removed(proxy);
+}
+
+static void assistant_property_changed(GDBusProxy *proxy, const char *name,
+						DBusMessageIter *iter)
+{
+	char *str;
+
+	str = proxy_description(proxy, "Assistant", COLORED_CHG);
+	print_iter(str, name, iter);
+	g_free(str);
+}
+
+static void property_changed(GDBusProxy *proxy, const char *name,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *interface;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+
+	if (!strcmp(interface, MEDIA_ASSISTANT_INTERFACE))
+		assistant_property_changed(proxy, name, iter);
+}
+
+static void assistant_unregister(void *data)
+{
+	GDBusProxy *proxy = data;
+
+	bt_shell_printf("Assistant %s unregistered\n",
+				g_dbus_proxy_get_path(proxy));
+}
+
+static void disconnect_handler(DBusConnection *connection, void *user_data)
+{
+	g_list_free_full(assistants, assistant_unregister);
+	assistants = NULL;
+}
+
+static uint8_t *str2bytearray(char *arg, size_t *val_len)
+{
+	uint8_t value[UINT8_MAX];
+	char *entry;
+	unsigned int i;
+
+	for (i = 0; (entry = strsep(&arg, " \t")) != NULL; i++) {
+		long val;
+		char *endptr = NULL;
+
+		if (*entry == '\0')
+			continue;
+
+		if (i >= G_N_ELEMENTS(value)) {
+			bt_shell_printf("Too much data\n");
+			return NULL;
+		}
+
+		val = strtol(entry, &endptr, 0);
+		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
+			bt_shell_printf("Invalid value at index %d\n", i);
+			return NULL;
+		}
+
+		value[i] = val;
+	}
+
+	*val_len = i;
+
+	return util_memdup(value, i);
+}
+
+static void append_qos(DBusMessageIter *iter, struct assistant_config *cfg)
+{
+	DBusMessageIter entry, var, dict;
+	const char *key = "QoS";
+	const char *bcode_key = "BCode";
+	uint8_t *bcode = cfg->qos.bcast.bcode;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
+						NULL, &entry);
+
+	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+	dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+						"a{sv}", &var);
+
+	dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, "{sv}",
+					&dict);
+
+	g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING,
+					&bcode_key, DBUS_TYPE_BYTE,
+					&bcode, BCODE_LEN);
+
+	dbus_message_iter_close_container(&var, &dict);
+	dbus_message_iter_close_container(&entry, &var);
+	dbus_message_iter_close_container(iter, &entry);
+}
+
+static void push_setup(DBusMessageIter *iter, void *user_data)
+{
+	struct assistant_config *cfg = user_data;
+	DBusMessageIter dict;
+	const char *meta = "Metadata";
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	if (cfg->meta)
+		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
+				DBUS_TYPE_BYTE, &cfg->meta->iov_base,
+				cfg->meta->iov_len);
+
+	if (cfg->qos.bcast.encryption)
+		append_qos(&dict, cfg);
+
+	dbus_message_iter_close_container(iter, &dict);
+}
+
+static void push_reply(DBusMessage *message, void *user_data)
+{
+	struct assistant_config *cfg = user_data;
+	DBusError error;
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message)) {
+		bt_shell_printf("Failed to push assistant: %s\n",
+				error.name);
+
+		dbus_error_free(&error);
+
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Assistant %s pushed\n",
+				g_dbus_proxy_get_path(cfg->proxy));
+
+	free(cfg->meta);
+	g_free(cfg);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void assistant_set_bcode_cfg(const char *input, void *user_data)
+{
+	struct assistant_config *cfg = user_data;
+
+	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
+		memset(cfg->qos.bcast.bcode, 0, BCODE_LEN);
+	} else {
+		if (strlen(input) > BCODE_LEN) {
+			bt_shell_printf("Input string too long %s\n", input);
+			goto fail;
+		}
+
+		memcpy(cfg->qos.bcast.bcode, input, strlen(input));
+	}
+
+	if (!g_dbus_proxy_method_call(cfg->proxy, "Push",
+					push_setup, push_reply,
+					cfg, NULL)) {
+		bt_shell_printf("Failed to push assistant\n");
+		goto fail;
+	}
+
+	return;
+
+fail:
+	free(cfg->meta);
+	g_free(cfg);
+
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+static void assistant_set_metadata_cfg(const char *input, void *user_data)
+{
+	struct assistant_config *cfg = user_data;
+	DBusMessageIter iter, dict, entry, value;
+	const char *key;
+
+	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto"))
+		goto done;
+
+	if (!cfg->meta)
+		cfg->meta = g_new0(struct iovec, 1);
+
+	cfg->meta->iov_base = str2bytearray((char *) input,
+				&cfg->meta->iov_len);
+	if (!cfg->meta->iov_base) {
+		free(cfg->meta);
+		cfg->meta = NULL;
+	}
+
+done:
+	/* Get QoS property to check if the stream is encrypted */
+	if (!g_dbus_proxy_get_property(cfg->proxy, "QoS", &iter))
+		goto fail;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+		goto fail;
+
+	dbus_message_iter_recurse(&iter, &dict);
+
+	if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
+		goto fail;
+
+	dbus_message_iter_recurse(&dict, &entry);
+	dbus_message_iter_get_basic(&entry, &key);
+
+	if (strcasecmp(key, "Encryption") != 0)
+		goto fail;
+
+	dbus_message_iter_next(&entry);
+	dbus_message_iter_recurse(&entry, &value);
+
+	if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_BYTE)
+		goto fail;
+
+	dbus_message_iter_get_basic(&value, &cfg->qos.bcast.encryption);
+
+	if (cfg->qos.bcast.encryption)
+		/* Prompt user to enter the Broadcast Code to decrypt
+		 * the stream
+		 */
+		bt_shell_prompt_input("Assistant",
+				"Enter Broadcast Code (auto/value):",
+				assistant_set_bcode_cfg, cfg);
+	else
+		if (!g_dbus_proxy_method_call(cfg->proxy, "Push",
+						push_setup, push_reply,
+						cfg, NULL)) {
+			bt_shell_printf("Failed to push assistant\n");
+			goto fail;
+		}
+
+	return;
+
+fail:
+	free(cfg->meta);
+	g_free(cfg);
+
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+static void cmd_push_assistant(int argc, char *argv[])
+{
+	struct assistant_config *cfg;
+
+	cfg = new0(struct assistant_config, 1);
+	if (!cfg)
+		goto fail;
+
+	/* Search for DBus object */
+	cfg->proxy = g_dbus_proxy_lookup(assistants, NULL, argv[1],
+						MEDIA_ASSISTANT_INTERFACE);
+	if (!cfg->proxy) {
+		bt_shell_printf("Assistant %s not found\n", argv[1]);
+		goto fail;
+	}
+
+	/* Prompt user to enter metadata */
+	bt_shell_prompt_input("Assistant",
+			"Enter Metadata (auto/value):",
+			assistant_set_metadata_cfg, cfg);
+
+	return;
+
+fail:
+	g_free(cfg);
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+static const struct bt_shell_menu assistant_menu = {
+	.name = "assistant",
+	.desc = "Media Assistant Submenu",
+	.entries = {
+	{ "push", "<assistant>", cmd_push_assistant,
+					"Send stream information to peer" },
+	{} },
+};
+
+static GDBusClient * client;
+
+void assistant_add_submenu(void)
+{
+	bt_shell_add_submenu(&assistant_menu);
+
+	dbus_conn = bt_shell_get_env("DBUS_CONNECTION");
+	if (!dbus_conn || client)
+		return;
+
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+							property_changed, NULL);
+	g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
+}
+
+void assistant_remove_submenu(void)
+{
+	g_dbus_client_unref(client);
+	client = NULL;
+}
+
diff --git a/client/assistant.h b/client/assistant.h
new file mode 100644
index 0000000..418b0b8
--- /dev/null
+++ b/client/assistant.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2024 NXP
+ *
+ *
+ */
+
+void assistant_add_submenu(void);
+void assistant_remove_submenu(void);
+
diff --git a/client/bluetoothctl-admin.1 b/client/bluetoothctl-admin.1
new file mode 100644
index 0000000..308c3a9
--- /dev/null
+++ b/client/bluetoothctl-admin.1
@@ -0,0 +1,61 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-ADMIN" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-admin \- Admin Policy Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [admin.commands]
+.SH ADMIN POLICY COMMANDS
+.SS allow
+.sp
+Allow service UUIDs and block rest of them.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# allow [clear/uuid1 uuid2 ...]\fP
+.TP
+.B Example
+\fB# allow 0x1101 0x1102 0x1103\fP
+.TP
+.B Example
+\fB# allow clear\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-admin.rst b/client/bluetoothctl-admin.rst
new file mode 100644
index 0000000..774af05
--- /dev/null
+++ b/client/bluetoothctl-admin.rst
@@ -0,0 +1,41 @@
+==================
+bluetoothctl-admin
+==================
+
+--------------------
+Admin Policy Submenu
+--------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [admin.commands]
+
+Admin Policy Commands
+=====================
+
+allow
+-----
+
+Allow service UUIDs and block rest of them.
+
+:Usage: **# allow [clear/uuid1 uuid2 ...]**
+:Example: **# allow 0x1101 0x1102 0x1103**
+:Example: **# allow clear**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-advertise.1 b/client/bluetoothctl-advertise.1
new file mode 100644
index 0000000..b492696
--- /dev/null
+++ b/client/bluetoothctl-advertise.1
@@ -0,0 +1,278 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-ADVERTISE" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-advertise \- Advertise Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [advertise.commands]
+.SH ADVERTISE OPTIONS COMMANDS
+.SS uuids
+.sp
+Set/Get advertise uuids.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# uuids [all/uuid1 uuid2 ...]\fP
+.TP
+.B Example
+\fB# uuids 0x1234\fP
+.TP
+.B Example
+\fB# uuids 0x12345678\fP
+.TP
+.B Example
+\fB# uuids 90f95193\-35de\-4306\-a6e9\-699328f15059\fP
+.UNINDENT
+.SS service
+.sp
+Set/Get advertise service data.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# service [uuid] [data=xx xx ...]\fP
+.UNINDENT
+.SS manufacturer
+.sp
+Set/Get advertise manufacturer data.
+.sp
+Updating is in real time while advertising. This is currently limited to 25
+bytes and will return an error message of \(dqToo much data\(dq if that maximum has
+been exceeded. However, this does not check if the advertising payload length
+maximum has been exceeded so you  may receive an error from bluetoothd that it
+\(dqFailed to register advertisement\(dq which means you need to reduce your
+manufacturer data length.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# manufacturer [id] [data=xx xx ...]\fP
+.UNINDENT
+.SS data
+.sp
+Set/Get advertise data.
+.sp
+This allows you to advertise data with a given type. You cannot use a registered
+data type value {1} with  this command. For LE the advertising shows up in the
+primary advertisements.
+.sp
+If you set only the type of the data without any data (data 0x0c) this will
+cause a parse error when turning advertise on.
+.sp
+You can modify the advertising data while it is advertising.
+.sp
+To get the currently set data use the command data without any arguments.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# data [type] [data=xx xx ...]\fP
+.TP
+.B Example
+\fB# data 0x0C 01 0x0F 13\fP
+.UNINDENT
+.SS discoverable
+.sp
+Set/Get advertise discoverable.
+.sp
+For LE discoverable on will set the LE General Discoverable Mode flag to true in
+the primary advertisement if on.
+.sp
+This feature can be changed during advertising, but will only trigger LE General
+Discoverable Mode even if you had previously selected discoverable\-timeout this
+will be ignored.
+.sp
+Entering the command by itself will show the status of the setting
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discoverable [on/off]\fP
+.UNINDENT
+.SS discoverable\-timeout
+.sp
+Set/Get advertise discoverable timeout.
+.sp
+Using this feature in LE will cause the LE Limited Discoverable Mode flag to be
+set in the primary advertisement and   The LE General Discoverable Mode flag
+will not be set.
+.sp
+The LE Limited Discoverable Mode flag will automatically turn off after [seconds]
+discoverable [on] must be set to use this feature.
+.sp
+Entering the command by itself will show the current value set.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discoverable\-timeout [seconds]\fP
+.UNINDENT
+.SS tx\-power
+.sp
+Show/Enable/Disable TX power to be advertised.
+.sp
+This sets the TX Power Level field in the advertising packet.
+.sp
+The value is in dBm and can be between \-127 and 127.
+.sp
+When this feature is turned on the LE device will advertise its transmit power
+in the primary advertisement.
+.sp
+This feature can be modified while advertising.
+.sp
+Entering the command by itself will show the current value set.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# tx\-power [on/off] [power]\fP
+.UNINDENT
+.SS name
+.sp
+Configure local name to be advertised.
+.sp
+Local name to be used in the advertising report.
+.sp
+If the string is too big to fit into the packet it will be truncated.
+.sp
+It will either advertise as a complete local name or if it has to be truncated
+then a shortened local name.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# name [on/off/name]\fP
+.TP
+.B Example
+\fB# name \(dq0123456789abcdef0123456789abcdef\(dq\fP
+.UNINDENT
+.SS appearance
+.sp
+Configure custom appearance to be advertised.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# appearance [on/off/value]\fP
+.UNINDENT
+.SS duration
+.sp
+Set/Get advertise duration.
+.sp
+The Duration parameter configures the length of an Instance.
+.sp
+The value is in seconds.
+.sp
+A value of 0 indicates a default value is chosen for the Duration.
+.sp
+The default is 2 seconds.
+.sp
+If only one advertising Instance has been added, then the Duration value will be
+ignored.
+.sp
+If multiple advertising Instances have been added, then the Duration value will
+be used to determine the length of time each Instance is advertised for.
+.sp
+The Duration value is used to calculate the number of advertising events that
+will be used to advertise each Instance.
+.sp
+The number of advertising events is calculated by dividing the Duration value by
+the advertising interval.
+.sp
+The advertising interval is determined by the advertising parameters that are
+set for each Instance. The advertising interval is the maximum of the
+advertising intervals set for each Instance.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# duration [seconds]\fP
+.UNINDENT
+.SS timeout
+.sp
+Set/Get advertise timeout.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# timeout [seconds]\fP
+.UNINDENT
+.SS secondary
+.sp
+Set/Get advertise secondary channel.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# secondary [1M/2M/Coded]\fP
+.UNINDENT
+.SS interval
+.sp
+Set/Get advertise interval.
+.sp
+The Interval parameter configures the advertising interval of an Instance.
+.sp
+The value is in milliseconds.
+.sp
+A value of 0 indicates a default value is chosen for the Interval.
+.sp
+The default is 100 milliseconds.
+.sp
+The Interval value is used to calculate the number of advertising events that
+will be used to advertise each Instance.
+.sp
+The number of advertising events is calculated by dividing the Duration value by
+the advertising interval.
+.sp
+The advertising interval is determined by the advertising parameters that are
+set for each Instance.
+.sp
+The advertising interval is the maximum of the advertising intervals set for
+each Instance.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# interval [milliseconds]\fP
+.UNINDENT
+.SS clear
+.sp
+Clear advertise config.
+.sp
+This will stop advertising if it is currently advertising.
+.sp
+If you want to change the advertise configuration while advertising you must
+first clear the advertise configuration and then set the new advertise
+configuration.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clear [uuids/service/manufacturer/config\-name...]\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-advertise.rst b/client/bluetoothctl-advertise.rst
new file mode 100644
index 0000000..4b56324
--- /dev/null
+++ b/client/bluetoothctl-advertise.rst
@@ -0,0 +1,239 @@
+======================
+bluetoothctl-advertise
+======================
+
+-----------------
+Advertise Submenu
+-----------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [advertise.commands]
+
+Advertise Options Commands
+==========================
+
+uuids
+-----
+
+Set/Get advertise uuids.
+
+:Usage: **# uuids [all/uuid1 uuid2 ...]**
+:Example: **# uuids 0x1234**
+:Example: **# uuids 0x12345678**
+:Example: **# uuids 90f95193-35de-4306-a6e9-699328f15059**
+
+service
+-------
+
+Set/Get advertise service data.
+
+:Usage: **# service [uuid] [data=xx xx ...]**
+
+manufacturer
+------------
+
+Set/Get advertise manufacturer data.
+
+Updating is in real time while advertising. This is currently limited to 25
+bytes and will return an error message of "Too much data" if that maximum has
+been exceeded. However, this does not check if the advertising payload length
+maximum has been exceeded so you  may receive an error from bluetoothd that it
+"Failed to register advertisement" which means you need to reduce your
+manufacturer data length.
+
+:Usage: **# manufacturer [id] [data=xx xx ...]**
+
+data
+----
+
+Set/Get advertise data.
+
+This allows you to advertise data with a given type. You cannot use a registered
+data type value {1} with  this command. For LE the advertising shows up in the
+primary advertisements.
+
+If you set only the type of the data without any data (data 0x0c) this will
+cause a parse error when turning advertise on.
+
+You can modify the advertising data while it is advertising.
+
+To get the currently set data use the command data without any arguments.
+
+:Usage: **# data [type] [data=xx xx ...]**
+:Example: **# data 0x0C 01 0x0F 13**
+
+discoverable
+------------
+
+Set/Get advertise discoverable.
+
+For LE discoverable on will set the LE General Discoverable Mode flag to true in
+the primary advertisement if on.
+
+This feature can be changed during advertising, but will only trigger LE General
+Discoverable Mode even if you had previously selected discoverable-timeout this
+will be ignored.
+
+Entering the command by itself will show the status of the setting
+
+:Usage: **# discoverable [on/off]**
+
+discoverable-timeout
+--------------------
+
+Set/Get advertise discoverable timeout.
+
+Using this feature in LE will cause the LE Limited Discoverable Mode flag to be
+set in the primary advertisement and   The LE General Discoverable Mode flag
+will not be set.
+
+The LE Limited Discoverable Mode flag will automatically turn off after [seconds]
+discoverable [on] must be set to use this feature.
+
+Entering the command by itself will show the current value set.
+
+:Usage: **# discoverable-timeout [seconds]**
+
+tx-power
+--------
+
+Show/Enable/Disable TX power to be advertised.
+
+This sets the TX Power Level field in the advertising packet.
+
+The value is in dBm and can be between -127 and 127.
+
+When this feature is turned on the LE device will advertise its transmit power
+in the primary advertisement.
+
+This feature can be modified while advertising.
+
+Entering the command by itself will show the current value set.
+
+:Usage: **# tx-power [on/off] [power]**
+
+name
+----
+
+Configure local name to be advertised.
+
+Local name to be used in the advertising report.
+
+If the string is too big to fit into the packet it will be truncated.
+
+It will either advertise as a complete local name or if it has to be truncated
+then a shortened local name.
+
+:Usage: **# name [on/off/name]**
+:Example: **# name "0123456789abcdef0123456789abcdef"**
+
+appearance
+----------
+
+Configure custom appearance to be advertised.
+
+:Usage: **# appearance [on/off/value]**
+
+duration
+--------
+
+Set/Get advertise duration.
+
+The Duration parameter configures the length of an Instance.
+
+The value is in seconds.
+
+A value of 0 indicates a default value is chosen for the Duration.
+
+The default is 2 seconds.
+
+If only one advertising Instance has been added, then the Duration value will be
+ignored.
+
+If multiple advertising Instances have been added, then the Duration value will
+be used to determine the length of time each Instance is advertised for.
+
+The Duration value is used to calculate the number of advertising events that
+will be used to advertise each Instance.
+
+The number of advertising events is calculated by dividing the Duration value by
+the advertising interval.
+
+The advertising interval is determined by the advertising parameters that are
+set for each Instance. The advertising interval is the maximum of the
+advertising intervals set for each Instance.
+
+:Usage: **# duration [seconds]**
+
+timeout
+-------
+
+Set/Get advertise timeout.
+
+:Usage: **# timeout [seconds]**
+
+secondary
+---------
+
+Set/Get advertise secondary channel.
+
+:Usage: **# secondary [1M/2M/Coded]**
+
+interval
+--------
+
+Set/Get advertise interval.
+
+The Interval parameter configures the advertising interval of an Instance.
+
+The value is in milliseconds.
+
+A value of 0 indicates a default value is chosen for the Interval.
+
+The default is 100 milliseconds.
+
+The Interval value is used to calculate the number of advertising events that
+will be used to advertise each Instance.
+
+The number of advertising events is calculated by dividing the Duration value by
+the advertising interval.
+
+The advertising interval is determined by the advertising parameters that are
+set for each Instance.
+
+The advertising interval is the maximum of the advertising intervals set for
+each Instance.
+
+:Usage: **# interval [milliseconds]**
+
+clear
+-----
+
+Clear advertise config.
+
+This will stop advertising if it is currently advertising.
+
+If you want to change the advertise configuration while advertising you must
+first clear the advertise configuration and then set the new advertise
+configuration.
+
+:Usage: **# clear [uuids/service/manufacturer/config-name...]**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-assistant.1 b/client/bluetoothctl-assistant.1
new file mode 100644
index 0000000..894a185
--- /dev/null
+++ b/client/bluetoothctl-assistant.1
@@ -0,0 +1,88 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-ASSISTANT" "1" "August 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-assistant \- Assistant Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [assistant.commands]
+.SH ASSISTANT COMMANDS
+.SS push
+.sp
+Send stream information to peer.
+.sp
+This command is used by a BAP Broadcast Assistant to send
+information about a broadcast stream to a peer BAP Scan
+Delegator.
+.sp
+The information is sent via a GATT Write Command for the
+BASS Broadcast Audio Scan Control Point characteristic.
+.sp
+After issuing the command, the user is prompted to enter
+stream metadata LTVs to send to the peer. If the auto
+option is chosen, the Broadcast Assistant will send the
+default metadata discovered about the stream. Otherwise,
+the default metadata will be overwritten by the LTVs
+entered by the user.
+.sp
+If the stream is encrypted, the user will also be prompted
+to enter the Broadcast Code. This is the key to decrypt the
+stream. On the UI level, the Broadcast Code shall be represented
+as a string of at least 4 octets, and no more than 16 octets
+when represented in UTF\-8. The string will be sent to the peer
+via GATT as an array of 16 octets.
+.sp
+If the auto value is chosen when prompted for the Broadcast
+Code, a zero filled array will be sent to the peer. Otherwise,
+the string entered by the user will be sent as an array of bytes.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# push <assistant>\fP
+.TP
+.B Example
+.nf
+\fB# push /org/bluez/hci0/src_05_1F_EE_F3_F8_7D/dev_00_60_37_31_7E_3F/bis1\fP
+\fB[Assistant] Enter Metadata (auto/value): 0x03 0x02 0x04 0x00\fP
+\fB[Assistant] Enter Broadcast Code (auto/value): Borne House\fP
+.fi
+.sp
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-assistant.rst b/client/bluetoothctl-assistant.rst
new file mode 100644
index 0000000..fb8c3a0
--- /dev/null
+++ b/client/bluetoothctl-assistant.rst
@@ -0,0 +1,67 @@
+======================
+bluetoothctl-assistant
+======================
+
+-----------------
+Assistant Submenu
+-----------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: August 2024
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [assistant.commands]
+
+Assistant Commands
+==================
+
+push
+----
+
+Send stream information to peer.
+
+This command is used by a BAP Broadcast Assistant to send
+information about a broadcast stream to a peer BAP Scan
+Delegator.
+
+The information is sent via a GATT Write Command for the
+BASS Broadcast Audio Scan Control Point characteristic.
+
+After issuing the command, the user is prompted to enter
+stream metadata LTVs to send to the peer. If the auto
+option is chosen, the Broadcast Assistant will send the
+default metadata discovered about the stream. Otherwise,
+the default metadata will be overwritten by the LTVs
+entered by the user.
+
+If the stream is encrypted, the user will also be prompted
+to enter the Broadcast Code. This is the key to decrypt the
+stream. On the UI level, the Broadcast Code shall be represented
+as a string of at least 4 octets, and no more than 16 octets
+when represented in UTF-8. The string will be sent to the peer
+via GATT as an array of 16 octets.
+
+If the auto value is chosen when prompted for the Broadcast
+Code, a zero filled array will be sent to the peer. Otherwise,
+the string entered by the user will be sent as an array of bytes.
+
+:Usage: **# push <assistant>**
+:Example: | **# push /org/bluez/hci0/src_05_1F_EE_F3_F8_7D/dev_00_60_37_31_7E_3F/bis1**
+          | **[Assistant] Enter Metadata (auto/value): 0x03 0x02 0x04 0x00**
+          | **[Assistant] Enter Broadcast Code (auto/value): Borne House**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-endpoint.1 b/client/bluetoothctl-endpoint.1
new file mode 100644
index 0000000..fd38628
--- /dev/null
+++ b/client/bluetoothctl-endpoint.1
@@ -0,0 +1,224 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-ENDPOINT" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-endpoint \- Endpoint Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [endpoint.commands]
+.SH ENDPOINT COMMANDS
+.SS list
+.sp
+List available endpoints.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list [local]\fP
+.UNINDENT
+.SS show
+.sp
+Endpoint information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# show [endpoint]\fP
+.UNINDENT
+.SS register
+.sp
+Register Endpoint.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# register <UUID> <codec[:company]> [capabilities...]\fP
+.TP
+.B Example LC3 BAP source
+.nf
+\fB#endpoint.register 00002bcb\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\fB#Auto Accept (yes/no):\fP y
+\fB#Max Transports (auto/value):\fP a
+\fB#Locations:\fP a
+\fB#Supported Context (value):\fP 3
+\fB#Context (value):\fP 3
+\fB#CIG (auto/value):\fP a
+\fB#CIS (auto/value):\fP a
+.fi
+.sp
+.TP
+.B Example LC3 BAP sink with extra capabilities
+.nf
+\fB#endpoint.register 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06 \(dq0x03 0xe5 0x03 0x00 0x02 0xe6 0x07\(dq\fP
+\fB#Enter Metadata (value/no):\fP n
+\fB#Auto Accept (yes/no):\fP y
+\fB#Max Transports (auto/value):\fP a
+\fB#Locations:\fP a
+\fB#Supported Context (value):\fP 3
+\fB#Context (value):\fP 3
+\fB#CIG (auto/value):\fP a
+\fB#CIS (auto/value):\fP a
+.fi
+.sp
+.TP
+.B Example LC3 BAP Broadcast source
+.nf
+\fB#endpoint.register 00001852\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\fB#Auto Accept (yes/no):\fP y
+\fB#Max Transports (auto/value):\fP a
+\fB#Locations:\fP 3
+\fB#Supported Context (value):\fP 1
+.fi
+.sp
+.TP
+.B Example LC3 BAP Broadcast sink
+.nf
+\fB#endpoint.register 00001851\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\fB#Auto Accept (yes/no):\fP y
+\fB#Max Transports (auto/value):\fP a
+\fB#Locations:\fP 3
+\fB#Supported Context (value):\fP 1
+.fi
+.sp
+.UNINDENT
+.sp
+Note:
+.sp
+If running the setup with an audio server that has LE Audio support (such as PipeWire) it will
+automatically register endpoints according to the configured roles. For more details
+about configuring a Broadcast Source with PipeWire check:
+ <https://gitlab.freedesktop.org/pipewire/pipewire/\-/blob/master/doc/dox/config/pipewire\-props.7.md> 
+.SS unregister
+.sp
+Unregister Endpoint.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister <UUID/object>\fP
+.UNINDENT
+.sp
+Note:
+.sp
+If the endpoint was registered by an audio server, it can\(aqt be unregistered from bluetoothctl.
+This must be done by the audio server as well.
+.SS config
+.sp
+Configure Endpoint.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# config <endpoint> <local endpoint> [preset]\fP
+.UNINDENT
+.sp
+Note:
+.sp
+If the endpoint was registered by an audio server, it can\(aqt be configured from bluetoothctl.
+This must be done by the audio server as well.
+.SS presets
+.sp
+List available presets.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# presets <endpoint>/<UUID> [codec[:company]] [preset] [codec config] [metadata]\fP
+.TP
+.B Example using endpoint
+.nf
+\fB#presets /local/endpoint/ep0 32_1_1\fP
+\fB#presets /local/endpoint/ep0\fP
+Preset 32_1_1
+Configuration.#0: len 0x02 type 0x01
+Configuration.Sampling Frequency: 32 Khz (0x06)
+Configuration.#1: len 0x02 type 0x02
+Configuration.Frame Duration: 7.5 ms (0x00)
+Configuration.#2: len 0x03 type 0x04
+Configuration.Frame Length: 60 (0x003c)
+.fi
+.sp
+.TP
+.B Example using UUID
+.nf
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06 32_1_1\fP
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\&...
+\fB*32_1_1\fP
+.fi
+.sp
+.TP
+.B Example setting up LC3 custom preset
+.nf
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06 custom\fP
+\fB#[Codec] Enter frequency (Khz):\fP 48
+\fB#[Codec] Enter frame duration (ms):\fP 10
+\fB#[Codec] Enter channel allocation:\fP 3
+\fB#[Codec] Enter frame length:\fP 100
+\fB#[QoS] Enter Target Latency (Low, Balance, High):\fP Low
+\fB#[QoS] Enter SDU Interval (us):\fP 1000
+\fB#[QoS] Enter Framing (Unframed, Framed):\fP Unframed
+\fB#[QoS] Enter PHY (1M, 2M):\fP 2M
+\fB#[QoS] Enter Max SDU:\fP 200
+\fB#[QoS] Enter RTN:\fP 3
+\fB#[QoS] Enter Max Transport Latency (ms):\fP 10
+\fB#[QoS] Enter Presentation Delay (us):\fP 20000
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\&...
+\fB*custom\fP
+.fi
+.sp
+.TP
+.B Example setting up LC3 custom preset with extra configuration
+.nf
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06 custom \(dq0x03 0xe8 0x00 0x00 0x02 0xe9 0x00\(dq\fP
+\fB#[Codec] Enter frequency (Khz):\fP 48
+\fB#[Codec] Enter frame duration (ms):\fP 10
+\fB#[Codec] Enter channel allocation:\fP 3
+\fB#[Codec] Enter frame length:\fP 100
+\fB#[QoS] Enter Target Latency (Low, Balance, High):\fP Low
+\fB#[QoS] Enter SDU Interval (us):\fP 1000
+\fB#[QoS] Enter Framing (Unframed, Framed):\fP Unframed
+\fB#[QoS] Enter PHY (1M, 2M):\fP 2M
+\fB#[QoS] Enter Max SDU:\fP 200
+\fB#[QoS] Enter RTN:\fP 3
+\fB#[QoS] Enter Max Transport Latency (ms):\fP 10
+\fB#[QoS] Enter Presentation Delay (us):\fP 20000
+\fB#presets 00002bc9\-0000\-1000\-8000\-00805f9b34fb 0x06\fP
+\&...
+\fB*custom\fP
+.fi
+.sp
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-endpoint.rst b/client/bluetoothctl-endpoint.rst
new file mode 100644
index 0000000..d13f37c
--- /dev/null
+++ b/client/bluetoothctl-endpoint.rst
@@ -0,0 +1,171 @@
+=====================
+bluetoothctl-endpoint
+=====================
+
+----------------
+Endpoint Submenu
+----------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [endpoint.commands]
+
+Endpoint Commands
+=================
+
+list
+----
+
+List available endpoints.
+
+:Usage: **# list [local]**
+
+show
+----
+
+Endpoint information.
+
+:Usage: **# show [endpoint]**
+
+register
+--------
+
+Register Endpoint.
+
+:Usage: **# register <UUID> <codec[:company]> [capabilities...]**
+:Example LC3 BAP source:
+	 | **#endpoint.register 00002bcb-0000-1000-8000-00805f9b34fb 0x06**
+	 | **#Auto Accept (yes/no):** y
+	 | **#Max Transports (auto/value):** a
+	 | **#Locations:** a
+	 | **#Supported Context (value):** 3
+	 | **#Context (value):** 3
+	 | **#CIG (auto/value):** a
+	 | **#CIS (auto/value):** a
+:Example LC3 BAP sink with extra capabilities:
+	 | **#endpoint.register 00002bc9-0000-1000-8000-00805f9b34fb 0x06 "0x03 0xe5 0x03 0x00 0x02 0xe6 0x07"**
+	 | **#Enter Metadata (value/no):** n
+	 | **#Auto Accept (yes/no):** y
+	 | **#Max Transports (auto/value):** a
+	 | **#Locations:** a
+	 | **#Supported Context (value):** 3
+	 | **#Context (value):** 3
+	 | **#CIG (auto/value):** a
+	 | **#CIS (auto/value):** a
+:Example LC3 BAP Broadcast source:
+	 | **#endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06**
+	 | **#Auto Accept (yes/no):** y
+	 | **#Max Transports (auto/value):** a
+	 | **#Locations:** 3
+	 | **#Supported Context (value):** 1
+:Example LC3 BAP Broadcast sink:
+	 | **#endpoint.register 00001851-0000-1000-8000-00805f9b34fb 0x06**
+	 | **#Auto Accept (yes/no):** y
+	 | **#Max Transports (auto/value):** a
+	 | **#Locations:** 3
+	 | **#Supported Context (value):** 1
+
+Note:
+
+If running the setup with an audio server that has LE Audio support (such as PipeWire) it will
+automatically register endpoints according to the configured roles. For more details
+about configuring a Broadcast Source with PipeWire check:
+https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/doc/dox/config/pipewire-props.7.md
+
+unregister
+----------
+
+Unregister Endpoint.
+
+:Usage: **# unregister <UUID/object>**
+
+Note:
+
+If the endpoint was registered by an audio server, it can't be unregistered from bluetoothctl.
+This must be done by the audio server as well.
+
+config
+------
+
+Configure Endpoint.
+
+:Usage: **# config <endpoint> <local endpoint> [preset]**
+
+Note:
+
+If the endpoint was registered by an audio server, it can't be configured from bluetoothctl.
+This must be done by the audio server as well.
+
+presets
+-------
+
+List available presets.
+
+:Usage: **# presets <endpoint>/<UUID> [codec[:company]] [preset] [codec config] [metadata]**
+:Example using endpoint:
+	  | **#presets /local/endpoint/ep0 32_1_1**
+	  | **#presets /local/endpoint/ep0**
+	  | Preset 32_1_1
+	  | Configuration.#0: len 0x02 type 0x01
+          | Configuration.Sampling Frequency: 32 Khz (0x06)
+          | Configuration.#1: len 0x02 type 0x02
+          | Configuration.Frame Duration: 7.5 ms (0x00)
+          | Configuration.#2: len 0x03 type 0x04
+          | Configuration.Frame Length: 60 (0x003c)
+:Example using UUID:
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06 32_1_1**
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06**
+	  | ...
+	  | ***32_1_1**
+:Example setting up LC3 custom preset:
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06 custom**
+	  | **#[Codec] Enter frequency (Khz):** 48
+	  | **#[Codec] Enter frame duration (ms):** 10
+	  | **#[Codec] Enter channel allocation:** 3
+	  | **#[Codec] Enter frame length:** 100
+	  | **#[QoS] Enter Target Latency (Low, Balance, High):** Low
+	  | **#[QoS] Enter SDU Interval (us):** 1000
+	  | **#[QoS] Enter Framing (Unframed, Framed):** Unframed
+	  | **#[QoS] Enter PHY (1M, 2M):** 2M
+	  | **#[QoS] Enter Max SDU:** 200
+	  | **#[QoS] Enter RTN:** 3
+	  | **#[QoS] Enter Max Transport Latency (ms):** 10
+	  | **#[QoS] Enter Presentation Delay (us):** 20000
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06**
+	  | ...
+	  | ***custom**
+:Example setting up LC3 custom preset with extra configuration:
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06 custom "0x03 0xe8 0x00 0x00 0x02 0xe9 0x00"**
+	  | **#[Codec] Enter frequency (Khz):** 48
+	  | **#[Codec] Enter frame duration (ms):** 10
+	  | **#[Codec] Enter channel allocation:** 3
+	  | **#[Codec] Enter frame length:** 100
+	  | **#[QoS] Enter Target Latency (Low, Balance, High):** Low
+	  | **#[QoS] Enter SDU Interval (us):** 1000
+	  | **#[QoS] Enter Framing (Unframed, Framed):** Unframed
+	  | **#[QoS] Enter PHY (1M, 2M):** 2M
+	  | **#[QoS] Enter Max SDU:** 200
+	  | **#[QoS] Enter RTN:** 3
+	  | **#[QoS] Enter Max Transport Latency (ms):** 10
+	  | **#[QoS] Enter Presentation Delay (us):** 20000
+	  | **#presets 00002bc9-0000-1000-8000-00805f9b34fb 0x06**
+	  | ...
+	  | ***custom**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-gatt.1 b/client/bluetoothctl-gatt.1
new file mode 100644
index 0000000..5f77486
--- /dev/null
+++ b/client/bluetoothctl-gatt.1
@@ -0,0 +1,215 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-GATT" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-gatt \- Generic Attribute Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [gatt.commands]
+.SH GENERIC ATTRIBUTE COMMANDS
+.SS list\-attributes
+.sp
+List attributes.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list\-attributes <attribute/UUID>\fP
+.UNINDENT
+.SS select\-attribute
+.sp
+Select attribute.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# select\-attribute <attribute/UUID>\fP
+.UNINDENT
+.SS attribute\-info
+.sp
+Select attribute.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# attribute\-info [attribute/UUID]\fP
+.UNINDENT
+.SS read
+.sp
+Read attribute value.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# read [offset]\fP
+.UNINDENT
+.SS write
+.sp
+Write attribute value.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# write <data=xx xx ...> [offset] [type]\fP
+.UNINDENT
+.SS acquire\-write
+.sp
+Acquire Write file descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# acquire\-write\fP
+.UNINDENT
+.SS release\-write
+.sp
+Release Write file descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# release\-write\fP
+.UNINDENT
+.SS acquire\-notify
+.sp
+Acquire Notify file descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# acquire\-notify\fP
+.UNINDENT
+.SS release\-notify
+.sp
+Release Notify file descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# release\-notify\fP
+.UNINDENT
+.SS notify
+.sp
+Notify attribute value.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# notify <on/off>\fP
+.UNINDENT
+.SS clone
+.sp
+Clone a device or attribute.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clone [dev/attribute/UUID]\fP
+.UNINDENT
+.SS register\-application
+.sp
+Register application.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# register\-application [UUID ...]\fP
+.UNINDENT
+.SS unregister\-application
+.sp
+Unregister application
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister\-application\fP
+.UNINDENT
+.SS register\-service
+.sp
+Register application service.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# register\-service <UUID> [handle]\fP
+.UNINDENT
+.SS unregister\-service
+.sp
+Unregister application service
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister\-service <UUID/object>\fP
+.UNINDENT
+.SS register\-includes
+.sp
+Register as Included service.
+.INDENT 0.0
+.TP
+.B Usage
+\fB#r egister\-includes <UUID> [handle]\fP
+.UNINDENT
+.SS unregister\-includes
+.sp
+Unregister Included service.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister\-includes <Service\-UUID><Inc\-UUID>\fP
+.UNINDENT
+.SS register\-characteristic
+.sp
+Register service characteristic.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# register\-characteristic <UUID> <Flags=read,write,notify...> [handle]\fP
+.UNINDENT
+.SS unregister\-characteristic
+.sp
+Unregister service characteristic.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister\-characteristic <UUID/object>\fP
+.UNINDENT
+.SS register\-descriptor
+.sp
+Register characteristic descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# register\-descriptor <UUID> <Flags=read,write...> [handle]\fP
+.UNINDENT
+.SS unregister\-descriptor
+.sp
+Unregister characteristic descriptor.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unregister\-descriptor <UUID/object>\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-gatt.rst b/client/bluetoothctl-gatt.rst
new file mode 100644
index 0000000..2a239be
--- /dev/null
+++ b/client/bluetoothctl-gatt.rst
@@ -0,0 +1,180 @@
+=================
+bluetoothctl-gatt
+=================
+
+-------------------------
+Generic Attribute Submenu
+-------------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [gatt.commands]
+
+
+Generic Attribute Commands
+==========================
+
+list-attributes
+---------------
+
+List attributes.
+
+:Usage: **# list-attributes <attribute/UUID>**
+
+select-attribute
+----------------
+
+Select attribute.
+
+:Usage: **# select-attribute <attribute/UUID>**
+
+attribute-info
+--------------
+
+Select attribute.
+
+:Usage: **# attribute-info [attribute/UUID]**
+
+read
+----
+
+Read attribute value.
+
+:Usage: **# read [offset]**
+
+write
+-----
+
+Write attribute value.
+
+:Usage: **# write <data=xx xx ...> [offset] [type]**
+
+acquire-write
+-------------
+
+Acquire Write file descriptor.
+
+:Usage: **# acquire-write**
+
+release-write
+-------------
+
+Release Write file descriptor.
+
+:Usage: **# release-write**
+
+acquire-notify
+--------------
+
+Acquire Notify file descriptor.
+
+:Usage: **# acquire-notify**
+
+release-notify
+--------------
+
+Release Notify file descriptor.
+
+:Usage: **# release-notify**
+
+notify
+------
+
+Notify attribute value.
+
+:Usage: **# notify <on/off>**
+
+clone
+-----
+
+Clone a device or attribute.
+
+:Usage: **# clone [dev/attribute/UUID]**
+
+register-application
+--------------------
+
+Register application.
+
+:Usage: **# register-application [UUID ...]**
+
+unregister-application
+----------------------
+
+Unregister application
+
+:Usage: **# unregister-application**
+
+register-service
+----------------
+
+Register application service.
+
+:Usage: **# register-service <UUID> [handle]**
+
+unregister-service
+------------------
+
+Unregister application service
+
+:Usage: **# unregister-service <UUID/object>**
+
+register-includes
+-----------------
+
+Register as Included service.
+
+:Usage: **#r egister-includes <UUID> [handle]**
+
+unregister-includes
+-------------------
+
+Unregister Included service.
+
+:Usage: **# unregister-includes <Service-UUID><Inc-UUID>**
+
+register-characteristic
+-----------------------
+
+Register service characteristic.
+
+:Usage: **# register-characteristic <UUID> <Flags=read,write,notify...> [handle]**
+
+unregister-characteristic
+-------------------------
+
+Unregister service characteristic.
+
+:Usage: **# unregister-characteristic <UUID/object>**
+
+register-descriptor
+-------------------
+
+Register characteristic descriptor.
+
+:Usage: **# register-descriptor <UUID> <Flags=read,write...> [handle]**
+
+unregister-descriptor
+---------------------
+
+Unregister characteristic descriptor.
+
+:Usage: **# unregister-descriptor <UUID/object>**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-mgmt.1 b/client/bluetoothctl-mgmt.1
new file mode 100644
index 0000000..0452373
--- /dev/null
+++ b/client/bluetoothctl-mgmt.1
@@ -0,0 +1,645 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-MGMT" "1" "July 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-mgmt \- Management Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [mgmt.commands]
+.SH MGMT COMMANDS
+.SS select
+.sp
+Select a different index
+.INDENT 0.0
+.TP
+.B Usage
+\fB# select <index>\fP
+.UNINDENT
+.SS revision
+.sp
+Get the MGMT Revision
+.INDENT 0.0
+.TP
+.B Usage
+\fB# revision\fP
+.UNINDENT
+.SS commands
+.sp
+List supported commands
+.INDENT 0.0
+.TP
+.B Usage
+\fB# commands\fP
+.UNINDENT
+.SS config
+.sp
+Show configuration info
+.INDENT 0.0
+.TP
+.B Usage
+\fB# config\fP
+.UNINDENT
+.SS info
+.sp
+Show controller info
+.INDENT 0.0
+.TP
+.B Usage
+\fB# info\fP
+.UNINDENT
+.SS extinfo
+.sp
+Show extended controller info
+.INDENT 0.0
+.TP
+.B Usage
+\fB# extinfo\fP
+.UNINDENT
+.SS auto\-power
+.sp
+Power all available features
+.INDENT 0.0
+.TP
+.B Usage
+\fB# auto\-power\fP
+.UNINDENT
+.SS power
+.sp
+Toggle powered state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# power <on/off>\fP
+.UNINDENT
+.SS discov
+.sp
+Toggle discoverable state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discov <yes/no/limited> [timeout]\fP
+.UNINDENT
+.SS connectable
+.sp
+Toggle connectable state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# connectable <on/off>\fP
+.UNINDENT
+.SS fast\-conn
+.sp
+Toggle fast connectable state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# fast\-conn <on/off>\fP
+.UNINDENT
+.SS bondable
+.sp
+Toggle bondable state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# bondable <on/off>\fP
+.UNINDENT
+.SS pairable
+.sp
+Toggle bondable state
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pairable <on/off>\fP
+.UNINDENT
+.SS linksec
+.sp
+Toggle link level security
+.INDENT 0.0
+.TP
+.B Usage
+\fB# linksec <on/off>\fP
+.UNINDENT
+.SS ssp
+.sp
+Toggle SSP mode
+.INDENT 0.0
+.TP
+.B Usage
+\fB# spp <on/off>\fP
+.UNINDENT
+.SS sc
+.sp
+Toggle SC support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# sc <on/off/only>\fP
+.UNINDENT
+.SS hs
+.sp
+Toggle HS support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# hs <on/off>\fP
+.UNINDENT
+.SS le
+.sp
+Toggle LE support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# le <on/off>\fP
+.UNINDENT
+.SS advertising
+.sp
+Toggle LE advertising
+.INDENT 0.0
+.TP
+.B Usage
+\fB# advertise <on/off>\fP
+.UNINDENT
+.SS bredr
+.sp
+Toggle BR/EDR support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# bredr <on/off>\fP
+.UNINDENT
+.SS privacy
+.sp
+Toggle privacy support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# privacy <on/off> [irk]\fP
+.UNINDENT
+.SS class
+.sp
+Set device major/minor class
+.INDENT 0.0
+.TP
+.B Usage
+\fB# class <major> <minor>\fP
+.UNINDENT
+.SS disconnect
+.sp
+Disconnect device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# disconnect [\-t type] <remote address>\fP
+.UNINDENT
+.SS con
+.sp
+List connections
+.INDENT 0.0
+.TP
+.B Usage
+\fB# con\fP
+.UNINDENT
+.SS find
+.sp
+Discover nearby devices
+.INDENT 0.0
+.TP
+.B Usage
+\fB# find [\-l|\-b] [\-L]\fP
+.UNINDENT
+.SS find\-service
+.sp
+Discover nearby service
+.INDENT 0.0
+.TP
+.B Usage
+\fB# find\-service [\-u UUID] [\-r RSSI_Threshold] [\-l|\-b]\fP
+.UNINDENT
+.SS stop\-find
+.sp
+Stop discovery
+.INDENT 0.0
+.TP
+.B Usage
+\fB# stop\-find [\-l|\-b]\fP
+.UNINDENT
+.SS name
+.sp
+Set local name
+.INDENT 0.0
+.TP
+.B Usage
+\fB# name <name> [shortname]\fP
+.UNINDENT
+.SS pair
+.sp
+Pair with a remote device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pair [\-c cap] [\-t type] <remote address>\fP
+.UNINDENT
+.SS cancelpair
+.sp
+Cancel pairing
+.INDENT 0.0
+.TP
+.B Usage
+\fB# cancelpair [\-t type] <remote address>\fP
+.UNINDENT
+.SS unpair
+.sp
+Unpair device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unpair [\-t type] <remote address>\fP
+.UNINDENT
+.SS keys
+.sp
+Load Link Keys
+.INDENT 0.0
+.TP
+.B Usage
+\fBkeys\fP
+.UNINDENT
+.SS ltks
+.sp
+Load Long Term Keys
+.INDENT 0.0
+.TP
+.B Usage
+\fB# ltks\fP
+.UNINDENT
+.SS irks
+.sp
+Load Identity Resolving Keys
+.INDENT 0.0
+.TP
+.B Usage
+\fB# irks [\-\-local index] [\-\-file file path]\fP
+.UNINDENT
+.SS block
+.sp
+Block Device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# block [\-t type] <remote address>\fP
+.UNINDENT
+.SS unblock
+.sp
+Unblock Device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unblock [\-t type] <remote address>\fP
+.UNINDENT
+.SS add\-uuid
+.sp
+Add UUID
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-uuid <UUID> <service class hint>\fP
+.UNINDENT
+.SS rm\-uuid
+.sp
+Remove UUID
+.INDENT 0.0
+.TP
+.B Usage
+\fB# rm\-uuid <UUID>\fP
+.UNINDENT
+.SS clr\-uuids
+.sp
+Clear UUIDs
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clear\-uuids\fP
+.UNINDENT
+.SS local\-oob
+.sp
+Local OOB data
+.INDENT 0.0
+.TP
+.B Usage
+\fB# local\-oob\fP
+.UNINDENT
+.SS remote\-oob
+.sp
+Remote OOB data
+.INDENT 0.0
+.TP
+.B Usage
+\fB# remote\-oob [\-t <addr_type>] [\-r <rand192>] [\-h <hash192>]
+[\-R <rand256>] [\-H <hash256>] <addr>\fP
+.UNINDENT
+.SS did
+.sp
+Set Device ID
+.INDENT 0.0
+.TP
+.B Usage
+\fB# did <source>:<vendor>:<product>:<version>\fP
+.UNINDENT
+.SS static\-addr
+.sp
+Set static address
+.INDENT 0.0
+.TP
+.B Usage
+\fB# static\-addr <address>\fP
+.UNINDENT
+.SS public\-addr
+.sp
+Set public address
+.INDENT 0.0
+.TP
+.B Usage
+\fB# public\-addr <address>\fP
+.UNINDENT
+.SS ext\-config
+.sp
+External configuration
+.INDENT 0.0
+.TP
+.B Usage
+\fB# ext\-config <on/off>\fP
+.UNINDENT
+.SS debug\-keys
+.sp
+Toggle debug keys
+.INDENT 0.0
+.TP
+.B Usage
+\fB# debug\-keys <on/off>\fP
+.UNINDENT
+.SS conn\-info
+.sp
+Get connection information
+.INDENT 0.0
+.TP
+.B Usage
+\fB# conn\-info [\-t type] <remote address>\fP
+.UNINDENT
+.SS io\-cap
+.sp
+Set IO Capability
+.INDENT 0.0
+.TP
+.B Usage
+\fB# io\-cap <cap>\fP
+.UNINDENT
+.SS scan\-params
+.sp
+Set Scan Parameters
+.INDENT 0.0
+.TP
+.B Usage
+\fB# scan\-params <interval> <window>\fP
+.UNINDENT
+.SS get\-clock
+.sp
+Get Clock Information
+.INDENT 0.0
+.TP
+.B Usage
+\fB# get\-clock [address]\fP
+.UNINDENT
+.SS add\-device
+.sp
+Add Device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-device [\-a action] [\-t type] <address>\fP
+.UNINDENT
+.SS del\-device
+.sp
+Remove Device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# del\-device [\-t type] <address>\fP
+.UNINDENT
+.SS clr\-devices
+.sp
+Clear Devices
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clr\-devices\fP
+.UNINDENT
+.SS bredr\-oob
+.sp
+Local OOB data (BR/EDR)
+.INDENT 0.0
+.TP
+.B Usage
+\fB# bredr\-oob\fP
+.UNINDENT
+.SS le\-oob
+.sp
+Local OOB data (LE)
+.INDENT 0.0
+.TP
+.B Usage
+\fB# le\-oob\fP
+.UNINDENT
+.SS advinfo
+.sp
+Show advertising features
+.INDENT 0.0
+.TP
+.B Usage
+\fB# advinfo\fP
+.UNINDENT
+.SS advsize
+.sp
+Show advertising size info
+.INDENT 0.0
+.TP
+.B Usage
+\fB# advsize [options] <instance_id>\fP
+.UNINDENT
+.SS add\-adv
+.sp
+Add advertising instance
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-adv [options] <instance_id>\fP
+.UNINDENT
+.SS rm\-adv
+.sp
+Remove advertising instance
+.INDENT 0.0
+.TP
+.B Usage
+\fB# rm\-adv <instance_id>\fP
+.UNINDENT
+.SS clr\-adv
+.sp
+Clear advertising instances
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clr\-adv\fP
+.UNINDENT
+.SS add\-ext\-adv\-params
+.sp
+Add extended advertising params
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-ext\-adv\-parms [options] <instance_id>\fP
+.UNINDENT
+.SS add\-ext\-adv\-data
+.sp
+Add extended advertising data
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-ext\-adv\-data [options] <instance_id>\fP
+.UNINDENT
+.SS appearance
+.sp
+Set appearance
+.INDENT 0.0
+.TP
+.B Usage
+\fB# appearance <appearance>\fP
+.UNINDENT
+.SS phy
+.sp
+Get/Set PHY Configuration
+.INDENT 0.0
+.TP
+.B Usage
+\fB# phy [LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] [LECODEDTX] [LECODEDRX]
+[BR1M1SLOT] [BR1M3SLOT] [BR1M5SLOT][EDR2M1SLOT] [EDR2M3SLOT]
+[EDR2M5SLOT][EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]\fP
+.UNINDENT
+.SS wbs
+.sp
+Toggle Wideband\-Speech support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# wbs <on/off>\fP
+.UNINDENT
+.SS secinfo
+.sp
+Show security information
+.INDENT 0.0
+.TP
+.B Usage
+\fB# secinfo\fP
+.UNINDENT
+.SS expinfo
+.sp
+Show experimental features
+.INDENT 0.0
+.TP
+.B Usage
+\fB# expinfo\fP
+.UNINDENT
+.SS exp\-debug
+.sp
+Set debug feature
+.INDENT 0.0
+.TP
+.B Usage
+\fB# exp\-debug <on/off>\fP
+.UNINDENT
+.SS exp\-privacy
+.sp
+Set LL privacy feature
+.INDENT 0.0
+.TP
+.B Usage
+\fB# exp\-privacy <on/off>\fP
+.UNINDENT
+.SS exp\-quality
+.sp
+Set bluetooth quality report feature
+.INDENT 0.0
+.TP
+.B Usage
+\fB# exp\-quality <on/off>\fP
+.UNINDENT
+.SS exp\-offload
+.sp
+Toggle codec support
+.INDENT 0.0
+.TP
+.B Usage
+\fB# exp\-offload <on/off>\fP
+.UNINDENT
+.SS read\-sysconfig
+.sp
+Read System Configuration
+.INDENT 0.0
+.TP
+.B Usage
+\fB# read\-sysconfig\fP
+.UNINDENT
+.SS set\-sysconfig
+.sp
+Set System Configuration
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-sysconfig <\-v|\-h> [options...]\fP
+.UNINDENT
+.SS get\-flags
+.sp
+Get device flags
+.SS set\-flags
+.sp
+Set device flags
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-flags [\-f flags] [\-t type] <address>\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-mgmt.rst b/client/bluetoothctl-mgmt.rst
new file mode 100644
index 0000000..4baed64
--- /dev/null
+++ b/client/bluetoothctl-mgmt.rst
@@ -0,0 +1,559 @@
+=================
+bluetoothctl-mgmt
+=================
+
+------------------
+Management Submenu
+------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: July 2023
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [mgmt.commands]
+
+Mgmt Commands
+=============
+
+select
+------
+
+Select a different index
+
+:Usage: **# select <index>**
+
+revision
+--------
+
+Get the MGMT Revision
+
+:Usage: **# revision**
+
+commands
+--------
+
+List supported commands
+
+:Usage: **# commands**
+
+config
+------
+
+Show configuration info
+
+:Usage: **# config**
+
+info
+----
+
+Show controller info
+
+:Usage: **# info**
+
+extinfo
+-------
+
+Show extended controller info
+
+:Usage: **# extinfo**
+
+auto-power
+----------
+
+Power all available features
+
+:Usage: **# auto-power**
+
+power
+-----
+
+Toggle powered state
+
+:Usage: **# power <on/off>**
+
+discov
+------
+
+Toggle discoverable state
+
+:Usage: **# discov <yes/no/limited> [timeout]**
+
+connectable
+-----------
+
+Toggle connectable state
+
+:Usage: **# connectable <on/off>**
+
+fast-conn
+---------
+
+Toggle fast connectable state
+
+:Usage: **# fast-conn <on/off>**
+
+bondable
+--------
+
+Toggle bondable state
+
+:Usage: **# bondable <on/off>**
+
+pairable
+--------
+
+Toggle bondable state
+
+:Usage: **# pairable <on/off>**
+
+linksec
+-------
+
+Toggle link level security
+
+:Usage: **# linksec <on/off>**
+
+ssp
+---
+
+Toggle SSP mode
+
+:Usage: **# spp <on/off>**
+
+sc
+--
+
+Toggle SC support
+
+:Usage: **# sc <on/off/only>**
+
+hs
+--
+
+Toggle HS support
+
+:Usage: **# hs <on/off>**
+
+le
+--
+
+Toggle LE support
+
+:Usage: **# le <on/off>**
+
+advertising
+-----------
+
+Toggle LE advertising
+
+:Usage: **# advertise <on/off>**
+
+bredr
+-----
+
+Toggle BR/EDR support
+
+:Usage: **# bredr <on/off>**
+
+privacy
+-------
+
+Toggle privacy support
+
+:Usage: **# privacy <on/off> [irk]**
+
+class
+-----
+
+Set device major/minor class
+
+:Usage: **# class <major> <minor>**
+
+disconnect
+----------
+
+Disconnect device
+
+:Usage: **# disconnect [-t type] <remote address>**
+
+con
+---
+
+List connections
+
+:Usage: **# con**
+
+find
+----
+
+Discover nearby devices
+
+:Usage: **# find [-l|-b] [-L]**
+
+find-service
+------------
+
+Discover nearby service
+
+:Usage: **# find-service [-u UUID] [-r RSSI_Threshold] [-l|-b]**
+
+stop-find
+---------
+
+Stop discovery
+
+:Usage: **# stop-find [-l|-b]**
+
+name
+----
+
+Set local name
+
+:Usage: **# name <name> [shortname]**
+
+pair
+----
+
+Pair with a remote device
+
+:Usage: **# pair [-c cap] [-t type] <remote address>**
+
+cancelpair
+----------
+
+Cancel pairing
+
+:Usage: **# cancelpair [-t type] <remote address>**
+
+unpair
+------
+
+Unpair device
+
+:Usage: **# unpair [-t type] <remote address>**
+
+keys
+----
+
+Load Link Keys
+
+:Usage: **keys**
+
+ltks
+----
+
+Load Long Term Keys
+
+:Usage: **# ltks**
+
+irks
+----
+
+Load Identity Resolving Keys
+
+:Usage: **# irks [--local index] [--file file path]**
+
+block
+-----
+
+Block Device
+
+:Usage: **# block [-t type] <remote address>**
+
+unblock
+-------
+
+Unblock Device
+
+:Usage: **# unblock [-t type] <remote address>**
+
+add-uuid
+--------
+
+Add UUID
+
+:Usage: **# add-uuid <UUID> <service class hint>**
+
+rm-uuid
+-------
+
+Remove UUID
+
+:Usage: **# rm-uuid <UUID>**
+
+clr-uuids
+---------
+
+Clear UUIDs
+
+:Usage: **# clear-uuids**
+
+local-oob
+---------
+
+Local OOB data
+
+:Usage: **# local-oob**
+
+remote-oob
+----------
+
+Remote OOB data
+
+:Usage: **# remote-oob [-t <addr_type>] [-r <rand192>] [-h <hash192>]
+	[-R <rand256>] [-H <hash256>] <addr>**
+
+did
+---
+
+Set Device ID
+
+:Usage: **# did <source>:<vendor>:<product>:<version>**
+
+static-addr
+-----------
+
+Set static address
+
+:Usage: **# static-addr <address>**
+
+public-addr
+-----------
+
+Set public address
+
+:Usage: **# public-addr <address>**
+
+ext-config
+----------
+
+External configuration
+
+:Usage: **# ext-config <on/off>**
+
+debug-keys
+----------
+
+Toggle debug keys
+
+:Usage: **# debug-keys <on/off>**
+
+conn-info
+---------
+
+Get connection information
+
+:Usage: **# conn-info [-t type] <remote address>**
+
+io-cap
+------
+
+Set IO Capability
+
+:Usage: **# io-cap <cap>**
+
+scan-params
+-----------
+
+Set Scan Parameters
+
+:Usage: **# scan-params <interval> <window>**
+
+get-clock
+---------
+
+Get Clock Information
+
+:Usage: **# get-clock [address]**
+
+add-device
+----------
+
+Add Device
+
+:Usage: **# add-device [-a action] [-t type] <address>**
+
+del-device
+----------
+
+Remove Device
+
+:Usage: **# del-device [-t type] <address>**
+
+clr-devices
+-----------
+
+Clear Devices
+
+:Usage: **# clr-devices**
+
+bredr-oob
+---------
+
+Local OOB data (BR/EDR)
+
+:Usage: **# bredr-oob**
+
+le-oob
+------
+
+Local OOB data (LE)
+
+:Usage: **# le-oob**
+
+advinfo
+-------
+
+Show advertising features
+
+:Usage: **# advinfo**
+
+advsize
+-------
+
+Show advertising size info
+
+:Usage: **# advsize [options] <instance_id>**
+
+add-adv
+-------
+
+Add advertising instance
+
+:Usage: **# add-adv [options] <instance_id>**
+
+rm-adv
+------
+
+Remove advertising instance
+
+:Usage: **# rm-adv <instance_id>**
+
+clr-adv
+-------
+
+Clear advertising instances
+
+:Usage: **# clr-adv**
+
+add-ext-adv-params
+------------------
+
+Add extended advertising params
+
+:Usage: **# add-ext-adv-parms [options] <instance_id>**
+
+add-ext-adv-data
+----------------
+
+Add extended advertising data
+
+:Usage: **# add-ext-adv-data [options] <instance_id>**
+
+appearance
+----------
+
+Set appearance
+
+:Usage: **# appearance <appearance>**
+
+phy
+---
+
+Get/Set PHY Configuration
+
+:Usage: **# phy [LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] [LECODEDTX] [LECODEDRX]
+	[BR1M1SLOT] [BR1M3SLOT] [BR1M5SLOT][EDR2M1SLOT] [EDR2M3SLOT]
+	[EDR2M5SLOT][EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]**
+
+wbs
+---
+
+Toggle Wideband-Speech support
+
+:Usage: **# wbs <on/off>**
+
+secinfo
+-------
+
+Show security information
+
+:Usage: **# secinfo**
+
+expinfo
+-------
+
+Show experimental features
+
+:Usage: **# expinfo**
+
+exp-debug
+---------
+
+Set debug feature
+
+:Usage: **# exp-debug <on/off>**
+
+exp-privacy
+-----------
+
+Set LL privacy feature
+
+:Usage: **# exp-privacy <on/off>**
+
+exp-quality
+-----------
+
+Set bluetooth quality report feature
+
+:Usage: **# exp-quality <on/off>**
+
+exp-offload
+-----------
+
+Toggle codec support
+
+:Usage: **# exp-offload <on/off>**
+
+read-sysconfig
+--------------
+
+Read System Configuration
+
+:Usage: **# read-sysconfig**
+
+set-sysconfig
+-------------
+
+Set System Configuration
+
+:Usage: **# set-sysconfig <-v|-h> [options...]**
+
+get-flags
+---------
+
+Get device flags
+
+
+set-flags
+---------
+
+Set device flags
+
+:Usage: **# set-flags [-f flags] [-t type] <address>**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-monitor.1 b/client/bluetoothctl-monitor.1
new file mode 100644
index 0000000..202d41a
--- /dev/null
+++ b/client/bluetoothctl-monitor.1
@@ -0,0 +1,111 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-MONITOR" "1" "July 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-monitor \- Monitor Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [monitor.commands]
+.SH MONITOR COMMANDS
+.SS set\-rssi\-threshold
+.sp
+Set RSSI threshold parameter
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-rssi\-threshold <low_threshold> <high_threshold>\fP
+.UNINDENT
+.SS set\-rssi\-timeout
+.sp
+Set RSSI timeout parameter
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-rssi\-timeout <low_timeout> <high_timeout>\fP
+.UNINDENT
+.SS set\-rssi\-sampling\-period
+.sp
+Set RSSI sampling period parameter
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-rssi\-timeout <low_timeout> <high_timeout>\fP
+.UNINDENT
+.SS add\-or\-pattern
+.sp
+Register \(aqor pattern\(aq type monitor with the specified RSSI parameters
+.INDENT 0.0
+.TP
+.B Usage
+\fB# add\-or\-pattern [patterns=pattern1 pattern2 ...]\fP
+.UNINDENT
+.SS get\-pattern
+.sp
+Get advertisement monitor
+.INDENT 0.0
+.TP
+.B Usage
+\fB# get\-pattern <monitor\-id/all>\fP
+.UNINDENT
+.SS remove\-pattern
+.sp
+Remove advertisement monitor
+.INDENT 0.0
+.TP
+.B Usage
+\fB# remove\-pattern <monitor\-id/all>\fP
+.UNINDENT
+.SS get\-supported\-info
+.sp
+Get advertisement manager supported features and supported monitor types
+.INDENT 0.0
+.TP
+.B Usage
+\fB# get\-supported\-info\fP
+.UNINDENT
+.SS print\-usage
+.sp
+Print the command usage
+.INDENT 0.0
+.TP
+.B Usage
+\fB# print\-usage <add\-or\-pattern>\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-monitor.rst b/client/bluetoothctl-monitor.rst
new file mode 100644
index 0000000..2357a56
--- /dev/null
+++ b/client/bluetoothctl-monitor.rst
@@ -0,0 +1,89 @@
+====================
+bluetoothctl-monitor
+====================
+
+---------------
+Monitor Submenu
+---------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: July 2023
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [monitor.commands]
+
+Monitor Commands
+================
+
+set-rssi-threshold
+------------------
+
+Set RSSI threshold parameter
+
+:Usage: **# set-rssi-threshold <low_threshold> <high_threshold>**
+
+set-rssi-timeout
+----------------
+
+Set RSSI timeout parameter
+
+:Usage: **# set-rssi-timeout <low_timeout> <high_timeout>**
+
+set-rssi-sampling-period
+-------------------------
+
+Set RSSI sampling period parameter
+
+:Usage: **# set-rssi-timeout <low_timeout> <high_timeout>**
+
+add-or-pattern
+--------------
+
+Register 'or pattern' type monitor with the specified RSSI parameters
+
+:Usage: **# add-or-pattern [patterns=pattern1 pattern2 ...]**
+
+get-pattern
+-----------
+
+Get advertisement monitor
+
+:Usage: **# get-pattern <monitor-id/all>**
+
+remove-pattern
+--------------
+
+Remove advertisement monitor
+
+:Usage: **# remove-pattern <monitor-id/all>**
+
+get-supported-info
+------------------
+
+Get advertisement manager supported features and supported monitor types
+
+:Usage: **# get-supported-info**
+
+print-usage
+-----------
+
+Print the command usage
+
+:Usage: **# print-usage <add-or-pattern>**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
+
diff --git a/client/bluetoothctl-player.1 b/client/bluetoothctl-player.1
new file mode 100644
index 0000000..8745ffa
--- /dev/null
+++ b/client/bluetoothctl-player.1
@@ -0,0 +1,199 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-PLAYER" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-player \- Media Player Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [player.commands]
+.SH MEDIA PLAYER COMMANDS
+.SS list
+.sp
+List available players.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list\fP
+.UNINDENT
+.SS show
+.sp
+Show player information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# show [player]\fP
+.UNINDENT
+.SS select
+.sp
+Select default player.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# select <player>\fP
+.UNINDENT
+.SS play
+.sp
+Start playback.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# play [item]\fP
+.UNINDENT
+.SS pause
+.sp
+Pause playback.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pause\fP
+.UNINDENT
+.SS stop
+.sp
+Stop playback.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# stop\fP
+.UNINDENT
+.SS next
+.sp
+Jump to next item.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# next\fP
+.UNINDENT
+.SS previous
+.sp
+Jump to previous item.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# previous\fP
+.UNINDENT
+.SS fast\-forward
+.sp
+Fast forward playback.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# fast\-forward\fP
+.UNINDENT
+.SS rewind
+.sp
+Rewind playback.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# rewind\fP
+.UNINDENT
+.SS equalizer
+.sp
+Enable/Disable equalizer.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# equalizer <on/off>\fP
+.UNINDENT
+.SS repeat
+.sp
+Set repeat mode.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# repeat <singletrack/alltrack/group/off>\fP
+.UNINDENT
+.SS shuffle
+.sp
+Set shuffle mode.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# shuffle <alltracks/group/off>\fP
+.UNINDENT
+.SS scan
+.sp
+Set scan mode.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# scan <alltracks/group/off>\fP
+.UNINDENT
+.SS change\-folder
+.sp
+Change current folder.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# change\-folder <item>\fP
+.UNINDENT
+.SS list\-items
+.sp
+List items of current folder.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list\-items [start] [end]\fP
+.UNINDENT
+.SS search
+.sp
+Search items containing string.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# search <string>\fP
+.UNINDENT
+.SS queue
+.sp
+Add item to playlist queue.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# queue <item>\fP
+.UNINDENT
+.SS show\-item
+.sp
+Show item information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# show\-item <item>\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-player.rst b/client/bluetoothctl-player.rst
new file mode 100644
index 0000000..e45e61a
--- /dev/null
+++ b/client/bluetoothctl-player.rst
@@ -0,0 +1,165 @@
+===================
+bluetoothctl-player
+===================
+
+--------------------
+Media Player Submenu
+--------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [player.commands]
+
+Media Player Commands
+=====================
+
+list
+----
+
+List available players.
+
+:Usage: **# list**
+
+show
+----
+
+Show player information.
+
+:Usage: **# show [player]**
+
+select
+------
+
+Select default player.
+
+:Usage: **# select <player>**
+
+play
+----
+
+Start playback.
+
+:Usage: **# play [item]**
+
+pause
+-----
+
+Pause playback.
+
+:Usage: **# pause**
+
+stop
+----
+
+Stop playback.
+
+:Usage: **# stop**
+
+next
+----
+
+Jump to next item.
+
+:Usage: **# next**
+
+previous
+--------
+
+Jump to previous item.
+
+:Usage: **# previous**
+
+fast-forward
+------------
+
+Fast forward playback.
+
+:Usage: **# fast-forward**
+
+rewind
+------
+
+Rewind playback.
+
+:Usage: **# rewind**
+
+equalizer
+---------
+
+Enable/Disable equalizer.
+
+:Usage: **# equalizer <on/off>**
+
+repeat
+------
+
+Set repeat mode.
+
+:Usage: **# repeat <singletrack/alltrack/group/off>**
+
+shuffle
+-------
+
+Set shuffle mode.
+
+:Usage: **# shuffle <alltracks/group/off>**
+
+scan
+----
+
+Set scan mode.
+
+:Usage: **# scan <alltracks/group/off>**
+
+change-folder
+-------------
+
+Change current folder.
+
+:Usage: **# change-folder <item>**
+
+list-items
+----------
+
+List items of current folder.
+
+:Usage: **# list-items [start] [end]**
+
+search
+------
+
+Search items containing string.
+
+:Usage: **# search <string>**
+
+queue
+-----
+
+Add item to playlist queue.
+
+:Usage: **# queue <item>**
+
+show-item
+---------
+
+Show item information.
+
+:Usage: **# show-item <item>**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-scan.1 b/client/bluetoothctl-scan.1
new file mode 100644
index 0000000..bea60a1
--- /dev/null
+++ b/client/bluetoothctl-scan.1
@@ -0,0 +1,172 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-SCAN" "1" "July 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-scan \- Scan Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [scan.commands]
+.SH SCAN COMMANDS
+.SS uuids
+.sp
+Set/Get UUIDs filter.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# uuids [all/uuid1 uuid2 ...]\fP
+.UNINDENT
+.SS rssi
+.sp
+Set/Get RSSI filter, and clears pathloss.
+.sp
+This sets the minimum rssi value for reporting device advertisements.
+.sp
+The value is in dBm.
+.sp
+If one or more discovery filters have been set, the RSSI delta\-threshold imposed
+by starting discovery by default will not be applied.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# rssi [rssi]\fP
+.TP
+.B Example
+\fB# rssi \-60\fP
+.UNINDENT
+.SS pathloss
+.sp
+Set/Get Pathloss filter, and clears RSSI.
+.sp
+This sets the maximum pathloss value for reporting device advertisements.
+.sp
+The value is in dB.
+.sp
+If one or more discovery filters have been set, the RSSI delta\-threshold
+imposed by starting discovery by default will not be applied.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pathloss [pathloss]\fP
+.TP
+.B Example
+\fB# pathloss 4\fP
+.UNINDENT
+.SS transport
+.sp
+Set/Get transport filter.
+.sp
+Transport parameter determines the type of scan.
+.sp
+The default is auto.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\(dqauto\(dq: interleaved scan
+.IP \(bu 2
+\(dqbredr\(dq: BR/EDR inquiry
+.IP \(bu 2
+\(dqle\(dq: LE scan only
+.UNINDENT
+.sp
+If \(dqle\(dq or \(dqbredr\(dq Transport is requested and the controller doesn\(aqt support it,
+an org.bluez.Error.Failed error will be returned.
+.sp
+If \(dqauto\(dq transport is requested, the scan will use LE, BREDR, or both,
+depending on what\(aqs currently enabled on the controller.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# transport [auto/bredr/le]\fP
+.UNINDENT
+.SS duplicate\-data
+.sp
+Set/Get duplicate data filter.
+.sp
+Disables duplicate detection of advertisement data.
+.sp
+When enabled, PropertiesChanged signals will be generated for ManufacturerData
+and ServiceData every time they are discovered.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# duplicate\-data [on/off]\fP
+.UNINDENT
+.SS discoverable
+.sp
+Set/Get discoverable filter.
+.sp
+Makes the adapter discoverable while discovering.
+.sp
+If the adapter is already discoverable, setting this filter won\(aqt have any
+effect.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discoverable [on/off]\fP
+.UNINDENT
+.SS pattern
+.sp
+Set/Get pattern filter.
+.sp
+Discover devices where the pattern matches either the prefix of the address or
+the device name, which is a convenient way to limit the number of device objects
+created during a discovery.
+.sp
+When set, it disregards device discoverable flags.
+.INDENT 0.0
+.TP
+.B Note
+The pattern matching is ignored if there are other clients that don\(aqt
+set any pattern, as it works as a logical OR. Also, setting an empty
+string \(dq\(dq pattern will match any device found.
+.TP
+.B Usage
+\fB# pattern [value]\fP
+.UNINDENT
+.SS clear
+.sp
+Clears discovery filter.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# clear [uuids/rssi/pathloss/transport/duplicate\-data/discoverable/pattern]\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-scan.rst b/client/bluetoothctl-scan.rst
new file mode 100644
index 0000000..54ea2e8
--- /dev/null
+++ b/client/bluetoothctl-scan.rst
@@ -0,0 +1,140 @@
+=================
+bluetoothctl-scan
+=================
+
+------------
+Scan Submenu
+------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: July 2023
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [scan.commands]
+
+Scan Commands
+=============
+
+uuids
+-----
+
+Set/Get UUIDs filter.
+
+:Usage: **# uuids [all/uuid1 uuid2 ...]**
+
+rssi
+----
+
+Set/Get RSSI filter, and clears pathloss.
+
+This sets the minimum rssi value for reporting device advertisements.
+
+The value is in dBm.
+
+If one or more discovery filters have been set, the RSSI delta-threshold imposed
+by starting discovery by default will not be applied.
+
+:Usage: **# rssi [rssi]**
+:Example: **# rssi -60**
+
+pathloss
+--------
+Set/Get Pathloss filter, and clears RSSI.
+
+This sets the maximum pathloss value for reporting device advertisements.
+
+The value is in dB.
+
+If one or more discovery filters have been set, the RSSI delta-threshold
+imposed by starting discovery by default will not be applied.
+
+:Usage: **# pathloss [pathloss]**
+:Example: **# pathloss 4**
+
+transport
+---------
+
+Set/Get transport filter.
+
+Transport parameter determines the type of scan.
+
+The default is auto.
+
+Possible values:
+
+- "auto": interleaved scan
+- "bredr": BR/EDR inquiry
+- "le": LE scan only
+
+If "le" or "bredr" Transport is requested and the controller doesn't support it,
+an org.bluez.Error.Failed error will be returned.
+
+If "auto" transport is requested, the scan will use LE, BREDR, or both,
+depending on what's currently enabled on the controller.
+
+:Usage: **# transport [auto/bredr/le]**
+
+duplicate-data
+--------------
+
+Set/Get duplicate data filter.
+
+Disables duplicate detection of advertisement data.
+
+When enabled, PropertiesChanged signals will be generated for ManufacturerData
+and ServiceData every time they are discovered.
+
+:Usage: **# duplicate-data [on/off]**
+
+discoverable
+------------
+
+Set/Get discoverable filter.
+
+Makes the adapter discoverable while discovering.
+
+If the adapter is already discoverable, setting this filter won't have any
+effect.
+
+:Usage: **# discoverable [on/off]**
+
+pattern
+-------
+
+Set/Get pattern filter.
+
+Discover devices where the pattern matches either the prefix of the address or
+the device name, which is a convenient way to limit the number of device objects
+created during a discovery.
+
+When set, it disregards device discoverable flags.
+
+:Note: The pattern matching is ignored if there are other clients that don't
+       set any pattern, as it works as a logical OR. Also, setting an empty
+       string "" pattern will match any device found.
+
+:Usage: **# pattern [value]**
+
+
+clear
+-----
+
+Clears discovery filter.
+
+:Usage: **# clear [uuids/rssi/pathloss/transport/duplicate-data/discoverable/pattern]**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl-transport.1 b/client/bluetoothctl-transport.1
new file mode 100644
index 0000000..038da7b
--- /dev/null
+++ b/client/bluetoothctl-transport.1
@@ -0,0 +1,140 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL-TRANSPORT" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl-transport \- Media Transport Submenu
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\-\-options] [transport.commands]
+.SH MEDIA TRANSPORT COMMANDS
+.SS list
+.sp
+List available transports.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list\fP
+.UNINDENT
+.SS show
+.sp
+Show transport information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# show [transport]\fP
+.UNINDENT
+.SS acquire
+.sp
+Acquire transport.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# acquire <transport> [transport1...]\fP
+.UNINDENT
+.sp
+Note:
+.sp
+If running the setup with an audio server that has LE Audio support (such as PipeWire) it will
+automatically acquire transports according to the configured roles.
+.SS select
+.sp
+Select transport. For transports created on a Broadcast Sink device only. This moves
+the transport to the \(dqbroadcasting\(dq state, pending acquire.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# select <transport> [transport1...]\fP
+.UNINDENT
+.sp
+Note:
+If running the setup with an audio server that has LE Audio support (such as PipeWire), it will
+prompt it to automatically acquire the transport.
+.SS unselect
+.sp
+Unelect transport. For transports created on a Broadcast Sink device only. This moves
+the transport to the \(dqidle\(dq state, pending release by the audio server. If the transport
+was acquired by bluetoothctl it can be released straight away, without having to be
+unselected.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unselect <transport> [transport1...]\fP
+.UNINDENT
+.sp
+Note:
+If running the setup with an audio server that has LE Audio support (such as PipeWire), it will
+prompt it to automatically release the transport.
+.SS release
+.sp
+Release transport.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# release <transport> [transport1...]\fP
+.UNINDENT
+.sp
+Note:
+.sp
+Transports acquired by an audio server, can only be released by said audio server.
+.SS send
+.sp
+Send contents of a file.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# send <transport> <filename>\fP
+.UNINDENT
+.SS receive
+.sp
+Get/Set file to receive.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# receive <transport> [filename]\fP
+.UNINDENT
+.SS volume
+.sp
+Get/Set transport volume.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# volume <transport> [value]\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl-transport.rst b/client/bluetoothctl-transport.rst
new file mode 100644
index 0000000..96156a8
--- /dev/null
+++ b/client/bluetoothctl-transport.rst
@@ -0,0 +1,116 @@
+======================
+bluetoothctl-transport
+======================
+
+-----------------------
+Media Transport Submenu
+-----------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [--options] [transport.commands]
+
+Media Transport Commands
+=========================
+
+list
+----
+
+List available transports.
+
+:Usage: **# list**
+
+show
+----
+
+Show transport information.
+
+:Usage: **# show [transport]**
+
+acquire
+-------
+
+Acquire transport.
+
+:Usage: **# acquire <transport> [transport1...]**
+
+Note:
+
+If running the setup with an audio server that has LE Audio support (such as PipeWire) it will
+automatically acquire transports according to the configured roles.
+
+select
+-------
+
+Select transport. For transports created on a Broadcast Sink device only. This moves
+the transport to the "broadcasting" state, pending acquire.
+
+:Usage: **# select <transport> [transport1...]**
+
+Note:
+If running the setup with an audio server that has LE Audio support (such as PipeWire), it will
+prompt it to automatically acquire the transport.
+
+unselect
+--------
+
+Unelect transport. For transports created on a Broadcast Sink device only. This moves
+the transport to the "idle" state, pending release by the audio server. If the transport
+was acquired by bluetoothctl it can be released straight away, without having to be
+unselected.
+
+:Usage: **# unselect <transport> [transport1...]**
+
+Note:
+If running the setup with an audio server that has LE Audio support (such as PipeWire), it will
+prompt it to automatically release the transport.
+
+release
+-------
+
+Release transport.
+
+:Usage: **# release <transport> [transport1...]**
+
+Note:
+
+Transports acquired by an audio server, can only be released by said audio server.
+
+send
+----
+
+Send contents of a file.
+
+:Usage: **# send <transport> <filename>**
+
+receive
+-------
+
+Get/Set file to receive.
+
+:Usage: **# receive <transport> [filename]**
+
+volume
+------
+
+Get/Set transport volume.
+
+:Usage: **# volume <transport> [value]**
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/bluetoothctl.1 b/client/bluetoothctl.1
new file mode 100644
index 0000000..7f3c61a
--- /dev/null
+++ b/client/bluetoothctl.1
@@ -0,0 +1,401 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHCTL" "1" "November 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+bluetoothctl \- Bluetooth Control Command Line Tool
+.SH SYNOPSIS
+.sp
+\fBbluetoothctl\fP [\fB\-a\fP \fIcapability\fP] [\fB\-e\fP] [\fB\-m\fP] [\fB\-t\fP \fIseconds\fP]
+[\fB\-v\fP] [\fB\-h\fP]
+.SH DESCRIPTION
+.sp
+\fBbluetoothctl(1)\fP interactive bluetooth control tool. The tool works with
+Bluetooth Classic (BR/EDR) and Bluetooth Low Energy (LE) controllers.
+.sp
+The tool is menu driven but can be automated from the command line.
+Examples are given in the automation section.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-a \ capability\fR,\fB \ \-\-agent \ capability
+Register agent handler: <capability>
+.TP
+.B  \-e\fP,\fB  \-\-endpoints
+Register Media endpoints
+.TP
+.B  \-m\fP,\fB  \-\-monitor
+Enable monitor output
+.TP
+.BI \-t \ seconds\fR,\fB \ \-\-timeout \ seconds
+Timeout in seconds for non\-interactive mode
+.TP
+.B  \-v\fP,\fB  \-\-version
+Display version
+.TP
+.B  \-h\fP,\fB  \-\-help
+Display help
+.UNINDENT
+.SH COMMANDS
+.SS list
+.sp
+List available controllers.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# list\fP
+.UNINDENT
+.SS show
+.sp
+Controller information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# show [ctrl]\fP
+.UNINDENT
+.SS select
+.sp
+Select default controller.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# select <ctrl>\fP
+.UNINDENT
+.SS devices
+.sp
+List available devices, with an optional property as the filter.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# devices [Paired/Bonded/Trusted/Connected]\fP
+.UNINDENT
+.SS system\-alias
+.sp
+Set controller alias.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# system\-alias <name>\fP
+.UNINDENT
+.SS reset\-alias
+.sp
+Reset controller alias.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# reset\-alias\fP
+.UNINDENT
+.SS power
+.sp
+Set controller power.
+.sp
+When the controller is powered off, the USB port the controller is attached to
+is put into a suspend state.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# power <on/off>\fP
+.UNINDENT
+.SS advertise
+.sp
+Enable/disable advertising with given type.
+.sp
+If you exit the program advertising will be disabled.
+.sp
+When advertising the controller should advertise with random address but may
+use its public address if it does not support the feature (address of the
+device).
+.sp
+A device can advertise if it initiated the connection to another advertising
+device.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# advertise <on/off/type>\fP
+.UNINDENT
+.SS set\-alias
+.sp
+Set device alias.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# set\-alias <alias>\fP
+.UNINDENT
+.SS scan
+.sp
+Scan for devices.
+.sp
+For LE, scanning is an important requirement before connecting or pairing.
+.sp
+The purpose of scanning is to find devices that are advertising with their
+discoverable flag set (either limited or general). Once you have found the
+address then you can connect or pair.
+.sp
+Note the following when scanning:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+When scanning the controller will use a random address that is not
+resolvable so the public address is not leaked. A new random address is
+created every time scan on is used.
+.IP \(bu 2
+When turning on scanning the device will start receiving advertising reports
+of what devices are advertising.
+.IP \(bu 2
+The filtering of duplicate advertising reports may be enabled depending on
+the filtering settings.
+.IP \(bu 2
+Device objects found during a scan session will only be persisted if they
+are connected/paired otherwise they are removed after some time.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B Usage
+\fB# scan <on/off/bredr/le>\fP
+.UNINDENT
+.SS pair
+.sp
+Pair with device.
+.sp
+This will pair with a device and then trust and connect to it. If the device is
+already paired this will first remove the pairing.
+.sp
+The command can either be used while the controller is in the connected or not
+connected state.
+.sp
+If the controller is already connected then the pair command can be used without
+an arguments. If the controller is not connected, the pair command can be given
+the address of a device with an active scan report and it will initiate the
+connection before pairing.
+.sp
+Before pairing the agent must be selected to choose the authentication
+mechanism.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pair <dev>\fP
+.UNINDENT
+.SS pairable
+.sp
+Set controller pairable mode.
+.sp
+This enables/disables pairing. If pairing is disabled then the controller will
+not accept any pairing requests.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# pairable <on/off>\fP
+.UNINDENT
+.SS discoverable
+.sp
+Set discoverable mode.
+.sp
+This enables/disables discoverable mode. If discoverable is disabled then the
+controller will not respond to any scan requests.
+.sp
+In LE if discoverable if off the controller will just passively scan and not
+make scan requests to advertising devices. If on it will make the advertising
+requests.
+.sp
+It will use a random address if supported by the controller. The length of time
+\(dqdiscoverable on\(dq is valid is determined by discoverable\-timeout command.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discoverable <on/off>\fP
+.UNINDENT
+.SS discoverable\-timeout
+.sp
+Set discoverable timeout.
+.sp
+The time in seconds that \(dqdiscoverable on\(dq is valid.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# discoverable\-timeout [value]\fP
+.UNINDENT
+.SS agent
+.sp
+Enable/disable agent with given capability.
+.sp
+This chooses the local authentication mechanism of the controller. It is needed
+for pairing and allows you to choose the IO capabilities of the controller.
+.sp
+The valid agent capabilities are: DisplayOnly, DisplayYesNo, KeyboardDisplay,
+KeyboardOnly, NoInputNoOutput.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# agent <on/off/capability>\fP
+.UNINDENT
+.SS default\-agent
+.sp
+Set current agent as the default one.
+.sp
+After selecting the agent this will make it the default agent.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# default\-agent\fP
+.UNINDENT
+.SS trust
+.sp
+Trust device.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# trust <dev>\fP
+.UNINDENT
+.SS untrust
+.sp
+Untrust device.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# untrust <dev>\fP
+.UNINDENT
+.SS block
+.sp
+Block device.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# block <dev>\fP
+.UNINDENT
+.SS unblock
+.sp
+Unblock device
+.INDENT 0.0
+.TP
+.B Usage
+\fB# unblock <dev>\fP
+.UNINDENT
+.SS remove
+.sp
+Remove device.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# remove <dev>\fP
+.UNINDENT
+.SS connect
+.sp
+Connect device.
+.sp
+This will initiate a connection to a device.
+.sp
+To connect with an LE device the controller must have an active scan report of
+the device it wants to connect to.
+.sp
+If no advertising report is received before the timeout a
+le\-connection\-abort\-by\-local error will be issued. In that case either try
+again to connect assuming the device is advertising.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# connect <dev>\fP
+.UNINDENT
+.SS disconnect
+.sp
+Disconnect device.
+.sp
+For LE when disconnecting from an active connection the device address is not
+needed.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# disconnect <dev>\fP
+.UNINDENT
+.SS info
+.sp
+Device information.
+.INDENT 0.0
+.TP
+.B Usage
+\fB# info <dev>\fP
+.UNINDENT
+.SH ADVERTISE SUBMENU
+.sp
+See \fBbluetoothctl\-advertise(1)\fP\&.
+.SH MONITOR SUBMENU
+.sp
+See \fBbluetoothctl\-monitor(1)\fP
+.SH SCAN SUBMENU
+.sp
+See \fBbluetoothctl\-scan(1)\fP
+.SH GATT SUBMENU
+.sp
+See \fBbluetoothctl\-gatt(1)\fP
+.SH ADMIN SUBMENU
+.sp
+See \fBbluetoothctl\-admin(1)\fP
+.SH PLAYER SUBMENU
+.sp
+See \fBbluetoothctl\-player(1)\fP
+.SH ENDPOINT SUBMENU
+.sp
+See \fBbluetoothctl\-endpoint(1)\fP
+.SH TRANSPORT SUBMENU
+.sp
+See \fBbluetoothctl\-transport(1)\fP
+.SH MANAGEMENT SUBMENU
+.sp
+See \fBbluetoothctl\-mgmt(1)\fP
+.SH ASSISTANT SUBMENU
+.sp
+See \fBbluetoothctl\-assistant(1)\fP
+.SH AUTOMATION
+.sp
+Two common ways to automate the tool are to use Here Docs or the program expect.
+Using Here Docs to show information about the Bluetooth controller.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+bluetoothctl <<EOF
+list
+show
+EOF
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under the terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/client/bluetoothctl.rst b/client/bluetoothctl.rst
new file mode 100644
index 0000000..7454c1d
--- /dev/null
+++ b/client/bluetoothctl.rst
@@ -0,0 +1,363 @@
+============
+bluetoothctl
+============
+
+-----------------------------------
+Bluetooth Control Command Line Tool
+-----------------------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under the terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: November 2022
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**bluetoothctl** [**-a** *capability*] [**-e**] [**-m**] [**-t** *seconds*]
+[**-v**] [**-h**]
+
+DESCRIPTION
+===========
+
+**bluetoothctl(1)** interactive bluetooth control tool. The tool works with
+Bluetooth Classic (BR/EDR) and Bluetooth Low Energy (LE) controllers.
+
+The tool is menu driven but can be automated from the command line.
+Examples are given in the automation section.
+
+OPTIONS
+=======
+
+-a capability, --agent capability        Register agent handler: <capability>
+-e, --endpoints                  Register Media endpoints
+-m, --monitor                    Enable monitor output
+-t seconds, --timeout seconds    Timeout in seconds for non-interactive mode
+-v, --version       Display version
+-h, --help          Display help
+
+
+Commands
+========
+
+list
+----
+
+List available controllers.
+
+:Usage: **# list**
+
+show
+----
+
+Controller information.
+
+:Usage: **# show [ctrl]**
+
+select
+------
+
+Select default controller.
+
+:Usage: **# select <ctrl>**
+
+devices
+-------
+
+List available devices, with an optional property as the filter.
+
+:Usage: **# devices [Paired/Bonded/Trusted/Connected]**
+
+system-alias
+------------
+
+Set controller alias.
+
+:Usage: **# system-alias <name>**
+
+reset-alias
+-----------
+
+Reset controller alias.
+
+:Usage: **# reset-alias**
+
+power
+-----
+
+Set controller power.
+
+When the controller is powered off, the USB port the controller is attached to
+is put into a suspend state.
+
+:Usage: **# power <on/off>**
+
+advertise
+---------
+
+Enable/disable advertising with given type.
+
+If you exit the program advertising will be disabled.
+
+When advertising the controller should advertise with random address but may
+use its public address if it does not support the feature (address of the
+device).
+
+A device can advertise if it initiated the connection to another advertising
+device.
+
+:Usage: **# advertise <on/off/type>**
+
+set-alias
+---------
+
+Set device alias.
+
+:Usage: **# set-alias <alias>**
+
+scan
+----
+
+Scan for devices.
+
+For LE, scanning is an important requirement before connecting or pairing.
+
+The purpose of scanning is to find devices that are advertising with their
+discoverable flag set (either limited or general). Once you have found the
+address then you can connect or pair.
+
+Note the following when scanning:
+
+  - When scanning the controller will use a random address that is not
+    resolvable so the public address is not leaked. A new random address is
+    created every time scan on is used.
+  - When turning on scanning the device will start receiving advertising reports
+    of what devices are advertising.
+  - The filtering of duplicate advertising reports may be enabled depending on
+    the filtering settings.
+  - Device objects found during a scan session will only be persisted if they
+    are connected/paired otherwise they are removed after some time.
+
+:Usage: **# scan <on/off/bredr/le>**
+
+pair
+----
+
+Pair with device.
+
+This will pair with a device and then trust and connect to it. If the device is
+already paired this will first remove the pairing.
+
+The command can either be used while the controller is in the connected or not
+connected state.
+
+If the controller is already connected then the pair command can be used without
+an arguments. If the controller is not connected, the pair command can be given
+the address of a device with an active scan report and it will initiate the
+connection before pairing.
+
+Before pairing the agent must be selected to choose the authentication
+mechanism.
+
+:Usage: **# pair <dev>**
+
+pairable
+--------
+
+Set controller pairable mode.
+
+This enables/disables pairing. If pairing is disabled then the controller will
+not accept any pairing requests.
+
+:Usage: **# pairable <on/off>**
+
+discoverable
+------------
+
+Set discoverable mode.
+
+This enables/disables discoverable mode. If discoverable is disabled then the
+controller will not respond to any scan requests.
+
+In LE if discoverable if off the controller will just passively scan and not
+make scan requests to advertising devices. If on it will make the advertising
+requests.
+
+It will use a random address if supported by the controller. The length of time
+"discoverable on" is valid is determined by discoverable-timeout command.
+
+:Usage: **# discoverable <on/off>**
+
+discoverable-timeout
+--------------------
+
+Set discoverable timeout.
+
+The time in seconds that "discoverable on" is valid.
+
+:Usage: **# discoverable-timeout [value]**
+
+agent
+-----
+
+Enable/disable agent with given capability.
+
+This chooses the local authentication mechanism of the controller. It is needed
+for pairing and allows you to choose the IO capabilities of the controller.
+
+The valid agent capabilities are: DisplayOnly, DisplayYesNo, KeyboardDisplay,
+KeyboardOnly, NoInputNoOutput.
+
+:Usage: **# agent <on/off/capability>**
+
+default-agent
+-------------
+
+Set current agent as the default one.
+
+After selecting the agent this will make it the default agent.
+
+:Usage: **# default-agent**
+
+trust
+-----
+
+Trust device.
+
+:Usage: **# trust <dev>**
+
+untrust
+-------
+
+Untrust device.
+
+:Usage: **# untrust <dev>**
+
+block
+-----
+
+Block device.
+
+:Usage: **# block <dev>**
+
+unblock
+-------
+Unblock device
+
+:Usage: **# unblock <dev>**
+
+remove
+------
+
+Remove device.
+
+:Usage: **# remove <dev>**
+
+connect
+-------
+
+Connect device.
+
+This will initiate a connection to a device.
+
+To connect with an LE device the controller must have an active scan report of
+the device it wants to connect to.
+
+If no advertising report is received before the timeout a
+le-connection-abort-by-local error will be issued. In that case either try
+again to connect assuming the device is advertising.
+
+:Usage: **# connect <dev>**
+
+disconnect
+----------
+
+Disconnect device.
+
+For LE when disconnecting from an active connection the device address is not
+needed.
+
+:Usage: **# disconnect <dev>**
+
+info
+----
+
+Device information.
+
+:Usage: **# info <dev>**
+
+
+Advertise Submenu
+=================
+
+See **bluetoothctl-advertise(1)**.
+
+Monitor Submenu
+===============
+
+See **bluetoothctl-monitor(1)**
+
+Scan Submenu
+============
+
+See **bluetoothctl-scan(1)**
+
+Gatt Submenu
+============
+
+See **bluetoothctl-gatt(1)**
+
+Admin Submenu
+=============
+
+See **bluetoothctl-admin(1)**
+
+Player Submenu
+==============
+
+See **bluetoothctl-player(1)**
+
+Endpoint Submenu
+================
+
+See **bluetoothctl-endpoint(1)**
+
+Transport Submenu
+=================
+
+See **bluetoothctl-transport(1)**
+
+Management Submenu
+==================
+
+See **bluetoothctl-mgmt(1)**
+
+Assistant Submenu
+==================
+
+See **bluetoothctl-assistant(1)**
+
+AUTOMATION
+==========
+Two common ways to automate the tool are to use Here Docs or the program expect.
+Using Here Docs to show information about the Bluetooth controller.
+
+.. code::
+
+   bluetoothctl <<EOF
+   list
+   show
+   EOF
+
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/client/gatt.c b/client/gatt.c
index 8f29202..4dac885 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *  Copyright 2024 NXP
  *
  *
  */
@@ -164,6 +165,7 @@ static void print_service_proxy(GDBusProxy *proxy, const char *description)
 	DBusMessageIter iter;
 	const char *uuid;
 	dbus_bool_t primary;
+	uint16_t handle;
 
 	if (g_dbus_proxy_get_property(proxy, "UUID", &iter) == FALSE)
 		return;
@@ -175,10 +177,16 @@ static void print_service_proxy(GDBusProxy *proxy, const char *description)
 
 	dbus_message_iter_get_basic(&iter, &primary);
 
+	if (g_dbus_proxy_get_property(proxy, "Handle", &iter) == FALSE)
+		return;
+
+	dbus_message_iter_get_basic(&iter, &handle);
+
 	memset(&service, 0, sizeof(service));
 	service.path = (char *) g_dbus_proxy_get_path(proxy);
 	service.uuid = (char *) uuid;
 	service.primary = primary;
+	service.handle = handle;
 
 	print_service(&service, description);
 }
@@ -252,15 +260,22 @@ static void print_characteristic(GDBusProxy *proxy, const char *description)
 	struct chrc chrc;
 	DBusMessageIter iter;
 	const char *uuid;
+	uint16_t handle;
 
 	if (g_dbus_proxy_get_property(proxy, "UUID", &iter) == FALSE)
 		return;
 
 	dbus_message_iter_get_basic(&iter, &uuid);
 
+	if (g_dbus_proxy_get_property(proxy, "Handle", &iter) == FALSE)
+		return;
+
+	dbus_message_iter_get_basic(&iter, &handle);
+
 	memset(&chrc, 0, sizeof(chrc));
 	chrc.path = (char *) g_dbus_proxy_get_path(proxy);
 	chrc.uuid = (char *) uuid;
+	chrc.handle = handle;
 
 	print_chrc(&chrc, description);
 }
@@ -346,15 +361,22 @@ static void print_descriptor(GDBusProxy *proxy, const char *description)
 	struct desc desc;
 	DBusMessageIter iter;
 	const char *uuid;
+	uint16_t handle;
 
 	if (g_dbus_proxy_get_property(proxy, "UUID", &iter) == FALSE)
 		return;
 
 	dbus_message_iter_get_basic(&iter, &uuid);
 
+	if (g_dbus_proxy_get_property(proxy, "Handle", &iter) == FALSE)
+		return;
+
+	dbus_message_iter_get_basic(&iter, &handle);
+
 	memset(&desc, 0, sizeof(desc));
 	desc.path = (char *) g_dbus_proxy_get_path(proxy);
 	desc.uuid = (char *) uuid;
+	desc.handle = handle;
 
 	print_desc(&desc, description);
 }
@@ -554,6 +576,241 @@ GDBusProxy *gatt_select_attribute(GDBusProxy *parent, const char *arg)
 	return select_attribute_by_uuid(NULL, arg);
 }
 
+static char *find_local_attribute(const char *arg,
+					struct service **service,
+					struct chrc **chrc, struct desc **desc)
+{
+	GList *l;
+
+	for (l = local_services; l; l = g_list_next(l)) {
+		struct service *s = l->data;
+		GList *cl;
+
+		if (!strcmp(arg, s->path)) {
+			if (service)
+				*service = s;
+			return s->path;
+		}
+
+		if (!strcmp(arg, s->uuid)) {
+			if (service)
+				*service = s;
+			return s->path;
+		}
+
+		for (cl = s->chrcs; cl; cl = g_list_next(cl)) {
+			struct chrc *c = cl->data;
+			GList *dl;
+
+			if (!strcmp(arg, c->path)) {
+				if (chrc)
+					*chrc = c;
+				return c->path;
+			}
+
+			if (!strcmp(arg, c->uuid)) {
+				if (chrc)
+					*chrc = c;
+				return c->path;
+			}
+
+			for (dl = c->descs; dl; dl = g_list_next(dl)) {
+				struct desc *d = dl->data;
+
+				if (!strcmp(arg, d->path)) {
+					if (desc)
+						*desc = d;
+					return d->path;
+				}
+
+				if (!strcmp(arg, d->uuid)) {
+					if (desc)
+						*desc = d;
+					return d->path;
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+char *gatt_select_local_attribute(const char *arg)
+{
+	return find_local_attribute(arg, NULL, NULL, NULL);
+}
+
+static int parse_offset(const char *arg)
+{
+	char *endptr = NULL;
+	unsigned long offset;
+
+	offset = strtoul(arg, &endptr, 0);
+	if (!endptr || *endptr != '\0' || offset > UINT16_MAX) {
+		bt_shell_printf("Invalid offload: %s", arg);
+		return -EINVAL;
+	}
+
+	return offset;
+}
+
+void gatt_read_local_attribute(char *data, int argc, char *argv[])
+{
+	int offset = 0;
+	struct service *s = NULL;
+	struct chrc *c = NULL;
+	struct desc *d = NULL;
+
+	if (!find_local_attribute(data, &s, &c, &d)) {
+		bt_shell_printf("Unable to find local attribute %s\n", data);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (argc > 1) {
+		offset = parse_offset(argv[1]);
+		if (offset < 0)
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (s) {
+		bt_shell_printf("UUID %s", s->uuid);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	if (c) {
+		if ((size_t)offset >= c->value_len) {
+			bt_shell_printf("Invalid offset: %d >= %zd", offset,
+								c->value_len);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+		bt_shell_hexdump(&c->value[offset], c->value_len - offset);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	if (d) {
+		if ((size_t)offset >= d->value_len) {
+			bt_shell_printf("Invalid offset: %d >= %zd", offset,
+								d->value_len);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+		bt_shell_hexdump(&d->value[offset], d->value_len - offset);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+}
+
+static uint8_t *str2bytearray(char *arg, size_t *val_len)
+{
+	uint8_t value[MAX_ATTR_VAL_LEN];
+	char *entry;
+	unsigned int i;
+
+	for (i = 0; (entry = strsep(&arg, " \t")) != NULL; i++) {
+		long val;
+		char *endptr = NULL;
+
+		if (*entry == '\0')
+			continue;
+
+		if (i >= G_N_ELEMENTS(value)) {
+			bt_shell_printf("Too much data\n");
+			return NULL;
+		}
+
+		val = strtol(entry, &endptr, 0);
+		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
+			bt_shell_printf("Invalid value at index %d\n", i);
+			return NULL;
+		}
+
+		value[i] = val;
+	}
+
+	*val_len = i;
+
+	return util_memdup(value, i);
+}
+
+static int write_value(size_t *dst_len, uint8_t **dst_value, uint8_t *src_val,
+			size_t src_len, uint16_t offset, uint16_t max_len)
+{
+	if ((offset + src_len) > max_len)
+		return -EOVERFLOW;
+
+	if ((offset + src_len) != *dst_len) {
+		*dst_len = offset + src_len;
+		*dst_value = g_realloc(*dst_value, *dst_len);
+	}
+
+	if (src_val && src_len)
+		memcpy(*dst_value + offset, src_val, src_len);
+
+	return 0;
+}
+
+void gatt_write_local_attribute(char *data, int argc, char *argv[])
+{
+	int offset = 0;
+	struct service *s = NULL;
+	struct chrc *c = NULL;
+	struct desc *d = NULL;
+	uint8_t *value;
+	size_t value_len;
+
+	if (!find_local_attribute(data, &s, &c, &d)) {
+		bt_shell_printf("Unable to find local attribute %s\n", data);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	value = str2bytearray(argv[1], &value_len);
+	if (!value)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	if (argc > 2) {
+		offset = parse_offset(argv[2]);
+		if (offset < 0)
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (s) {
+		bt_shell_printf("Unable to overwrite local service %s\n", data);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (c) {
+		if (write_value(&c->value_len, &c->value,
+					value, value_len,
+					offset, c->max_val_len)) {
+			bt_shell_printf("Unable to write local attribute %s\n",
+									data);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		bt_shell_printf("[" COLORED_CHG "] Attribute %s (%s) written\n",
+				c->path, bt_uuidstr_to_str(c->uuid));
+
+		g_dbus_emit_property_changed(c->service->conn, c->path,
+					     CHRC_INTERFACE, "Value");
+	}
+
+	if (d) {
+		if (write_value(&d->value_len, &d->value,
+					value, value_len,
+					offset, d->max_val_len)) {
+			bt_shell_printf("Unable to write local attribute %s\n",
+									data);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		bt_shell_printf("[" COLORED_CHG "] Attribute %s (%s) written\n",
+				d->path, bt_uuidstr_to_str(d->uuid));
+
+		g_dbus_emit_property_changed(d->chrc->service->conn, d->path,
+					     DESC_INTERFACE, "Value");
+	}
+
+	free(value);
+}
+
 static char *attribute_generator(const char *text, int state, GList *source)
 {
 	static int index;
@@ -650,20 +907,6 @@ static void read_attribute(GDBusProxy *proxy, uint16_t offset)
 	bt_shell_printf("Attempting to read %s\n", g_dbus_proxy_get_path(proxy));
 }
 
-static int parse_offset(const char *arg)
-{
-	char *endptr = NULL;
-	unsigned long offset;
-
-	offset = strtoul(arg, &endptr, 0);
-	if (!endptr || *endptr != '\0' || offset > UINT16_MAX) {
-		bt_shell_printf("Invalid offload: %s", arg);
-		return -EINVAL;
-	}
-
-	return offset;
-}
-
 void gatt_read_attribute(GDBusProxy *proxy, int argc, char *argv[])
 {
 	const char *iface;
@@ -744,11 +987,15 @@ static int sock_send(struct io *io, struct iovec *iov, size_t iovlen)
 	struct msghdr msg;
 	int ret;
 
+	ret = io_get_fd(io);
+	if (ret < 0)
+		return ret;
+
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iov = iov;
 	msg.msg_iovlen = iovlen;
 
-	ret = sendmsg(io_get_fd(io), &msg, MSG_NOSIGNAL);
+	ret = sendmsg(ret, &msg, MSG_NOSIGNAL);
 	if (ret < 0) {
 		ret = -errno;
 		bt_shell_printf("sendmsg: %s", strerror(-ret));
@@ -782,38 +1029,6 @@ static void write_attribute(GDBusProxy *proxy,
 					g_dbus_proxy_get_path(proxy));
 }
 
-static uint8_t *str2bytearray(char *arg, size_t *val_len)
-{
-	uint8_t value[MAX_ATTR_VAL_LEN];
-	char *entry;
-	unsigned int i;
-
-	for (i = 0; (entry = strsep(&arg, " \t")) != NULL; i++) {
-		long int val;
-		char *endptr = NULL;
-
-		if (*entry == '\0')
-			continue;
-
-		if (i >= G_N_ELEMENTS(value)) {
-			bt_shell_printf("Too much data\n");
-			return NULL;
-		}
-
-		val = strtol(entry, &endptr, 0);
-		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
-			bt_shell_printf("Invalid value at index %d\n", i);
-			return NULL;
-		}
-
-		value[i] = val;
-	}
-
-	*val_len = i;
-
-	return util_memdup(value, i);
-}
-
 void gatt_write_attribute(GDBusProxy *proxy, int argc, char *argv[])
 {
 	const char *iface;
@@ -862,6 +1077,11 @@ static bool sock_read(struct io *io, void *user_data)
 	if (io != notify_io.io && !chrc)
 		return true;
 
+	if (fd < 0) {
+		bt_shell_printf("recvmsg: %s", strerror(-fd));
+		return false;
+	}
+
 	iov.iov_base = buf;
 	iov.iov_len = sizeof(buf);
 
@@ -1212,7 +1432,7 @@ static gboolean get_uuids(const GDBusPropertyTable *property,
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
 				DBUS_TYPE_STRING_AS_STRING, &entry);
 
-	for (uuid = uuids; uuid; uuid = g_list_next(uuid->next))
+	for (uuid = uuids; uuid; uuid = g_list_next(uuid))
 		dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
 							&uuid->data);
 
@@ -1238,7 +1458,7 @@ void gatt_register_app(DBusConnection *conn, GDBusProxy *proxy,
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	for (i = 0; i < argc; i++)
+	for (i = 1; i < argc; i++)
 		uuids = g_list_append(uuids, g_strdup(argv[i]));
 
 	if (uuids) {
@@ -1496,6 +1716,8 @@ static void service_set_primary(const char *input, void *user_data)
 		g_dbus_unregister_interface(service->conn, service->path,
 						SERVICE_INTERFACE);
 	}
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static uint16_t parse_handle(const char *arg)
@@ -1548,8 +1770,6 @@ void gatt_register_service(DBusConnection *conn, GDBusProxy *proxy,
 
 	bt_shell_prompt_input(service->path, "Primary (yes/no):",
 		 service_set_primary, service);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static struct service *service_find(const char *pattern)
@@ -2132,23 +2352,6 @@ static int parse_value_arg(DBusMessageIter *iter, uint8_t **value, int *len)
 	return 0;
 }
 
-static int write_value(size_t *dst_len, uint8_t **dst_value, uint8_t *src_val,
-			size_t src_len, uint16_t offset, uint16_t max_len)
-{
-	if ((offset + src_len) > max_len)
-		return -EOVERFLOW;
-
-	if ((offset + src_len) != *dst_len) {
-		*dst_len = offset + src_len;
-		*dst_value = g_realloc(*dst_value, *dst_len);
-	}
-
-	if (src_val && src_len)
-		memcpy(*dst_value + offset, src_val, src_len);
-
-	return 0;
-}
-
 static void authorize_write_response(const char *input, void *user_data)
 {
 	struct authorize_attribute_data *aad = user_data;
@@ -2589,6 +2792,8 @@ static void chrc_set_value(const char *input, void *user_data)
 	}
 
 	chrc->max_val_len = chrc->value_len;
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static gboolean attr_authorization_flag_exists(char **flags)
@@ -2645,8 +2850,6 @@ void gatt_register_chrc(DBusConnection *conn, GDBusProxy *proxy,
 	print_chrc(chrc, COLORED_NEW);
 
 	bt_shell_prompt_input(chrc->path, "Enter value:", chrc_set_value, chrc);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static struct chrc *chrc_find(const char *pattern)
@@ -3015,9 +3218,13 @@ static void proxy_property_changed(GDBusProxy *proxy, const char *name,
 			dbus_message_iter_get_fixed_array(&array, &value, &len);
 		}
 
-		write_value(&chrc->value_len, &chrc->value, value, len,
-				0, chrc->max_val_len);
-		bt_shell_hexdump(value, len);
+		if (write_value(&chrc->value_len, &chrc->value, value, len,
+				0, chrc->max_val_len)) {
+			bt_shell_printf("Unable to update property value for "
+					"%s\n", name);
+		} else {
+			bt_shell_hexdump(value, len);
+		}
 	}
 
 	g_dbus_emit_property_changed(conn, chrc->path, CHRC_INTERFACE, name);
diff --git a/client/gatt.h b/client/gatt.h
index fc2b8a8..bed9d3a 100644
--- a/client/gatt.h
+++ b/client/gatt.h
@@ -32,6 +32,10 @@ void gatt_release_write(GDBusProxy *proxy, const char *arg);
 void gatt_acquire_notify(GDBusProxy *proxy, const char *arg);
 void gatt_release_notify(GDBusProxy *proxy, const char *arg);
 
+char *gatt_select_local_attribute(const char *arg);
+void gatt_read_local_attribute(char *data, int argc, char *argv[]);
+void gatt_write_local_attribute(char *data, int argc, char *argv[]);
+
 void gatt_add_manager(GDBusProxy *proxy);
 void gatt_remove_manager(GDBusProxy *proxy);
 
diff --git a/client/main.c b/client/main.c
index 2816e88..3f8143d 100644
--- a/client/main.c
+++ b/client/main.c
@@ -4,7 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2012  Intel Corporation. All rights reserved.
- *
+ *  Copyright 2024 NXP
  *
  */
 
@@ -22,22 +22,28 @@
 
 #include <glib.h>
 
+#include "src/shared/mainloop.h"
 #include "src/shared/shell.h"
+#include "src/shared/timeout.h"
 #include "src/shared/util.h"
+#include "src/shared/ad.h"
 #include "gdbus/gdbus.h"
+#include "print.h"
 #include "agent.h"
 #include "gatt.h"
 #include "advertising.h"
 #include "adv_monitor.h"
 #include "admin.h"
 #include "player.h"
+#include "mgmt.h"
+#include "assistant.h"
 
 /* String display constants */
 #define COLORED_NEW	COLOR_GREEN "NEW" COLOR_OFF
 #define COLORED_CHG	COLOR_YELLOW "CHG" COLOR_OFF
 #define COLORED_DEL	COLOR_RED "DEL" COLOR_OFF
 
-#define PROMPT_ON	COLOR_BLUE "[bluetooth]" COLOR_OFF "# "
+#define PROMPT_ON	"[bluetooth]# "
 #define PROMPT_OFF	"Waiting to connect to bluetoothd..."
 
 static DBusConnection *dbus_conn;
@@ -50,10 +56,12 @@ struct adapter {
 	GDBusProxy *ad_proxy;
 	GDBusProxy *adv_monitor_proxy;
 	GList *devices;
+	GList *sets;
 };
 
 static struct adapter *default_ctrl;
 static GDBusProxy *default_dev;
+static char *default_local_attr;
 static GDBusProxy *default_attr;
 static GList *ctrl_list;
 static GList *battery_proxies;
@@ -61,6 +69,7 @@ static GList *battery_proxies;
 static const char *agent_arguments[] = {
 	"on",
 	"off",
+	"auto",
 	"DisplayOnly",
 	"DisplayYesNo",
 	"KeyboardDisplay",
@@ -97,14 +106,14 @@ static void setup_standard_input(void)
 
 static void connect_handler(DBusConnection *connection, void *user_data)
 {
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT_ON, COLOR_BLUE);
 }
 
 static void disconnect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_detach();
 
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT_OFF, NULL);
 
 	g_list_free_full(ctrl_list, proxy_leak);
 	g_list_free_full(battery_proxies, proxy_leak);
@@ -140,10 +149,32 @@ static void print_adapter(GDBusProxy *proxy, const char *description)
 
 }
 
+#define	DISTANCE_VAL_INVALID	0x7FFF
+
+static struct set_discovery_filter_args {
+	char *transport;
+	char *pattern;
+	dbus_uint16_t rssi;
+	dbus_int16_t pathloss;
+	char **uuids;
+	size_t uuids_len;
+	dbus_bool_t duplicate;
+	dbus_bool_t discoverable;
+	bool set;
+	bool active;
+	unsigned int timeout;
+} filter = {
+	.rssi = DISTANCE_VAL_INVALID,
+	.pathloss = DISTANCE_VAL_INVALID,
+	.set = true,
+};
+
 static void print_device(GDBusProxy *proxy, const char *description)
 {
 	DBusMessageIter iter;
 	const char *address, *name;
+	uint8_t *flags;
+	int flags_len = 0;
 
 	if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
 		return;
@@ -155,203 +186,39 @@ static void print_device(GDBusProxy *proxy, const char *description)
 	else
 		name = "<unknown>";
 
-	bt_shell_printf("%s%s%sDevice %s %s\n",
-				description ? "[" : "",
-				description ? : "",
-				description ? "] " : "",
-				address, name);
-}
-
-static void print_fixed_iter(const char *label, const char *name,
-						DBusMessageIter *iter)
-{
-	dbus_bool_t *valbool;
-	dbus_uint32_t *valu32;
-	dbus_uint16_t *valu16;
-	dbus_int16_t *vals16;
-	unsigned char *byte;
-	int len;
-
-	switch (dbus_message_iter_get_arg_type(iter)) {
-	case DBUS_TYPE_BOOLEAN:
-		dbus_message_iter_get_fixed_array(iter, &valbool, &len);
-
-		if (len <= 0)
-			return;
-
-		bt_shell_printf("%s%s:\n", label, name);
-		bt_shell_hexdump((void *)valbool, len * sizeof(*valbool));
-
-		break;
-	case DBUS_TYPE_UINT32:
-		dbus_message_iter_get_fixed_array(iter, &valu32, &len);
-
-		if (len <= 0)
-			return;
-
-		bt_shell_printf("%s%s:\n", label, name);
-		bt_shell_hexdump((void *)valu32, len * sizeof(*valu32));
-
-		break;
-	case DBUS_TYPE_UINT16:
-		dbus_message_iter_get_fixed_array(iter, &valu16, &len);
-
-		if (len <= 0)
-			return;
-
-		bt_shell_printf("%s%s:\n", label, name);
-		bt_shell_hexdump((void *)valu16, len * sizeof(*valu16));
-
-		break;
-	case DBUS_TYPE_INT16:
-		dbus_message_iter_get_fixed_array(iter, &vals16, &len);
+	if (g_dbus_proxy_get_property(proxy, "AdvertisingFlags", &iter)) {
+		DBusMessageIter array;
 
-		if (len <= 0)
-			return;
-
-		bt_shell_printf("%s%s:\n", label, name);
-		bt_shell_hexdump((void *)vals16, len * sizeof(*vals16));
+		dbus_message_iter_recurse(&iter, &array);
+		dbus_message_iter_get_fixed_array(&array, &flags, &flags_len);
+	}
 
-		break;
-	case DBUS_TYPE_BYTE:
-		dbus_message_iter_get_fixed_array(iter, &byte, &len);
+	if (!flags_len)
+		goto done;
 
-		if (len <= 0)
+	if (!(flags[0] & (BT_AD_FLAG_LIMITED | BT_AD_FLAG_GENERAL))) {
+		/* Only print hidden/non-discoverable if filter.discoverable is
+		 * not set.
+		 */
+		if (filter.discoverable)
 			return;
 
-		bt_shell_printf("%s%s:\n", label, name);
-		bt_shell_hexdump((void *)byte, len * sizeof(*byte));
+		bt_shell_printf("%s%s%s" COLOR_BOLDGRAY "Device %s %s"
+					COLOR_OFF "\n",
+					description ? "[" : "",
+					description ? : "",
+					description ? "] " : "",
+					address, name);
 
-		break;
-	default:
-		return;
-	};
-}
-
-static void print_iter(const char *label, const char *name,
-						DBusMessageIter *iter)
-{
-	dbus_bool_t valbool;
-	dbus_uint32_t valu32;
-	dbus_uint16_t valu16;
-	dbus_int16_t vals16;
-	unsigned char byte;
-	const char *valstr;
-	DBusMessageIter subiter;
-	char *entry;
-
-	if (iter == NULL) {
-		bt_shell_printf("%s%s is nil\n", label, name);
 		return;
 	}
 
-	switch (dbus_message_iter_get_arg_type(iter)) {
-	case DBUS_TYPE_INVALID:
-		bt_shell_printf("%s%s is invalid\n", label, name);
-		break;
-	case DBUS_TYPE_STRING:
-	case DBUS_TYPE_OBJECT_PATH:
-		dbus_message_iter_get_basic(iter, &valstr);
-		bt_shell_printf("%s%s: %s\n", label, name, valstr);
-		break;
-	case DBUS_TYPE_BOOLEAN:
-		dbus_message_iter_get_basic(iter, &valbool);
-		bt_shell_printf("%s%s: %s\n", label, name,
-					valbool == TRUE ? "yes" : "no");
-		break;
-	case DBUS_TYPE_UINT32:
-		dbus_message_iter_get_basic(iter, &valu32);
-		bt_shell_printf("%s%s: 0x%08x\n", label, name, valu32);
-		break;
-	case DBUS_TYPE_UINT16:
-		dbus_message_iter_get_basic(iter, &valu16);
-		bt_shell_printf("%s%s: 0x%04x\n", label, name, valu16);
-		break;
-	case DBUS_TYPE_INT16:
-		dbus_message_iter_get_basic(iter, &vals16);
-		bt_shell_printf("%s%s: %d\n", label, name, vals16);
-		break;
-	case DBUS_TYPE_BYTE:
-		dbus_message_iter_get_basic(iter, &byte);
-		bt_shell_printf("%s%s: 0x%02x (%d)\n", label, name, byte, byte);
-		break;
-	case DBUS_TYPE_VARIANT:
-		dbus_message_iter_recurse(iter, &subiter);
-		print_iter(label, name, &subiter);
-		break;
-	case DBUS_TYPE_ARRAY:
-		dbus_message_iter_recurse(iter, &subiter);
-
-		if (dbus_type_is_fixed(
-				dbus_message_iter_get_arg_type(&subiter))) {
-			print_fixed_iter(label, name, &subiter);
-			break;
-		}
-
-		while (dbus_message_iter_get_arg_type(&subiter) !=
-							DBUS_TYPE_INVALID) {
-			print_iter(label, name, &subiter);
-			dbus_message_iter_next(&subiter);
-		}
-		break;
-	case DBUS_TYPE_DICT_ENTRY:
-		dbus_message_iter_recurse(iter, &subiter);
-		entry = g_strconcat(name, " Key", NULL);
-		print_iter(label, entry, &subiter);
-		g_free(entry);
-
-		entry = g_strconcat(name, " Value", NULL);
-		dbus_message_iter_next(&subiter);
-		print_iter(label, entry, &subiter);
-		g_free(entry);
-		break;
-	default:
-		bt_shell_printf("%s%s has unsupported type\n", label, name);
-		break;
-	}
-}
-
-static void print_property_with_label(GDBusProxy *proxy, const char *name,
-					const char *label)
-{
-	DBusMessageIter iter;
-
-	if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
-		return;
-
-	print_iter("\t", label ? label : name, &iter);
-}
-
-static void print_property(GDBusProxy *proxy, const char *name)
-{
-	print_property_with_label(proxy, name, NULL);
-}
-
-static void print_uuid(const char *label, const char *uuid)
-{
-	const char *text;
-
-	text = bt_uuidstr_to_str(uuid);
-	if (text) {
-		char str[26];
-		unsigned int n;
-
-		str[sizeof(str) - 1] = '\0';
-
-		n = snprintf(str, sizeof(str), "%s", text);
-		if (n > sizeof(str) - 1) {
-			str[sizeof(str) - 2] = '.';
-			str[sizeof(str) - 3] = '.';
-			if (str[sizeof(str) - 4] == ' ')
-				str[sizeof(str) - 4] = '.';
-
-			n = sizeof(str) - 1;
-		}
-
-		bt_shell_printf("\t%s: %s%*c(%s)\n", label, str, 26 - n, ' ',
-									uuid);
-	} else
-		bt_shell_printf("\t%s: %*c(%s)\n", label, 26, ' ', uuid);
+done:
+	bt_shell_printf("%s%s%sDevice %s %s\n",
+					description ? "[" : "",
+					description ? : "",
+					description ? "] " : "",
+					address, name);
 }
 
 static void print_uuids(GDBusProxy *proxy)
@@ -368,7 +235,7 @@ static void print_uuids(GDBusProxy *proxy)
 
 		dbus_message_iter_get_basic(&value, &uuid);
 
-		print_uuid("UUID", uuid);
+		print_uuid("\t", "UUID", uuid);
 
 		dbus_message_iter_next(&value);
 	}
@@ -389,13 +256,13 @@ static void print_experimental(GDBusProxy *proxy)
 
 		dbus_message_iter_get_basic(&value, &uuid);
 
-		print_uuid("ExperimentalFeatures", uuid);
+		print_uuid("\t", "ExperimentalFeatures", uuid);
 
 		dbus_message_iter_next(&value);
 	}
 }
 
-static gboolean device_is_child(GDBusProxy *device, GDBusProxy *parent)
+static gboolean proxy_is_child(GDBusProxy *device, GDBusProxy *parent)
 {
 	DBusMessageIter iter;
 	const char *adapter, *path;
@@ -432,14 +299,14 @@ static gboolean service_is_child(GDBusProxy *service)
 					"org.bluez.Device1") != NULL;
 }
 
-static struct adapter *find_parent(GDBusProxy *device)
+static struct adapter *find_parent(GDBusProxy *proxy)
 {
 	GList *list;
 
 	for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) {
 		struct adapter *adapter = list->data;
 
-		if (device_is_child(device, adapter->proxy) == TRUE)
+		if (proxy_is_child(proxy, adapter->proxy) == TRUE)
 			return adapter;
 	}
 	return NULL;
@@ -466,12 +333,12 @@ static void set_default_device(GDBusProxy *proxy, const char *attribute)
 	path = g_dbus_proxy_get_path(proxy);
 
 	dbus_message_iter_get_basic(&iter, &desc);
-	desc = g_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", desc,
+	desc = g_strdup_printf("[%s%s%s]# ", desc,
 				attribute ? ":" : "",
 				attribute ? attribute + strlen(path) : "");
 
 done:
-	bt_shell_set_prompt(desc ? desc : PROMPT_ON);
+	bt_shell_set_prompt(desc ? desc : PROMPT_ON, COLOR_BLUE);
 	g_free(desc);
 }
 
@@ -562,6 +429,27 @@ static void admon_manager_added(GDBusProxy *proxy)
 	adv_monitor_register_app(dbus_conn);
 }
 
+static void print_set(GDBusProxy *proxy, const char *description)
+{
+	bt_shell_printf("%s%s%sDeviceSet %s\n",
+				description ? "[" : "",
+				description ? : "",
+				description ? "] " : "",
+				g_dbus_proxy_get_path(proxy));
+}
+
+static void set_added(GDBusProxy *proxy)
+{
+	struct adapter *adapter = find_parent(proxy);
+
+	if (!adapter)
+		return;
+
+	adapter->sets = g_list_append(adapter->sets, proxy);
+	print_set(proxy, COLORED_NEW);
+	bt_shell_set_env(g_dbus_proxy_get_path(proxy), proxy);
+}
+
 static void proxy_added(GDBusProxy *proxy, void *user_data)
 {
 	const char *interface;
@@ -597,6 +485,8 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
 	} else if (!strcmp(interface,
 				"org.bluez.AdvertisementMonitorManager1")) {
 		admon_manager_added(proxy);
+	} else if (!strcmp(interface, "org.bluez.DeviceSet1")) {
+		set_added(proxy);
 	}
 }
 
@@ -604,6 +494,7 @@ static void set_default_attribute(GDBusProxy *proxy)
 {
 	const char *path;
 
+	default_local_attr = NULL;
 	default_attr = proxy;
 
 	path = g_dbus_proxy_get_path(proxy);
@@ -646,6 +537,7 @@ static void adapter_removed(GDBusProxy *proxy)
 
 			ctrl_list = g_list_remove_link(ctrl_list, ll);
 			g_list_free(adapter->devices);
+			g_list_free(adapter->sets);
 			g_free(adapter);
 			g_list_free(ll);
 			return;
@@ -653,6 +545,19 @@ static void adapter_removed(GDBusProxy *proxy)
 	}
 }
 
+static void set_removed(GDBusProxy *proxy)
+{
+	struct adapter *adapter = find_parent(proxy);
+
+	if (!adapter)
+		return;
+
+	adapter->sets = g_list_remove(adapter->sets, proxy);
+
+	print_set(proxy, COLORED_DEL);
+	bt_shell_set_env(g_dbus_proxy_get_path(proxy), NULL);
+}
+
 static void proxy_removed(GDBusProxy *proxy, void *user_data)
 {
 	const char *interface;
@@ -693,6 +598,8 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
 	} else if (!strcmp(interface,
 			"org.bluez.AdvertisementMonitorManager1")) {
 		adv_monitor_remove_manager(dbus_conn);
+	} else if (!strcmp(interface, "org.bluez.DeviceSet1")) {
+		set_removed(proxy);
 	}
 }
 
@@ -719,7 +626,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 	interface = g_dbus_proxy_get_interface(proxy);
 
 	if (!strcmp(interface, "org.bluez.Device1")) {
-		if (default_ctrl && device_is_child(proxy,
+		if (default_ctrl && proxy_is_child(proxy,
 					default_ctrl->proxy) == TRUE) {
 			DBusMessageIter addr_iter;
 			char *str;
@@ -899,6 +806,11 @@ static gboolean parse_argument(int argc, char *argv[], const char **arg_table,
 {
 	const char **opt;
 
+	if (argc < 2) {
+		bt_shell_printf("Missing argument to %s\n", argv[0]);
+		return FALSE;
+	}
+
 	if (!strcmp(argv[1], "help")) {
 		for (opt = arg_table; opt && *opt; opt++)
 			bt_shell_printf("%s\n", *opt);
@@ -977,6 +889,8 @@ static void cmd_show(int argc, char *argv[])
 		bt_shell_printf("Controller %s\n", address);
 	}
 
+	print_property(adapter->proxy, "Manufacturer");
+	print_property(adapter->proxy, "Version");
 	print_property(adapter->proxy, "Name");
 	print_property(adapter->proxy, "Alias");
 	print_property(adapter->proxy, "Class");
@@ -1156,6 +1070,7 @@ static void cmd_pairable(int argc, char *argv[])
 
 static void cmd_discoverable(int argc, char *argv[])
 {
+	DBusMessageIter iter;
 	dbus_bool_t discoverable;
 	char *str;
 
@@ -1165,6 +1080,18 @@ static void cmd_discoverable(int argc, char *argv[])
 	if (check_default_ctrl() == FALSE)
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 
+	if (discoverable && g_dbus_proxy_get_property(default_ctrl->proxy,
+					"DiscoverableTimeout", &iter)) {
+		uint32_t value;
+
+		dbus_message_iter_get_basic(&iter, &value);
+
+		if (!value)
+			bt_shell_printf("Warning: setting discoverable while "
+					"discoverable-timeout not set(0) is not"
+					" recommended\n");
+	}
+
 	str = g_strdup_printf("discoverable %s",
 				discoverable == TRUE ? "on" : "off");
 
@@ -1255,26 +1182,6 @@ static void cmd_default_agent(int argc, char *argv[])
 	agent_default(dbus_conn, agent_manager);
 }
 
-#define	DISTANCE_VAL_INVALID	0x7FFF
-
-static struct set_discovery_filter_args {
-	char *transport;
-	char *pattern;
-	dbus_uint16_t rssi;
-	dbus_int16_t pathloss;
-	char **uuids;
-	size_t uuids_len;
-	dbus_bool_t duplicate;
-	dbus_bool_t discoverable;
-	bool set;
-	bool active;
-	unsigned int timeout;
-} filter = {
-	.rssi = DISTANCE_VAL_INVALID,
-	.pathloss = DISTANCE_VAL_INVALID,
-	.set = true,
-};
-
 static void start_discovery_reply(DBusMessage *message, void *user_data)
 {
 	dbus_bool_t enable = GPOINTER_TO_UINT(user_data);
@@ -1412,9 +1319,14 @@ static void cmd_scan(int argc, char *argv[])
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 
 	if (enable == TRUE) {
-		if (strcmp(mode, "")) {
+		if (!g_strcmp0(mode, "")) {
+			g_free(filter.transport);
+			filter.transport = NULL;
+			filter.set = false;
+		} else {
 			g_free(filter.transport);
 			filter.transport = g_strdup(mode);
+			filter.set = false;
 		}
 
 		set_discovery_filter(false);
@@ -1437,7 +1349,7 @@ static void cmd_scan_filter_uuids(int argc, char *argv[])
 		char **uuid;
 
 		for (uuid = filter.uuids; uuid && *uuid; uuid++)
-			print_uuid("UUID", *uuid);
+			print_uuid("\t", "UUID", *uuid);
 
 		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 	}
@@ -1721,6 +1633,39 @@ static struct GDBusProxy *find_device(int argc, char *argv[])
 	return proxy;
 }
 
+static struct GDBusProxy *find_set(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+
+	if (check_default_ctrl() == FALSE)
+		return NULL;
+
+	proxy = find_proxies_by_path(default_ctrl->sets, argv[1]);
+	if (!proxy) {
+		bt_shell_printf("DeviceSet %s not available\n", argv[1]);
+		return NULL;
+	}
+
+	return proxy;
+}
+
+static void cmd_set_info(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+
+	proxy = find_set(argc, argv);
+	if (!proxy)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	bt_shell_printf("DeviceSet %s\n", g_dbus_proxy_get_path(proxy));
+
+	print_property(proxy, "AutoConnect");
+	print_property(proxy, "Devices");
+	print_property(proxy, "Size");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
 static void cmd_info(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
@@ -1730,7 +1675,7 @@ static void cmd_info(int argc, char *argv[])
 
 	proxy = find_device(argc, argv);
 	if (!proxy)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		return cmd_set_info(argc, argv);
 
 	if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -1767,6 +1712,7 @@ static void cmd_info(int argc, char *argv[])
 	print_property(proxy, "TxPower");
 	print_property(proxy, "AdvertisingFlags");
 	print_property(proxy, "AdvertisingData");
+	print_property(proxy, "Sets");
 
 	battery_proxy = find_proxies_by_path(battery_proxies,
 					g_dbus_proxy_get_path(proxy));
@@ -2146,10 +2092,41 @@ static void cmd_set_alias(int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
+static void set_default_local_attribute(char *attr)
+{
+	char *desc = NULL;
+
+	default_local_attr = attr;
+	default_attr = NULL;
+
+	desc = g_strdup_printf("[%s]# ", attr);
+
+	bt_shell_set_prompt(desc, COLOR_BLUE);
+	g_free(desc);
+}
+
 static void cmd_select_attribute(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
 
+	if (!strcasecmp("local", argv[1])) {
+		char *attr;
+
+		if (argc < 2) {
+			bt_shell_printf("attribute/UUID required\n");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		attr = gatt_select_local_attribute(argv[2]);
+		if (!attr) {
+			bt_shell_printf("Unable to find %s\n", argv[2]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		set_default_local_attribute(attr);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
 	if (!default_dev) {
 		bt_shell_printf("No device connected\n");
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -2234,6 +2211,11 @@ static void cmd_attribute_info(int argc, char *argv[])
 
 static void cmd_read(int argc, char *argv[])
 {
+	if (default_local_attr) {
+		gatt_read_local_attribute(default_local_attr, argc, argv);
+		return;
+	}
+
 	if (!default_attr) {
 		bt_shell_printf("No attribute selected\n");
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -2244,6 +2226,11 @@ static void cmd_read(int argc, char *argv[])
 
 static void cmd_write(int argc, char *argv[])
 {
+	if (default_local_attr) {
+		gatt_write_local_attribute(default_local_attr, argc, argv);
+		return;
+	}
+
 	if (!default_attr) {
 		bt_shell_printf("No attribute selected\n");
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -2419,11 +2406,13 @@ static char *generic_generator(const char *text, int state,
 
 		index++;
 
-		if (g_dbus_proxy_get_property(proxy, property, &iter) == FALSE)
+		if (!property)
+			str = g_dbus_proxy_get_path(proxy);
+		else if (g_dbus_proxy_get_property(proxy, property, &iter))
+			dbus_message_iter_get_basic(&iter, &str);
+		else
 			continue;
 
-		dbus_message_iter_get_basic(&iter, &str);
-
 		if (!strncasecmp(str, text, len))
 			return strdup(str);
 	}
@@ -2469,6 +2458,23 @@ static char *dev_generator(const char *text, int state)
 			default_ctrl ? default_ctrl->devices : NULL, "Address");
 }
 
+static char *set_generator(const char *text, int state)
+{
+	return generic_generator(text, state,
+			default_ctrl ? default_ctrl->sets : NULL, NULL);
+}
+
+static char *dev_set_generator(const char *text, int state)
+{
+	char *str;
+
+	str = dev_generator(text, state);
+	if (str)
+		return str;
+
+	return set_generator(text, state);
+}
+
 static char *attribute_generator(const char *text, int state)
 {
 	return gatt_attribute_generator(text, state);
@@ -2730,6 +2736,21 @@ static void cmd_advertise_interval(int argc, char *argv[])
 	ad_advertise_interval(dbus_conn, &min, &max);
 }
 
+static void cmd_advertise_rsi(int argc, char *argv[])
+{
+	dbus_bool_t value;
+
+	if (argc < 2) {
+		ad_advertise_rsi(dbus_conn, NULL);
+		return;
+	}
+
+	if (!parse_argument(argc, argv, NULL, NULL, &value, NULL))
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	ad_advertise_rsi(dbus_conn, &value);
+}
+
 static void ad_clear_uuids(void)
 {
 	ad_disable_uuids(dbus_conn);
@@ -2928,6 +2949,8 @@ static const struct bt_shell_menu advertise_menu = {
 			"Set/Get advertise secondary channel" },
 	{ "interval", "[min] [max] ", cmd_advertise_interval,
 			"Set/Get advertise interval range" },
+	{ "rsi", "[on/off]", cmd_advertise_rsi,
+			"Show/Enable/Disable RSI to be advertised", NULL },
 	{ "clear", "[uuids/service/manufacturer/config-name...]", cmd_ad_clear,
 			"Clear advertise config" },
 	{ } },
@@ -3001,8 +3024,9 @@ static const struct bt_shell_menu gatt_menu = {
 	.entries = {
 	{ "list-attributes", "[dev/local]", cmd_list_attributes,
 				"List attributes", dev_generator },
-	{ "select-attribute", "<attribute/UUID>",  cmd_select_attribute,
-				"Select attribute", attribute_generator },
+	{ "select-attribute", "<attribute/UUID/local> [attribute/UUID]",
+				cmd_select_attribute, "Select attribute",
+				attribute_generator },
 	{ "attribute-info", "[attribute/UUID]",  cmd_attribute_info,
 				"Select attribute", attribute_generator },
 	{ "read", "[offset]", cmd_read, "Read attribute value" },
@@ -3030,7 +3054,7 @@ static const struct bt_shell_menu gatt_menu = {
 					"Unregister application service" },
 	{ "register-includes", "<UUID> [handle]", cmd_register_includes,
 					"Register as Included service in." },
-	{ "unregister-includes", "<Service-UUID><Inc-UUID>",
+	{ "unregister-includes", "<Service-UUID> <Inc-UUID>",
 			cmd_unregister_includes,
 				 "Unregister Included service." },
 	{ "register-characteristic",
@@ -3074,7 +3098,7 @@ static const struct bt_shell_menu main_menu = {
 							NULL },
 	{ "discoverable-timeout", "[value]", cmd_discoverable_timeout,
 					"Set discoverable timeout", NULL },
-	{ "agent",        "<on/off/capability>", cmd_agent,
+	{ "agent",        "<on/off/auto/capability>", cmd_agent,
 				"Enable/disable agent with given capability",
 							capability_generator},
 	{ "default-agent",NULL,       cmd_default_agent,
@@ -3085,8 +3109,8 @@ static const struct bt_shell_menu main_menu = {
 	{ "set-alias",    "<alias>",  cmd_set_alias, "Set device alias" },
 	{ "scan",         "<on/off/bredr/le>", cmd_scan,
 				"Scan for devices", scan_generator },
-	{ "info",         "[dev]",    cmd_info, "Device information",
-							dev_generator },
+	{ "info",         "[dev/set]",    cmd_info, "Device/Set information",
+							dev_set_generator },
 	{ "pair",         "[dev]",    cmd_pair, "Pair with device",
 							dev_generator },
 	{ "cancel-pairing",  "[dev]",    cmd_cancel_pairing,
@@ -3137,13 +3161,25 @@ static const struct bt_shell_opt opt = {
 
 static void client_ready(GDBusClient *client, void *user_data)
 {
+	unsigned int *timeout_id = user_data;
+
+	if (*timeout_id > 0)
+		timeout_remove(*timeout_id);
 	setup_standard_input();
 }
 
+static bool timeout_quit(void *user_data)
+{
+	mainloop_exit_failure();
+	return true;
+}
+
 int main(int argc, char *argv[])
 {
 	GDBusClient *client;
 	int status;
+	int timeout;
+	unsigned int timeout_id;
 
 	bt_shell_init(argc, argv, &opt);
 	bt_shell_set_menu(&main_menu);
@@ -3151,7 +3187,7 @@ int main(int argc, char *argv[])
 	bt_shell_add_submenu(&advertise_monitor_menu);
 	bt_shell_add_submenu(&scan_menu);
 	bt_shell_add_submenu(&gatt_menu);
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT_OFF, NULL);
 
 	if (agent_option)
 		auto_register_agent = g_strdup(agent_option);
@@ -3169,6 +3205,8 @@ int main(int argc, char *argv[])
 
 	admin_add_submenu();
 	player_add_submenu();
+	mgmt_add_submenu();
+	assistant_add_submenu();
 
 	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
 
@@ -3179,12 +3217,18 @@ int main(int argc, char *argv[])
 	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
 							property_changed, NULL);
 
-	g_dbus_client_set_ready_watch(client, client_ready, NULL);
-
+	timeout = bt_shell_get_timeout();
+	timeout_id = 0;
+	if (timeout > 0)
+		timeout_id = timeout_add(timeout * 1000, timeout_quit, NULL,
+						NULL);
+	g_dbus_client_set_ready_watch(client, client_ready, &timeout_id);
 	status = bt_shell_run();
 
 	admin_remove_submenu();
 	player_remove_submenu();
+	mgmt_remove_submenu();
+	assistant_remove_submenu();
 
 	g_dbus_client_unref(client);
 
diff --git a/client/mgmt.c b/client/mgmt.c
new file mode 100644
index 0000000..602b922
--- /dev/null
+++ b/client/mgmt.c
@@ -0,0 +1,6053 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <wordexp.h>
+#include <ctype.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/hci_lib.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "lib/uuid.h"
+
+#include "src/uuid-helper.h"
+#include "lib/mgmt.h"
+
+#include "src/shared/mainloop.h"
+#include "src/shared/io.h"
+#include "src/shared/util.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/shell.h"
+#include "client/mgmt.h"
+
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+static struct mgmt *mgmt = NULL;
+static uint16_t mgmt_index = MGMT_INDEX_NONE;
+
+static bool discovery = false;
+static bool resolve_names = true;
+
+static struct {
+	uint16_t index;
+	uint16_t req;
+	struct mgmt_addr_info addr;
+} prompt = {
+	.index = MGMT_INDEX_NONE,
+};
+
+
+static int pending_index = 0;
+
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
+#define PROMPT_ON	COLOR_BLUE "[mgmt]" COLOR_OFF "# "
+
+static void update_prompt(uint16_t index)
+{
+	char str[32];
+
+	if (index == MGMT_INDEX_NONE)
+		snprintf(str, sizeof(str), "[mgmt]# ");
+	else
+		snprintf(str, sizeof(str), "[hci%u]# ", index);
+
+	bt_shell_set_prompt(str, COLOR_BLUE);
+}
+
+void mgmt_set_index(const char *arg)
+{
+	if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+						!strcmp(arg, "all"))
+		mgmt_index = MGMT_INDEX_NONE;
+	else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+		mgmt_index = atoi(&arg[3]);
+	else
+		mgmt_index = atoi(arg);
+
+	update_prompt(mgmt_index);
+}
+
+static bool parse_setting(int argc, char **argv, uint8_t *val)
+{
+	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
+		*val = 1;
+	else if (strcasecmp(argv[1], "off") == 0)
+		*val = 0;
+	else
+		*val = atoi(argv[1]);
+	return true;
+}
+
+#define print(fmt, arg...) do { \
+		bt_shell_printf(fmt "\n", ## arg); \
+} while (0)
+
+#define error(fmt, arg...) do { \
+		bt_shell_printf(COLOR_RED fmt "\n" COLOR_OFF, ## arg); \
+} while (0)
+
+static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
+{
+	size_t i, len;
+
+	len = MIN((strlen(hexstr) / 2), buflen);
+	memset(buf, 0, len);
+
+	for (i = 0; i < len; i++)
+		sscanf(hexstr + (i * 2), "%02hhX", &buf[i]);
+
+	return len;
+}
+
+static size_t bin2hex(const uint8_t *buf, size_t buflen, char *str,
+								size_t strlen)
+{
+	size_t i;
+
+	for (i = 0; i < buflen && i < (strlen / 2); i++)
+		sprintf(str + (i * 2), "%02x", buf[i]);
+
+	return i;
+}
+
+static void print_eir(const uint8_t *eir, uint16_t eir_len)
+{
+	uint16_t parsed = 0;
+	char str[33];
+
+	while (parsed < eir_len - 1) {
+		uint8_t field_len = eir[0];
+
+		if (field_len == 0)
+			break;
+
+		parsed += field_len + 1;
+
+		if (parsed > eir_len)
+			break;
+
+		switch (eir[1]) {
+		case 0x01:
+			print("Flags: 0x%02x", eir[2]);
+			break;
+		case 0x0d:
+			print("Class of Device: 0x%02x%02x%02x",
+						eir[4], eir[3], eir[2]);
+			break;
+		case 0x0e:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("SSP Hash C-192: %s", str);
+			break;
+		case 0x0f:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("SSP Rand R-192: %s", str);
+			break;
+		case 0x1b:
+			ba2str((bdaddr_t *) (eir + 2), str);
+			print("LE Device Address: %s (%s)", str,
+					eir[8] ? "random" : "public");
+			break;
+		case 0x1c:
+			print("LE Role: 0x%02x", eir[2]);
+			break;
+		case 0x1d:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("SSP Hash C-256: %s", str);
+			break;
+		case 0x1e:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("SSP Rand R-256: %s", str);
+			break;
+		case 0x22:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("LE SC Confirmation Value: %s", str);
+			break;
+		case 0x23:
+			bin2hex(eir + 2, 16, str, sizeof(str));
+			print("LE SC Random Value: %s", str);
+			break;
+		default:
+			print("Type %u: %u byte%s", eir[1], field_len - 1,
+					(field_len - 1) == 1 ? "" : "s");
+			break;
+		}
+
+		eir += field_len + 1;
+	}
+}
+
+static bool load_identity(const char *path, struct mgmt_irk_info *irk)
+{
+	char *addr, *key;
+	unsigned int type;
+	int n;
+	FILE *fp;
+
+	fp = fopen(path, "r");
+	if (!fp) {
+		error("Failed to open identity file: %s", strerror(errno));
+		return false;
+	}
+
+	n = fscanf(fp, "%m[0-9a-f:] (type %u) %m[0-9a-f]", &addr, &type, &key);
+
+	fclose(fp);
+
+	if (n != 3)
+		return false;
+
+	str2ba(addr, &irk->addr.bdaddr);
+	hex2bin(key, irk->val, sizeof(irk->val));
+
+	free(addr);
+	free(key);
+
+	switch (type) {
+	case 0:
+		irk->addr.type = BDADDR_LE_PUBLIC;
+		break;
+	case 1:
+		irk->addr.type = BDADDR_LE_RANDOM;
+		break;
+	default:
+		error("Invalid address type %u", type);
+		return false;
+	}
+
+	return true;
+}
+
+static void controller_error(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	const struct mgmt_ev_controller_error *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too short (%u bytes) controller error event", len);
+		return;
+	}
+
+	print("hci%u error 0x%02x", index, ev->error_code);
+}
+
+static void index_added(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	print("hci%u added", index);
+}
+
+static void index_removed(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	print("hci%u removed", index);
+}
+
+static void unconf_index_added(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	print("hci%u added (unconfigured)", index);
+}
+
+static void unconf_index_removed(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	print("hci%u removed (unconfigured)", index);
+}
+
+static void ext_index_added(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	const struct mgmt_ev_ext_index_added *ev = param;
+
+	print("hci%u added (type %u bus %u)", index, ev->type, ev->bus);
+}
+
+static void ext_index_removed(uint16_t index, uint16_t len,
+				const void *param, void *user_data)
+{
+	const struct mgmt_ev_ext_index_removed *ev = param;
+
+	print("hci%u removed (type %u bus %u)", index, ev->type, ev->bus);
+}
+
+static const char *options_str[] = {
+				"external",
+				"public-address",
+};
+
+static const char *options2str(uint32_t options)
+{
+	static char str[256];
+	unsigned i;
+	int off;
+
+	off = 0;
+	str[0] = '\0';
+
+	for (i = 0; i < NELEM(options_str); i++) {
+		if ((options & (1 << i)) != 0)
+			off += snprintf(str + off, sizeof(str) - off, "%s ",
+							options_str[i]);
+	}
+
+	return str;
+}
+
+static void new_config_options(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const uint32_t *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too short new_config_options event (%u)", len);
+		return;
+	}
+
+	print("hci%u new_config_options: %s", index, options2str(get_le32(ev)));
+}
+
+static const char *settings_str[] = {
+				"powered",
+				"connectable",
+				"fast-connectable",
+				"discoverable",
+				"bondable",
+				"link-security",
+				"ssp",
+				"br/edr",
+				"hs",
+				"le",
+				"advertising",
+				"secure-conn",
+				"debug-keys",
+				"privacy",
+				"configuration",
+				"static-addr",
+				"phy-configuration",
+				"wide-band-speech",
+				"cis-central",
+				"cis-peripheral",
+				"iso-broadcaster",
+				"sync-receiver"
+};
+
+static const char *settings2str(uint32_t settings)
+{
+	static char str[256];
+	unsigned i;
+	int off;
+
+	off = 0;
+	str[0] = '\0';
+
+	for (i = 0; i < NELEM(settings_str); i++) {
+		if ((settings & (1 << i)) != 0)
+			off += snprintf(str + off, sizeof(str) - off, "%s ",
+							settings_str[i]);
+	}
+
+	return str;
+}
+
+static void new_settings(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const uint32_t *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too short new_settings event (%u)", len);
+		return;
+	}
+
+	print("hci%u new_settings: %s", index, settings2str(get_le32(ev)));
+}
+
+static void discovering(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_discovering *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too short (%u bytes) discovering event", len);
+		return;
+	}
+
+	print("hci%u type %u discovering %s", index, ev->type,
+					ev->discovering ? "on" : "off");
+
+	if (ev->discovering == 0 && discovery)
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void new_link_key(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_new_link_key *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid new_link_key length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->key.addr.bdaddr, addr);
+	print("hci%u new_link_key %s type 0x%02x pin_len %d store_hint %u",
+		index, addr, ev->key.type, ev->key.pin_len, ev->store_hint);
+}
+
+static const char *typestr(uint8_t type)
+{
+	static const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
+
+	if (type <= BDADDR_LE_RANDOM)
+		return str[type];
+
+	return "(unknown)";
+}
+
+static void connected(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_device_connected *ev = param;
+	uint16_t eir_len;
+	char addr[18];
+
+	if (len < sizeof(*ev)) {
+		error("Invalid connected event length (%u bytes)", len);
+		return;
+	}
+
+	eir_len = get_le16(&ev->eir_len);
+	if (len != sizeof(*ev) + eir_len) {
+		error("Invalid connected event length (%u != eir_len %u)",
+								len, eir_len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s type %s connected eir_len %u", index, addr,
+					typestr(ev->addr.type), eir_len);
+}
+
+static void disconnected(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_device_disconnected *ev = param;
+	char addr[18];
+	uint8_t reason;
+
+	if (len < sizeof(struct mgmt_addr_info)) {
+		error("Invalid disconnected event length (%u bytes)", len);
+		return;
+	}
+
+	if (len < sizeof(*ev))
+		reason = MGMT_DEV_DISCONN_UNKNOWN;
+	else
+		reason = ev->reason;
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s type %s disconnected with reason %u",
+			index, addr, typestr(ev->addr.type), reason);
+}
+
+static void conn_failed(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_connect_failed *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid connect_failed event length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s type %s connect failed (status 0x%02x, %s)",
+			index, addr, typestr(ev->addr.type), ev->status,
+			mgmt_errstr(ev->status));
+}
+
+static void auth_failed(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_auth_failed *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid auth_failed event length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s auth failed with status 0x%02x (%s)",
+			index, addr, ev->status, mgmt_errstr(ev->status));
+}
+
+static void class_of_dev_changed(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_ev_class_of_dev_changed *ev = param;
+
+	if (len != sizeof(*ev)) {
+		error("Invalid class_of_dev_changed length (%u bytes)", len);
+		return;
+	}
+
+	print("hci%u class of device changed: 0x%02x%02x%02x", index,
+			ev->dev_class[2], ev->dev_class[1], ev->dev_class[0]);
+}
+
+static void local_name_changed(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_local_name_changed *ev = param;
+
+	if (len != sizeof(*ev)) {
+		error("Invalid local_name_changed length (%u bytes)", len);
+		return;
+	}
+
+	print("hci%u name changed: %s", index, ev->name);
+}
+
+static void confirm_name_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_confirm_name *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("confirm_name failed with status 0x%02x (%s)", status,
+							mgmt_errstr(status));
+		return;
+	}
+
+	if (len != sizeof(*rp)) {
+		error("confirm_name rsp length %u instead of %zu",
+							len, sizeof(*rp));
+		return;
+	}
+
+	ba2str(&rp->addr.bdaddr, addr);
+
+	if (status != 0)
+		error("confirm_name for %s failed: 0x%02x (%s)",
+			addr, status, mgmt_errstr(status));
+	else
+		print("confirm_name succeeded for %s", addr);
+}
+
+static char *eir_get_name(const uint8_t *eir, uint16_t eir_len)
+{
+	uint8_t parsed = 0;
+
+	if (eir_len < 2)
+		return NULL;
+
+	while (parsed < eir_len - 1) {
+		uint8_t field_len = eir[0];
+
+		if (field_len == 0)
+			break;
+
+		parsed += field_len + 1;
+
+		if (parsed > eir_len)
+			break;
+
+		/* Check for short of complete name */
+		if (eir[1] == 0x09 || eir[1] == 0x08)
+			return strndup((char *) &eir[2], field_len - 1);
+
+		eir += field_len + 1;
+	}
+
+	return NULL;
+}
+
+static unsigned int eir_get_flags(const uint8_t *eir, uint16_t eir_len)
+{
+	uint8_t parsed = 0;
+
+	if (eir_len < 2)
+		return 0;
+
+	while (parsed < eir_len - 1) {
+		uint8_t field_len = eir[0];
+
+		if (field_len == 0)
+			break;
+
+		parsed += field_len + 1;
+
+		if (parsed > eir_len)
+			break;
+
+		/* Check for flags */
+		if (eir[1] == 0x01)
+			return eir[2];
+
+		eir += field_len + 1;
+	}
+
+	return 0;
+}
+
+static void device_found(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_device_found *ev = param;
+	struct mgmt *mgmt = user_data;
+	uint16_t eir_len;
+	uint32_t flags;
+
+	if (len < sizeof(*ev)) {
+		error("Too short device_found length (%u bytes)", len);
+		return;
+	}
+
+	flags = btohl(ev->flags);
+
+	eir_len = get_le16(&ev->eir_len);
+	if (len != sizeof(*ev) + eir_len) {
+		error("dev_found: expected %zu bytes, got %u bytes",
+						sizeof(*ev) + eir_len, len);
+		return;
+	}
+
+	if (discovery) {
+		char addr[18], *name;
+
+		ba2str(&ev->addr.bdaddr, addr);
+		print("hci%u dev_found: %s type %s rssi %d "
+			"flags 0x%04x ", index, addr,
+			typestr(ev->addr.type), ev->rssi, flags);
+
+		if (ev->addr.type != BDADDR_BREDR)
+			print("AD flags 0x%02x ",
+					eir_get_flags(ev->eir, eir_len));
+
+		name = eir_get_name(ev->eir, eir_len);
+		if (name)
+			print("name %s", name);
+		else
+			print("eir_len %u", eir_len);
+
+		free(name);
+	}
+
+	if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
+		struct mgmt_cp_confirm_name cp;
+
+		memset(&cp, 0, sizeof(cp));
+		memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
+		if (resolve_names)
+			cp.name_known = 0;
+		else
+			cp.name_known = 1;
+
+		mgmt_reply(mgmt, MGMT_OP_CONFIRM_NAME, index, sizeof(cp), &cp,
+						confirm_name_rsp, NULL, NULL);
+	}
+}
+
+static void pin_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("PIN Code reply failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("PIN Reply successful");
+}
+
+static int mgmt_pin_reply(uint16_t index, const struct mgmt_addr_info *addr,
+					const char *pin, size_t len)
+{
+	struct mgmt_cp_pin_code_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(cp.addr));
+	cp.pin_len = len;
+	memcpy(cp.pin_code, pin, len);
+
+	return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_REPLY, index,
+				sizeof(cp), &cp, pin_rsp, NULL, NULL);
+}
+
+static void pin_neg_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("PIN Neg reply failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("PIN Negative Reply successful");
+}
+
+static int mgmt_pin_neg_reply(uint16_t index, const struct mgmt_addr_info *addr)
+{
+	struct mgmt_cp_pin_code_neg_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(cp.addr));
+
+	return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_NEG_REPLY, index,
+				sizeof(cp), &cp, pin_neg_rsp, NULL, NULL);
+}
+
+static void confirm_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("User Confirm reply failed. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("User Confirm Reply successful");
+}
+
+static int mgmt_confirm_reply(uint16_t index, const struct mgmt_addr_info *addr)
+{
+	struct mgmt_cp_user_confirm_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(*addr));
+
+	return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_REPLY, index,
+				sizeof(cp), &cp, confirm_rsp, NULL, NULL);
+}
+
+static void confirm_neg_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Confirm Neg reply failed. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("User Confirm Negative Reply successful");
+}
+
+static int mgmt_confirm_neg_reply(uint16_t index,
+					const struct mgmt_addr_info *addr)
+{
+	struct mgmt_cp_user_confirm_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(*addr));
+
+	return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
+				sizeof(cp), &cp, confirm_neg_rsp, NULL, NULL);
+}
+
+static void passkey_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("User Passkey reply failed. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("User Passkey Reply successful");
+}
+
+static int mgmt_passkey_reply(uint16_t index, const struct mgmt_addr_info *addr,
+						uint32_t passkey)
+{
+	struct mgmt_cp_user_passkey_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(*addr));
+	put_le32(passkey, &cp.passkey);
+
+	return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_REPLY, index,
+				sizeof(cp), &cp, passkey_rsp, NULL, NULL);
+}
+
+static void passkey_neg_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Passkey Neg reply failed. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("User Passkey Negative Reply successful");
+}
+
+static int mgmt_passkey_neg_reply(uint16_t index,
+					const struct mgmt_addr_info *addr)
+{
+	struct mgmt_cp_user_passkey_reply cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr, addr, sizeof(*addr));
+
+	return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_NEG_REPLY, index,
+				sizeof(cp), &cp, passkey_neg_rsp, NULL, NULL);
+}
+
+static void prompt_input(const char *input, void *user_data)
+{
+	size_t len;
+
+	len = strlen(input);
+
+	switch (prompt.req) {
+	case MGMT_EV_PIN_CODE_REQUEST:
+		if (len)
+			mgmt_pin_reply(prompt.index, &prompt.addr, input, len);
+		else
+			mgmt_pin_neg_reply(prompt.index, &prompt.addr);
+		break;
+	case MGMT_EV_USER_PASSKEY_REQUEST:
+		if (strlen(input) > 0)
+			mgmt_passkey_reply(prompt.index, &prompt.addr,
+								atoi(input));
+		else
+			mgmt_passkey_neg_reply(prompt.index,
+								&prompt.addr);
+		break;
+	case MGMT_EV_USER_CONFIRM_REQUEST:
+		if (len) {
+			if (input[0] == 'y' || input[0] == 'Y')
+				mgmt_confirm_reply(prompt.index, &prompt.addr);
+			else
+				mgmt_confirm_neg_reply(prompt.index,
+						&prompt.addr);
+		} else {
+			mgmt_confirm_neg_reply(prompt.index, &prompt.addr);
+			bt_shell_set_prompt(PROMPT_ON, COLOR_BLUE);
+		}
+		break;
+	}
+}
+
+static void ask(uint16_t index, uint16_t req, const struct mgmt_addr_info *addr,
+						const char *fmt, ...)
+{
+	char msg[256];
+	va_list ap;
+	int off;
+
+	prompt.index = index;
+	prompt.req = req;
+	memcpy(&prompt.addr, addr, sizeof(*addr));
+
+	va_start(ap, fmt);
+	off = vsnprintf(msg, sizeof(msg), fmt, ap);
+	va_end(ap);
+
+	snprintf(msg + off, sizeof(msg) - off, " %s ",
+					COLOR_BOLDGRAY ">>" COLOR_OFF);
+
+	bt_shell_prompt_input("", msg, prompt_input, NULL);
+}
+
+static void request_pin(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_pin_code_request *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid pin_code request length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s request PIN", index, addr);
+
+	ask(index, MGMT_EV_PIN_CODE_REQUEST, &ev->addr,
+				"PIN Request (press enter to reject)");
+}
+
+static void user_confirm(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_user_confirm_request *ev = param;
+	uint32_t val;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid user_confirm request length (%u)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	val = get_le32(&ev->value);
+
+	print("hci%u %s User Confirm %06u hint %u", index, addr,
+							val, ev->confirm_hint);
+
+	if (ev->confirm_hint)
+		ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
+				"Accept pairing with %s (yes/no)", addr);
+	else
+		ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
+			"Confirm value %06u for %s (yes/no)", val, addr);
+}
+
+static void request_passkey(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_user_passkey_request *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid passkey request length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s request passkey", index, addr);
+
+	ask(index, MGMT_EV_USER_PASSKEY_REQUEST, &ev->addr,
+			"Passkey Request (press enter to reject)");
+}
+
+static void passkey_notify(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_passkey_notify *ev = param;
+	char addr[18];
+
+	if (len != sizeof(*ev)) {
+		error("Invalid passkey request length (%u bytes)", len);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u %s request passkey", index, addr);
+
+	print("Passkey Notify: %06u (entered %u)", get_le32(&ev->passkey),
+								ev->entered);
+}
+
+static void local_oob_data_updated(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_ev_local_oob_data_updated *ev = param;
+	uint16_t eir_len;
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) local_oob_updated event", len);
+		return;
+	}
+
+	eir_len = le16_to_cpu(ev->eir_len);
+	if (len != sizeof(*ev) + eir_len) {
+		error("local_oob_updated: expected %zu bytes, got %u bytes",
+						sizeof(*ev) + eir_len, len);
+		return;
+	}
+
+	print("hci%u oob data updated: type %u len %u", index,
+						ev->type, eir_len);
+}
+
+static void advertising_added(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_ev_advertising_added *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) advertising_added event", len);
+		return;
+	}
+
+	print("hci%u advertising_added: instance %u", index, ev->instance);
+}
+
+static void advertising_removed(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_ev_advertising_removed *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) advertising_removed event", len);
+		return;
+	}
+
+	print("hci%u advertising_removed: instance %u", index, ev->instance);
+}
+
+static void flags_changed(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_device_flags_changed *ev = param;
+	char addr[18];
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) %s event", len, __func__);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+	print("hci%u device_flags_changed: %s (%s)", index, addr,
+							typestr(ev->addr.type));
+	print("     supp: 0x%08x  curr: 0x%08x",
+					ev->supported_flags, ev->current_flags);
+}
+
+static void advmon_added(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_adv_monitor_added *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) %s event", len, __func__);
+		return;
+	}
+
+	print("hci%u %s: handle %u", index, __func__,
+					le16_to_cpu(ev->monitor_handle));
+}
+
+static void advmon_removed(uint16_t index, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_ev_adv_monitor_removed *ev = param;
+
+	if (len < sizeof(*ev)) {
+		error("Too small (%u bytes) %s event", len, __func__);
+		return;
+	}
+
+	print("hci%u %s: handle %u", index, __func__,
+					le16_to_cpu(ev->monitor_handle));
+}
+
+static void version_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_version *rp = param;
+
+	if (status != 0) {
+		error("Reading mgmt version failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small version reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("MGMT Version %u, revision %u", rp->version,
+						get_le16(&rp->revision));
+
+done:
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_revision(int argc, char **argv)
+{
+	if (mgmt_send(mgmt, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
+				0, NULL, version_rsp, NULL, NULL) == 0) {
+		error("Unable to send read_version cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void commands_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_commands *rp = param;
+	uint16_t num_commands, num_events;
+	size_t expected_len;
+	int i;
+
+	if (status != 0) {
+		error("Read Supported Commands failed: status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small commands reply (%u bytes)", len);
+		goto done;
+	}
+
+	num_commands = get_le16(&rp->num_commands);
+	num_events = get_le16(&rp->num_events);
+
+	expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
+						num_events * sizeof(uint16_t);
+
+	if (len < expected_len) {
+		error("Too small commands reply (%u != %zu)",
+							len, expected_len);
+		goto done;
+	}
+
+	print("%u commands:", num_commands);
+	for (i = 0; i < num_commands; i++) {
+		uint16_t op = get_le16(rp->opcodes + i);
+		print("\t%s (0x%04x)", mgmt_opstr(op), op);
+	}
+
+	print("%u events:", num_events);
+	for (i = 0; i < num_events; i++) {
+		uint16_t ev = get_le16(rp->opcodes + num_commands + i);
+		print("\t%s (0x%04x)", mgmt_evstr(ev), ev);
+	}
+
+done:
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_commands(int argc,
+								char **argv)
+{
+	if (mgmt_send(mgmt, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
+				0, NULL, commands_rsp, NULL, NULL) == 0) {
+		error("Unable to send read_commands cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void config_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_config_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint32_t supported_options, missing_options;
+
+	if (status != 0) {
+		error("Reading hci%u config failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("hci%u:\tUnconfigured controller", index);
+
+	print("\tmanufacturer %u", le16_to_cpu(rp->manufacturer));
+
+	supported_options = le32_to_cpu(rp->supported_options);
+	print("\tsupported options: %s", options2str(supported_options));
+
+	missing_options = le32_to_cpu(rp->missing_options);
+	print("\tmissing options: %s", options2str(missing_options));
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void unconf_index_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_unconf_index_list *rp = param;
+	uint16_t count;
+	unsigned int i;
+
+	if (status != 0) {
+		error("Reading index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small index list reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = le16_to_cpu(rp->num_controllers);
+
+	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
+		error("Index count (%u) doesn't match reply length (%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Unconfigured index list with %u item%s",
+					count, count != 1 ? "s" : "");
+
+	for (i = 0; i < count; i++) {
+		uint16_t index = le16_to_cpu(rp->index[i]);
+
+		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, index, 0, NULL,
+				config_info_rsp, UINT_TO_PTR(index), NULL)) {
+			error("Unable to send read_config_info cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		pending_index++;
+	}
+
+	if (!count)
+		bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_config(int argc, char **argv)
+{
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_UNCONF_INDEX_LIST,
+					MGMT_INDEX_NONE, 0, NULL,
+					unconf_index_rsp, mgmt, NULL)) {
+			error("Unable to send unconf_index_list cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		return;
+	}
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, mgmt_index, 0, NULL,
+				config_info_rsp, UINT_TO_PTR(index), NULL)) {
+		error("Unable to send read_config_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void config_options_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_config_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint32_t supported_options, missing_options;
+
+	if (status != 0) {
+		error("Reading hci%u config failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("hci%u:\tConfiguration options", index);
+
+	supported_options = le32_to_cpu(rp->supported_options);
+	print("\tsupported options: %s", options2str(supported_options));
+
+	missing_options = le32_to_cpu(rp->missing_options);
+	print("\tmissing options: %s", options2str(missing_options));
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint32_t supported_settings, current_settings;
+	char addr[18];
+
+	if (status != 0) {
+		error("Reading hci%u info failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("hci%u:\tPrimary controller", index);
+
+	ba2str(&rp->bdaddr, addr);
+	print("\taddr %s version %u manufacturer %u class 0x%02x%02x%02x",
+			addr, rp->version, le16_to_cpu(rp->manufacturer),
+			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+
+	supported_settings = le32_to_cpu(rp->supported_settings);
+	print("\tsupported settings: %s", settings2str(supported_settings));
+
+	current_settings = le32_to_cpu(rp->current_settings);
+	print("\tcurrent settings: %s", settings2str(current_settings));
+
+	print("\tname %s", rp->name);
+	print("\tshort name %s", rp->short_name);
+
+	if (supported_settings & MGMT_SETTING_CONFIGURATION) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
+					index, 0, NULL, config_options_rsp,
+					UINT_TO_PTR(index), NULL)) {
+			error("Unable to send read_config cmd");
+			goto done;
+		}
+		return;
+	}
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void ext_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_ext_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint32_t supported_settings, current_settings;
+	char addr[18];
+
+	if (status != 0) {
+		error("Reading hci%u info failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("hci%u:\tPrimary controller", index);
+
+	ba2str(&rp->bdaddr, addr);
+	print("\taddr %s version %u manufacturer %u",
+			addr, rp->version, le16_to_cpu(rp->manufacturer));
+
+	supported_settings = le32_to_cpu(rp->supported_settings);
+	print("\tsupported settings: %s", settings2str(supported_settings));
+
+	current_settings = le32_to_cpu(rp->current_settings);
+	print("\tcurrent settings: %s", settings2str(current_settings));
+
+	if (supported_settings & MGMT_SETTING_CONFIGURATION) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
+					index, 0, NULL, config_options_rsp,
+					UINT_TO_PTR(index), NULL)) {
+			error("Unable to send read_config cmd");
+			goto done;
+		}
+		return;
+	}
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void index_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_index_list *rp = param;
+	struct mgmt *mgmt = user_data;
+	uint16_t count;
+	unsigned int i;
+
+	if (status != 0) {
+		error("Reading index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small index list reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = le16_to_cpu(rp->num_controllers);
+
+	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
+		error("Index count (%u) doesn't match reply length (%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Index list with %u item%s", count, count != 1 ? "s" : "");
+
+	for (i = 0; i < count; i++) {
+		uint16_t index = le16_to_cpu(rp->index[i]);
+
+		if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
+					info_rsp, UINT_TO_PTR(index), NULL)) {
+			error("Unable to send read_info cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		pending_index++;
+	}
+
+	if (!count)
+		bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_info(int argc, char **argv)
+{
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST,
+					MGMT_INDEX_NONE, 0, NULL,
+					index_rsp, mgmt, NULL)) {
+			error("Unable to send index_list cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		return;
+	}
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, mgmt_index, 0, NULL, info_rsp,
+					UINT_TO_PTR(mgmt_index), NULL)) {
+		error("Unable to send read_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void ext_index_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_ext_index_list *rp = param;
+	uint16_t count;
+	unsigned int i;
+
+	if (status != 0) {
+		error("Reading ext index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small ext index list reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = get_le16(&rp->num_controllers);
+
+	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
+		error("Index count (%u) doesn't match reply length (%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Extended index list with %u item%s",
+					count, count != 1 ? "s" : "");
+
+	for (i = 0; i < count; i++) {
+		uint16_t index = le16_to_cpu(rp->entry[i].index);
+		const char *busstr = hci_bustostr(rp->entry[i].bus);
+
+		switch (rp->entry[i].type) {
+		case 0x00:
+			print("Primary controller (hci%u,%s)", index, busstr);
+			if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO,
+						index, 0, NULL, ext_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+				error("Unable to send read_ext_info cmd");
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			pending_index++;
+			break;
+		case 0x01:
+			print("Unconfigured controller (hci%u,%s)",
+								index, busstr);
+			if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
+						index, 0, NULL, config_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+				error("Unable to send read_config cmd");
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			pending_index++;
+			break;
+		case 0x02:
+			print("AMP controller (hci%u,%s)", index, busstr);
+			break;
+		default:
+			print("Type %u controller (hci%u,%s)",
+					rp->entry[i].type, index, busstr);
+			break;
+		}
+	}
+
+	print("");
+
+	if (!count)
+		bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_extinfo(int argc, char **argv)
+{
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
+					MGMT_INDEX_NONE, 0, NULL,
+					ext_index_rsp, mgmt, NULL)) {
+			error("Unable to send ext_index_list cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		return;
+	}
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO, mgmt_index, 0, NULL,
+					ext_info_rsp,
+					UINT_TO_PTR(mgmt_index), NULL)) {
+		error("Unable to send ext_read_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void print_cap(const uint8_t *cap, uint16_t cap_len)
+{
+	uint16_t parsed = 0;
+
+	while (parsed < cap_len - 1) {
+		uint8_t field_len = cap[0];
+
+		if (field_len == 0)
+			break;
+
+		parsed += field_len + 1;
+
+		if (parsed > cap_len)
+			break;
+
+		switch (cap[1]) {
+		case 0x01:
+			print("\tFlags: 0x%02x", cap[2]);
+			break;
+		case 0x02:
+			print("\tMax Key Size (BR/EDR): %u", cap[2]);
+			break;
+		case 0x03:
+			print("\tMax Key Size (LE): %u", cap[2]);
+			break;
+		default:
+			print("\tType %u: %u byte%s", cap[1], field_len - 1,
+					(field_len - 1) == 1 ? "" : "s");
+			break;
+		}
+
+		cap += field_len + 1;
+	}
+}
+
+static void sec_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_controller_cap *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+
+	if (status != 0) {
+		error("Reading hci%u security failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	print("Primary controller (hci%u)", index);
+	print("\tInfo length: %u", le16_to_cpu(rp->cap_len));
+	print_cap(rp->cap, le16_to_cpu(rp->cap_len));
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void sec_index_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_ext_index_list *rp = param;
+	uint16_t count;
+	unsigned int i;
+
+	if (status != 0) {
+		error("Reading ext index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small ext index list reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = get_le16(&rp->num_controllers);
+
+	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
+		error("Index count (%u) doesn't match reply length (%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	for (i = 0; i < count; i++) {
+		uint16_t index = le16_to_cpu(rp->entry[i].index);
+
+		if (rp->entry[i].type != 0x00)
+			continue;
+
+		if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP,
+						index, 0, NULL, sec_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+			error("Unable to send read_security_info cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+		pending_index++;
+	}
+
+	if (!count)
+		bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_secinfo(int argc, char **argv)
+{
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
+					MGMT_INDEX_NONE, 0, NULL,
+					sec_index_rsp, mgmt, NULL)) {
+			error("Unable to send ext_index_list cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		return;
+	}
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP, mgmt_index, 0, NULL,
+					sec_info_rsp,
+					UINT_TO_PTR(mgmt_index), NULL)) {
+		error("Unable to send read_security_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void exp_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_exp_features_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+
+	if (status != 0) {
+		error("Reading hci%u exp features failed with status 0x%02x (%s)",
+					index, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small info reply (%u bytes)", len);
+		goto done;
+	}
+
+	if (index == MGMT_INDEX_NONE)
+		print("Global");
+	else
+		print("Primary controller (hci%u)", index);
+
+	print("\tNumber of experimental features: %u",
+					le16_to_cpu(rp->feature_count));
+
+done:
+	pending_index--;
+
+	if (pending_index > 0)
+		return;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void exp_index_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_ext_index_list *rp = param;
+	uint16_t count;
+	unsigned int i;
+
+	if (status != 0) {
+		error("Reading ext index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small ext index list reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = get_le16(&rp->num_controllers);
+
+	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
+		error("Index count (%u) doesn't match reply length (%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	for (i = 0; i < count; i++) {
+		uint16_t index = le16_to_cpu(rp->entry[i].index);
+
+		if (rp->entry[i].type != 0x00)
+			continue;
+
+		if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
+						index, 0, NULL, exp_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+				error("Unable to send read_exp_features_info cmd");
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+		pending_index++;
+	}
+}
+
+static void cmd_expinfo(int argc, char **argv)
+{
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
+					MGMT_INDEX_NONE, 0, NULL,
+					exp_index_rsp, mgmt, NULL)) {
+			error("Unable to send ext_index_list cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
+					MGMT_INDEX_NONE, 0, NULL,
+					exp_info_rsp,
+					UINT_TO_PTR(MGMT_INDEX_NONE), NULL)) {
+			error("Unable to send read_exp_features_info cmd");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		pending_index++;
+		return;
+	}
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, mgmt_index,
+					0, NULL, exp_info_rsp,
+					UINT_TO_PTR(mgmt_index), NULL)) {
+		error("Unable to send read_exp_features_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void exp_debug_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set debug feature failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Debug feature successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_exp_debug(int argc, char **argv)
+{
+	/* d4992530-b9ec-469f-ab01-6c481c47da1c */
+	static const uint8_t uuid[16] = {
+				0x1c, 0xda, 0x47, 0x1c, 0x48, 0x6c, 0x01, 0xab,
+				0x9f, 0x46, 0xec, 0xb9, 0x30, 0x25, 0x99, 0xd4,
+	};
+	struct mgmt_cp_set_exp_feature cp;
+	uint8_t val;
+
+	if (parse_setting(argc, argv, &val) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(cp.uuid, uuid, 16);
+	cp.action = val;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
+			sizeof(cp), &cp, exp_debug_rsp, NULL, NULL) == 0) {
+		error("Unable to send debug feature cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void exp_privacy_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set LL privacy feature failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("LL privacy feature successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_exp_privacy(int argc, char **argv)
+{
+	/* 15c0a148-c273-11ea-b3de-0242ac130004 */
+	static const uint8_t uuid[16] = {
+				0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
+				0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
+	};
+	struct mgmt_cp_set_exp_feature cp;
+	uint8_t val;
+
+	if (parse_setting(argc, argv, &val) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(cp.uuid, uuid, 16);
+	cp.action = val;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
+			sizeof(cp), &cp, exp_privacy_rsp, NULL, NULL) == 0) {
+		error("Unable to send LL privacy feature cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void exp_quality_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set Quality Report feature failed: 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Quality Report feature successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_exp_quality(int argc, char **argv)
+{
+	/* 330859bc-7506-492d-9370-9a6f0614037f */
+	static const uint8_t uuid[16] = {
+				0x7f, 0x03, 0x14, 0x06, 0x6f, 0x9a, 0x70, 0x93,
+				0x2d, 0x49, 0x06, 0x75, 0xbc, 0x59, 0x08, 0x33,
+	};
+	struct mgmt_cp_set_exp_feature cp;
+	uint8_t val;
+
+	if (mgmt_index == MGMT_INDEX_NONE) {
+		error("BQR feature requires a valid controller index");
+		return;
+	}
+
+	if (parse_setting(argc, argv, &val) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	if (val != 0 && val != 1) {
+		error("Invalid value %u", val);
+		return;
+	}
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(cp.uuid, uuid, 16);
+	cp.action = val;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
+			sizeof(cp), &cp, exp_quality_rsp, NULL, NULL) == 0) {
+		error("Unable to send quality report feature cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void print_mgmt_tlv(void *data, void *user_data)
+{
+	const struct mgmt_tlv *entry = data;
+	char buf[256];
+
+	bin2hex(entry->value, entry->length, buf, sizeof(buf));
+	print("Type: 0x%04x\tLength: %02hhu\tValue: %s", entry->type,
+							entry->length, buf);
+}
+
+static void read_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	struct mgmt_tlv_list *tlv_list;
+
+	if (status != 0) {
+		error("Read system configuration failed with status "
+				"0x%02x (%s)", status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	tlv_list = mgmt_tlv_list_load_from_buf(param, len);
+	if (!tlv_list) {
+		error("Unable to parse response of read system configuration");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	mgmt_tlv_list_foreach(tlv_list, print_mgmt_tlv, NULL);
+	mgmt_tlv_list_free(tlv_list);
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_read_sysconfig(int argc, char **argv)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_DEF_SYSTEM_CONFIG, index,
+			0, NULL, read_sysconfig_rsp, NULL, NULL)) {
+		error("Unable to send read system configuration cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static bool parse_mgmt_tlv(const char *input, uint16_t *type, uint8_t *length,
+								uint8_t *value)
+{
+	int i, value_starting_pos;
+
+	if (sscanf(input, "%4hx:%1hhu:%n", type, length,
+						&value_starting_pos) < 2) {
+		return false;
+	}
+
+	input += value_starting_pos;
+
+	if (*length * 2 != strlen(input))
+		return false;
+
+	for (i = 0; i < *length; i++) {
+		if (sscanf(input + i * 2, "%2hhx", &value[i]) < 1)
+			return false;
+	}
+
+	return true;
+}
+
+static void set_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
+								void *user_data)
+{
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Could not set default system configuration with status "
+				"0x%02x (%s)", status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Set default system configuration success");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static bool set_sysconfig(int argc, char **argv)
+{
+	struct mgmt_tlv_list *tlv_list = NULL;
+	int i;
+	uint16_t index, type;
+	uint8_t length;
+	uint8_t value[256] = {};
+	bool success = false;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	tlv_list = mgmt_tlv_list_new();
+	if (!tlv_list) {
+		error("tlv_list failed to init");
+		goto failed;
+	}
+
+	for (i = 0; i < argc; i++) {
+		if (!parse_mgmt_tlv(argv[i], &type, &length, value)) {
+			error("failed to parse");
+			goto failed;
+		}
+
+		if (!mgmt_tlv_add(tlv_list, type, length, value)) {
+			error("failed to add");
+			goto failed;
+		}
+	}
+
+	if (!mgmt_send_tlv(mgmt, MGMT_OP_SET_DEF_SYSTEM_CONFIG, index,
+				tlv_list, set_sysconfig_rsp, NULL, NULL)) {
+		error("Failed to send \"Set Default System Configuration\""
+								" command");
+		goto failed;
+	}
+
+	success = true;
+
+failed:
+	if (tlv_list)
+		mgmt_tlv_list_free(tlv_list);
+
+	return success;
+}
+
+static void set_sysconfig_usage(void)
+{
+	bt_shell_usage();
+	print("Parameters:\n\t-v <type:length:value>...\n"
+		"e.g.:\n\tset-sysconfig -v 001a:2:1234 001f:1:00");
+}
+
+static void cmd_set_sysconfig(int argc, char **argv)
+{
+	bool success = false;
+
+	if (strcasecmp(argv[1], "-v") == 0 && argc > 2) {
+		argc -= 2;
+		argv += 2;
+		success = set_sysconfig(argc, argv);
+	}
+
+	if (!success) {
+		set_sysconfig_usage();
+		bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void auto_power_enable_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	uint16_t index = PTR_TO_UINT(user_data);
+
+	print("Successfully enabled controller with index %u", index);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void auto_power_info_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_read_info *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint32_t supported_settings, current_settings, missing_settings;
+	uint8_t val = 0x01;
+
+	if (status) {
+		error("Reading info failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	supported_settings = le32_to_cpu(rp->supported_settings);
+	current_settings = le32_to_cpu(rp->current_settings);
+	missing_settings = current_settings ^ supported_settings;
+
+	if (missing_settings & MGMT_SETTING_BREDR)
+		mgmt_send(mgmt, MGMT_OP_SET_BREDR, index, sizeof(val), &val,
+							NULL, NULL, NULL);
+
+	if (missing_settings & MGMT_SETTING_SSP)
+		mgmt_send(mgmt, MGMT_OP_SET_SSP, index, sizeof(val), &val,
+							NULL, NULL, NULL);
+
+	if (missing_settings & MGMT_SETTING_LE)
+		mgmt_send(mgmt, MGMT_OP_SET_LE, index, sizeof(val), &val,
+							NULL, NULL, NULL);
+
+	if (missing_settings & MGMT_SETTING_SECURE_CONN)
+		mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index,
+							sizeof(val), &val,
+							NULL, NULL, NULL);
+
+	if (missing_settings & MGMT_SETTING_BONDABLE)
+		mgmt_send(mgmt, MGMT_OP_SET_BONDABLE, index, sizeof(val), &val,
+							NULL, NULL, NULL);
+
+	if (current_settings & MGMT_SETTING_POWERED)
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+
+	if (!mgmt_send(mgmt, MGMT_OP_SET_POWERED, index, sizeof(val), &val,
+						auto_power_enable_rsp,
+						UINT_TO_PTR(index), NULL)) {
+		error("Unable to send set powerd cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void auto_power_index_evt(uint16_t index, uint16_t len,
+					const void *param, void *user_data)
+{
+	uint16_t index_filter = PTR_TO_UINT(user_data);
+
+	if (index != index_filter)
+		return;
+
+	print("New controller with index %u", index);
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
+						auto_power_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+		error("Unable to send read info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void auto_power_index_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_read_index_list *rp = param;
+	uint16_t index = PTR_TO_UINT(user_data);
+	uint16_t i, count;
+	bool found = false;
+
+	if (status) {
+		error("Reading index list failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = le16_to_cpu(rp->num_controllers);
+	for (i = 0; i < count; i++) {
+		if (le16_to_cpu(rp->index[i]) == index)
+			found = true;
+	}
+
+	if (!found) {
+		print("Waiting for index %u to appear", index);
+
+		mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index,
+						auto_power_index_evt,
+						UINT_TO_PTR(index), NULL);
+		return;
+	}
+
+	print("Found controller with index %u", index);
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
+						auto_power_info_rsp,
+						UINT_TO_PTR(index), NULL)) {
+		error("Unable to send read info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_auto_power(int argc, char **argv)
+{
+	int index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
+						auto_power_index_rsp,
+						UINT_TO_PTR(index), NULL)) {
+		error("Unable to send read index list cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void get_flags_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_device_flags *rp = param;
+
+	if (status != 0) {
+		error("Get device flags failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Supported Flags: 0x%08x", rp->supported_flags);
+	print("Current Flags:   0x%08x", rp->current_flags);
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option get_flags_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_get_flags(int argc, char **argv)
+{
+	struct mgmt_cp_get_device_flags cp;
+	uint8_t type = BDADDR_BREDR;
+	char addr[18];
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", get_flags_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	ba2str(&cp.addr.bdaddr, addr);
+	print("Get device flag of %s (%s)", addr, typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_GET_DEVICE_FLAGS, index, sizeof(cp), &cp,
+					get_flags_rsp, NULL, NULL) == 0) {
+		error("Unable to send Get Device Flags command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void set_flags_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Set device flags failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option set_flags_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ "flags",	1, 0, 'f' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_set_flags(int argc, char **argv)
+{
+	struct mgmt_cp_set_device_flags cp;
+	uint8_t type = BDADDR_BREDR;
+	uint32_t flags = 0;
+	char addr[18];
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+f:t:h", set_flags_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'f':
+			flags = strtol(optarg, NULL, 0);
+			break;
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+	cp.current_flags = flags;
+
+	ba2str(&cp.addr.bdaddr, addr);
+	print("Set device flag of %s (%s)", addr, typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_FLAGS, index, sizeof(cp), &cp,
+					set_flags_rsp, NULL, NULL) == 0) {
+		error("Unable to send Set Device Flags command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+}
+
+/* Wrapper to get the index and opcode to the response callback */
+struct command_data {
+	uint16_t id;
+	uint16_t op;
+	void (*callback) (uint16_t id, uint16_t op, uint8_t status,
+					uint16_t len, const void *param);
+};
+
+static void cmd_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	struct command_data *data = user_data;
+
+	data->callback(data->op, data->id, status, len, param);
+}
+
+static unsigned int send_cmd(struct mgmt *mgmt, uint16_t op, uint16_t id,
+				uint16_t len, const void *param,
+				void (*cb)(uint16_t id, uint16_t op,
+						uint8_t status, uint16_t len,
+						const void *param))
+{
+	struct command_data *data;
+	unsigned int send_id;
+
+	data = new0(struct command_data, 1);
+	if (!data)
+		return 0;
+
+	data->id = id;
+	data->op = op;
+	data->callback = cb;
+
+	send_id = mgmt_send(mgmt, op, id, len, param, cmd_rsp, data, free);
+	if (send_id == 0)
+		free(data);
+
+	return send_id;
+}
+
+static void setting_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
+							const void *param)
+{
+	const uint32_t *rp = param;
+
+	if (status != 0) {
+		error("%s for hci%u failed with status 0x%02x (%s)",
+			mgmt_opstr(op), id, status, mgmt_errstr(status));
+		goto done;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small %s response (%u bytes)",
+							mgmt_opstr(op), len);
+		goto done;
+	}
+
+	print("hci%u %s complete, settings: %s", id, mgmt_opstr(op),
+						settings2str(get_le32(rp)));
+
+done:
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_setting(uint16_t op, int argc, char **argv)
+{
+	int index;
+	uint8_t val;
+
+	if (parse_setting(argc, argv, &val) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (send_cmd(mgmt, op, index, sizeof(val), &val, setting_rsp) == 0) {
+		error("Unable to send %s cmd", mgmt_opstr(op));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_power(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_POWERED, argc, argv);
+}
+
+static void cmd_discov(int argc, char **argv)
+{
+	struct mgmt_cp_set_discoverable cp;
+	uint16_t index;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
+		cp.val = 1;
+	else if (strcasecmp(argv[1], "off") == 0)
+		cp.val = 0;
+	else if (strcasecmp(argv[1], "limited") == 0)
+		cp.val = 2;
+	else
+		cp.val = atoi(argv[1]);
+
+	if (argc > 2)
+		cp.timeout = htobs(atoi(argv[2]));
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (send_cmd(mgmt, MGMT_OP_SET_DISCOVERABLE, index, sizeof(cp), &cp,
+							setting_rsp) == 0) {
+		error("Unable to send set_discoverable cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_connectable(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_CONNECTABLE, argc, argv);
+}
+
+static void cmd_fast_conn(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_FAST_CONNECTABLE, argc, argv);
+}
+
+static void cmd_bondable(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_BONDABLE, argc, argv);
+}
+
+static void cmd_linksec(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_LINK_SECURITY, argc, argv);
+}
+
+static void cmd_ssp(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_SSP, argc, argv);
+}
+
+static void cmd_sc(int argc, char **argv)
+{
+	uint8_t val;
+	uint16_t index;
+
+	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
+		val = 1;
+	else if (strcasecmp(argv[1], "off") == 0)
+		val = 0;
+	else if (strcasecmp(argv[1], "only") == 0)
+		val = 2;
+	else
+		val = atoi(argv[1]);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (send_cmd(mgmt, MGMT_OP_SET_SECURE_CONN, index,
+					sizeof(val), &val, setting_rsp) == 0) {
+		error("Unable to send set_secure_conn cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_hs(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_HS, argc, argv);
+}
+
+static void cmd_le(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_LE, argc, argv);
+}
+
+static void cmd_advertising(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_ADVERTISING, argc, argv);
+}
+
+static void cmd_bredr(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_BREDR, argc, argv);
+}
+
+static void cmd_privacy(int argc, char **argv)
+{
+	struct mgmt_cp_set_privacy cp;
+	uint16_t index;
+
+	if (parse_setting(argc, argv, &cp.privacy) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (argc > 2) {
+		if (hex2bin(argv[2], cp.irk,
+					sizeof(cp.irk)) != sizeof(cp.irk)) {
+			error("Invalid key format");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	} else {
+		int fd;
+
+		fd = open("/dev/urandom", O_RDONLY);
+		if (fd < 0) {
+			error("open(/dev/urandom): %s", strerror(errno));
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (read(fd, cp.irk, sizeof(cp.irk)) != sizeof(cp.irk)) {
+			error("Reading from urandom failed");
+			close(fd);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		close(fd);
+	}
+
+	if (send_cmd(mgmt, MGMT_OP_SET_PRIVACY, index, sizeof(cp), &cp,
+							setting_rsp) == 0) {
+		error("Unable to send Set Privacy command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void exp_offload_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set offload codec failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Offload codec feature successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_exp_offload_codecs(int argc, char **argv)
+{
+	/* a6695ace-ee7f-4fb9-881a-5fac66c629af */
+	static const uint8_t uuid[16] = {
+				0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
+				0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
+	};
+
+	struct mgmt_cp_set_exp_feature cp;
+	uint8_t val;
+	uint16_t index;
+
+	if (parse_setting(argc, argv, &val) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(cp.uuid, uuid, 16);
+	cp.action = val;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, index,
+			sizeof(cp), &cp, exp_offload_rsp, NULL, NULL) == 0) {
+		error("Unable to send offload codecs feature cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void class_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
+							const void *param)
+{
+	const struct mgmt_ev_class_of_dev_changed *rp = param;
+
+	if (len == 0 && status != 0) {
+		error("%s failed, status 0x%02x (%s)",
+				mgmt_opstr(op), status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Unexpected %s len %u", mgmt_opstr(op), len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("%s succeeded. Class 0x%02x%02x%02x", mgmt_opstr(op),
+		rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_class(int argc, char **argv)
+{
+	uint8_t class[2];
+	uint16_t index;
+
+	class[0] = atoi(argv[1]);
+	class[1] = atoi(argv[2]);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (send_cmd(mgmt, MGMT_OP_SET_DEV_CLASS, index, sizeof(class), class,
+							class_rsp) == 0) {
+		error("Unable to send set_dev_class cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void disconnect_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_disconnect *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("Disconnect failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Invalid disconnect response length (%u)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->addr.bdaddr, addr);
+
+	if (status == 0)
+		print("%s disconnected", addr);
+	else
+		error("Disconnecting %s failed with status 0x%02x (%s)",
+				addr, status, mgmt_errstr(status));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option disconnect_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_disconnect(int argc, char **argv)
+{
+	struct mgmt_cp_disconnect cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", disconnect_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argv += optind;
+	optind = 0;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	if (mgmt_send(mgmt, MGMT_OP_DISCONNECT, index, sizeof(cp), &cp,
+					disconnect_rsp, NULL, NULL) == 0) {
+		error("Unable to send disconnect cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void con_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_connections *rp = param;
+	uint16_t count, i;
+
+	if (len < sizeof(*rp)) {
+		error("Too small (%u bytes) get_connections rsp", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	count = get_le16(&rp->conn_count);
+	if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
+		error("Invalid get_connections length (count=%u, len=%u)",
+								count, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	for (i = 0; i < count; i++) {
+		char addr[18];
+
+		ba2str(&rp->addr[i].bdaddr, addr);
+
+		print("%s type %s", addr, typestr(rp->addr[i].type));
+	}
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_con(int argc, char **argv)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send(mgmt, MGMT_OP_GET_CONNECTIONS, index, 0, NULL,
+						con_rsp, NULL, NULL) == 0) {
+		error("Unable to send get_connections cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void find_service_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Start Service Discovery failed: status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Service discovery started");
+	discovery = true;
+}
+
+static const struct option find_service_options[] = {
+	{ "help",	no_argument, 0, 'h' },
+	{ "le-only",	no_argument, 0, 'l' },
+	{ "bredr-only",	no_argument, 0, 'b' },
+	{ "uuid",	required_argument, 0, 'u' },
+	{ "rssi",	required_argument, 0, 'r' },
+	{ 0, 0, 0, 0 }
+};
+
+#define MAX_UUIDS 4
+
+static void cmd_find_service(int argc, char **argv)
+{
+	struct mgmt_cp_start_service_discovery *cp;
+	uint8_t buf[sizeof(*cp) + 16 * MAX_UUIDS];
+	bt_uuid_t uuid;
+	uint8_t type = SCAN_TYPE_DUAL;
+	int8_t rssi;
+	uint16_t count;
+	int opt;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	rssi = 127;
+	count = 0;
+
+	while ((opt = getopt_long(argc, argv, "+lbu:r:h",
+					find_service_options, NULL)) != -1) {
+		switch (opt) {
+		case 'l':
+			type &= ~SCAN_TYPE_BREDR;
+			type |= SCAN_TYPE_LE;
+			break;
+		case 'b':
+			type |= SCAN_TYPE_BREDR;
+			type &= ~SCAN_TYPE_LE;
+			break;
+		case 'u':
+			if (count == MAX_UUIDS) {
+				print("Max %u UUIDs supported", MAX_UUIDS);
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+
+			if (bt_string_to_uuid(&uuid, optarg) < 0) {
+				print("Invalid UUID: %s", optarg);
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			cp = (void *) buf;
+			bt_uuid_to_le(&uuid, cp->uuids[count++]);
+			break;
+		case 'r':
+			rssi = atoi(optarg);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	optind = 0;
+
+	cp = (void *) buf;
+	cp->type = type;
+	cp->rssi = rssi;
+	cp->uuid_count = cpu_to_le16(count);
+
+	if (mgmt_send(mgmt, MGMT_OP_START_SERVICE_DISCOVERY, index,
+				sizeof(*cp) + count * 16, cp,
+				find_service_rsp, NULL, NULL) == 0) {
+		error("Unable to send start_service_discovery cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void find_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Unable to start discovery. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Discovery started");
+	discovery = true;
+}
+
+static const struct option find_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "le-only",	1, 0, 'l' },
+	{ "bredr-only",	1, 0, 'b' },
+	{ "limited",	1, 0, 'L' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_find(int argc, char **argv)
+{
+	struct mgmt_cp_start_discovery cp;
+	uint8_t op = MGMT_OP_START_DISCOVERY;
+	uint8_t type = SCAN_TYPE_DUAL;
+	int opt;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	while ((opt = getopt_long(argc, argv, "+lbLh", find_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'l':
+			type &= ~SCAN_TYPE_BREDR;
+			type |= SCAN_TYPE_LE;
+			break;
+		case 'b':
+			type |= SCAN_TYPE_BREDR;
+			type &= ~SCAN_TYPE_LE;
+			break;
+		case 'L':
+			op = MGMT_OP_START_LIMITED_DISCOVERY;
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	optind = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = type;
+
+	if (mgmt_send(mgmt, op, index, sizeof(cp), &cp, find_rsp,
+							NULL, NULL) == 0) {
+		error("Unable to send start_discovery cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void stop_find_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Stop Discovery failed: status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	print("Discovery stopped");
+	discovery = false;
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option stop_find_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "le-only",	1, 0, 'l' },
+	{ "bredr-only",	1, 0, 'b' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_stop_find(int argc, char **argv)
+{
+	struct mgmt_cp_stop_discovery cp;
+	uint8_t type = SCAN_TYPE_DUAL;
+	int opt;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	while ((opt = getopt_long(argc, argv, "+lbh", stop_find_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'l':
+			type &= ~SCAN_TYPE_BREDR;
+			type |= SCAN_TYPE_LE;
+			break;
+		case 'b':
+			type |= SCAN_TYPE_BREDR;
+			type &= ~SCAN_TYPE_LE;
+			break;
+		case 'h':
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		}
+	}
+
+	optind = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = type;
+
+	if (mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, index, sizeof(cp), &cp,
+					     stop_find_rsp, NULL, NULL) == 0) {
+		error("Unable to send stop_discovery cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void name_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Unable to set local name with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_name(int argc, char **argv)
+{
+	struct mgmt_cp_set_local_name cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
+	if (argc > 2)
+		strncpy((char *) cp.short_name, argv[2],
+					MGMT_MAX_SHORT_NAME_LENGTH - 1);
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_LOCAL_NAME, index, sizeof(cp), &cp,
+						name_rsp, NULL, NULL) == 0) {
+		error("Unable to send set_name cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void pair_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_pair_device *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("Pairing failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Unexpected pair_rsp len %u", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->addr.bdaddr, addr);
+
+	if (status)
+		error("Pairing with %s (%s) failed. status 0x%02x (%s)",
+			addr, typestr(rp->addr.type), status,
+			mgmt_errstr(status));
+	else
+		print("Paired with %s (%s)", addr, typestr(rp->addr.type));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void register_pair_callbacks(struct mgmt *mgmt, uint16_t index)
+{
+	mgmt_register(mgmt, MGMT_EV_PIN_CODE_REQUEST, index, request_pin,
+								mgmt, NULL);
+	mgmt_register(mgmt, MGMT_EV_USER_CONFIRM_REQUEST, index, user_confirm,
+								mgmt, NULL);
+	mgmt_register(mgmt, MGMT_EV_USER_PASSKEY_REQUEST, index,
+						request_passkey, mgmt, NULL);
+	mgmt_register(mgmt, MGMT_EV_PASSKEY_NOTIFY, index,
+						passkey_notify, mgmt, NULL);
+}
+
+static const struct option pair_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "capability",	1, 0, 'c' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_pair(int argc, char **argv)
+{
+	struct mgmt_cp_pair_device cp;
+	uint8_t cap = 0x01;
+	uint8_t type = BDADDR_BREDR;
+	char addr[18];
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'c':
+			cap = strtol(optarg, NULL, 0);
+			break;
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	register_pair_callbacks(mgmt, index);
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+	cp.io_cap = cap;
+
+	ba2str(&cp.addr.bdaddr, addr);
+	print("Pairing with %s (%s)", addr, typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_PAIR_DEVICE, index, sizeof(cp), &cp,
+						pair_rsp, NULL, NULL) == 0) {
+		error("Unable to send pair_device cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cancel_pair_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_addr_info *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("Cancel Pairing failed with 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Unexpected cancel_pair_rsp len %u", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->bdaddr, addr);
+
+	if (status)
+		error("Cancel Pairing with %s (%s) failed. 0x%02x (%s)",
+			addr, typestr(rp->type), status,
+			mgmt_errstr(status));
+	else
+		print("Pairing Cancelled with %s", addr);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option cancel_pair_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_cancel_pair(int argc, char **argv)
+{
+	struct mgmt_addr_info cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", cancel_pair_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.bdaddr);
+	cp.type = type;
+
+	if (mgmt_reply(mgmt, MGMT_OP_CANCEL_PAIR_DEVICE, index, sizeof(cp), &cp,
+					cancel_pair_rsp, NULL, NULL) == 0) {
+		error("Unable to send cancel_pair_device cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void unpair_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_unpair_device *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("Unpair device failed. status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Unexpected unpair_device_rsp len %u", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->addr.bdaddr, addr);
+
+	if (status)
+		error("Unpairing %s failed. status 0x%02x (%s)",
+				addr, status, mgmt_errstr(status));
+	else
+		print("%s unpaired", addr);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option unpair_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_unpair(int argc, char **argv)
+{
+	struct mgmt_cp_unpair_device cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", unpair_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+	cp.disconnect = 1;
+
+	if (mgmt_send(mgmt, MGMT_OP_UNPAIR_DEVICE, index, sizeof(cp), &cp,
+						unpair_rsp, NULL, NULL) == 0) {
+		error("Unable to send unpair_device cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void keys_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Load keys failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Keys successfully loaded");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_keys(int argc, char **argv)
+{
+	struct mgmt_cp_load_link_keys cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (mgmt_send(mgmt, MGMT_OP_LOAD_LINK_KEYS, index, sizeof(cp), &cp,
+						keys_rsp, NULL, NULL) == 0) {
+		error("Unable to send load_keys cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void ltks_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Load keys failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Long term keys successfully loaded");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_ltks(int argc, char **argv)
+{
+	struct mgmt_cp_load_long_term_keys cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index, sizeof(cp), &cp,
+						ltks_rsp, NULL, NULL) == 0) {
+		error("Unable to send load_ltks cmd");
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+}
+
+static void irks_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Load IRKs failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Identity Resolving Keys successfully loaded");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option irks_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "local",	1, 0, 'l' },
+	{ "file",	1, 0, 'f' },
+	{ 0, 0, 0, 0 }
+};
+
+#define MAX_IRKS 4
+
+static void cmd_irks(int argc, char **argv)
+{
+	struct mgmt_cp_load_irks *cp;
+	uint8_t buf[sizeof(*cp) + 23 * MAX_IRKS];
+	uint16_t count, local_index;
+	char path[PATH_MAX];
+	int opt;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp = (void *) buf;
+	count = 0;
+
+	while ((opt = getopt_long(argc, argv, "+l:f:h",
+					irks_options, NULL)) != -1) {
+		switch (opt) {
+		case 'l':
+			if (count >= MAX_IRKS) {
+				error("Number of IRKs exceeded");
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			if (strlen(optarg) > 3 &&
+					strncasecmp(optarg, "hci", 3) == 0)
+				local_index = atoi(optarg + 3);
+			else
+				local_index = atoi(optarg);
+			snprintf(path, sizeof(path),
+				"/sys/kernel/debug/bluetooth/hci%u/identity",
+				local_index);
+			if (!load_identity(path, &cp->irks[count])) {
+				error("Unable to load identity");
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			count++;
+			break;
+		case 'f':
+			if (count >= MAX_IRKS) {
+				error("Number of IRKs exceeded");
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			if (!load_identity(optarg, &cp->irks[count])) {
+				error("Unable to load identities");
+				optind = 0;
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			count++;
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	optind = 0;
+
+	cp->irk_count = cpu_to_le16(count);
+
+	if (mgmt_send(mgmt, MGMT_OP_LOAD_IRKS, index,
+					sizeof(*cp) + count * 23, cp,
+					irks_rsp, NULL, NULL) == 0) {
+		error("Unable to send load_irks cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void block_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
+							const void *param)
+{
+	const struct mgmt_addr_info *rp = param;
+	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("%s failed, status 0x%02x (%s)",
+				mgmt_opstr(op), status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Unexpected %s len %u", mgmt_opstr(op), len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->bdaddr, addr);
+
+	if (status)
+		error("%s %s (%s) failed. status 0x%02x (%s)",
+				mgmt_opstr(op), addr, typestr(rp->type),
+				status, mgmt_errstr(status));
+	else
+		print("%s %s succeeded", mgmt_opstr(op), addr);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option block_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_block(int argc, char **argv)
+{
+	struct mgmt_cp_block_device cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
+							NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	if (send_cmd(mgmt, MGMT_OP_BLOCK_DEVICE, index, sizeof(cp), &cp,
+							block_rsp) == 0) {
+		error("Unable to send block_device cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_unblock(int argc, char **argv)
+{
+	struct mgmt_cp_unblock_device cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
+							NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	if (send_cmd(mgmt, MGMT_OP_UNBLOCK_DEVICE, index, sizeof(cp), &cp,
+							block_rsp) == 0) {
+		error("Unable to send unblock_device cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_add_uuid(int argc, char **argv)
+{
+	struct mgmt_cp_add_uuid cp;
+	bt_uuid_t uuid;
+	uint16_t index;
+
+	if (argc < 3) {
+		print("UUID and service hint needed");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (bt_string_to_uuid(&uuid, argv[1]) < 0) {
+		print("Invalid UUID: %s", argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	memset(&cp, 0, sizeof(cp));
+	bt_uuid_to_le(&uuid, cp.uuid);
+
+	cp.svc_hint = atoi(argv[2]);
+
+	if (send_cmd(mgmt, MGMT_OP_ADD_UUID, index, sizeof(cp), &cp,
+							class_rsp) == 0) {
+		error("Unable to send add_uuid cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_remove_uuid(int argc, char **argv)
+{
+	struct mgmt_cp_remove_uuid cp;
+	bt_uuid_t uuid;
+	uint16_t index;
+
+	if (argc < 2) {
+		print("UUID needed");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (bt_string_to_uuid(&uuid, argv[1]) < 0) {
+		print("Invalid UUID: %s", argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	memset(&cp, 0, sizeof(cp));
+
+	bt_uuid_to_le(&uuid, cp.uuid);
+
+	if (send_cmd(mgmt, MGMT_OP_REMOVE_UUID, index, sizeof(cp), &cp,
+							class_rsp) == 0) {
+		error("Unable to send remove_uuid cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_clr_uuids(int argc, char **argv)
+{
+	char *uuid_any = "00000000-0000-0000-0000-000000000000";
+	char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
+
+	cmd_remove_uuid(2, rm_argv);
+}
+
+static void local_oob_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_local_oob_data *rp = param;
+	char str[33];
+
+	if (status != 0) {
+		error("Read Local OOB Data failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small (%u bytes) read_local_oob rsp", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bin2hex(rp->hash192, 16, str, sizeof(str));
+	print("Hash C from P-192: %s", str);
+
+	bin2hex(rp->rand192, 16, str, sizeof(str));
+	print("Randomizer R with P-192: %s", str);
+
+	if (len < sizeof(*rp))
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+
+	bin2hex(rp->hash256, 16, str, sizeof(str));
+	print("Hash C from P-256: %s", str);
+
+	bin2hex(rp->rand256, 16, str, sizeof(str));
+	print("Randomizer R with P-256: %s", str);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_local_oob(int argc, char **argv)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_DATA, index, 0, NULL,
+					local_oob_rsp, NULL, NULL) == 0) {
+		error("Unable to send read_local_oob cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void remote_oob_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_addr_info *rp = param;
+	char addr[18];
+
+	if (status != 0) {
+		error("Add Remote OOB Data failed: 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return;
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small (%u bytes) add_remote_oob rsp", len);
+		return;
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	print("Remote OOB data added for %s (%u)", addr, rp->type);
+}
+
+static const struct option remote_oob_opt[] = {
+	{ "help",	0, 0, '?' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_remote_oob(int argc, char **argv)
+{
+	struct mgmt_cp_add_remote_oob_data cp;
+	int opt;
+	uint16_t index;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.addr.type = BDADDR_BREDR;
+
+	while ((opt = getopt_long(argc, argv, "+t:r:R:h:H:",
+					remote_oob_opt, NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			cp.addr.type = strtol(optarg, NULL, 0);
+			break;
+		case 'r':
+			hex2bin(optarg, cp.rand192, 16);
+			break;
+		case 'h':
+			hex2bin(optarg, cp.hash192, 16);
+			break;
+		case 'R':
+			hex2bin(optarg, cp.rand256, 16);
+			break;
+		case 'H':
+			hex2bin(optarg, cp.hash256, 16);
+			break;
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	str2ba(argv[0], &cp.addr.bdaddr);
+
+	print("Adding OOB data for %s (%s)", argv[0], typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_ADD_REMOTE_OOB_DATA, index,
+				sizeof(cp), &cp, remote_oob_rsp,
+				NULL, NULL) == 0) {
+		error("Unable to send add_remote_oob cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void did_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set Device ID failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Device ID successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_did(int argc, char **argv)
+{
+	struct mgmt_cp_set_device_id cp;
+	uint16_t vendor, product, version , source;
+	int result;
+	uint16_t index;
+
+	result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
+								&version);
+	if (result == 3) {
+		source = 0x0001;
+		goto done;
+	}
+
+	result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
+								&version);
+	if (result == 3) {
+		source = 0x0002;
+		goto done;
+	}
+
+	return;
+done:
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp.source = htobs(source);
+	cp.vendor = htobs(vendor);
+	cp.product = htobs(product);
+	cp.version = htobs(version);
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_ID, index, sizeof(cp), &cp,
+						did_rsp, NULL, NULL) == 0) {
+		error("Unable to send set_device_id cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void static_addr_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set static address failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Static address successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_static_addr(int argc, char **argv)
+{
+	struct mgmt_cp_set_static_address cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	str2ba(argv[1], &cp.bdaddr);
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_STATIC_ADDRESS, index, sizeof(cp), &cp,
+					static_addr_rsp, NULL, NULL) == 0) {
+		error("Unable to send set_static_address cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void options_rsp(uint16_t op, uint16_t id, uint8_t status,
+					uint16_t len, const void *param)
+{
+	const uint32_t *rp = param;
+
+	if (status != 0) {
+		error("%s for hci%u failed with status 0x%02x (%s)",
+			mgmt_opstr(op), id, status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small %s response (%u bytes)",
+							mgmt_opstr(op), len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("hci%u %s complete, options: %s", id, mgmt_opstr(op),
+						options2str(get_le32(rp)));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_public_addr(int argc, char **argv)
+{
+	struct mgmt_cp_set_public_address cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	str2ba(argv[1], &cp.bdaddr);
+
+	if (send_cmd(mgmt, MGMT_OP_SET_PUBLIC_ADDRESS, index, sizeof(cp), &cp,
+							options_rsp) == 0) {
+		error("Unable to send Set Public Address cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_ext_config(int argc, char **argv)
+{
+	struct mgmt_cp_set_external_config cp;
+	uint16_t index;
+
+	if (parse_setting(argc, argv, &cp.config) == false)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (send_cmd(mgmt, MGMT_OP_SET_EXTERNAL_CONFIG, index, sizeof(cp), &cp,
+							options_rsp) == 0) {
+		error("Unable to send Set External Config cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_debug_keys(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_DEBUG_KEYS, argc, argv);
+}
+
+static void conn_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_conn_info *rp = param;	char addr[18];
+
+	if (len == 0 && status != 0) {
+		error("Get Conn Info failed, status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Unexpected Get Conn Info len %u", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->addr.bdaddr, addr);
+
+	if (status) {
+		error("Get Conn Info for %s (%s) failed. status 0x%02x (%s)",
+						addr, typestr(rp->addr.type),
+						status, mgmt_errstr(status));
+	} else {
+		print("Connection Information for %s (%s)",
+						addr, typestr(rp->addr.type));
+		print("\tRSSI %d\tTX power %d\tmaximum TX power %d",
+				rp->rssi, rp->tx_power, rp->max_tx_power);
+	}
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option conn_info_options[] = {
+	{ "help",       0, 0, 'h' },
+	{ "type",       1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_conn_info(int argc, char **argv)
+{
+	struct mgmt_cp_get_conn_info cp;
+	uint8_t type = BDADDR_BREDR;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", conn_info_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	if (mgmt_send(mgmt, MGMT_OP_GET_CONN_INFO, index, sizeof(cp), &cp,
+					conn_info_rsp, NULL, NULL) == 0) {
+		error("Unable to send get_conn_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void io_cap_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Could not set IO Capability with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("IO Capabilities successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_io_cap(int argc, char **argv)
+{
+	struct mgmt_cp_set_io_capability cp;
+	uint8_t cap;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cap = strtol(argv[1], NULL, 0);
+	memset(&cp, 0, sizeof(cp));
+	cp.io_capability = cap;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_IO_CAPABILITY, index, sizeof(cp), &cp,
+					io_cap_rsp, NULL, NULL) == 0) {
+		error("Unable to send set-io-cap cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void scan_params_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Set scan parameters failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Scan parameters successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_scan_params(int argc, char **argv)
+{
+	struct mgmt_cp_set_scan_params cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp.interval = strtol(argv[1], NULL, 0);
+	cp.window = strtol(argv[2], NULL, 0);
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_SCAN_PARAMS, index, sizeof(cp), &cp,
+					scan_params_rsp, NULL, NULL) == 0) {
+		error("Unable to send set_scan_params cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void clock_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_clock_info *rp = param;
+
+	if (len < sizeof(*rp)) {
+		error("Unexpected Get Clock Info len %u", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (status) {
+		error("Get Clock Info failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Local Clock:   %u", le32_to_cpu(rp->local_clock));
+	print("Piconet Clock: %u", le32_to_cpu(rp->piconet_clock));
+	print("Accurary:      %u", le16_to_cpu(rp->accuracy));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_clock_info(int argc, char **argv)
+{
+	struct mgmt_cp_get_clock_info cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (argc > 1)
+		str2ba(argv[1], &cp.addr.bdaddr);
+
+	if (mgmt_send(mgmt, MGMT_OP_GET_CLOCK_INFO, index, sizeof(cp), &cp,
+					clock_info_rsp, NULL, NULL) == 0) {
+		error("Unable to send get_clock_info cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void add_device_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Add device failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option add_device_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "action",	1, 0, 'a' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_add_device(int argc, char **argv)
+{
+	struct mgmt_cp_add_device cp;
+	uint8_t action = 0x00;
+	uint8_t type = BDADDR_BREDR;
+	char addr[18];
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+a:t:h", add_device_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'a':
+			action = strtol(optarg, NULL, 0);
+			break;
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+	cp.action = action;
+
+	ba2str(&cp.addr.bdaddr, addr);
+	print("Adding device with %s (%s)", addr, typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_ADD_DEVICE, index, sizeof(cp), &cp,
+					add_device_rsp, NULL, NULL) == 0) {
+		error("Unable to send add device command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void remove_device_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Remove device failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct option del_device_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "type",	1, 0, 't' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_del_device(int argc, char **argv)
+{
+	struct mgmt_cp_remove_device cp;
+	uint8_t type = BDADDR_BREDR;
+	char addr[18];
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+t:h", del_device_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 't':
+			type = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+		default:
+			bt_shell_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		bt_shell_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+	str2ba(argv[0], &cp.addr.bdaddr);
+	cp.addr.type = type;
+
+	ba2str(&cp.addr.bdaddr, addr);
+	print("Removing device with %s (%s)", addr, typestr(cp.addr.type));
+
+	if (mgmt_send(mgmt, MGMT_OP_REMOVE_DEVICE, index, sizeof(cp), &cp,
+					remove_device_rsp, NULL, NULL) == 0) {
+		error("Unable to send remove device command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_clr_devices(int argc, char **argv)
+{
+	char *bdaddr_any = "00:00:00:00:00:00";
+	char *rm_argv[] = { "del-device", bdaddr_any, NULL };
+
+	cmd_del_device(2, rm_argv);
+}
+
+static void local_oob_ext_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_local_oob_ext_data *rp = param;
+	uint16_t eir_len;
+
+	if (status != 0) {
+		error("Read Local OOB Ext Data failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small (%u bytes) read_local_oob_ext rsp", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	eir_len = le16_to_cpu(rp->eir_len);
+	if (len != sizeof(*rp) + eir_len) {
+		error("local_oob_ext: expected %zu bytes, got %u bytes",
+						sizeof(*rp) + eir_len, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print_eir(rp->eir, eir_len);
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_bredr_oob(int argc, char **argv)
+{
+	struct mgmt_cp_read_local_oob_ext_data cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp.type = SCAN_TYPE_BREDR;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
+					index, sizeof(cp), &cp,
+					local_oob_ext_rsp, NULL, NULL)) {
+		error("Unable to send read_local_oob_ext cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_le_oob(int argc, char **argv)
+{
+	struct mgmt_cp_read_local_oob_ext_data cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp.type = SCAN_TYPE_LE;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
+					index, sizeof(cp), &cp,
+					local_oob_ext_rsp, NULL, NULL)) {
+		error("Unable to send read_local_oob_ext cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static const char *adv_flags_str[] = {
+				"connectable",
+				"general-discoverable",
+				"limited-discoverable",
+				"managed-flags",
+				"tx-power",
+				"scan-rsp-appearance",
+				"scan-rsp-local-name",
+				"Secondary-channel-1M",
+				"Secondary-channel-2M",
+				"Secondary-channel-CODED",
+};
+
+static const char *adv_flags2str(uint32_t flags)
+{
+	static char str[256];
+	unsigned i;
+	int off;
+
+	off = 0;
+	str[0] = '\0';
+
+	for (i = 0; i < NELEM(adv_flags_str); i++) {
+		if ((flags & (1 << i)) != 0)
+			off += snprintf(str + off, sizeof(str) - off, "%s ",
+							adv_flags_str[i]);
+	}
+
+	return str;
+}
+
+static void adv_features_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_adv_features *rp = param;
+	uint32_t supported_flags;
+
+	if (status != 0) {
+		error("Reading adv features failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small adv features reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp) + rp->num_instances * sizeof(uint8_t)) {
+		error("Instances count (%u) doesn't match reply length (%u)",
+							rp->num_instances, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	supported_flags = le32_to_cpu(rp->supported_flags);
+	print("Supported flags: %s", adv_flags2str(supported_flags));
+	print("Max advertising data len: %u", rp->max_adv_data_len);
+	print("Max scan response data len: %u", rp->max_scan_rsp_len);
+	print("Max instances: %u", rp->max_instances);
+
+	print("Instances list with %u item%s", rp->num_instances,
+					rp->num_instances != 1 ? "s" : "");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_advinfo(int argc, char **argv)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_FEATURES, index, 0, NULL,
+					adv_features_rsp, NULL, NULL)) {
+		error("Unable to send advertising features command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void adv_size_info_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_adv_size_info *rp = param;
+	uint32_t flags;
+
+	if (status != 0) {
+		error("Reading adv size info failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small adv size info reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	flags = le32_to_cpu(rp->flags);
+	print("Instance: %u", rp->instance);
+	print("Flags: %s", adv_flags2str(flags));
+	print("Max advertising data len: %u", rp->max_adv_data_len);
+	print("Max scan response data len: %u", rp->max_scan_rsp_len);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void advsize_usage(void)
+{
+	bt_shell_usage();
+	print("Options:\n"
+		"\t -c, --connectable         \"connectable\" flag\n"
+		"\t -g, --general-discov      \"general-discoverable\" flag\n"
+		"\t -l, --limited-discov      \"limited-discoverable\" flag\n"
+		"\t -m, --managed-flags       \"managed-flags\" flag\n"
+		"\t -p, --tx-power            \"tx-power\" flag\n"
+		"\t -a, --appearance          \"appearance\" flag\n"
+		"\t -n, --local-name          \"local-name\" flag");
+}
+
+static const struct option advsize_options[] = {
+	{ "help",		0, 0, 'h' },
+	{ "connectable",	0, 0, 'c' },
+	{ "general-discov",	0, 0, 'g' },
+	{ "limited-discov",	0, 0, 'l' },
+	{ "managed-flags",	0, 0, 'm' },
+	{ "tx-power",		0, 0, 'p' },
+	{ "appearance",		0, 0, 'a' },
+	{ "local-name",		0, 0, 'n' },
+	{ 0, 0, 0, 0}
+};
+
+static void cmd_advsize(int argc, char **argv)
+{
+	struct mgmt_cp_get_adv_size_info cp;
+	uint8_t instance;
+	uint32_t flags = 0;
+	int opt;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+cglmphna",
+						advsize_options, NULL)) != -1) {
+		switch (opt) {
+		case 'c':
+			flags |= MGMT_ADV_FLAG_CONNECTABLE;
+			break;
+		case 'g':
+			flags |= MGMT_ADV_FLAG_DISCOV;
+			break;
+		case 'l':
+			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
+			break;
+		case 'm':
+			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
+			break;
+		case 'p':
+			flags |= MGMT_ADV_FLAG_TX_POWER;
+			break;
+		case 'a':
+			flags |= MGMT_ADV_FLAG_APPEARANCE;
+			break;
+		case 'n':
+			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
+			break;
+		default:
+			advsize_usage();
+			optind = 0;
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc != 1) {
+		advsize_usage();
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	instance = strtol(argv[0], NULL, 0);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.instance = instance;
+	cp.flags = cpu_to_le32(flags);
+
+	if (!mgmt_send(mgmt, MGMT_OP_GET_ADV_SIZE_INFO, index, sizeof(cp), &cp,
+					adv_size_info_rsp, NULL, NULL)) {
+		error("Unable to send advertising size info command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void add_adv_rsp(uint8_t status, uint16_t len, const void *param,
+								void *user_data)
+{
+	const struct mgmt_rp_add_advertising *rp = param;
+
+	if (status != 0) {
+		error("Add Advertising failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Invalid Add Advertising response length (%u)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Instance added: %u", rp->instance);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void add_adv_usage(void)
+{
+	bt_shell_usage();
+	print("Options:\n"
+		"\t -u, --uuid <uuid>         Service UUID\n"
+		"\t -d, --adv-data <data>     Advertising Data bytes\n"
+		"\t -s, --scan-rsp <data>     Scan Response Data bytes\n"
+		"\t -t, --timeout <timeout>   Timeout in seconds\n"
+		"\t -D, --duration <duration> Duration in seconds\n"
+		"\t -P, --phy <phy>           Phy type, Specify 1M/2M/CODED\n"
+		"\t -c, --connectable         \"connectable\" flag\n"
+		"\t -g, --general-discov      \"general-discoverable\" flag\n"
+		"\t -l, --limited-discov      \"limited-discoverable\" flag\n"
+		"\t -n, --scan-rsp-local-name \"local-name\" flag\n"
+		"\t -a, --scan-rsp-appearance \"appearance\" flag\n"
+		"\t -m, --managed-flags       \"managed-flags\" flag\n"
+		"\t -p, --tx-power            \"tx-power\" flag\n"
+		"e.g.:\n"
+		"\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
+}
+
+static const struct option add_adv_options[] = {
+	{ "help",		0, 0, 'h' },
+	{ "uuid",		1, 0, 'u' },
+	{ "adv-data",		1, 0, 'd' },
+	{ "scan-rsp",		1, 0, 's' },
+	{ "timeout",		1, 0, 't' },
+	{ "duration",		1, 0, 'D' },
+	{ "phy",		1, 0, 'P' },
+	{ "connectable",	0, 0, 'c' },
+	{ "general-discov",	0, 0, 'g' },
+	{ "limited-discov",	0, 0, 'l' },
+	{ "managed-flags",	0, 0, 'm' },
+	{ "tx-power",		0, 0, 'p' },
+	{ 0, 0, 0, 0}
+};
+
+static bool parse_bytes(char *optarg, uint8_t **bytes, size_t *len)
+{
+	unsigned i;
+
+	if (!optarg) {
+		add_adv_usage();
+		return false;
+	}
+
+	*len = strlen(optarg);
+
+	if (*len % 2) {
+		error("Malformed data");
+		return false;
+	}
+
+	*len /= 2;
+	if (*len > UINT8_MAX) {
+		error("Data too long");
+		return false;
+	}
+
+	*bytes = malloc(*len);
+	if (!*bytes) {
+		error("Failed to allocate memory");
+		return false;
+	}
+
+	for (i = 0; i < *len; i++) {
+		if (sscanf(optarg + (i * 2), "%2hhx", *bytes + i) != 1) {
+			error("Invalid data");
+			free(*bytes);
+			*bytes = NULL;
+			return false;
+		}
+	}
+
+	return true;
+}
+
+#define MAX_AD_UUID_BYTES 32
+
+static void cmd_add_adv(int argc, char **argv)
+{
+	struct mgmt_cp_add_advertising *cp = NULL;
+	int opt;
+	uint8_t *adv_data = NULL, *scan_rsp = NULL;
+	size_t adv_len = 0, scan_rsp_len = 0;
+	size_t cp_len;
+	uint8_t uuids[MAX_AD_UUID_BYTES];
+	size_t uuid_bytes = 0;
+	uint8_t uuid_type = 0;
+	uint16_t timeout = 0, duration = 0;
+	uint8_t instance;
+	bt_uuid_t uuid;
+	bool success = false;
+	bool quit = true;
+	uint32_t flags = 0;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+u:d:s:t:D:P:cglmphna",
+						add_adv_options, NULL)) != -1) {
+		switch (opt) {
+		case 'u':
+			if (bt_string_to_uuid(&uuid, optarg) < 0) {
+				print("Invalid UUID: %s", optarg);
+				goto done;
+			}
+
+			if (uuid_type && uuid_type != uuid.type) {
+				print("UUID types must be consistent");
+				goto done;
+			}
+
+			if (uuid.type == BT_UUID16) {
+				if (uuid_bytes + 2 >= MAX_AD_UUID_BYTES) {
+					print("Too many UUIDs");
+					goto done;
+				}
+
+				bt_uuid_to_le(&uuid, uuids + uuid_bytes);
+				uuid_bytes += 2;
+			} else if (uuid.type == BT_UUID128) {
+				if (uuid_bytes + 16 >= MAX_AD_UUID_BYTES) {
+					print("Too many UUIDs");
+					goto done;
+				}
+
+				bt_uuid_to_le(&uuid, uuids + uuid_bytes);
+				uuid_bytes += 16;
+			} else {
+				printf("Unsupported UUID type");
+				goto done;
+			}
+
+			if (!uuid_type)
+				uuid_type = uuid.type;
+
+			break;
+		case 'd':
+			if (adv_len) {
+				print("Only one adv-data option allowed");
+				goto done;
+			}
+
+			if (!parse_bytes(optarg, &adv_data, &adv_len))
+				goto done;
+			break;
+		case 's':
+			if (scan_rsp_len) {
+				print("Only one scan-rsp option allowed");
+				goto done;
+			}
+
+			if (!parse_bytes(optarg, &scan_rsp, &scan_rsp_len))
+				goto done;
+			break;
+		case 't':
+			timeout = strtol(optarg, NULL, 0);
+			break;
+		case 'D':
+			duration = strtol(optarg, NULL, 0);
+			break;
+		case 'c':
+			flags |= MGMT_ADV_FLAG_CONNECTABLE;
+			break;
+		case 'g':
+			flags |= MGMT_ADV_FLAG_DISCOV;
+			break;
+		case 'l':
+			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
+			break;
+		case 'm':
+			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
+			break;
+		case 'p':
+			flags |= MGMT_ADV_FLAG_TX_POWER;
+			break;
+		case 'n':
+			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
+			break;
+		case 'a':
+			flags |= MGMT_ADV_FLAG_APPEARANCE;
+			break;
+		case 'P':
+			if (strcasecmp(optarg, "1M") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_1M;
+			else if (strcasecmp(optarg, "2M") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_2M;
+			else if (strcasecmp(optarg, "CODED") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_CODED;
+			else
+				goto done;
+			break;
+		case 'h':
+			success = true;
+			/* fall through */
+		default:
+			add_adv_usage();
+			optind = 0;
+			goto done;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc != 1) {
+		add_adv_usage();
+		goto done;
+	}
+
+	if (uuid_bytes)
+		uuid_bytes += 2;
+
+	instance = strtol(argv[0], NULL, 0);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp_len = sizeof(*cp) + uuid_bytes + adv_len + scan_rsp_len;
+	cp = malloc0(cp_len);
+	if (!cp)
+		goto done;
+
+	cp->instance = instance;
+	put_le32(flags, &cp->flags);
+	put_le16(timeout, &cp->timeout);
+	put_le16(duration, &cp->duration);
+	cp->adv_data_len = adv_len + uuid_bytes;
+	cp->scan_rsp_len = scan_rsp_len;
+
+	if (uuid_bytes) {
+		cp->data[0] = uuid_bytes - 1;
+		cp->data[1] = uuid_type == SDP_UUID16 ? 0x03 : 0x07;
+		memcpy(cp->data + 2, uuids, uuid_bytes - 2);
+	}
+
+	if (adv_len)
+		memcpy(cp->data + uuid_bytes, adv_data, adv_len);
+
+	if (scan_rsp_len)
+		memcpy(cp->data + uuid_bytes + adv_len, scan_rsp, scan_rsp_len);
+
+	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADVERTISING, index, cp_len, cp,
+						add_adv_rsp, NULL, NULL)) {
+		error("Unable to send \"Add Advertising\" command");
+		goto done;
+	}
+
+	quit = false;
+
+done:
+	free(adv_data);
+	free(scan_rsp);
+	free(cp);
+
+	if (quit)
+		bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void rm_adv_rsp(uint8_t status, uint16_t len, const void *param,
+								void *user_data)
+{
+	const struct mgmt_rp_remove_advertising *rp = param;
+
+	if (status != 0) {
+		error("Remove Advertising failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Invalid Remove Advertising response length (%u)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Instance removed: %u", rp->instance);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_rm_adv(int argc, char **argv)
+{
+	struct mgmt_cp_remove_advertising cp;
+	uint8_t instance;
+	uint16_t index;
+
+	instance = strtol(argv[1], NULL, 0);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.instance = instance;
+
+	if (!mgmt_send(mgmt, MGMT_OP_REMOVE_ADVERTISING, index, sizeof(cp), &cp,
+						rm_adv_rsp, NULL, NULL)) {
+		error("Unable to send \"Remove Advertising\" command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_clr_adv(int argc, char **argv)
+{
+	char *all_instances = "0";
+	char *rm_argv[] = { "rm-adv", all_instances, NULL };
+
+	cmd_rm_adv(2, rm_argv);
+}
+
+static void add_ext_adv_params_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_add_ext_adv_params *rp = param;
+
+	if (status != 0) {
+		error("Add Ext Adv Params failed status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Invalid Add Ext Adv Params response length (%u)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Instance added: %u", rp->instance);
+	print("Tx Power: %u", rp->tx_power);
+	print("Max adv data len: %u", rp->max_adv_data_len);
+	print("Max scan resp len: %u", rp->max_scan_rsp_len);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void add_ext_adv_params_usage(void)
+{
+	bt_shell_usage();
+	print("Options:\n"
+		"\t -d, --duration <duration>  Duration in seconds\n"
+		"\t -t, --timeout <timeout>    Timeout in seconds\n"
+		"\t -r, --min-interval <valr>  Minimum interval\n"
+		"\t -x, --max-interval <valr>  Maximum interval\n"
+		"\t -w, --tx-power <power>     Tx power\n"
+		"\t -P, --phy <phy>            Phy type, Specify 1M/2M/CODED\n"
+		"\t -c, --connectable          \"connectable\" flag\n"
+		"\t -g, --general-discov       \"general-discoverable\" flag\n"
+		"\t -l, --limited-discov       \"limited-discoverable\" flag\n"
+		"\t -m, --managed-flags        \"managed-flags\" flag\n"
+		"\t -p, --add-tx-power         \"tx-power\" flag\n"
+		"\t -a, --scan-rsp-appearance  \"appearance\" flag\n"
+		"\t -n, --scan-rsp-local-name  \"local-name\" flag\n"
+		"\t -s, --adv-scan-rsp         \"scan resp in adv\" flag\n"
+		"\t -h, --help                 Show help\n"
+		"e.g.:\n"
+		"\tadd-ext-adv-params -r 0x801 -x 0x802 -P 2M -g 1");
+}
+
+static const struct option add_ext_adv_params_options[] = {
+	{ "help",		0, 0, 'h' },
+	{ "duration",		1, 0, 'd' },
+	{ "timeout",		1, 0, 't' },
+	{ "min-internal",	1, 0, 'r' },
+	{ "max-interval",	1, 0, 'x' },
+	{ "tx-power",		1, 0, 'w' },
+	{ "phy",		1, 0, 'P' },
+	{ "connectable",	0, 0, 'c' },
+	{ "general-discov",	0, 0, 'g' },
+	{ "limited-discov",	0, 0, 'l' },
+	{ "scan-rsp-local-name", 0, 0, 'n' },
+	{ "scan-rsp-appearance", 0, 0, 'a' },
+	{ "managed-flags",	0, 0, 'm' },
+	{ "add-tx-power",	0, 0, 'p' },
+	{ "adv-scan-rsp",	0, 0, 's' },
+	{ 0, 0, 0, 0}
+};
+
+static void cmd_add_ext_adv_params(int argc, char **argv)
+{
+	struct mgmt_cp_add_ext_adv_params *cp = NULL;
+	int opt;
+	uint16_t timeout = 0, duration = 0;
+	uint8_t instance;
+	bool success = false;
+	bool quit = true;
+	uint32_t flags = 0;
+	uint32_t min_interval = 0;
+	uint32_t max_interval = 0;
+	uint8_t tx_power = 0;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "d:t:r:x:w:P:cglmpansh",
+				add_ext_adv_params_options, NULL)) != -1) {
+		switch (opt) {
+		case 'd':
+			duration = strtol(optarg, NULL, 0);
+			flags |= MGMT_ADV_PARAM_DURATION;
+			break;
+		case 't':
+			timeout = strtol(optarg, NULL, 0);
+			flags |= MGMT_ADV_PARAM_TIMEOUT;
+			break;
+		case 'r':
+			min_interval = strtol(optarg, NULL, 0);
+			break;
+		case 'x':
+			max_interval = strtol(optarg, NULL, 0);
+			break;
+		case 'w':
+			tx_power = strtol(optarg, NULL, 0);
+			flags |= MGMT_ADV_PARAM_TX_POWER;
+			break;
+		case 'P':
+			if (strcasecmp(optarg, "1M") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_1M;
+			else if (strcasecmp(optarg, "2M") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_2M;
+			else if (strcasecmp(optarg, "CODED") == 0)
+				flags |= MGMT_ADV_FLAG_SEC_CODED;
+			else
+				goto done;
+			break;
+		case 'c':
+			flags |= MGMT_ADV_FLAG_CONNECTABLE;
+			break;
+		case 'g':
+			flags |= MGMT_ADV_FLAG_DISCOV;
+			break;
+		case 'l':
+			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
+			break;
+		case 'n':
+			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
+			break;
+		case 'a':
+			flags |= MGMT_ADV_FLAG_APPEARANCE;
+			break;
+		case 'm':
+			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
+			break;
+		case 'p':
+			flags |= MGMT_ADV_FLAG_TX_POWER;
+			break;
+		case 's':
+			flags |= MGMT_ADV_PARAM_SCAN_RSP;
+			break;
+		case 'h':
+			success = true;
+			/* fall through */
+		default:
+			add_ext_adv_params_usage();
+			optind = 0;
+			goto done;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc != 1) {
+		add_ext_adv_params_usage();
+		goto done;
+	}
+
+	/* Only if both min_interval and max_interval are defined */
+	if (min_interval && max_interval)
+		flags |= MGMT_ADV_PARAM_INTERVALS;
+
+	instance = strtol(argv[0], NULL, 0);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp = malloc0(sizeof(*cp));
+	if (!cp)
+		goto done;
+
+	cp->instance = instance;
+	put_le32(flags, &cp->flags);
+	put_le16(timeout, &cp->timeout);
+	put_le16(duration, &cp->duration);
+	put_le32(min_interval, &cp->min_interval);
+	put_le32(max_interval, &cp->max_interval);
+	cp->tx_power = tx_power;
+
+	if (!mgmt_send(mgmt, MGMT_OP_ADD_EXT_ADV_PARAMS, index, sizeof(*cp), cp,
+					add_ext_adv_params_rsp, NULL, NULL)) {
+		error("Unable to send \"Add Ext Advertising Params\" command");
+		goto done;
+	}
+
+	quit = false;
+
+done:
+	free(cp);
+
+	if (quit)
+		bt_shell_noninteractive_quit(success ?
+						EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void add_ext_adv_data_rsp(uint8_t status, uint16_t len,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_add_ext_adv_data *rp = param;
+
+	if (status != 0) {
+		error("Add Ext Advertising Data failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len != sizeof(*rp)) {
+		error("Invalid Add Ext Advertising Data response length (%u)",
+									len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Instance added: %u", rp->instance);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void add_ext_adv_data_usage(void)
+{
+	bt_shell_usage();
+	print("Options:\n"
+		"\t -u, --uuid <uuid>         Service UUID\n"
+		"\t -d, --adv-data <data>     Advertising Data bytes\n"
+		"\t -s, --scan-rsp <data>     Scan Response Data bytes\n"
+		"e.g.:\n"
+		"\tadd-ext-adv-data -u 180d -u 180f -d 080954657374204C45 1");
+}
+
+static const struct option add_ext_adv_data_options[] = {
+	{ "help",		0, 0, 'h' },
+	{ "uuid",		1, 0, 'u' },
+	{ "adv-data",		1, 0, 'd' },
+	{ "scan-rsp",		1, 0, 's' },
+	{ 0, 0, 0, 0}
+};
+
+static void cmd_add_ext_adv_data(int argc, char **argv)
+{
+	struct mgmt_cp_add_ext_adv_data *cp = NULL;
+	int opt;
+	uint8_t *adv_data = NULL, *scan_rsp = NULL;
+	size_t adv_len = 0, scan_rsp_len = 0;
+	size_t cp_len;
+	uint8_t uuids[MAX_AD_UUID_BYTES];
+	size_t uuid_bytes = 0;
+	uint8_t uuid_type = 0;
+	uint8_t instance;
+	bt_uuid_t uuid;
+	bool success = false;
+	bool quit = true;
+	uint16_t index;
+
+	while ((opt = getopt_long(argc, argv, "+u:d:s:h",
+				add_ext_adv_data_options, NULL)) != -1) {
+		switch (opt) {
+		case 'u':
+			if (bt_string_to_uuid(&uuid, optarg) < 0) {
+				print("Invalid UUID: %s", optarg);
+				goto done;
+			}
+
+			if (uuid_type && uuid_type != uuid.type) {
+				print("UUID types must be consistent");
+				goto done;
+			}
+
+			if (uuid.type == BT_UUID16) {
+				if (uuid_bytes + 2 >= MAX_AD_UUID_BYTES) {
+					print("Too many UUIDs");
+					goto done;
+				}
+
+				bt_uuid_to_le(&uuid, uuids + uuid_bytes);
+				uuid_bytes += 2;
+			} else if (uuid.type == BT_UUID128) {
+				if (uuid_bytes + 16 >= MAX_AD_UUID_BYTES) {
+					print("Too many UUIDs");
+					goto done;
+				}
+
+				bt_uuid_to_le(&uuid, uuids + uuid_bytes);
+				uuid_bytes += 16;
+			} else {
+				printf("Unsupported UUID type");
+				goto done;
+			}
+
+			if (!uuid_type)
+				uuid_type = uuid.type;
+
+			break;
+		case 'd':
+			if (adv_len) {
+				print("Only one adv-data option allowed");
+				goto done;
+			}
+
+			if (!parse_bytes(optarg, &adv_data, &adv_len))
+				goto done;
+			break;
+		case 's':
+			if (scan_rsp_len) {
+				print("Only one scan-rsp option allowed");
+				goto done;
+			}
+
+			if (!parse_bytes(optarg, &scan_rsp, &scan_rsp_len))
+				goto done;
+			break;
+		case 'h':
+			success = true;
+			/* fall through */
+		default:
+			add_ext_adv_data_usage();
+			optind = 0;
+			goto done;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc != 1) {
+		add_ext_adv_data_usage();
+		goto done;
+	}
+
+	if (uuid_bytes)
+		uuid_bytes += 2;
+
+	instance = strtol(argv[0], NULL, 0);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp_len = sizeof(*cp) + uuid_bytes + adv_len + scan_rsp_len;
+	cp = malloc0(cp_len);
+	if (!cp)
+		goto done;
+
+	cp->instance = instance;
+	cp->adv_data_len = adv_len + uuid_bytes;
+	cp->scan_rsp_len = scan_rsp_len;
+
+	if (uuid_bytes) {
+		cp->data[0] = uuid_bytes - 1;
+		cp->data[1] = uuid_type == SDP_UUID16 ? 0x03 : 0x07;
+		memcpy(cp->data + 2, uuids, uuid_bytes - 2);
+	}
+
+	if (adv_len)
+		memcpy(cp->data + uuid_bytes, adv_data, adv_len);
+
+	if (scan_rsp_len)
+		memcpy(cp->data + uuid_bytes + adv_len, scan_rsp, scan_rsp_len);
+
+	if (!mgmt_send(mgmt, MGMT_OP_ADD_EXT_ADV_DATA, index, cp_len, cp,
+					add_ext_adv_data_rsp, NULL, NULL)) {
+		error("Unable to send \"Add Ext Advertising Data\" command");
+		goto done;
+	}
+
+	quit = false;
+
+done:
+	free(adv_data);
+	free(scan_rsp);
+	free(cp);
+
+	if (quit)
+		bt_shell_noninteractive_quit(success ?
+						EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void appearance_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0)
+		error("Could not set Appearance with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+	else
+		print("Appearance successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_appearance(int argc, char **argv)
+{
+	struct mgmt_cp_set_appearance cp;
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	cp.appearance = cpu_to_le16(strtol(argv[1], NULL, 0));
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_APPEARANCE, index, sizeof(cp), &cp,
+					appearance_rsp, NULL, NULL) == 0) {
+		error("Unable to send appearance cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static const char *phys_str[] = {
+	"BR1M1SLOT",
+	"BR1M3SLOT",
+	"BR1M5SLOT",
+	"EDR2M1SLOT",
+	"EDR2M3SLOT",
+	"EDR2M5SLOT",
+	"EDR3M1SLOT",
+	"EDR3M3SLOT",
+	"EDR3M5SLOT",
+	"LE1MTX",
+	"LE1MRX",
+	"LE2MTX",
+	"LE2MRX",
+	"LECODEDTX",
+	"LECODEDRX",
+};
+
+static const char *phys2str(uint32_t phys)
+{
+	static char str[256];
+	unsigned int i;
+	int off;
+
+	off = 0;
+	str[0] = '\0';
+
+	for (i = 0; i < NELEM(phys_str); i++) {
+		if ((phys & (1 << i)) != 0)
+			off += snprintf(str + off, sizeof(str) - off, "%s ",
+							phys_str[i]);
+	}
+
+	return str;
+}
+
+static bool str2phy(const char *phy_str, uint32_t *phy_val)
+{
+	unsigned int i;
+
+	for (i = 0; i < NELEM(phys_str); i++) {
+		if (strcasecmp(phys_str[i], phy_str) == 0) {
+			*phy_val = (1 << i);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void get_phy_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	uint32_t supported_phys, selected_phys, configurable_phys;
+
+	if (status != 0) {
+		error("Get PHY Configuration failed with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small get-phy reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	supported_phys = get_le32(&rp->supported_phys);
+	configurable_phys = get_le32(&rp->configurable_phys);
+	selected_phys = get_le32(&rp->selected_phys);
+
+	print("Supported phys: %s", phys2str(supported_phys));
+	print("Configurable phys: %s", phys2str(configurable_phys));
+	print("Selected phys: %s", phys2str(selected_phys));
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void get_phy(void)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send(mgmt, MGMT_OP_GET_PHY_CONFIGURATION, index, 0, NULL,
+					get_phy_rsp, NULL, NULL) == 0) {
+		error("Unable to send Get PHY cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void set_phy_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	if (status != 0) {
+		error("Could not set PHY Configuration with status 0x%02x (%s)",
+						status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("PHY Configuration successfully set");
+
+	bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_phy(int argc, char **argv)
+{
+	struct mgmt_cp_set_phy_confguration cp;
+	int i;
+	uint32_t phys = 0;
+	uint16_t index;
+
+	if (argc < 2)
+		return get_phy();
+
+	for (i = 1; i < argc; i++) {
+		uint32_t phy_val;
+
+		if (str2phy(argv[i], &phy_val))
+			phys |= phy_val;
+	}
+
+	cp.selected_phys = cpu_to_le32(phys);
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send(mgmt, MGMT_OP_SET_PHY_CONFIGURATION, index, sizeof(cp),
+					&cp, set_phy_rsp, NULL, NULL) == 0) {
+		error("Unable to send %s cmd",
+				mgmt_opstr(MGMT_OP_SET_PHY_CONFIGURATION));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void cmd_wbs(int argc, char **argv)
+{
+	cmd_setting(MGMT_OP_SET_WIDEBAND_SPEECH, argc, argv);
+}
+
+static const char * const advmon_features_str[] = {
+	"Pattern monitor with logic OR.",
+};
+
+static const char *advmon_features2str(uint32_t features)
+{
+	static char str[512];
+	unsigned int off, i;
+
+	off = 0;
+	snprintf(str, sizeof(str), "\n\tNone");
+
+	for (i = 0; i < NELEM(advmon_features_str); i++) {
+		if ((features & (1 << i)) != 0 && off < sizeof(str))
+			off += snprintf(str + off, sizeof(str) - off, "\n\t%s",
+						advmon_features_str[i]);
+	}
+
+	return str;
+}
+
+static void advmon_features_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_read_adv_monitor_features *rp = param;
+	uint32_t supported_features, enabled_features;
+	uint16_t num_handles;
+	int i;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Reading adv monitor features failed with status 0x%02x "
+					"(%s)", status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (len < sizeof(*rp)) {
+		error("Too small adv monitor features reply (%u bytes)", len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	supported_features = le32_to_cpu(rp->supported_features);
+	enabled_features = le32_to_cpu(rp->enabled_features);
+	num_handles = le16_to_cpu(rp->num_handles);
+
+	if (len < sizeof(*rp) + num_handles * sizeof(uint16_t)) {
+		error("Handles count (%u) doesn't match reply length (%u)",
+							num_handles, len);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Supported features:%s", advmon_features2str(supported_features));
+	print("Enabled features:%s", advmon_features2str(enabled_features));
+	print("Max number of handles: %u", le16_to_cpu(rp->max_num_handles));
+	print("Max number of patterns: %u", rp->max_num_patterns);
+	print("Handles list with %u item%s", num_handles,
+			num_handles == 0 ? "" : num_handles == 1 ? ":" : "s:");
+	for (i = 0; i < num_handles; i++)
+		print("\t0x%04x ", le16_to_cpu(rp->handles[i]));
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_advmon_features(int argc, char **argv)
+{
+	uint16_t index;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_MONITOR_FEATURES, index, 0, NULL,
+					advmon_features_rsp, NULL, NULL)) {
+		error("Unable to send advertising monitor features command");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void advmon_add_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_add_adv_patterns_monitor *rp = param;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Could not add advertisement monitor with status "
+				"0x%02x (%s)", status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Advertisement monitor with handle:0x%04x added",
+					le16_to_cpu(rp->monitor_handle));
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static bool str2pattern(struct mgmt_adv_pattern *pattern, const char *str)
+{
+	int type_len, offset_len, offset_end_pos, str_len;
+	int i, j;
+	char pattern_str[62] = { 0 };
+	char tmp;
+
+	if (sscanf(str, "%2hhx%n:%2hhx%n:%61s", &pattern->ad_type, &type_len,
+			&pattern->offset, &offset_end_pos, pattern_str) != 3)
+		return false;
+
+	offset_len = offset_end_pos - type_len - 1;
+	str_len = strlen(pattern_str);
+	pattern->length = str_len / 2 + str_len % 2;
+
+	if (type_len > 2 || offset_len > 2 ||
+					pattern->offset + pattern->length > 31)
+		return false;
+
+	for (i = 0, j = 0; i < str_len; i++, j++) {
+		if (sscanf(&pattern_str[i++], "%2hhx", &pattern->value[j])
+									!= 1)
+			return false;
+		if (i < str_len && sscanf(&pattern_str[i], "%1hhx", &tmp) != 1)
+			return false;
+	}
+
+	return true;
+}
+
+static const struct option add_monitor_rssi_options[] = {
+	{ "help",		0, 0, 'h' },
+	{ "high-threshold",	1, 0, 'R' },
+	{ "low-threshold",	1, 0, 'r' },
+	{ "high-timeout",	1, 0, 'T' },
+	{ "low-timeout",	1, 0, 't' },
+	{ "sampling",		1, 0, 's' },
+	{ 0, 0, 0, 0 }
+};
+
+static void advmon_add_pattern_usage(void)
+{
+	bt_shell_usage();
+	print("patterns format:\n"
+		"\t<ad_type:offset:pattern> [patterns]\n"
+		"e.g.:\n"
+		"\tadd-pattern 0:1:c504 ff:a:9a55beef");
+}
+
+static void advmon_add_pattern_rssi_usage(void)
+{
+	bt_shell_usage();
+	print("RSSI options:\n"
+		"\t -R, --high-threshold <dBm>  "
+			"RSSI high threshold. Default: -70\n"
+		"\t -r, --low-threshold <dBm>   "
+			"RSSI low threshold. Default: -50\n"
+		"\t -T, --high-timeout <s>      "
+			"RSSI high threshold duration. Default: 0\n"
+		"\t -t, --low-timeout <s>       "
+			"RSSI low threshold duration. Default: 5\n"
+		"\t -s, --sampling <N * 100ms>  "
+			"RSSI sampling period. Default: 0\n"
+		"patterns format:\n"
+		"\t<ad_type:offset:pattern> [patterns]\n"
+		"e.g.:\n"
+		"\tadd-pattern-rssi -R 0xb2 -r -102 0:1:c504 ff:a:9a55beef");
+}
+
+static void cmd_advmon_add_pattern(int argc, char **argv)
+{
+	bool success = true;
+	uint16_t index;
+	int i, cp_len;
+	struct mgmt_cp_add_adv_monitor *cp = NULL;
+
+	if (!strcmp(argv[1], "-h"))
+		goto done;
+
+	argc -= 1;
+	argv += 1;
+
+	cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
+	cp = malloc0(cp_len);
+	if (!cp) {
+		error("Failed to alloc patterns.");
+		success = false;
+		goto done;
+	}
+
+	cp->pattern_count = argc;
+
+	for (i = 0; i < argc; i++) {
+		if (!str2pattern(&cp->patterns[i], argv[i])) {
+			error("Failed to parse monitor patterns.");
+			success = false;
+			goto done;
+		}
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR, index,
+				cp_len, cp, advmon_add_rsp, NULL, NULL)) {
+		error("Unable to send Add Advertising Monitor command");
+		success = false;
+		goto done;
+	}
+
+	free(cp);
+	return;
+
+done:
+	free(cp);
+	advmon_add_pattern_usage();
+	bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void cmd_advmon_add_pattern_rssi(int argc, char **argv)
+{
+	bool success = true;
+	int opt;
+	int8_t rssi_low = -70;
+	int8_t rssi_high = -50;
+	uint16_t rssi_low_timeout = 5;
+	uint16_t rssi_high_timeout = 0;
+	uint8_t rssi_sampling_period = 0;
+	uint16_t index;
+	int i, cp_len;
+	struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = NULL;
+
+	while ((opt = getopt_long(argc, argv, "+hr:R:t:T:s:",
+				add_monitor_rssi_options, NULL)) != -1) {
+		switch (opt) {
+		case 'h':
+			goto done;
+		case 'r':
+			rssi_low = strtol(optarg, NULL, 0);
+			break;
+		case 'R':
+			rssi_high = strtol(optarg, NULL, 0);
+			break;
+		case 't':
+			rssi_low_timeout = strtol(optarg, NULL, 0);
+			break;
+		case 'T':
+			rssi_high_timeout = strtol(optarg, NULL, 0);
+			break;
+		case 's':
+			rssi_sampling_period = strtol(optarg, NULL, 0);
+			break;
+		default:
+			success = false;
+			goto done;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
+	cp = malloc0(cp_len);
+	if (!cp) {
+		error("Failed to alloc patterns.");
+		success = false;
+		goto done;
+	}
+
+	cp->pattern_count = argc;
+	cp->rssi.high_threshold = rssi_high;
+	cp->rssi.low_threshold = rssi_low;
+	cp->rssi.high_threshold_timeout = htobs(rssi_high_timeout);
+	cp->rssi.low_threshold_timeout = htobs(rssi_low_timeout);
+	cp->rssi.sampling_period = rssi_sampling_period;
+
+	for (i = 0; i < argc; i++) {
+		if (!str2pattern(&cp->patterns[i], argv[i])) {
+			error("Failed to parse monitor patterns.");
+			success = false;
+			goto done;
+		}
+	}
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, index,
+				cp_len, cp, advmon_add_rsp, NULL, NULL)) {
+		error("Unable to send Add Advertising Monitor RSSI command");
+		success = false;
+		goto done;
+	}
+
+	free(cp);
+	return;
+
+done:
+	free(cp);
+	optind = 0;
+	advmon_add_pattern_rssi_usage();
+	bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void advmon_remove_rsp(uint8_t status, uint16_t len, const void *param,
+							void *user_data)
+{
+	const struct mgmt_rp_remove_adv_monitor *rp = param;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Could not remove advertisement monitor with status "
+				"0x%02x (%s)", status, mgmt_errstr(status));
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	print("Advertisement monitor with handle: 0x%04x removed",
+					le16_to_cpu(rp->monitor_handle));
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_advmon_remove(int argc, char **argv)
+{
+	struct mgmt_cp_remove_adv_monitor cp;
+	uint16_t index, monitor_handle;
+
+	index = mgmt_index;
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (sscanf(argv[1], "%hx", &monitor_handle) != 1) {
+		error("Wrong formatted handle argument");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	cp.monitor_handle = cpu_to_le16(monitor_handle);
+	if (mgmt_send(mgmt, MGMT_OP_REMOVE_ADV_MONITOR, index, sizeof(cp), &cp,
+					advmon_remove_rsp, NULL, NULL) == 0) {
+		error("Unable to send appearance cmd");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
+{
+	mgmt_register(mgmt, MGMT_EV_CONTROLLER_ERROR, index, controller_error,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index, index_added,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_INDEX_REMOVED, index, index_removed,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_NEW_SETTINGS, index, new_settings,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_DISCOVERING, index, discovering,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_NEW_LINK_KEY, index, new_link_key,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_DEVICE_CONNECTED, index, connected,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_DEVICE_DISCONNECTED, index, disconnected,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_CONNECT_FAILED, index, conn_failed,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_AUTH_FAILED, index, auth_failed,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED, index,
+					class_of_dev_changed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_LOCAL_NAME_CHANGED, index,
+					local_name_changed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_DEVICE_FOUND, index, device_found,
+								mgmt, NULL);
+	mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_ADDED, index,
+					unconf_index_added, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_REMOVED, index,
+					unconf_index_removed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_NEW_CONFIG_OPTIONS, index,
+					new_config_options, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_EXT_INDEX_ADDED, index,
+					ext_index_added, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_EXT_INDEX_REMOVED, index,
+					ext_index_removed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_LOCAL_OOB_DATA_UPDATED, index,
+					local_oob_data_updated, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_ADVERTISING_ADDED, index,
+						advertising_added, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_ADVERTISING_REMOVED, index,
+					advertising_removed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_DEVICE_FLAGS_CHANGED, index,
+					flags_changed, NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_ADDED, index, advmon_added,
+								NULL, NULL);
+	mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_REMOVED, index, advmon_removed,
+								NULL, NULL);
+}
+
+static void cmd_select(int argc, char **argv)
+{
+	mgmt_cancel_all(mgmt);
+	mgmt_unregister_all(mgmt);
+
+	mgmt_set_index(argv[1]);
+
+	register_mgmt_callbacks(mgmt, mgmt_index);
+
+	print("Selected index %u", mgmt_index);
+}
+
+static const struct bt_shell_menu monitor_menu = {
+	.name = "monitor",
+	.desc = "Advertisement Monitor Submenu",
+	.entries = {
+	{ "features",		NULL,
+		cmd_advmon_features,	"Show advertisement monitor "
+					"features"			},
+	{ "remove",		"<handle>",
+		cmd_advmon_remove,	"Remove advertisement monitor "	},
+	{ "add-pattern",	"[-,h] <patterns>",
+		cmd_advmon_add_pattern,	"Add advertisement monitor pattern" },
+	{ "add-pattern-rssi",	"[options] <patterns>",
+		cmd_advmon_add_pattern_rssi,
+		"Add advertisement monitor pattern with RSSI options"    },
+	{ } },
+};
+
+static const struct bt_shell_menu mgmt_menu = {
+	.name = "mgmt",
+	.desc = "Management Submenu",
+	.entries = {
+	{ "select",		"<index>",
+		cmd_select,		"Select a different index"	},
+	{ "revision",		NULL,
+		cmd_revision,		"Get the MGMT Revision"		},
+	{ "commands",		NULL,
+		cmd_commands,		"List supported commands"	},
+	{ "config",		NULL,
+		cmd_config,		"Show configuration info"	},
+	{ "info",		NULL,
+		cmd_info,		"Show controller info"		},
+	{ "extinfo",		NULL,
+		cmd_extinfo,		"Show extended controller info"	},
+	{ "auto-power",		NULL,
+		cmd_auto_power,		"Power all available features"	},
+	{ "power",		"<on/off>",
+		cmd_power,		"Toggle powered state"		},
+	{ "discov",		"<yes/no/limited> [timeout]",
+		cmd_discov,		"Toggle discoverable state"	},
+	{ "connectable",	"<on/off>",
+	cmd_connectable,		"Toggle connectable state"	},
+	{ "fast-conn",		"<on/off>",
+		cmd_fast_conn,		"Toggle fast connectable state"	},
+	{ "bondable",		"<on/off>",
+		cmd_bondable,		"Toggle bondable state"		},
+	{ "pairable",		"<on/off>",
+		cmd_bondable,		"Toggle bondable state"		},
+	{ "linksec",		"<on/off>",
+		cmd_linksec,		"Toggle link level security"	},
+	{ "ssp",		"<on/off>",
+		cmd_ssp,		"Toggle SSP mode"		},
+	{ "sc",			"<on/off/only>",
+		cmd_sc,			"Toogle SC support"		},
+	{ "hs",			"<on/off>",
+		cmd_hs,			"Toggle HS support"		},
+	{ "le",			"<on/off>",
+		cmd_le,			"Toggle LE support"		},
+	{ "advertising",	"<on/off>",
+	cmd_advertising,		"Toggle LE advertising",	},
+	{ "bredr",		"<on/off>",
+		cmd_bredr,		"Toggle BR/EDR support",	},
+	{ "privacy",		"<on/off> [irk]",
+		cmd_privacy,		"Toggle privacy support"	},
+	{ "class",		"<major> <minor>",
+		cmd_class,		"Set device major/minor class"	},
+	{ "disconnect", 	"[-t type] <remote address>",
+		cmd_disconnect,		"Disconnect device"		},
+	{ "con",		NULL,
+		cmd_con,		"List connections"		},
+	{ "find",		"[-l|-b] [-L]",
+		cmd_find,		"Discover nearby devices"	},
+	{ "find-service",	"[-u UUID] [-r RSSI_Threshold] [-l|-b]",
+		cmd_find_service,	"Discover nearby service"	},
+	{ "stop-find",		"[-l|-b]",
+		cmd_stop_find,		"Stop discovery"		},
+	{ "name",		"<name> [shortname]",
+		cmd_name,		"Set local name"		},
+	{ "pair",		"[-c cap] [-t type] <remote address>",
+		cmd_pair,		"Pair with a remote device"	},
+	{ "cancelpair",		"[-t type] <remote address>",
+		cmd_cancel_pair,	"Cancel pairing"		},
+	{ "unpair",		"[-t type] <remote address>",
+		cmd_unpair,		"Unpair device"			},
+	{ "keys",		NULL,
+		cmd_keys,		"Load Link Keys"		},
+	{ "ltks",		NULL,
+		cmd_ltks,		"Load Long Term Keys"		},
+	{ "irks",		"[--local index] [--file file path]",
+		cmd_irks,		"Load Identity Resolving Keys"	},
+	{ "block",		"[-t type] <remote address>",
+		cmd_block,		"Block Device"			},
+	{ "unblock",		"[-t type] <remote address>",
+		cmd_unblock,		"Unblock Device"		},
+	{ "add-uuid",		"<UUID> <service class hint>",
+		cmd_add_uuid,		"Add UUID"			},
+	{ "rm-uuid",		"<UUID>",
+		cmd_remove_uuid,	"Remove UUID"			},
+	{ "clr-uuids",		NULL,
+		cmd_clr_uuids,		"Clear UUIDs"			},
+	{ "local-oob",		NULL,
+		cmd_local_oob,		"Local OOB data"		},
+	{ "remote-oob",		"[-t <addr_type>] [-r <rand192>] "
+				"[-h <hash192>] [-R <rand256>] "
+				"[-H <hash256>] <addr>",
+		cmd_remote_oob,		"Remote OOB data"		},
+	{ "did",		"<source>:<vendor>:<product>:<version>",
+		cmd_did,		"Set Device ID"			},
+	{ "static-addr",	"<address>",
+		cmd_static_addr,	"Set static address"		},
+	{ "public-addr",	"<address>",
+		cmd_public_addr,	"Set public address"		},
+	{ "ext-config",		"<on/off>",
+		cmd_ext_config,		"External configuration"	},
+	{ "debug-keys",		"<on/off>",
+		cmd_debug_keys,		"Toogle debug keys"		},
+	{ "conn-info",		"[-t type] <remote address>",
+		cmd_conn_info,		"Get connection information"	},
+	{ "io-cap",		"<cap>",
+		cmd_io_cap,		"Set IO Capability"		},
+	{ "scan-params",	"<interval> <window>",
+		cmd_scan_params,	"Set Scan Parameters"		},
+	{ "get-clock",		"[address]",
+		cmd_clock_info,		"Get Clock Information"		},
+	{ "add-device", 	"[-a action] [-t type] <address>",
+		cmd_add_device,		"Add Device"			},
+	{ "del-device", 	"[-t type] <address>",
+		cmd_del_device,		"Remove Device"			},
+	{ "clr-devices",	NULL,
+		cmd_clr_devices,	"Clear Devices"			},
+	{ "bredr-oob",		NULL,
+		cmd_bredr_oob,		"Local OOB data (BR/EDR)"	},
+	{ "le-oob",		NULL,
+		cmd_le_oob,		"Local OOB data (LE)"		},
+	{ "advinfo",		NULL,
+		cmd_advinfo,		"Show advertising features"	},
+	{ "advsize",		"[options] <instance_id>",
+		cmd_advsize,		"Show advertising size info"	},
+	{ "add-adv",		"[options] <instance_id>",
+		cmd_add_adv,		"Add advertising instance"	},
+	{ "rm-adv",		"<instance_id>",
+		cmd_rm_adv,		"Remove advertising instance"	},
+	{ "clr-adv",		NULL,
+		cmd_clr_adv,		"Clear advertising instances"	},
+	{ "add-ext-adv-params",	"[options] <instance_id>",
+		cmd_add_ext_adv_params,
+				"Add extended advertising params"	},
+	{ "add-ext-adv-data",	"[options] <instance_id>",
+		cmd_add_ext_adv_data,
+				"Add extended advertising data"		},
+	{ "appearance",		"<appearance>",
+		cmd_appearance,		"Set appearance"		},
+	{ "phy",		"[LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] "
+				"[LECODEDTX] [LECODEDRX] "
+				"[BR1M1SLOT] [BR1M3SLOT] [BR1M5SLOT]"
+				"[EDR2M1SLOT] [EDR2M3SLOT] [EDR2M5SLOT]"
+				"[EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]",
+		cmd_phy,		"Get/Set PHY Configuration"	},
+	{ "wbs",		"<on/off>",
+		cmd_wbs,		"Toggle Wideband-Speech support"},
+	{ "secinfo",		NULL,
+		cmd_secinfo,		"Show security information"	},
+	{ "expinfo",		NULL,
+		cmd_expinfo,		"Show experimental features"	},
+	{ "exp-debug",		"<on/off>",
+		cmd_exp_debug,		"Set debug feature"		},
+	{ "exp-privacy",	"<on/off>",
+		cmd_exp_privacy,	"Set LL privacy feature"	},
+	{ "exp-quality",	"<on/off>", cmd_exp_quality,
+		"Set bluetooth quality report feature"			},
+	{ "exp-offload",		"<on/off>",
+		cmd_exp_offload_codecs,	"Toggle codec support"		},
+	{ "read-sysconfig",	NULL,
+		cmd_read_sysconfig,	"Read System Configuration"	},
+	{ "set-sysconfig",	"<-v|-h> [options...]",
+		cmd_set_sysconfig,	"Set System Configuration"	},
+	{ "get-flags",		"[-t type] <address>",
+		cmd_get_flags,		"Get device flags"		},
+	{ "set-flags",		"[-f flags] [-t type] <address>",
+		cmd_set_flags,		"Set device flags"		},
+	{} },
+};
+
+static void mgmt_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	print("%s%s", prefix, str);
+}
+
+bool mgmt_add_submenu(void)
+{
+	mgmt = mgmt_new_default();
+	if (!mgmt) {
+		fprintf(stderr, "Unable to open mgmt_socket\n");
+		return false;
+	}
+
+	bt_shell_add_submenu(&mgmt_menu);
+	bt_shell_add_submenu(&monitor_menu);
+
+	if (getenv("MGMT_DEBUG"))
+		mgmt_set_debug(mgmt, mgmt_debug, "mgmt: ", NULL);
+
+	register_mgmt_callbacks(mgmt, mgmt_index);
+
+	return true;
+}
+
+void mgmt_remove_submenu(void)
+{
+	mgmt_cancel_all(mgmt);
+	mgmt_unregister_all(mgmt);
+	mgmt_unref(mgmt);
+}
diff --git a/client/mgmt.h b/client/mgmt.h
new file mode 100644
index 0000000..5a2026e
--- /dev/null
+++ b/client/mgmt.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023 Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+bool mgmt_add_submenu(void);
+void mgmt_remove_submenu(void);
+void mgmt_set_index(const char *arg);
diff --git a/client/player.c b/client/player.c
index 4324089..eed8d23 100644
--- a/client/player.c
+++ b/client/player.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -24,6 +25,8 @@
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <wordexp.h>
+#include <sys/timerfd.h>
+#include <sys/stat.h>
 
 #include <glib.h>
 
@@ -31,6 +34,7 @@
 
 #include "lib/bluetooth.h"
 #include "lib/uuid.h"
+#include "lib/iso.h"
 
 #include "profiles/audio/a2dp-codecs.h"
 #include "src/shared/lc3.h"
@@ -39,6 +43,8 @@
 #include "src/shared/shell.h"
 #include "src/shared/io.h"
 #include "src/shared/queue.h"
+#include "src/shared/bap-debug.h"
+#include "print.h"
 #include "player.h"
 
 /* String display constants */
@@ -58,18 +64,63 @@
 #define NSEC_USEC(_t) (_t / 1000L)
 #define SEC_USEC(_t)  (_t  * 1000000L)
 #define TS_USEC(_ts)  (SEC_USEC((_ts)->tv_sec) + NSEC_USEC((_ts)->tv_nsec))
+#define ROUND_CLOSEST(_x, _y) (((_x) + (_y / 2)) / (_y))
+
+#define EP_SRC_LOCATIONS 0x00000003
+#define EP_SNK_LOCATIONS 0x00000003
+
+#define EP_SRC_CTXT 0x000f
+#define EP_SUPPORTED_SRC_CTXT EP_SRC_CTXT
+#define EP_SNK_CTXT 0x0fff
+#define EP_SUPPORTED_SNK_CTXT EP_SNK_CTXT
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct avdtp_media_codec_capability {
+	uint8_t rfa0:4;
+	uint8_t media_type:4;
+	uint8_t media_codec_type;
+	uint8_t data[0];
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct avdtp_media_codec_capability {
+	uint8_t media_type:4;
+	uint8_t rfa0:4;
+	uint8_t media_codec_type;
+	uint8_t data[0];
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
+
+#define BCAST_CODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
+				0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
 
 struct endpoint {
 	char *path;
 	char *uuid;
 	uint8_t codec;
+	uint16_t cid;
+	uint16_t vid;
 	struct iovec *caps;
+	struct iovec *meta;
+	uint32_t locations;
+	uint16_t supported_context;
+	uint16_t context;
 	bool auto_accept;
-	bool acquiring;
-	uint8_t cig;
-	uint8_t cis;
-	char *transport;
+	uint8_t max_transports;
+	uint8_t iso_group;
+	uint8_t iso_stream;
+	struct queue *acquiring;
+	struct queue *transports;
 	DBusMessage *msg;
+	struct preset *preset;
+	struct codec_preset *codec_preset;
+	bool broadcast;
+	struct iovec *bcode;
 };
 
 static DBusConnection *dbus_conn;
@@ -82,6 +133,7 @@ static GList *endpoints = NULL;
 static GList *local_endpoints = NULL;
 static GList *transports = NULL;
 static struct queue *ios = NULL;
+static uint8_t bcast_code[] = BCAST_CODE;
 
 struct transport {
 	GDBusProxy *proxy;
@@ -89,8 +141,11 @@ struct transport {
 	uint16_t mtu[2];
 	char *filename;
 	int fd;
+	struct stat stat;
 	struct io *io;
 	uint32_t seq;
+	struct io *timer_io;
+	int num;
 };
 
 static void endpoint_unregister(void *data)
@@ -511,88 +566,6 @@ static char *proxy_description(GDBusProxy *proxy, const char *title,
 					title, path);
 }
 
-static void print_iter(const char *label, const char *name,
-						DBusMessageIter *iter)
-{
-	dbus_bool_t valbool;
-	dbus_uint32_t valu32;
-	dbus_uint16_t valu16;
-	dbus_int16_t vals16;
-	unsigned char byte;
-	const char *valstr;
-	DBusMessageIter subiter;
-
-	if (iter == NULL) {
-		bt_shell_printf("%s%s is nil\n", label, name);
-		return;
-	}
-
-	switch (dbus_message_iter_get_arg_type(iter)) {
-	case DBUS_TYPE_INVALID:
-		bt_shell_printf("%s%s is invalid\n", label, name);
-		break;
-	case DBUS_TYPE_STRING:
-	case DBUS_TYPE_OBJECT_PATH:
-		dbus_message_iter_get_basic(iter, &valstr);
-		bt_shell_printf("%s%s: %s\n", label, name, valstr);
-		break;
-	case DBUS_TYPE_BOOLEAN:
-		dbus_message_iter_get_basic(iter, &valbool);
-		bt_shell_printf("%s%s: %s\n", label, name,
-					valbool == TRUE ? "yes" : "no");
-		break;
-	case DBUS_TYPE_UINT32:
-		dbus_message_iter_get_basic(iter, &valu32);
-		bt_shell_printf("%s%s: 0x%08x (%u)\n", label, name, valu32,
-								valu32);
-		break;
-	case DBUS_TYPE_UINT16:
-		dbus_message_iter_get_basic(iter, &valu16);
-		bt_shell_printf("%s%s: 0x%04x (%u)\n", label, name, valu16,
-								valu16);
-		break;
-	case DBUS_TYPE_INT16:
-		dbus_message_iter_get_basic(iter, &vals16);
-		bt_shell_printf("%s%s: %d\n", label, name, vals16);
-		break;
-	case DBUS_TYPE_BYTE:
-		dbus_message_iter_get_basic(iter, &byte);
-		bt_shell_printf("%s%s: 0x%02x (%d)\n", label, name, byte, byte);
-		break;
-	case DBUS_TYPE_VARIANT:
-		dbus_message_iter_recurse(iter, &subiter);
-		print_iter(label, name, &subiter);
-		break;
-	case DBUS_TYPE_ARRAY:
-		dbus_message_iter_recurse(iter, &subiter);
-		while (dbus_message_iter_get_arg_type(&subiter) !=
-							DBUS_TYPE_INVALID) {
-			print_iter(label, name, &subiter);
-			dbus_message_iter_next(&subiter);
-		}
-		break;
-	case DBUS_TYPE_DICT_ENTRY:
-		dbus_message_iter_recurse(iter, &subiter);
-		dbus_message_iter_get_basic(&subiter, &valstr);
-		dbus_message_iter_next(&subiter);
-		print_iter(label, valstr, &subiter);
-		break;
-	default:
-		bt_shell_printf("%s%s has unsupported type\n", label, name);
-		break;
-	}
-}
-
-static void print_property(GDBusProxy *proxy, const char *name)
-{
-	DBusMessageIter iter;
-
-	if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
-		return;
-
-	print_iter("\t", name, &iter);
-}
-
 static void print_media(GDBusProxy *proxy, const char *description)
 {
 	char *str;
@@ -1025,11 +998,6 @@ static const struct bt_shell_menu player_menu = {
 	{} },
 };
 
-static char *endpoint_generator(const char *text, int state)
-{
-	return generic_generator(text, state, endpoints);
-}
-
 static char *local_endpoint_generator(const char *text, int state)
 {
 	int len = strlen(text);
@@ -1051,6 +1019,17 @@ static char *local_endpoint_generator(const char *text, int state)
 	return NULL;
 }
 
+static char *endpoint_generator(const char *text, int state)
+{
+	char *ret;
+
+	ret = generic_generator(text, state, endpoints);
+	if (ret)
+		return ret;
+
+	return local_endpoint_generator(text, state);
+}
+
 static void print_endpoint(void *data, void *user_data)
 {
 	GDBusProxy *proxy = data;
@@ -1128,8 +1107,19 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn,
 	bt_shell_printf("\tTransport %s\n", path);
 	print_iter("\t", "Properties", &props);
 
-	free(ep->transport);
-	ep->transport = strdup(path);
+	if (!ep->max_transports) {
+		bt_shell_printf("Maximum transports reached: rejecting\n");
+		return g_dbus_create_error(msg,
+					 "org.bluez.Error.Rejected",
+					 "Maximum transports reached");
+	}
+
+	ep->max_transports--;
+
+	if (!ep->transports)
+		ep->transports = queue_new();
+
+	queue_push_tail(ep->transports, strdup(path));
 
 	if (ep->auto_accept) {
 		bt_shell_printf("Auto Accepting...\n");
@@ -1142,38 +1132,27 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn,
 	return NULL;
 }
 
-struct codec_capabilities {
-	uint8_t len;
-	uint8_t type;
-	uint8_t data[UINT8_MAX];
-};
-
-#define data(args...) ((const unsigned char[]) { args })
-
-#define CODEC_DATA(args...) \
-	{ \
-		.iov_base = (void *)data(args), \
-		.iov_len = sizeof(data(args)), \
-	}
-
-#define CODEC_CAPABILITIES(_uuid, _codec_id, _data) \
+#define CODEC_CAPABILITIES(_name, _uuid, _codec_id, _data, _meta) \
 	{ \
+		.name = _name, \
 		.uuid = _uuid, \
 		.codec_id = _codec_id, \
 		.data = _data, \
+		.meta = _meta, \
 	}
 
-#define LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max) \
-	CODEC_DATA(0x03, LC3_FREQ, _freq, _freq >> 8, \
-		   0x02, LC3_DURATION, _duration, \
-		   0x02, LC3_CHAN_COUNT, _chan_count, \
-		   0x05, LC3_FRAME_LEN, _len_min, _len_min >> 8, _len_max, \
-		   _len_max >> 8)
+#define LC3_DATA(_freq, _duration, _len_min, _len_max) \
+	UTIL_IOV_INIT(0x03, LC3_FREQ, _freq, _freq >> 8, \
+			0x02, LC3_DURATION, _duration, \
+			0x05, LC3_FRAME_LEN, _len_min, _len_min >> 8, \
+			_len_max, _len_max >> 8)
 
 static const struct capabilities {
+	const char *name;
 	const char *uuid;
 	uint8_t codec_id;
 	struct iovec data;
+	struct iovec meta;
 } caps[] = {
 	/* A2DP SBC Source:
 	 *
@@ -1183,8 +1162,10 @@ static const struct capabilities {
 	 * Blocks: 4 8 12 16
 	 * Bitpool Range: 2-64
 	 */
-	CODEC_CAPABILITIES(A2DP_SOURCE_UUID, A2DP_CODEC_SBC,
-					CODEC_DATA(0xff, 0xff, 2, 64)),
+	CODEC_CAPABILITIES("a2dp_src/sbc", A2DP_SOURCE_UUID, A2DP_CODEC_SBC,
+				UTIL_IOV_INIT(0xff, 0xff, 2, 64),
+				UTIL_IOV_INIT()),
+
 	/* A2DP SBC Sink:
 	 *
 	 * Channel Modes: Mono DualChannel Stereo JointStereo
@@ -1193,46 +1174,68 @@ static const struct capabilities {
 	 * Blocks: 4 8 12 16
 	 * Bitpool Range: 2-64
 	 */
-	CODEC_CAPABILITIES(A2DP_SINK_UUID, A2DP_CODEC_SBC,
-					CODEC_DATA(0xff, 0xff, 2, 64)),
+	CODEC_CAPABILITIES("a2dp_snk/sbc", A2DP_SINK_UUID, A2DP_CODEC_SBC,
+				UTIL_IOV_INIT(0xff, 0xff, 2, 64),
+				UTIL_IOV_INIT()),
+
 	/* PAC LC3 Sink:
 	 *
 	 * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
 	 * Duration: 7.5 ms 10 ms
-	 * Channel count: 3
-	 * Frame length: 30-240
+	 * Frame length: 26-240
 	 */
-	CODEC_CAPABILITIES(PAC_SINK_UUID, LC3_ID,
-					LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
-						3u, 30, 240)),
+	CODEC_CAPABILITIES("pac_snk/lc3", PAC_SINK_UUID, LC3_ID,
+				LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 26,
+					240),
+				UTIL_IOV_INIT()),
+
 	/* PAC LC3 Source:
 	 *
 	 * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
 	 * Duration: 7.5 ms 10 ms
 	 * Channel count: 3
-	 * Frame length: 30-240
+	 * Frame length: 26-240
 	 */
-	CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID,
-					LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
-						3u, 30, 240)),
-};
+	CODEC_CAPABILITIES("pac_src/lc3", PAC_SOURCE_UUID, LC3_ID,
+				LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 26,
+					240),
+				UTIL_IOV_INIT()),
+
+	/* Broadcast LC3 Source:
+	 *
+	 * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
+	 * Duration: 7.5 ms 10 ms
+	 * Channel count: 3
+	 * Frame length: 26-240
+	 */
+	CODEC_CAPABILITIES("bcaa/lc3", BCAA_SERVICE_UUID, LC3_ID,
+				LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 26,
+					240),
+				UTIL_IOV_INIT()),
 
-struct codec_qos {
-	uint32_t interval;
-	uint8_t  framing;
-	char *phy;
-	uint16_t sdu;
-	uint8_t  rtn;
-	uint16_t latency;
-	uint32_t delay;
+	/* Broadcast LC3 Sink:
+	 *
+	 * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
+	 * Duration: 7.5 ms 10 ms
+	 * Channel count: 3
+	 * Frame length: 26-240
+	 */
+	CODEC_CAPABILITIES("baa/lc3", BAA_SERVICE_UUID, LC3_ID,
+				LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 26,
+					240),
+				UTIL_IOV_INIT()),
 };
 
 struct codec_preset {
-	const char *name;
+	char *name;
 	const struct iovec data;
-	const struct codec_qos qos;
-	bool is_default;
-	uint8_t latency;
+	const struct iovec meta;
+	struct bt_bap_qos qos;
+	uint8_t target_latency;
+	uint32_t chan_alloc;
+	bool custom;
+	bool alt;
+	struct codec_preset *alt_preset;
 };
 
 #define SBC_PRESET(_name, _data) \
@@ -1241,13 +1244,6 @@ struct codec_preset {
 		.data = _data, \
 	}
 
-#define SBC_DEFAULT_PRESET(_name, _data) \
-	{ \
-		.name = _name, \
-		.data = _data, \
-		.is_default = true, \
-	}
-
 static struct codec_preset sbc_presets[] = {
 	/* Table 4.7: Recommended sets of SBC parameters in the SRC device
 	 * Other settings: Block length = 16, Allocation method = Loudness,
@@ -1257,110 +1253,44 @@ static struct codec_preset sbc_presets[] = {
 	 * mono, and 512kb/s for two-channel modes.
 	 */
 	SBC_PRESET("MQ_MONO_44_1",
-		CODEC_DATA(0x28, 0x15, 2, SBC_BITPOOL_MQ_MONO_44100)),
+		UTIL_IOV_INIT(0x28, 0x15, 2, SBC_BITPOOL_MQ_MONO_44100)),
 	SBC_PRESET("MQ_MONO_48",
-		CODEC_DATA(0x18, 0x15, 2, SBC_BITPOOL_MQ_MONO_48000)),
+		UTIL_IOV_INIT(0x18, 0x15, 2, SBC_BITPOOL_MQ_MONO_48000)),
 	SBC_PRESET("MQ_STEREO_44_1",
-		CODEC_DATA(0x21, 0x15, 2, SBC_BITPOOL_MQ_JOINT_STEREO_44100)),
+		UTIL_IOV_INIT(0x21, 0x15, 2,
+				SBC_BITPOOL_MQ_JOINT_STEREO_44100)),
 	SBC_PRESET("MQ_STEREO_48",
-		CODEC_DATA(0x11, 0x15, 2, SBC_BITPOOL_MQ_JOINT_STEREO_48000)),
+		UTIL_IOV_INIT(0x11, 0x15, 2,
+				SBC_BITPOOL_MQ_JOINT_STEREO_48000)),
 	SBC_PRESET("HQ_MONO_44_1",
-		CODEC_DATA(0x28, 0x15, 2, SBC_BITPOOL_HQ_MONO_44100)),
+		UTIL_IOV_INIT(0x28, 0x15, 2, SBC_BITPOOL_HQ_MONO_44100)),
 	SBC_PRESET("HQ_MONO_48",
-		CODEC_DATA(0x18, 0x15, 2, SBC_BITPOOL_HQ_MONO_48000)),
-	SBC_DEFAULT_PRESET("HQ_STEREO_44_1",
-		CODEC_DATA(0x21, 0x15, 2, SBC_BITPOOL_HQ_JOINT_STEREO_44100)),
+		UTIL_IOV_INIT(0x18, 0x15, 2, SBC_BITPOOL_HQ_MONO_48000)),
+	SBC_PRESET("HQ_STEREO_44_1",
+		UTIL_IOV_INIT(0x21, 0x15, 2,
+				SBC_BITPOOL_HQ_JOINT_STEREO_44100)),
 	SBC_PRESET("HQ_STEREO_48",
-		CODEC_DATA(0x11, 0x15, 2, SBC_BITPOOL_HQ_JOINT_STEREO_48000)),
+		UTIL_IOV_INIT(0x11, 0x15, 2,
+			      SBC_BITPOOL_HQ_JOINT_STEREO_48000)),
 	/* Higher bitrates not recommended by A2DP spec, it dual channel to
 	 * avoid going above 53 bitpool:
 	 *
 	 * https://habr.com/en/post/456476/
 	 * https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1092
 	 */
-	SBC_PRESET("XQ_DUAL_44_1", CODEC_DATA(0x24, 0x15, 2, 43)),
-	SBC_PRESET("XQ_DUAL_48", CODEC_DATA(0x14, 0x15, 2, 39)),
+	SBC_PRESET("XQ_DUAL_44_1", UTIL_IOV_INIT(0x24, 0x15, 2, 43)),
+	SBC_PRESET("XQ_DUAL_48", UTIL_IOV_INIT(0x14, 0x15, 2, 39)),
 	/* Ultra high bitpool that fits in 512 kbps mandatory bitrate */
-	SBC_PRESET("UQ_STEREO_44_1", CODEC_DATA(0x21, 0x15, 2, 64)),
-	SBC_PRESET("UQ_STEREO_48", CODEC_DATA(0x11, 0x15, 2, 58)),
+	SBC_PRESET("UQ_STEREO_44_1", UTIL_IOV_INIT(0x21, 0x15, 2, 64)),
+	SBC_PRESET("UQ_STEREO_48", UTIL_IOV_INIT(0x11, 0x15, 2, 58)),
 };
 
-#define QOS_CONFIG(_interval, _framing, _phy, _sdu, _rtn, _latency, _delay) \
-	{ \
-		.interval = _interval, \
-		.framing = _framing, \
-		.phy = _phy, \
-		.sdu = _sdu, \
-		.rtn = _rtn, \
-		.latency = _latency, \
-		.delay = _delay, \
-	}
-
-#define QOS_UNFRAMED(_interval, _phy, _sdu, _rtn, _latency, _delay) \
-	QOS_CONFIG(_interval, 0x00, _phy, _sdu, _rtn, _latency, _delay)
-
-#define QOS_FRAMED(_interval, _phy, _sdu, _rtn, _latency, _delay) \
-	QOS_CONFIG(_interval, 0x01, _phy, _sdu, _rtn, _latency, _delay)
-
-#define QOS_UNFRAMED_1M(_interval, _sdu, _rtn, _latency, _delay) \
-	QOS_UNFRAMED(_interval, "1M", _sdu, _rtn, _latency, _delay) \
-
-#define QOS_FRAMED_1M(_interval, _sdu, _rtn, _latency, _delay) \
-	QOS_FRAMED(_interval, "1M", _sdu, _rtn, _latency, _delay) \
-
-#define QOS_UNFRAMED_2M(_interval, _sdu, _rtn, _latency, _delay) \
-	QOS_UNFRAMED(_interval, "2M", _sdu, _rtn, _latency, _delay) \
-
-#define QOS_FRAMED_2M(_interval, _sdu, _rtn, _latency, _delay) \
-	QOS_FRAMED(_interval, "2M", _sdu, _rtn, _latency, _delay) \
-
-#define LC3_7_5_UNFRAMED(_sdu, _rtn, _latency, _delay) \
-	QOS_UNFRAMED(7500u, "2M", _sdu, _rtn, _latency, _delay)
-
-#define LC3_7_5_FRAMED(_sdu, _rtn, _latency, _delay) \
-	QOS_FRAMED(7500u, "2M", _sdu, _rtn, _latency, _delay)
-
-#define LC3_10_UNFRAMED(_sdu, _rtn, _latency, _delay) \
-	QOS_UNFRAMED_2M(10000u, _sdu, _rtn, _latency, _delay)
-
-#define LC3_10_FRAMED(_sdu, _rtn, _latency, _delay) \
-	QOS_FRAMED_2M(10000u, _sdu, _rtn, _latency, _delay)
-
-#define LC3_PRESET_DATA(_freq, _duration, _len) \
-	CODEC_DATA(0x02, LC3_CONFIG_FREQ, _freq, \
-		   0x02, LC3_CONFIG_DURATION, _duration, \
-		   0x03, LC3_CONFIG_FRAME_LEN, _len, _len >> 8)
-
-#define LC3_PRESET_8KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_8KHZ, _duration, _len)
-
-#define LC3_PRESET_11KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_11KHZ, _duration, _len)
-
-#define LC3_PRESET_16KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_16KHZ, _duration, _len)
-
-#define LC3_PRESET_22KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_22KHZ, _duration, _len)
-
-#define LC3_PRESET_24KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_24KHZ, _duration, _len)
-
-#define LC3_PRESET_32KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_32KHZ, _duration, _len)
-
-#define LC3_PRESET_44KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_44KHZ, _duration, _len)
-
-#define LC3_PRESET_48KHZ(_duration, _len) \
-	LC3_PRESET_DATA(LC3_CONFIG_FREQ_48KHZ, _duration, _len)
-
 #define LC3_PRESET_LL(_name, _data, _qos) \
 	{ \
 		.name = _name, \
 		.data = _data, \
 		.qos = _qos, \
-		.latency = 0x01, \
+		.target_latency = 0x01, \
 	}
 
 #define LC3_PRESET(_name, _data, _qos) \
@@ -1368,7 +1298,7 @@ static struct codec_preset sbc_presets[] = {
 		.name = _name, \
 		.data = _data, \
 		.qos = _qos, \
-		.latency = 0x02, \
+		.target_latency = 0x02, \
 	}
 
 #define LC3_PRESET_HR(_name, _data, _qos) \
@@ -1376,140 +1306,291 @@ static struct codec_preset sbc_presets[] = {
 		.name = _name, \
 		.data = _data, \
 		.qos = _qos, \
-		.latency = 0x03, \
+		.target_latency = 0x03, \
 	}
 
-#define LC3_DEFAULT_PRESET(_name, _data, _qos) \
+#define LC3_PRESET_B(_name, _data, _qos) \
 	{ \
 		.name = _name, \
 		.data = _data, \
-		.is_default = true, \
 		.qos = _qos, \
-		.latency = 0x02, \
+		.target_latency = 0x00, \
 	}
 
-static struct codec_preset lc3_presets[] = {
+static struct codec_preset lc3_ucast_presets[] = {
 	/* Table 4.43: QoS configuration support setting requirements */
-	LC3_PRESET("8_1_1",
-			LC3_PRESET_8KHZ(LC3_CONFIG_DURATION_7_5, 26u),
-			LC3_7_5_UNFRAMED(26u, 2u, 8u, 40000u)),
-	LC3_PRESET("8_2_1",
-			LC3_PRESET_8KHZ(LC3_CONFIG_DURATION_10, 30u),
-			LC3_10_UNFRAMED(30u, 2u, 10u, 40000u)),
-	LC3_PRESET("16_1_1",
-			LC3_PRESET_16KHZ(LC3_CONFIG_DURATION_7_5, 30u),
-			LC3_7_5_UNFRAMED(30u, 2u, 8u, 40000u)),
-	LC3_DEFAULT_PRESET("16_2_1",
-			LC3_PRESET_16KHZ(LC3_CONFIG_DURATION_10, 40u),
-			LC3_10_UNFRAMED(40u, 2u, 10u, 40000u)),
-	LC3_PRESET("24_1_1",
-			LC3_PRESET_24KHZ(LC3_CONFIG_DURATION_7_5, 45u),
-			LC3_7_5_UNFRAMED(45u, 2u, 8u, 40000u)),
-	LC3_PRESET("24_2_1",
-			LC3_PRESET_24KHZ(LC3_CONFIG_DURATION_10, 60u),
-			LC3_10_UNFRAMED(60u, 2u, 10u, 40000u)),
-	LC3_PRESET("32_1_1",
-			LC3_PRESET_32KHZ(LC3_CONFIG_DURATION_7_5, 60u),
-			LC3_7_5_UNFRAMED(60u, 2u, 8u, 40000u)),
-	LC3_PRESET("32_2_1",
-			LC3_PRESET_32KHZ(LC3_CONFIG_DURATION_10, 80u),
-			LC3_10_UNFRAMED(80u, 2u, 10u, 40000u)),
-	LC3_PRESET("44_1_1",
-			LC3_PRESET_44KHZ(LC3_CONFIG_DURATION_7_5, 98u),
-			QOS_FRAMED_2M(8163u, 98u, 5u, 24u, 40000u)),
-	LC3_PRESET("44_2_1",
-			LC3_PRESET_44KHZ(LC3_CONFIG_DURATION_10, 130u),
-			QOS_FRAMED_2M(10884u, 130u, 5u, 31u, 40000u)),
-	LC3_PRESET("48_1_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 75u),
-			LC3_7_5_UNFRAMED(75u, 5u, 15u, 40000u)),
-	LC3_PRESET("48_2_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 100u),
-			LC3_10_UNFRAMED(100u, 5u, 20u, 40000u)),
-	LC3_PRESET("48_3_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 90u),
-			LC3_7_5_UNFRAMED(90u, 5u, 15u, 40000u)),
-	LC3_PRESET("48_4_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 120u),
-			LC3_10_UNFRAMED(120u, 5u, 20u, 40000u)),
-	LC3_PRESET("48_5_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 117u),
-			LC3_7_5_UNFRAMED(117u, 5u, 15u, 40000u)),
-	LC3_PRESET("48_6_1",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 155u),
-			LC3_10_UNFRAMED(155u, 5u, 20u, 40000u)),
+	LC3_PRESET("8_1_1", LC3_CONFIG_8_1, LC3_QOS_8_1_1),
+	LC3_PRESET("8_2_1", LC3_CONFIG_8_2, LC3_QOS_8_2_1),
+	LC3_PRESET("16_1_1", LC3_CONFIG_16_1, LC3_QOS_16_1_1),
+	LC3_PRESET("16_2_1", LC3_CONFIG_16_2, LC3_QOS_16_2_1),
+	LC3_PRESET("24_1_1", LC3_CONFIG_24_1, LC3_QOS_24_1_1),
+	LC3_PRESET("24_2_1", LC3_CONFIG_24_2, LC3_QOS_24_2_1),
+	LC3_PRESET("32_1_1", LC3_CONFIG_32_1, LC3_QOS_32_1_1),
+	LC3_PRESET("32_2_1", LC3_CONFIG_32_2, LC3_QOS_32_1_1),
+	LC3_PRESET("44_1_1", LC3_CONFIG_44_1, LC3_QOS_44_1_1),
+	LC3_PRESET("44_2_1", LC3_CONFIG_44_2, LC3_QOS_44_2_1),
+	LC3_PRESET("48_1_1", LC3_CONFIG_48_1, LC3_QOS_48_1_1),
+	LC3_PRESET("48_2_1", LC3_CONFIG_48_2, LC3_QOS_48_2_1),
+	LC3_PRESET("48_3_1", LC3_CONFIG_48_3, LC3_QOS_48_3_1),
+	LC3_PRESET("48_4_1", LC3_CONFIG_48_4, LC3_QOS_48_4_1),
+	LC3_PRESET("48_5_1", LC3_CONFIG_48_5, LC3_QOS_48_5_1),
+	LC3_PRESET("48_6_1", LC3_CONFIG_48_6, LC3_QOS_48_6_1),
 	/* QoS Configuration settings for high reliability audio data */
-	LC3_PRESET_HR("44_1_2",
-			LC3_PRESET_44KHZ(LC3_CONFIG_DURATION_7_5, 98u),
-			QOS_FRAMED_2M(8163u, 98u, 23u, 54u, 40000u)),
-	LC3_PRESET_HR("44_2_2",
-			LC3_PRESET_44KHZ(LC3_CONFIG_DURATION_10, 130u),
-			QOS_FRAMED_2M(10884u, 130u, 23u, 71u, 40000u)),
-	LC3_PRESET_HR("48_1_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 75u),
-			LC3_7_5_UNFRAMED(75u, 23u, 45u, 40000u)),
-	LC3_PRESET_HR("48_2_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 100u),
-			LC3_10_UNFRAMED(100u, 23u, 60u, 40000u)),
-	LC3_PRESET_HR("48_3_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 90u),
-			LC3_7_5_UNFRAMED(90u, 23u, 45u, 40000u)),
-	LC3_PRESET_HR("48_4_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 120u),
-			LC3_10_UNFRAMED(120u, 23u, 60u, 40000u)),
-	LC3_PRESET_HR("48_5_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_7_5, 117u),
-			LC3_7_5_UNFRAMED(117u, 23u, 45u, 40000u)),
-	LC3_PRESET_HR("48_6_2",
-			LC3_PRESET_48KHZ(LC3_CONFIG_DURATION_10, 155u),
-			LC3_10_UNFRAMED(155u, 23u, 60u, 40000u)),
+	LC3_PRESET_HR("8_1_2", LC3_CONFIG_8_1, LC3_QOS_8_1_2),
+	LC3_PRESET_HR("8_2_2", LC3_CONFIG_8_2, LC3_QOS_8_2_2),
+	LC3_PRESET_HR("16_1_2", LC3_CONFIG_16_1, LC3_QOS_16_1_2),
+	LC3_PRESET_HR("16_2_2", LC3_CONFIG_16_2, LC3_QOS_16_2_2),
+	LC3_PRESET_HR("24_1_2", LC3_CONFIG_24_1, LC3_QOS_24_1_2),
+	LC3_PRESET_HR("24_2_2", LC3_CONFIG_24_2, LC3_QOS_24_2_2),
+	LC3_PRESET_HR("32_1_2", LC3_CONFIG_32_1, LC3_QOS_32_1_2),
+	LC3_PRESET_HR("32_2_2", LC3_CONFIG_32_2, LC3_QOS_32_2_2),
+	LC3_PRESET_HR("44_1_2", LC3_CONFIG_44_1, LC3_QOS_44_1_2),
+	LC3_PRESET_HR("44_2_2", LC3_CONFIG_44_2, LC3_QOS_44_2_2),
+	LC3_PRESET_HR("48_1_2", LC3_CONFIG_48_1, LC3_QOS_48_1_2),
+	LC3_PRESET_HR("48_2_2", LC3_CONFIG_48_2, LC3_QOS_48_2_2),
+	LC3_PRESET_HR("48_3_2", LC3_CONFIG_48_3, LC3_QOS_48_3_2),
+	LC3_PRESET_HR("48_4_2", LC3_CONFIG_48_4, LC3_QOS_48_4_2),
+	LC3_PRESET_HR("48_5_2", LC3_CONFIG_48_5, LC3_QOS_48_5_2),
+	LC3_PRESET_HR("48_6_2", LC3_CONFIG_48_6, LC3_QOS_48_6_2),
+	/* QoS configuration support setting requirements for the UGG and UGT */
+	LC3_PRESET_LL("16_1_gs", LC3_CONFIG_16_1, LC3_QOS_16_1_GS),
+	LC3_PRESET_LL("16_2_gs", LC3_CONFIG_16_2, LC3_QOS_16_2_GS),
+	LC3_PRESET_LL("32_1_gs", LC3_CONFIG_32_1, LC3_QOS_32_1_GS),
+	LC3_PRESET_LL("32_2_gs", LC3_CONFIG_32_2, LC3_QOS_32_2_GS),
+	LC3_PRESET_LL("48_1_gs", LC3_CONFIG_48_1, LC3_QOS_48_1_GS),
+	LC3_PRESET_LL("48_2_gs", LC3_CONFIG_48_2, LC3_QOS_48_2_GS),
+	LC3_PRESET_LL("32_1_gr", LC3_CONFIG_32_1, LC3_QOS_32_1_GR),
+	LC3_PRESET_LL("32_2_gr", LC3_CONFIG_32_2, LC3_QOS_32_2_GR),
+	LC3_PRESET_LL("48_1_gr", LC3_CONFIG_48_1, LC3_QOS_48_1_GR),
+	LC3_PRESET_LL("48_2_gr", LC3_CONFIG_48_2, LC3_QOS_48_2_GR),
+	LC3_PRESET_LL("48_3_gr", LC3_CONFIG_48_3, LC3_QOS_48_3_GR),
+	LC3_PRESET_LL("48_4_gr", LC3_CONFIG_48_4, LC3_QOS_48_4_GR),
+	LC3_PRESET_LL("32_1_gr_l+r", LC3_CONFIG_32_1_AC(2),
+				LC3_QOS_32_1_GR_AC(2)),
+	LC3_PRESET_LL("32_2_gr_l+r", LC3_CONFIG_32_2_AC(2),
+				LC3_QOS_32_2_GR_AC(2)),
+	LC3_PRESET_LL("48_1_gr_l+r", LC3_CONFIG_48_1_AC(2),
+				LC3_QOS_48_1_GR_AC(2)),
+	LC3_PRESET_LL("48_2_gr_l+r", LC3_CONFIG_48_2_AC(2),
+				LC3_QOS_48_2_GR_AC(2)),
+	LC3_PRESET_LL("48_3_gr_l+r", LC3_CONFIG_48_3_AC(2),
+				LC3_QOS_48_3_GR_AC(2)),
+	LC3_PRESET_LL("48_4_gr_l+r", LC3_CONFIG_48_4_AC(2),
+				LC3_QOS_48_4_GR_AC(2)),
+};
+
+static struct codec_preset lc3_bcast_presets[] = {
+	/* Table 6.4: Broadcast Audio Stream configuration support requirements
+	 * for the Broadcast Source and Broadcast Sink
+	 */
+	LC3_PRESET_B("8_1_1", LC3_CONFIG_8_1, LC3_QOS_8_1_1_B),
+	LC3_PRESET_B("8_2_1", LC3_CONFIG_8_2, LC3_QOS_8_2_1_B),
+	LC3_PRESET_B("16_1_1", LC3_CONFIG_16_1, LC3_QOS_16_1_1_B),
+	LC3_PRESET_B("16_2_1", LC3_CONFIG_16_2, LC3_QOS_16_2_1_B),
+	LC3_PRESET_B("24_1_1", LC3_CONFIG_24_1, LC3_QOS_24_1_1_B),
+	LC3_PRESET_B("24_2_1", LC3_CONFIG_24_2, LC3_QOS_24_2_1_B),
+	LC3_PRESET_B("32_1_1", LC3_CONFIG_32_1, LC3_QOS_32_1_1_B),
+	LC3_PRESET_B("32_2_1", LC3_CONFIG_32_2, LC3_QOS_32_2_1_B),
+	LC3_PRESET_B("44_1_1", LC3_CONFIG_44_1, LC3_QOS_44_1_1_B),
+	LC3_PRESET_B("44_2_1", LC3_CONFIG_44_2, LC3_QOS_44_2_1_B),
+	LC3_PRESET_B("48_1_1", LC3_CONFIG_48_1, LC3_QOS_48_1_1_B),
+	LC3_PRESET_B("48_2_1", LC3_CONFIG_48_2, LC3_QOS_48_2_1_B),
+	LC3_PRESET_B("48_3_1", LC3_CONFIG_48_3, LC3_QOS_48_3_1_B),
+	LC3_PRESET_B("48_4_1", LC3_CONFIG_48_4, LC3_QOS_48_4_1_B),
+	LC3_PRESET_B("48_5_1", LC3_CONFIG_48_5, LC3_QOS_48_5_1_B),
+	LC3_PRESET_B("48_6_1", LC3_CONFIG_48_6, LC3_QOS_48_6_1_B),
+	/* Broadcast Audio Stream configuration settings for high-reliability
+	 * audio data.
+	 */
+	LC3_PRESET_B("8_1_2", LC3_CONFIG_8_1, LC3_QOS_8_1_1_B),
+	LC3_PRESET_B("8_2_2", LC3_CONFIG_8_2, LC3_QOS_8_2_2_B),
+	LC3_PRESET_B("16_1_2", LC3_CONFIG_16_1, LC3_QOS_16_1_2_B),
+	LC3_PRESET_B("16_2_2", LC3_CONFIG_16_2, LC3_QOS_16_2_2_B),
+	LC3_PRESET_B("24_1_2", LC3_CONFIG_24_1, LC3_QOS_24_1_2_B),
+	LC3_PRESET_B("24_2_2", LC3_CONFIG_24_2, LC3_QOS_24_2_2_B),
+	LC3_PRESET_B("32_1_2", LC3_CONFIG_32_1, LC3_QOS_32_1_2_B),
+	LC3_PRESET_B("32_2_2", LC3_CONFIG_32_2, LC3_QOS_32_2_2_B),
+	LC3_PRESET_B("44_1_2", LC3_CONFIG_44_1, LC3_QOS_44_1_2_B),
+	LC3_PRESET_B("44_2_2", LC3_CONFIG_44_2, LC3_QOS_44_2_2_B),
+	LC3_PRESET_B("48_1_2", LC3_CONFIG_48_1, LC3_QOS_48_1_2_B),
+	LC3_PRESET_B("48_2_2", LC3_CONFIG_48_2, LC3_QOS_48_2_2_B),
+	LC3_PRESET_B("48_3_2", LC3_CONFIG_48_3, LC3_QOS_48_3_2_B),
+	LC3_PRESET_B("48_4_2", LC3_CONFIG_48_4, LC3_QOS_48_4_2_B),
+	LC3_PRESET_B("48_5_2", LC3_CONFIG_48_5, LC3_QOS_48_5_2_B),
+	LC3_PRESET_B("48_6_2", LC3_CONFIG_48_6, LC3_QOS_48_6_2_B),
 };
 
-#define PRESET(_uuid, _presets) \
+static void print_ltv(const char *str, void *user_data)
+{
+	const char *label = user_data;
+
+	bt_shell_printf("\t%s.%s\n", label, str);
+}
+
+static void print_lc3_caps(uint8_t *data, int len)
+{
+	const char *label = "Capabilities";
+
+	bt_bap_debug_caps(data, len, print_ltv, (void *)label);
+}
+
+static void print_lc3_cfg(void *data, int len)
+{
+	const char *label = "Configuration";
+
+	bt_bap_debug_config(data, len, print_ltv, (void *)label);
+}
+
+static void print_lc3_meta(void *data, int len)
+{
+	const char *label = "Metadata";
+
+	bt_bap_debug_metadata(data, len, print_ltv, (void *)label);
+}
+
+#define PRESET(_uuid, _codec, _presets, _default_index) \
 	{ \
 		.uuid = _uuid, \
+		.codec = _codec, \
+		.default_preset = &_presets[_default_index], \
 		.presets = _presets, \
 		.num_presets = ARRAY_SIZE(_presets), \
 	}
 
-static const struct preset {
+static struct preset {
 	const char *uuid;
+	uint8_t codec;
+	uint16_t cid;
+	uint16_t vid;
+	struct queue *custom;
+	struct codec_preset *default_preset;
 	struct codec_preset *presets;
 	size_t num_presets;
 } presets[] = {
-	PRESET(A2DP_SOURCE_UUID, sbc_presets),
-	PRESET(A2DP_SINK_UUID, sbc_presets),
-	PRESET(PAC_SINK_UUID, lc3_presets),
-	PRESET(PAC_SOURCE_UUID, lc3_presets),
+	PRESET(A2DP_SOURCE_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(PAC_SINK_UUID, LC3_ID, lc3_ucast_presets, 3),
+	PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_ucast_presets, 3),
+	PRESET(BCAA_SERVICE_UUID,  LC3_ID, lc3_bcast_presets, 3),
+	PRESET(BAA_SERVICE_UUID,  LC3_ID, lc3_bcast_presets, 3),
 };
 
-static struct codec_preset *find_preset(const char *uuid, const char *name)
+static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid)
+{
+	char **list;
+	char *endptr = NULL;
+
+	if (!codec)
+		return;
+
+	list = g_strsplit(codec, ":", 2);
+
+	if (vid)
+		*vid = strtol(list[0], &endptr, 0);
+
+	if (cid)
+		*cid = strtol(list[1], &endptr, 0);
+
+	g_strfreev(list);
+}
+
+static struct preset *find_presets(const char *uuid, uint8_t codec,
+					uint16_t vid, uint16_t cid)
 {
 	size_t i;
 
-	for (i = 0; i < ARRAY_SIZE(presets); i++) {
-		const struct preset *preset = &presets[i];
+	if (codec == 0xff) {
+		GList *l;
 
-		if (!strcasecmp(preset->uuid, uuid)) {
-			size_t j;
+		for (l = local_endpoints; l; l = g_list_next(l)) {
+			struct endpoint *ep = l->data;
 
-			for (j = 0; j < preset->num_presets; j++) {
-				struct codec_preset *p;
+			if (strcasecmp(ep->uuid, uuid) || ep->codec != codec)
+				continue;
 
-				p = &preset->presets[j];
+			if (ep->codec == 0xff && (ep->vid != vid ||
+							ep->cid != cid))
+				continue;
 
-				if (!name) {
-					if (p->is_default)
-						return p;
-				} else if (!strcmp(p->name, name))
-					return p;
-			}
+			return ep->preset;
 		}
+
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(presets); i++) {
+		struct preset *preset = &presets[i];
+
+		if (preset->codec != codec)
+			continue;
+
+		if (!strcasecmp(preset->uuid, uuid))
+			return preset;
 	}
 
 	return NULL;
 }
 
+static struct preset *find_vendor_presets(const char *uuid, const char *codec)
+{
+	uint16_t cid;
+	uint16_t vid;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	parse_vendor_codec(codec, &vid, &cid);
+
+	return find_presets(uuid, 0xff, vid, cid);
+}
+
+static struct preset *find_presets_name(const char *uuid, const char *codec)
+{
+	uint8_t id;
+	char *endptr = NULL;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	if (strrchr(codec, ':'))
+		return find_vendor_presets(uuid, codec);
+
+	id = strtol(codec, &endptr, 0);
+
+	return find_presets(uuid, id, 0x0000, 0x0000);
+}
+
+static bool match_custom_name(const void *data, const void *match_data)
+{
+	const struct codec_preset *preset = data;
+	const char *name = match_data;
+
+	return !strcmp(preset->name, name);
+}
+
+static struct codec_preset *preset_find_name(struct preset *preset,
+						const char *name)
+{
+	size_t i;
+
+	if (!preset)
+		return NULL;
+
+	if (!name)
+		return preset->default_preset;
+
+	for (i = 0; i < preset->num_presets; i++) {
+		struct codec_preset *p;
+
+		p = &preset->presets[i];
+
+		if (!strcmp(p->name, name))
+			return p;
+	}
+
+	return queue_find(preset->custom, match_custom_name, name);
+}
+
 static DBusMessage *endpoint_select_config_reply(DBusMessage *msg,
 						 uint8_t *data, size_t len)
 {
@@ -1574,7 +1655,7 @@ static void select_config_response(const char *input, void *user_data)
 	uint8_t *data;
 	size_t len;
 
-	p = find_preset(ep->uuid, input);
+	p = preset_find_name(ep->preset, input);
 	if (p) {
 		data = p->data.iov_base;
 		len = p->data.iov_len;
@@ -1615,6 +1696,13 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 	bt_shell_printf("Endpoint: SelectConfiguration\n");
 	print_iter("\t", "Capabilities", &args);
 
+	if (!ep->max_transports) {
+		bt_shell_printf("Maximum transports reached: rejecting\n");
+		return g_dbus_create_error(msg,
+					 "org.bluez.Error.Rejected",
+					 "Maximum transports reached");
+	}
+
 	if (!ep->auto_accept) {
 		ep->msg = dbus_message_ref(msg);
 		bt_shell_prompt_input("Endpoint", "Enter preset/configuration:",
@@ -1622,7 +1710,7 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = preset_find_name(ep->preset, NULL);
 	if (!p) {
 		reply = g_dbus_create_error(msg, "org.bluez.Error.Rejected",
 								NULL);
@@ -1631,8 +1719,11 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 
 	reply = endpoint_select_config_reply(msg, p->data.iov_base,
 						p->data.iov_len);
-	if (!reply)
-		return NULL;
+	if (!reply) {
+		reply = g_dbus_create_error(msg, "org.bluez.Error.Rejected",
+								NULL);
+		return reply;
+	}
 
 	bt_shell_printf("Auto Accepting using %s...\n", p->name);
 
@@ -1642,140 +1733,392 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 struct endpoint_config {
 	GDBusProxy *proxy;
 	struct endpoint *ep;
-	struct iovec *caps;
+	struct iovec *caps;		/* Codec Specific Configuration LTVs */
+	struct iovec *meta;		/* Metadata LTVs*/
 	uint8_t target_latency;
-	const struct codec_qos *qos;
+	struct bt_bap_qos qos;		/* BAP QOS configuration parameters */
 };
 
-static void append_properties(DBusMessageIter *iter,
-						struct endpoint_config *cfg)
+static void append_io_qos(DBusMessageIter *iter, struct bt_bap_io_qos *qos)
 {
-	DBusMessageIter dict;
-	struct codec_qos *qos = (void *)cfg->qos;
-	const char *key = "Capabilities";
+	bt_shell_printf("Interval %u\n", qos->interval);
 
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+	g_dbus_dict_append_entry(iter, "Interval", DBUS_TYPE_UINT32,
+						&qos->interval);
 
-	bt_shell_printf("Capabilities: ");
-	bt_shell_hexdump(cfg->caps->iov_base, cfg->caps->iov_len);
+	bt_shell_printf("PHY 0x%02x\n", qos->phy);
 
-	g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
-					DBUS_TYPE_BYTE, &cfg->caps->iov_base,
-					cfg->caps->iov_len);
+	g_dbus_dict_append_entry(iter, "PHY", DBUS_TYPE_BYTE, &qos->phy);
 
-	if (!qos)
-		goto done;
+	bt_shell_printf("SDU %u\n", qos->sdu);
 
-	if (cfg->target_latency) {
-		bt_shell_printf("TargetLatency 0x%02x\n", qos->interval);
-		g_dbus_dict_append_entry(&dict, "TargetLatency",
-					DBUS_TYPE_BYTE, &cfg->target_latency);
-	}
+	g_dbus_dict_append_entry(iter, "SDU", DBUS_TYPE_UINT16, &qos->sdu);
 
-	if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) {
-		bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig);
-		g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE,
-							&cfg->ep->cig);
-	}
+	bt_shell_printf("Retransmissions %u\n", qos->rtn);
 
-	if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) {
-		bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis);
-		g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE,
-							&cfg->ep->cis);
-	}
+	g_dbus_dict_append_entry(iter, "Retransmissions", DBUS_TYPE_BYTE,
+						&qos->rtn);
 
-	bt_shell_printf("Interval %u\n", qos->interval);
+	bt_shell_printf("Latency %u\n", qos->latency);
 
-	g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32,
-						&qos->interval);
+	g_dbus_dict_append_entry(iter, "Latency", DBUS_TYPE_UINT16,
+						&qos->latency);
+}
 
-	bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");
+static void append_ucast_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
+{
+	struct bt_bap_ucast_qos *qos = &cfg->qos.ucast;
 
-	g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
-						&qos->framing);
+	if (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET) {
+		bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group);
+		g_dbus_dict_append_entry(iter, "CIG", DBUS_TYPE_BYTE,
+							&cfg->ep->iso_group);
+	}
 
-	bt_shell_printf("PHY %s\n", qos->phy);
+	if (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET) {
+		bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream);
+		g_dbus_dict_append_entry(iter, "CIS", DBUS_TYPE_BYTE,
+							&cfg->ep->iso_stream);
+	}
 
-	g_dbus_dict_append_entry(&dict, "PHY", DBUS_TYPE_STRING, &qos->phy);
+	bt_shell_printf("Framing 0x%02x\n", qos->framing);
 
-	bt_shell_printf("SDU %u\n", cfg->qos->sdu);
+	g_dbus_dict_append_entry(iter, "Framing", DBUS_TYPE_BYTE,
+					&qos->framing);
 
-	g_dbus_dict_append_entry(&dict, "SDU", DBUS_TYPE_UINT16, &qos->sdu);
+	bt_shell_printf("PresentationDelay %u\n", qos->delay);
 
-	bt_shell_printf("Retransmissions %u\n", qos->rtn);
+	g_dbus_dict_append_entry(iter, "PresentationDelay",
+					DBUS_TYPE_UINT32, &qos->delay);
 
-	g_dbus_dict_append_entry(&dict, "Retransmissions", DBUS_TYPE_BYTE,
-						&qos->rtn);
+	if (cfg->target_latency) {
+		bt_shell_printf("TargetLatency 0x%02x\n", cfg->target_latency);
+		g_dbus_dict_append_entry(iter, "TargetLatency", DBUS_TYPE_BYTE,
+					&cfg->target_latency);
+	}
 
-	bt_shell_printf("Latency %u\n", qos->latency);
+	append_io_qos(iter, &qos->io_qos);
+}
 
-	g_dbus_dict_append_entry(&dict, "Latency", DBUS_TYPE_UINT16,
-						&qos->latency);
+static void append_bcast_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
+{
+	struct bt_bap_bcast_qos *qos = &cfg->qos.bcast;
 
-	bt_shell_printf("Delay %u\n", qos->delay);
+	if (cfg->ep->iso_group != BT_ISO_QOS_BIG_UNSET) {
+		bt_shell_printf("BIG 0x%2.2x\n", cfg->ep->iso_group);
+		g_dbus_dict_append_entry(iter, "BIG", DBUS_TYPE_BYTE,
+							&cfg->ep->iso_group);
+	}
 
-	g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32,
-						&qos->delay);
+	if (cfg->ep->iso_stream != BT_ISO_QOS_BIS_UNSET) {
+		bt_shell_printf("BIS 0x%2.2x\n", cfg->ep->iso_stream);
+		g_dbus_dict_append_entry(iter, "BIS", DBUS_TYPE_BYTE,
+							&cfg->ep->iso_stream);
+	}
 
-done:
-	dbus_message_iter_close_container(iter, &dict);
-}
+	if (qos->sync_factor) {
+		bt_shell_printf("SyncFactor %u\n", qos->sync_factor);
+		g_dbus_dict_append_entry(iter, "SyncFactor", DBUS_TYPE_BYTE,
+						&qos->sync_factor);
+	}
 
-static struct iovec *iov_append(struct iovec **iov, const void *data,
-							size_t len)
-{
-	if (!*iov) {
-		*iov = new0(struct iovec, 1);
-		(*iov)->iov_base = new0(uint8_t, UINT8_MAX);
+	if (qos->options) {
+		bt_shell_printf("Options %u\n", qos->options);
+		g_dbus_dict_append_entry(iter, "Options", DBUS_TYPE_BYTE,
+						&qos->options);
 	}
 
-	if (data && len) {
-		memcpy((*iov)->iov_base + (*iov)->iov_len, data, len);
-		(*iov)->iov_len += len;
+	if (qos->skip) {
+		bt_shell_printf("Skip %u\n", qos->skip);
+		g_dbus_dict_append_entry(iter, "Skip", DBUS_TYPE_UINT16,
+						&qos->skip);
 	}
 
-	return *iov;
-}
+	if (qos->sync_timeout) {
+		bt_shell_printf("SyncTimeout %u\n", qos->sync_timeout);
+		g_dbus_dict_append_entry(iter, "SyncTimeout", DBUS_TYPE_UINT16,
+						&qos->sync_timeout);
+	}
 
-static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
-						DBusMessage *msg,
-						struct codec_preset *preset)
-{
-	DBusMessage *reply;
-	DBusMessageIter iter;
-	struct endpoint_config *cfg;
+	if (qos->sync_cte_type) {
+		bt_shell_printf("SyncCteType %u\n", qos->sync_cte_type);
+		g_dbus_dict_append_entry(iter, "SyncCteType", DBUS_TYPE_BYTE,
+					&qos->sync_cte_type);
+	}
 
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return NULL;
+	if (qos->mse) {
+		bt_shell_printf("MSE %u\n", qos->mse);
+		g_dbus_dict_append_entry(iter, "MSE", DBUS_TYPE_BYTE,
+						&qos->mse);
+	}
 
-	cfg = new0(struct endpoint_config, 1);
-	cfg->ep = ep;
+	if (qos->timeout) {
+		bt_shell_printf("Timeout %u\n", qos->timeout);
+		g_dbus_dict_append_entry(iter, "Timeout", DBUS_TYPE_UINT16,
+						&qos->timeout);
+	}
 
-	/* Copy capabilities */
-	iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
-	cfg->target_latency = preset->latency;
+	if (cfg->ep->bcode->iov_len != 0) {
+		const char *key = "BCode";
 
-	if (preset->qos.phy)
-		/* Set QoS parameters */
-		cfg->qos = &preset->qos;
+		bt_shell_printf("BCode:\n");
+		bt_shell_hexdump(cfg->ep->bcode->iov_base,
+				cfg->ep->bcode->iov_len);
 
-	dbus_message_iter_init_append(reply, &iter);
+		g_dbus_dict_append_basic_array(iter, DBUS_TYPE_STRING,
+						&key, DBUS_TYPE_BYTE,
+						&cfg->ep->bcode->iov_base,
+						cfg->ep->bcode->iov_len);
+	}
 
-	append_properties(&iter, cfg);
+	bt_shell_printf("Framing 0x%02x\n", qos->framing);
+
+	g_dbus_dict_append_entry(iter, "Framing", DBUS_TYPE_BYTE,
+					&qos->framing);
+
+	bt_shell_printf("PresentationDelay %u\n", qos->delay);
+
+	g_dbus_dict_append_entry(iter, "PresentationDelay",
+					DBUS_TYPE_UINT32, &qos->delay);
+
+	/* Add BAP codec QOS configuration */
+	append_io_qos(iter, &qos->io_qos);
+}
+
+static void append_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
+{
+	DBusMessageIter entry, var, dict;
+	const char *key = "QoS";
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
+						NULL, &entry);
+
+	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+	dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+						"a{sv}", &var);
+
+	dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, "{sv}",
+					&dict);
+
+	if (cfg->ep->broadcast)
+		append_bcast_qos(&dict, cfg);
+	else
+		append_ucast_qos(&dict, cfg);
+
+	dbus_message_iter_close_container(&var, &dict);
+	dbus_message_iter_close_container(&entry, &var);
+	dbus_message_iter_close_container(iter, &entry);
+}
+
+static void append_properties(DBusMessageIter *iter,
+						struct endpoint_config *cfg)
+{
+	DBusMessageIter dict;
+	const char *key = "Capabilities";
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	if (cfg->ep->codec == LC3_ID) {
+		print_lc3_cfg(cfg->caps->iov_base, cfg->caps->iov_len);
+	} else {
+		bt_shell_printf("Capabilities: ");
+		bt_shell_hexdump(cfg->caps->iov_base, cfg->caps->iov_len);
+	}
+
+	g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
+					DBUS_TYPE_BYTE, &cfg->caps->iov_base,
+					cfg->caps->iov_len);
+
+	if (cfg->meta && cfg->meta->iov_len) {
+		const char *meta = "Metadata";
+
+		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
+				DBUS_TYPE_BYTE, &cfg->meta->iov_base,
+				cfg->meta->iov_len);
+
+		if (cfg->ep->codec == LC3_ID) {
+			print_lc3_meta(cfg->meta->iov_base, cfg->meta->iov_len);
+		} else {
+			bt_shell_printf("Metadata:\n");
+			bt_shell_hexdump(cfg->meta->iov_base,
+						cfg->meta->iov_len);
+		}
+	}
+
+	append_qos(&dict, cfg);
+
+	dbus_message_iter_close_container(iter, &dict);
+}
+
+static int parse_chan_alloc(DBusMessageIter *iter, uint32_t *location,
+						uint8_t *channels)
+{
+	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
+		const char *key;
+		DBusMessageIter value, entry;
+		int var;
+
+		dbus_message_iter_recurse(iter, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		var = dbus_message_iter_get_arg_type(&value);
+
+		if (!strcasecmp(key, "ChannelAllocation")) {
+			if (var != DBUS_TYPE_UINT32)
+				return -EINVAL;
+			dbus_message_iter_get_basic(&value, location);
+			if (*channels)
+				*channels = __builtin_popcount(*location);
+			return 0;
+		} else if (!strcasecmp(key, "Locations")) {
+			uint32_t tmp;
+
+			if (var != DBUS_TYPE_UINT32)
+				return -EINVAL;
+
+			dbus_message_iter_get_basic(&value, &tmp);
+			*location &= tmp;
+
+			if (*channels)
+				*channels = __builtin_popcount(*location);
+		}
+
+		dbus_message_iter_next(iter);
+	}
+
+	return *location ? 0 : -EINVAL;
+}
+
+static void ltv_find(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
+{
+	bool *found = user_data;
+
+	*found = true;
+}
+
+static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
+						DBusMessage *msg,
+						struct codec_preset *preset)
+{
+	DBusMessage *reply;
+	DBusMessageIter iter, props;
+	struct endpoint_config *cfg;
+	struct bt_bap_io_qos *qos;
+	uint32_t location = ep->locations;
+	uint8_t channels = 1;
+
+	if (!preset)
+		return NULL;
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return NULL;
+
+	cfg = new0(struct endpoint_config, 1);
+	cfg->ep = ep;
+
+	/* Copy capabilities */
+	cfg->caps = util_iov_dup(&preset->data, 1);
+	cfg->target_latency = preset->target_latency;
+
+	dbus_message_iter_init(msg, &iter);
+	dbus_message_iter_recurse(&iter, &props);
+
+	if (!parse_chan_alloc(&props, &location, &channels)) {
+		uint32_t chan_alloc = 0;
+		uint8_t type = LC3_CONFIG_CHAN_ALLOC;
+		bool found = false;
+
+		if (preset->chan_alloc & location)
+			chan_alloc = preset->chan_alloc & location;
+		else if (preset->alt_preset &&
+					preset->alt_preset->chan_alloc &
+					location) {
+			chan_alloc = preset->alt_preset->chan_alloc & location;
+			preset = preset->alt_preset;
+
+			/* Copy alternate capabilities */
+			util_iov_free(cfg->caps, 1);
+			cfg->caps = util_iov_dup(&preset->data, 1);
+			cfg->target_latency = preset->target_latency;
+		} else
+			chan_alloc = location;
+
+		/* Check if Channel Allocation is present in caps */
+		util_ltv_foreach(cfg->caps->iov_base, cfg->caps->iov_len,
+					&type, ltv_find, &found);
+
+		/* If Channel Allocation has not been set directly via
+		 * preset->data then attempt to set it if chan_alloc has been
+		 * set.
+		 */
+		if (!found && chan_alloc) {
+			uint8_t chan_alloc_ltv[] = {
+				0x05, LC3_CONFIG_CHAN_ALLOC, chan_alloc & 0xff,
+				chan_alloc >> 8, chan_alloc >> 16,
+				chan_alloc >> 24
+			};
+
+			put_le32(chan_alloc, &chan_alloc_ltv[2]);
+			util_iov_append(cfg->caps, &chan_alloc_ltv,
+						sizeof(chan_alloc_ltv));
+		}
+	}
+
+	/* Copy metadata */
+	if (preset->meta.iov_len)
+		cfg->meta = util_iov_dup(&preset->meta, 1);
+	else
+		cfg->meta = util_iov_dup(ep->meta, 1);
+
+	if (ep->broadcast)
+		qos = &preset->qos.bcast.io_qos;
+	else
+		qos = &preset->qos.ucast.io_qos;
+
+	if (qos->phy) {
+		/* Set QoS parameters */
+		cfg->qos = preset->qos;
+		/* Adjust the SDU size based on the number of
+		 * locations/channels that is being requested.
+		 */
+		if (channels > 1)
+			qos->sdu *= channels;
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	bt_shell_printf("selecting %s...\n", preset->name);
+
+	append_properties(&iter, cfg);
 
 	free(cfg);
 
 	return reply;
 }
 
+static struct codec_preset *endpoint_find_codec_preset(struct endpoint *ep,
+							const char *name)
+{
+	if (ep->codec_preset &&
+			(!name || !strcmp(ep->codec_preset->name, name)))
+		return ep->codec_preset;
+
+	return preset_find_name(ep->preset, name);
+}
+
 static void select_properties_response(const char *input, void *user_data)
 {
 	struct endpoint *ep = user_data;
 	struct codec_preset *p;
 	DBusMessage *reply;
 
-	p = find_preset(ep->uuid, input);
+	p = endpoint_find_codec_preset(ep, input);
 	if (p) {
 		reply = endpoint_select_properties_reply(ep, ep->msg, p);
 		goto done;
@@ -1803,6 +2146,13 @@ static DBusMessage *endpoint_select_properties(DBusConnection *conn,
 	bt_shell_printf("Endpoint: SelectProperties\n");
 	print_iter("\t", "Properties", &args);
 
+	if (!ep->max_transports) {
+		bt_shell_printf("Maximum transports reached: rejecting\n");
+		return g_dbus_create_error(msg,
+					 "org.bluez.Error.Rejected",
+					 "Maximum transports reached");
+	}
+
 	if (!ep->auto_accept) {
 		ep->msg = dbus_message_ref(msg);
 		bt_shell_prompt_input("Endpoint", "Enter preset/configuration:",
@@ -1810,26 +2160,37 @@ static DBusMessage *endpoint_select_properties(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = endpoint_find_codec_preset(ep, NULL);
 	if (!p)
-		NULL;
+		return NULL;
 
 	reply = endpoint_select_properties_reply(ep, msg, p);
 	if (!reply)
 		return NULL;
 
-	bt_shell_printf("Auto Accepting using %s...\n", p->name);
-
 	return reply;
 }
 
+static bool match_str(const void *data, const void *user_data)
+{
+	return !strcmp(data, user_data);
+}
+
 static DBusMessage *endpoint_clear_configuration(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
 	struct endpoint *ep = user_data;
+	DBusMessageIter args;
+	const char *path;
+
+	dbus_message_iter_init(msg, &args);
 
-	free(ep->transport);
-	ep->transport = NULL;
+	dbus_message_iter_get_basic(&args, &path);
+
+	if (ep->max_transports != UINT8_MAX)
+		ep->max_transports++;
+
+	queue_remove_if(ep->transports, match_str, (void *)path);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
@@ -1853,217 +2214,1526 @@ static struct endpoint *endpoint_find(const char *pattern)
 	return NULL;
 }
 
-static void cmd_show_endpoint(int argc, char *argv[])
+static void print_aptx_common(a2dp_aptx_t *aptx)
 {
-	GDBusProxy *proxy;
+	bt_shell_printf("\n\t\tFrequencies: ");
+	if (aptx->frequency & APTX_SAMPLING_FREQ_16000)
+		bt_shell_printf("16kHz ");
+	if (aptx->frequency & APTX_SAMPLING_FREQ_32000)
+		bt_shell_printf("32kHz ");
+	if (aptx->frequency & APTX_SAMPLING_FREQ_44100)
+		bt_shell_printf("44.1kHz ");
+	if (aptx->frequency & APTX_SAMPLING_FREQ_48000)
+		bt_shell_printf("48kHz ");
 
-	proxy = g_dbus_proxy_lookup(endpoints, NULL, argv[1],
-						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
-	if (!proxy) {
-		bt_shell_printf("Endpoint %s not found\n", argv[1]);
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-	}
+	bt_shell_printf("\n\t\tChannel modes: ");
+	if (aptx->channel_mode & APTX_CHANNEL_MODE_MONO)
+		bt_shell_printf("Mono ");
+	if (aptx->channel_mode & APTX_CHANNEL_MODE_STEREO)
+		bt_shell_printf("Stereo ");
+}
 
-	bt_shell_printf("Endpoint %s\n", g_dbus_proxy_get_path(proxy));
+static void print_aptx(a2dp_aptx_t *aptx, uint8_t size)
+{
+	bt_shell_printf("\t\tVendor Specific Value (aptX)");
 
-	print_property(proxy, "UUID");
-	print_property(proxy, "Codec");
-	print_property(proxy, "Capabilities");
-	print_property(proxy, "Device");
-	print_property(proxy, "DelayReporting");
+	if (size < sizeof(*aptx)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
+	print_aptx_common(aptx);
 
-static const GDBusMethodTable endpoint_methods[] = {
-	{ GDBUS_ASYNC_METHOD("SetConfiguration",
-					GDBUS_ARGS({ "endpoint", "o" },
-						{ "properties", "a{sv}" } ),
-					NULL, endpoint_set_configuration) },
-	{ GDBUS_ASYNC_METHOD("SelectConfiguration",
-					GDBUS_ARGS({ "caps", "ay" } ),
-					GDBUS_ARGS({ "cfg", "ay" } ),
-					endpoint_select_configuration) },
-	{ GDBUS_ASYNC_METHOD("SelectProperties",
-					GDBUS_ARGS({ "properties", "a{sv}" } ),
-					GDBUS_ARGS({ "properties", "a{sv}" } ),
-					endpoint_select_properties) },
-	{ GDBUS_ASYNC_METHOD("ClearConfiguration",
-					GDBUS_ARGS({ "transport", "o" } ),
-					NULL, endpoint_clear_configuration) },
-	{ },
-};
+	bt_shell_printf("\n");
+}
 
-static void endpoint_free(void *data)
+static void print_faststream(a2dp_faststream_t *faststream, uint8_t size)
 {
-	struct endpoint *ep = data;
+	bt_shell_printf("\t\tVendor Specific Value (FastStream)");
 
-	if (ep->caps) {
-		g_free(ep->caps->iov_base);
-		g_free(ep->caps);
+	if (size < sizeof(*faststream)) {
+		bt_shell_printf(" (broken)\n");
+		return;
 	}
 
-	if (ep->msg)
-		dbus_message_unref(ep->msg);
+	bt_shell_printf("\n\t\tDirections: ");
+	if (faststream->direction & FASTSTREAM_DIRECTION_SINK)
+		bt_shell_printf("sink ");
+	if (faststream->direction & FASTSTREAM_DIRECTION_SOURCE)
+		bt_shell_printf("source ");
 
-	g_free(ep->path);
-	g_free(ep->uuid);
-	g_free(ep);
+	if (faststream->direction & FASTSTREAM_DIRECTION_SINK) {
+		bt_shell_printf("\n\t\tSink Frequencies: ");
+		if (faststream->sink_frequency &
+				FASTSTREAM_SINK_SAMPLING_FREQ_44100)
+			bt_shell_printf("44.1kHz ");
+		if (faststream->sink_frequency &
+				FASTSTREAM_SINK_SAMPLING_FREQ_48000)
+			bt_shell_printf("48kHz ");
+	}
+
+	if (faststream->direction & FASTSTREAM_DIRECTION_SOURCE) {
+		bt_shell_printf("\n\t\tSource Frequencies: ");
+		if (faststream->source_frequency &
+				FASTSTREAM_SOURCE_SAMPLING_FREQ_16000)
+			bt_shell_printf("16kHz ");
+	}
+
+	bt_shell_printf("\n");
 }
 
-static gboolean endpoint_get_uuid(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static void print_aptx_ll(a2dp_aptx_ll_t *aptx_ll, uint8_t size)
 {
-	struct endpoint *ep = data;
+	a2dp_aptx_ll_new_caps_t *aptx_ll_new;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ep->uuid);
+	bt_shell_printf("\t\tVendor Specific Value (aptX Low Latency)");
 
-	return TRUE;
+	if (size < sizeof(*aptx_ll)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
+
+	print_aptx_common(&aptx_ll->aptx);
+
+	bt_shell_printf("\n\tBidirectional link: %s",
+			aptx_ll->bidirect_link ? "Yes" : "No");
+
+	aptx_ll_new = &aptx_ll->new_caps[0];
+	if (aptx_ll->has_new_caps &&
+	    size >= sizeof(*aptx_ll) + sizeof(*aptx_ll_new)) {
+		bt_shell_printf("\n\tTarget codec buffer level: %u",
+			(unsigned int)aptx_ll_new->target_level2 |
+			((unsigned int)(aptx_ll_new->target_level1) << 8));
+		bt_shell_printf("\n\tInitial codec buffer level: %u",
+			(unsigned int)aptx_ll_new->initial_level2 |
+			((unsigned int)(aptx_ll_new->initial_level1) << 8));
+		bt_shell_printf("\n\tSRA max rate: %g",
+			aptx_ll_new->sra_max_rate / 10000.0);
+		bt_shell_printf("\n\tSRA averaging time: %us",
+			(unsigned int)aptx_ll_new->sra_avg_time);
+		bt_shell_printf("\n\tGood working codec buffer level: %u",
+			(unsigned int)aptx_ll_new->good_working_level2 |
+			((unsigned int)(aptx_ll_new->good_working_level1) << 8)
+			);
+	}
+
+	bt_shell_printf("\n");
 }
 
-static gboolean endpoint_get_codec(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static void print_aptx_hd(a2dp_aptx_hd_t *aptx_hd, uint8_t size)
 {
-	struct endpoint *ep = data;
+	bt_shell_printf("\t\tVendor Specific Value (aptX HD)");
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &ep->codec);
+	if (size < sizeof(*aptx_hd)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
 
-	return TRUE;
+	print_aptx_common(&aptx_hd->aptx);
+
+	bt_shell_printf("\n");
 }
 
-static gboolean endpoint_get_capabilities(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static void print_ldac(a2dp_ldac_t *ldac, uint8_t size)
 {
-	struct endpoint *ep = data;
-	DBusMessageIter array;
+	bt_shell_printf("\t\tVendor Specific Value (LDAC)");
 
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-					DBUS_TYPE_BYTE_AS_STRING, &array);
+	if (size < sizeof(*ldac)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
 
-	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
-					     &ep->caps->iov_base,
-					     ep->caps->iov_len);
+	bt_shell_printf("\n\t\tFrequencies: ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_44100)
+		bt_shell_printf("44.1kHz ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_48000)
+		bt_shell_printf("48kHz ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_88200)
+		bt_shell_printf("88.2kHz ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_96000)
+		bt_shell_printf("96kHz ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_176400)
+		bt_shell_printf("176.4kHz ");
+	if (ldac->frequency & LDAC_SAMPLING_FREQ_192000)
+		bt_shell_printf("192kHz ");
 
-	dbus_message_iter_close_container(iter, &array);
+	bt_shell_printf("\n\t\tChannel modes: ");
+	if (ldac->channel_mode & LDAC_CHANNEL_MODE_MONO)
+		bt_shell_printf("Mono ");
+	if (ldac->channel_mode & LDAC_CHANNEL_MODE_DUAL)
+		bt_shell_printf("Dual ");
+	if (ldac->channel_mode & LDAC_CHANNEL_MODE_STEREO)
+		bt_shell_printf("Stereo ");
 
-	return TRUE;
+	bt_shell_printf("\n");
 }
 
-static const GDBusPropertyTable endpoint_properties[] = {
-	{ "UUID", "s", endpoint_get_uuid, NULL, NULL },
-	{ "Codec", "y", endpoint_get_codec, NULL, NULL },
-	{ "Capabilities", "ay", endpoint_get_capabilities, NULL, NULL },
-	{ }
-};
-
-static void register_endpoint_setup(DBusMessageIter *iter, void *user_data)
+static void print_opus_g(a2dp_opus_g_t *opus, uint8_t size)
 {
-	struct endpoint *ep = user_data;
-	DBusMessageIter dict;
-	const char *key = "Capabilities";
-
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &ep->path);
+	bt_shell_printf("\t\tVendor Specific Value (Opus [Google])");
 
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
-
-	g_dbus_dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &ep->uuid);
+	if (size < sizeof(*opus)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
 
-	g_dbus_dict_append_entry(&dict, "Codec", DBUS_TYPE_BYTE, &ep->codec);
+	bt_shell_printf("\n\t\tFrequencies: ");
+	if (opus->data & OPUS_G_FREQUENCY_48000)
+		bt_shell_printf("48kHz ");
 
-	g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
-					DBUS_TYPE_BYTE, &ep->caps->iov_base,
-					ep->caps->iov_len);
+	bt_shell_printf("\n\t\tChannel modes: ");
+	if (opus->data & OPUS_G_CHANNELS_MONO)
+		bt_shell_printf("Mono ");
+	if (opus->data & OPUS_G_CHANNELS_STEREO)
+		bt_shell_printf("Stereo ");
+	if (opus->data & OPUS_G_CHANNELS_DUAL)
+		bt_shell_printf("Dual Mono ");
 
-	bt_shell_printf("Capabilities:\n");
-	bt_shell_hexdump(ep->caps->iov_base, ep->caps->iov_len);
+	bt_shell_printf("\n\t\tFrame durations: ");
+	if (opus->data & OPUS_G_DURATION_100)
+		bt_shell_printf("10 ms ");
+	if (opus->data & OPUS_G_DURATION_200)
+		bt_shell_printf("20 ms ");
 
-	dbus_message_iter_close_container(iter, &dict);
+	bt_shell_printf("\n");
 }
 
-static void register_endpoint_reply(DBusMessage *message, void *user_data)
+static void print_vendor(a2dp_vendor_codec_t *vendor, uint8_t size)
 {
-	struct endpoint *ep = user_data;
-	DBusError error;
-
-	dbus_error_init(&error);
+	uint32_t vendor_id;
+	uint16_t codec_id;
+	int i;
 
-	if (dbus_set_error_from_message(&error, message)) {
-		bt_shell_printf("Failed to register endpoint: %s\n",
-				error.name);
-		dbus_error_free(&error);
-		local_endpoints = g_list_remove(local_endpoints, ep);
-		g_dbus_unregister_interface(dbus_conn, ep->path,
-						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	if (size < sizeof(*vendor)) {
+		bt_shell_printf("\tMedia Codec: Vendor Specific A2DP Codec "
+				"(broken)");
+		return;
 	}
 
-	bt_shell_printf("Endpoint %s registered\n", ep->path);
+	vendor_id = A2DP_GET_VENDOR_ID(*vendor);
+	codec_id = A2DP_GET_CODEC_ID(*vendor);
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	bt_shell_printf("\tMedia Codec: Vendor Specific A2DP Codec");
+
+	bt_shell_printf("\n\tVendor ID 0x%08x", vendor_id);
+
+	bt_shell_printf("\n\tVendor Specific Codec ID 0x%04x", codec_id);
+
+	bt_shell_printf("\n\tVendor Specific Data:");
+	for (i = 6; i < size; ++i)
+		bt_shell_printf(" 0x%.02x", ((unsigned char *)vendor)[i]);
+	bt_shell_printf("\n");
+
+	if (vendor_id == APTX_VENDOR_ID && codec_id == APTX_CODEC_ID)
+		print_aptx((void *) vendor, size);
+	else if (vendor_id == FASTSTREAM_VENDOR_ID &&
+			codec_id == FASTSTREAM_CODEC_ID)
+		print_faststream((void *) vendor, size);
+	else if (vendor_id == APTX_LL_VENDOR_ID && codec_id == APTX_LL_CODEC_ID)
+		print_aptx_ll((void *) vendor, size);
+	else if (vendor_id == APTX_HD_VENDOR_ID && codec_id == APTX_HD_CODEC_ID)
+		print_aptx_hd((void *) vendor, size);
+	else if (vendor_id == LDAC_VENDOR_ID && codec_id == LDAC_CODEC_ID)
+		print_ldac((void *) vendor, size);
+	else if (vendor_id == OPUS_G_VENDOR_ID && codec_id == OPUS_G_CODEC_ID)
+		print_opus_g((void *) vendor, size);
 }
 
-static void endpoint_register(struct endpoint *ep)
+static void print_mpeg24(a2dp_aac_t *aac, uint8_t size)
 {
-	GList *l;
+	unsigned int freq, bitrate;
 
-	if (!g_dbus_register_interface(dbus_conn, ep->path,
-					BLUEZ_MEDIA_ENDPOINT_INTERFACE,
-					endpoint_methods, NULL,
-					endpoint_properties, ep,
-					endpoint_free)) {
-		goto fail;
+	if (size < sizeof(*aac)) {
+		bt_shell_printf("\tMedia Codec: MPEG24 (broken)\n");
+		return;
 	}
 
-	for (l = medias; l; l = g_list_next(l)) {
-		if (!g_dbus_proxy_method_call(l->data, "RegisterEndpoint",
-						register_endpoint_setup,
-						register_endpoint_reply,
-						ep, NULL)) {
-			g_dbus_unregister_interface(dbus_conn, ep->path,
-						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
-			goto fail;
-		}
+	freq = AAC_GET_FREQUENCY(*aac);
+	bitrate = AAC_GET_BITRATE(*aac);
+
+	bt_shell_printf("\tMedia Codec: MPEG24\n\tObject Types: ");
+
+	if (aac->object_type & AAC_OBJECT_TYPE_MPEG2_AAC_LC)
+		bt_shell_printf("MPEG-2 AAC LC ");
+	if (aac->object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LC)
+		bt_shell_printf("MPEG-4 AAC LC ");
+	if (aac->object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LTP)
+		bt_shell_printf("MPEG-4 AAC LTP ");
+	if (aac->object_type & AAC_OBJECT_TYPE_MPEG4_AAC_SCA)
+		bt_shell_printf("MPEG-4 AAC scalable ");
+
+	bt_shell_printf("\n\tFrequencies: ");
+	if (freq & AAC_SAMPLING_FREQ_8000)
+		bt_shell_printf("8kHz ");
+	if (freq & AAC_SAMPLING_FREQ_11025)
+		bt_shell_printf("11.025kHz ");
+	if (freq & AAC_SAMPLING_FREQ_12000)
+		bt_shell_printf("12kHz ");
+	if (freq & AAC_SAMPLING_FREQ_16000)
+		bt_shell_printf("16kHz ");
+	if (freq & AAC_SAMPLING_FREQ_22050)
+		bt_shell_printf("22.05kHz ");
+	if (freq & AAC_SAMPLING_FREQ_24000)
+		bt_shell_printf("24kHz ");
+	if (freq & AAC_SAMPLING_FREQ_32000)
+		bt_shell_printf("32kHz ");
+	if (freq & AAC_SAMPLING_FREQ_44100)
+		bt_shell_printf("44.1kHz ");
+	if (freq & AAC_SAMPLING_FREQ_48000)
+		bt_shell_printf("48kHz ");
+	if (freq & AAC_SAMPLING_FREQ_64000)
+		bt_shell_printf("64kHz ");
+	if (freq & AAC_SAMPLING_FREQ_88200)
+		bt_shell_printf("88.2kHz ");
+	if (freq & AAC_SAMPLING_FREQ_96000)
+		bt_shell_printf("96kHz ");
+
+	bt_shell_printf("\n\tChannels: ");
+	if (aac->channels & AAC_CHANNELS_1)
+		bt_shell_printf("1 ");
+	if (aac->channels & AAC_CHANNELS_2)
+		bt_shell_printf("2 ");
+
+	bt_shell_printf("\n\tBitrate: %u", bitrate);
+
+	bt_shell_printf("\n\tVBR: %s", aac->vbr ? "Yes\n" : "No\n");
+}
+
+static void print_mpeg12(a2dp_mpeg_t *mpeg, uint8_t size)
+{
+	uint16_t bitrate;
+
+	if (size < sizeof(*mpeg)) {
+		bt_shell_printf("\tMedia Codec: MPEG12 (broken)\n");
+		return;
 	}
 
+	bitrate = MPEG_GET_BITRATE(*mpeg);
+
+	bt_shell_printf("\tMedia Codec: MPEG12\n\tChannel Modes: ");
+
+	if (mpeg->channel_mode & MPEG_CHANNEL_MODE_MONO)
+		bt_shell_printf("Mono ");
+	if (mpeg->channel_mode & MPEG_CHANNEL_MODE_DUAL_CHANNEL)
+		bt_shell_printf("DualChannel ");
+	if (mpeg->channel_mode & MPEG_CHANNEL_MODE_STEREO)
+		bt_shell_printf("Stereo ");
+	if (mpeg->channel_mode & MPEG_CHANNEL_MODE_JOINT_STEREO)
+		bt_shell_printf("JointStereo");
+
+	bt_shell_printf("\n\tFrequencies: ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_16000)
+		bt_shell_printf("16Khz ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_22050)
+		bt_shell_printf("22.05Khz ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_24000)
+		bt_shell_printf("24Khz ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_32000)
+		bt_shell_printf("32Khz ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_44100)
+		bt_shell_printf("44.1Khz ");
+	if (mpeg->frequency & MPEG_SAMPLING_FREQ_48000)
+		bt_shell_printf("48Khz ");
+
+	bt_shell_printf("\n\tCRC: %s", mpeg->crc ? "Yes" : "No");
+
+	bt_shell_printf("\n\tLayer: ");
+	if (mpeg->layer & MPEG_LAYER_MP1)
+		bt_shell_printf("1 ");
+	if (mpeg->layer & MPEG_LAYER_MP2)
+		bt_shell_printf("2 ");
+	if (mpeg->layer & MPEG_LAYER_MP3)
+		bt_shell_printf("3 ");
+
+	if (bitrate & MPEG_BIT_RATE_FREE) {
+		bt_shell_printf("\n\tBit Rate: Free format");
+	} else {
+		if (mpeg->layer & MPEG_LAYER_MP1) {
+			bt_shell_printf("\n\tLayer 1 Bit Rate: ");
+			if (bitrate & MPEG_MP1_BIT_RATE_32000)
+				bt_shell_printf("32kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_64000)
+				bt_shell_printf("64kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_96000)
+				bt_shell_printf("96kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_128000)
+				bt_shell_printf("128kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_160000)
+				bt_shell_printf("160kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_192000)
+				bt_shell_printf("192kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_224000)
+				bt_shell_printf("224kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_256000)
+				bt_shell_printf("256kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_320000)
+				bt_shell_printf("320kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_352000)
+				bt_shell_printf("352kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_384000)
+				bt_shell_printf("384kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_416000)
+				bt_shell_printf("416kbps ");
+			if (bitrate & MPEG_MP1_BIT_RATE_448000)
+				bt_shell_printf("448kbps ");
+		}
+
+		if (mpeg->layer & MPEG_LAYER_MP2) {
+			bt_shell_printf("\n\tLayer 2 Bit Rate: ");
+			if (bitrate & MPEG_MP2_BIT_RATE_32000)
+				bt_shell_printf("32kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_48000)
+				bt_shell_printf("48kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_56000)
+				bt_shell_printf("56kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_64000)
+				bt_shell_printf("64kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_80000)
+				bt_shell_printf("80kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_96000)
+				bt_shell_printf("96kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_112000)
+				bt_shell_printf("112kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_128000)
+				bt_shell_printf("128kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_160000)
+				bt_shell_printf("160kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_192000)
+				bt_shell_printf("192kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_224000)
+				bt_shell_printf("224kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_256000)
+				bt_shell_printf("256kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_320000)
+				bt_shell_printf("320kbps ");
+			if (bitrate & MPEG_MP2_BIT_RATE_384000)
+				bt_shell_printf("384kbps ");
+		}
+
+		if (mpeg->layer & MPEG_LAYER_MP3) {
+			bt_shell_printf("\n\tLayer 3 Bit Rate: ");
+			if (bitrate & MPEG_MP3_BIT_RATE_32000)
+				bt_shell_printf("32kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_40000)
+				bt_shell_printf("40kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_48000)
+				bt_shell_printf("48kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_56000)
+				bt_shell_printf("56kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_64000)
+				bt_shell_printf("64kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_80000)
+				bt_shell_printf("80kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_96000)
+				bt_shell_printf("96kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_112000)
+				bt_shell_printf("112kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_128000)
+				bt_shell_printf("128kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_160000)
+				bt_shell_printf("160kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_192000)
+				bt_shell_printf("192kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_224000)
+				bt_shell_printf("224kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_256000)
+				bt_shell_printf("256kbps ");
+			if (bitrate & MPEG_MP3_BIT_RATE_320000)
+				bt_shell_printf("320kbps ");
+		}
+	}
+
+	bt_shell_printf("\n\tVBR: %s", mpeg->vbr ? "Yes" : "No");
+
+	bt_shell_printf("\n\tPayload Format: ");
+	if (mpeg->mpf)
+		bt_shell_printf("RFC-2250 RFC-3119\n");
+	else
+		bt_shell_printf("RFC-2250\n");
+}
+
+static void print_sbc(a2dp_sbc_t *sbc, uint8_t size)
+{
+	if (size < sizeof(*sbc)) {
+		bt_shell_printf("\tMedia Codec: SBC (broken)\n");
+		return;
+	}
+
+	bt_shell_printf("\tMedia Codec: SBC\n\tChannel Modes: ");
+
+	if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO)
+		bt_shell_printf("Mono ");
+	if (sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL)
+		bt_shell_printf("DualChannel ");
+	if (sbc->channel_mode & SBC_CHANNEL_MODE_STEREO)
+		bt_shell_printf("Stereo ");
+	if (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO)
+		bt_shell_printf("JointStereo");
+
+	bt_shell_printf("\n\tFrequencies: ");
+	if (sbc->frequency & SBC_SAMPLING_FREQ_16000)
+		bt_shell_printf("16Khz ");
+	if (sbc->frequency & SBC_SAMPLING_FREQ_32000)
+		bt_shell_printf("32Khz ");
+	if (sbc->frequency & SBC_SAMPLING_FREQ_44100)
+		bt_shell_printf("44.1Khz ");
+	if (sbc->frequency & SBC_SAMPLING_FREQ_48000)
+		bt_shell_printf("48Khz ");
+
+	bt_shell_printf("\n\tSubbands: ");
+	if (sbc->allocation_method & SBC_SUBBANDS_4)
+		bt_shell_printf("4 ");
+	if (sbc->allocation_method & SBC_SUBBANDS_8)
+		bt_shell_printf("8");
+
+	bt_shell_printf("\n\tBlocks: ");
+	if (sbc->block_length & SBC_BLOCK_LENGTH_4)
+		bt_shell_printf("4 ");
+	if (sbc->block_length & SBC_BLOCK_LENGTH_8)
+		bt_shell_printf("8 ");
+	if (sbc->block_length & SBC_BLOCK_LENGTH_12)
+		bt_shell_printf("12 ");
+	if (sbc->block_length & SBC_BLOCK_LENGTH_16)
+		bt_shell_printf("16 ");
+
+	bt_shell_printf("\n\tBitpool Range: %d-%d\n",
+				sbc->min_bitpool, sbc->max_bitpool);
+}
+
+static int print_a2dp_codec(uint8_t codec, void *data, uint8_t size)
+{
+	int i;
+
+	switch (codec) {
+	case A2DP_CODEC_SBC:
+		print_sbc(data, size);
+		break;
+	case A2DP_CODEC_MPEG12:
+		print_mpeg12(data, size);
+		break;
+	case A2DP_CODEC_MPEG24:
+		print_mpeg24(data, size);
+		break;
+	case A2DP_CODEC_VENDOR:
+		print_vendor(data, size);
+		break;
+	default:
+		bt_shell_printf("\tMedia Codec: Unknown\n");
+		bt_shell_printf("\t\tCodec Data:");
+		for (i = 0; i < size - 2; ++i)
+			bt_shell_printf(" 0x%.02x", ((unsigned char *)data)[i]);
+		bt_shell_printf("\n");
+	}
+
+	return 0;
+}
+
+static void print_hexdump(const char *label, struct iovec *iov)
+{
+	if (!iov)
+		return;
+
+	bt_shell_printf("%s:\n", label);
+	bt_shell_hexdump(iov->iov_base, iov->iov_len);
+}
+
+static void print_codec(const char *uuid, uint8_t codec, struct iovec *caps,
+						struct iovec *meta)
+{
+	if (!strcasecmp(uuid, A2DP_SINK_UUID) ||
+			!strcasecmp(uuid, A2DP_SOURCE_UUID)) {
+		print_a2dp_codec(codec, caps->iov_base, caps->iov_len);
+		return;
+	}
+
+	if (codec != LC3_ID) {
+		print_hexdump("Capabilities", caps);
+		print_hexdump("Metadata", meta);
+		return;
+	}
+
+	print_lc3_caps(caps->iov_base, caps->iov_len);
+
+	if (!meta)
+		return;
+
+	print_lc3_meta(meta->iov_base, meta->iov_len);
+}
+
+static void print_capabilities(GDBusProxy *proxy)
+{
+	DBusMessageIter iter, subiter;
+	const char *uuid;
+	uint8_t codec;
+	struct iovec caps, meta;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (!g_dbus_proxy_get_property(proxy, "Codec", &iter))
+		return;
+
+	dbus_message_iter_get_basic(&iter, &codec);
+
+	if (!g_dbus_proxy_get_property(proxy, "Capabilities", &iter))
+		return;
+
+	dbus_message_iter_recurse(&iter, &subiter);
+
+	dbus_message_iter_get_fixed_array(&subiter, &caps.iov_base,
+						(int *)&caps.iov_len);
+
+	if (g_dbus_proxy_get_property(proxy, "Metadata", &iter)) {
+		dbus_message_iter_recurse(&iter, &subiter);
+		dbus_message_iter_get_fixed_array(&subiter, &meta.iov_base,
+						  (int *)&meta.iov_len);
+	} else {
+		meta.iov_base = NULL;
+		meta.iov_len = 0;
+	}
+
+	print_codec(uuid, codec, &caps, &meta);
+}
+
+static void print_preset(struct codec_preset *codec, uint8_t codec_id)
+{
+	bt_shell_printf("\tPreset %s\n", codec->name);
+
+	if (codec_id == LC3_ID)
+		print_lc3_cfg(codec->data.iov_base, codec->data.iov_len);
+}
+
+static void print_local_endpoint(struct endpoint *ep)
+{
+	bt_shell_printf("Endpoint %s\n", ep->path);
+	bt_shell_printf("\tUUID %s\n", ep->uuid);
+	bt_shell_printf("\tCodec 0x%02x (%u)\n", ep->codec, ep->codec);
+
+	if (ep->caps)
+		print_codec(ep->uuid, ep->codec, ep->caps, ep->meta);
+
+	if (ep->codec_preset)
+		print_preset(ep->codec_preset, ep->codec);
+
+	if (ep->locations)
+		bt_shell_printf("\tLocations 0x%08x (%u)\n", ep->locations,
+				ep->locations);
+	if (ep->supported_context)
+		bt_shell_printf("\tSupportedContext 0x%08x (%u)\n",
+				ep->supported_context, ep->supported_context);
+	if (ep->context)
+		bt_shell_printf("\tContext 0x%08x (%u)\n", ep->context,
+				ep->context);
+}
+
+static void print_endpoint_properties(GDBusProxy *proxy)
+{
+	bt_shell_printf("Endpoint %s\n", g_dbus_proxy_get_path(proxy));
+
+	print_property(proxy, "UUID");
+	print_property(proxy, "Codec");
+	print_capabilities(proxy);
+	print_property(proxy, "Device");
+	print_property(proxy, "DelayReporting");
+	print_property(proxy, "Locations");
+	print_property(proxy, "SupportedContext");
+	print_property(proxy, "Context");
+	print_property(proxy, "QoS");
+}
+
+static void print_endpoints(void *data, void *user_data)
+{
+	print_endpoint_properties(data);
+}
+
+static void print_local_endpoints(void *data, void *user_data)
+{
+	print_local_endpoint(data);
+}
+
+static void cmd_show_endpoint(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+
+	/* Show all endpoints if no argument is given */
+	if (argc != 2) {
+		g_list_foreach(endpoints, print_endpoints, NULL);
+		g_list_foreach(local_endpoints, print_local_endpoints, NULL);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	proxy = g_dbus_proxy_lookup(endpoints, NULL, argv[1],
+						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+	if (!proxy) {
+		struct endpoint *ep;
+
+		ep = endpoint_find(argv[1]);
+		if (ep)
+			return print_local_endpoint(ep);
+
+		bt_shell_printf("Endpoint %s not found\n", argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
+	print_endpoint_properties(proxy);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const GDBusMethodTable endpoint_methods[] = {
+	{ GDBUS_ASYNC_METHOD("SetConfiguration",
+					GDBUS_ARGS({ "endpoint", "o" },
+						{ "properties", "a{sv}" } ),
+					NULL, endpoint_set_configuration) },
+	{ GDBUS_ASYNC_METHOD("SelectConfiguration",
+					GDBUS_ARGS({ "caps", "ay" } ),
+					GDBUS_ARGS({ "cfg", "ay" } ),
+					endpoint_select_configuration) },
+	{ GDBUS_ASYNC_METHOD("SelectProperties",
+					GDBUS_ARGS({ "properties", "a{sv}" } ),
+					GDBUS_ARGS({ "properties", "a{sv}" } ),
+					endpoint_select_properties) },
+	{ GDBUS_ASYNC_METHOD("ClearConfiguration",
+					GDBUS_ARGS({ "transport", "o" } ),
+					NULL, endpoint_clear_configuration) },
+	{ },
+};
+
+static void endpoint_free(void *data)
+{
+	struct endpoint *ep = data;
+
+	util_iov_free(ep->caps, 1);
+	util_iov_free(ep->meta, 1);
+
+	if (ep->msg)
+		dbus_message_unref(ep->msg);
+
+	queue_destroy(ep->preset->custom, free);
+	ep->preset->custom = NULL;
+
+	if (ep->codec == 0xff)
+		free(ep->preset);
+
+	queue_destroy(ep->acquiring, NULL);
+	queue_destroy(ep->transports, free);
+
+	g_free(ep->path);
+	g_free(ep->uuid);
+	g_free(ep);
+}
+
+static gboolean endpoint_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ep->uuid);
+
+	return TRUE;
+}
+
+static gboolean endpoint_get_codec(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &ep->codec);
+
+	return TRUE;
+}
+
+static gboolean endpoint_get_capabilities(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+					     &ep->caps->iov_base,
+					     ep->caps->iov_len);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+struct vendor {
+	uint16_t cid;
+	uint16_t vid;
+} __packed;
+
+static gboolean endpoint_get_vendor(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+	struct vendor vendor = { ep->cid, ep->vid };
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &vendor);
+
+	return TRUE;
+}
+
+static gboolean endpoint_vendor_exists(const GDBusPropertyTable *property,
+							void *data)
+{
+	struct endpoint *ep = data;
+
+	return ep->cid && ep->vid;
+}
+
+static gboolean endpoint_get_metadata(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+				DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+				&ep->meta->iov_base,
+				ep->meta->iov_len);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static gboolean endpoint_metadata_exists(const GDBusPropertyTable *property,
+							void *data)
+{
+	struct endpoint *ep = data;
+
+	return ep->meta ? TRUE : FALSE;
+}
+
+static gboolean endpoint_get_locations(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ep->locations);
+
+	return TRUE;
+}
+
+static gboolean endpoint_locations_exists(const GDBusPropertyTable *property,
+							void *data)
+{
+	struct endpoint *ep = data;
+
+	return ep->supported_context ? TRUE : FALSE;
+}
+
+static gboolean
+endpoint_get_supported_context(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&ep->supported_context);
+
+	return TRUE;
+}
+
+static gboolean
+endpoint_supported_context_exists(const GDBusPropertyTable *property,
+							void *data)
+{
+	struct endpoint *ep = data;
+
+	return ep->supported_context ? TRUE : FALSE;
+}
+
+static gboolean endpoint_get_context(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct endpoint *ep = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &ep->context);
+
+	return TRUE;
+}
+
+static gboolean endpoint_context_exists(const GDBusPropertyTable *property,
+							void *data)
+{
+	struct endpoint *ep = data;
+
+	return ep->context ? TRUE : FALSE;
+}
+
+static const GDBusPropertyTable endpoint_properties[] = {
+	{ "UUID", "s", endpoint_get_uuid, NULL, NULL },
+	{ "Codec", "y", endpoint_get_codec, NULL, NULL },
+	{ "Capabilities", "ay", endpoint_get_capabilities, NULL, NULL },
+	{ "Metadata", "ay", endpoint_get_metadata, NULL,
+				endpoint_metadata_exists },
+	{ "Vendor", "u", endpoint_get_vendor, NULL, endpoint_vendor_exists },
+	{ "Locations", "u", endpoint_get_locations, NULL,
+				endpoint_locations_exists },
+	{ "SupportedContext", "q", endpoint_get_supported_context, NULL,
+				endpoint_supported_context_exists },
+	{ "Context", "q", endpoint_get_context, NULL, endpoint_context_exists },
+	{ }
+};
+
+static void register_endpoint_setup(DBusMessageIter *iter, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	DBusMessageIter dict;
+	const char *key = "Capabilities";
+	const char *meta = "Metadata";
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &ep->path);
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	g_dbus_dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &ep->uuid);
+
+	g_dbus_dict_append_entry(&dict, "Codec", DBUS_TYPE_BYTE, &ep->codec);
+
+	if (ep->cid && ep->vid) {
+		struct vendor vendor = { ep->cid, ep->vid };
+
+		g_dbus_dict_append_entry(&dict, "Vendor", DBUS_TYPE_UINT32,
+						 &vendor);
+	}
+
+	if (ep->caps) {
+		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
+					DBUS_TYPE_BYTE, &ep->caps->iov_base,
+					ep->caps->iov_len);
+
+		bt_shell_printf("Capabilities:\n");
+		bt_shell_hexdump(ep->caps->iov_base, ep->caps->iov_len);
+	}
+
+	if (ep->meta) {
+		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
+				DBUS_TYPE_BYTE, &ep->meta->iov_base,
+				ep->meta->iov_len);
+
+		bt_shell_printf("Metadata:\n");
+		bt_shell_hexdump(ep->meta->iov_base, ep->meta->iov_len);
+	}
+
+	if (ep->locations)
+		g_dbus_dict_append_entry(&dict, "Locations", DBUS_TYPE_UINT32,
+						&ep->locations);
+
+	if (ep->supported_context)
+		g_dbus_dict_append_entry(&dict, "SupportedContext",
+						DBUS_TYPE_UINT16,
+						&ep->supported_context);
+
+	if (ep->context)
+		g_dbus_dict_append_entry(&dict, "Context", DBUS_TYPE_UINT16,
+						&ep->context);
+
+	dbus_message_iter_close_container(iter, &dict);
+}
+
+static void register_endpoint_reply(DBusMessage *message, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	DBusError error;
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message)) {
+		bt_shell_printf("Failed to register endpoint: %s\n",
+				error.name);
+		dbus_error_free(&error);
+		if (g_list_find(local_endpoints, ep)) {
+			local_endpoints = g_list_remove(local_endpoints, ep);
+			g_dbus_unregister_interface(dbus_conn, ep->path,
+						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+		}
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Endpoint %s registered\n", ep->path);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static bool media_supports_uuid(GDBusProxy *proxy, const char *uuid)
+{
+	DBusMessageIter iter, array;
+
+	if (!g_dbus_proxy_get_property(proxy, "SupportedUUIDs", &iter))
+		return false;
+
+	dbus_message_iter_recurse(&iter, &array);
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
+		const char *support_uuid;
+
+		dbus_message_iter_get_basic(&array, &support_uuid);
+
+		if (!strcasecmp(uuid, support_uuid))
+			return true;
+
+		dbus_message_iter_next(&array);
+	}
+
+	return false;
+}
+
+static void endpoint_register(struct endpoint *ep)
+{
+	GList *l;
+	int registered = 0;
+
+	if (!g_dbus_register_interface(dbus_conn, ep->path,
+					BLUEZ_MEDIA_ENDPOINT_INTERFACE,
+					endpoint_methods, NULL,
+					endpoint_properties, ep,
+					endpoint_free)) {
+		goto fail;
+	}
+
+	for (l = medias; l; l = g_list_next(l)) {
+		if (!media_supports_uuid(l->data, ep->uuid))
+			continue;
+
+		if (!g_dbus_proxy_method_call(l->data, "RegisterEndpoint",
+						register_endpoint_setup,
+						register_endpoint_reply,
+						ep, NULL)) {
+			g_dbus_unregister_interface(dbus_conn, ep->path,
+						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+			goto fail;
+		}
+
+		registered++;
+	}
+
+	if (!registered)
+		goto fail;
+
 	return;
 
-fail:
-	bt_shell_printf("Failed register endpoint\n");
-	local_endpoints = g_list_remove(local_endpoints, ep);
-	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+fail:
+	bt_shell_printf("Failed register endpoint\n");
+	local_endpoints = g_list_remove(local_endpoints, ep);
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+}
+
+static void endpoint_iso_stream(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+
+	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
+		ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
+	} else {
+		value = strtol(input, &endptr, 0);
+
+		if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		ep->iso_stream = value;
+	}
+
+	endpoint_register(ep);
+}
+
+static void endpoint_iso_group(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+
+	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
+		ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
+	} else {
+		value = strtol(input, &endptr, 0);
+
+		if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		ep->iso_group = value;
+	}
+
+	bt_shell_prompt_input(ep->path, "CIS (auto/value):",
+		endpoint_iso_stream, ep);
+}
+
+static void endpoint_context(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+
+	value = strtol(input, &endptr, 0);
+
+	if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ep->context = value;
+
+	bt_shell_prompt_input(ep->path, "CIG (auto/value):",
+		endpoint_iso_group, ep);
+}
+
+static void endpoint_supported_context(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+
+	value = strtol(input, &endptr, 0);
+
+	if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ep->supported_context = value;
+
+	if (ep->broadcast) {
+		endpoint_register(ep);
+		return;
+	}
+
+	bt_shell_prompt_input(ep->path, "Context (value):", endpoint_context,
+									ep);
+}
+
+static void endpoint_locations(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+	uint8_t channels;
+
+	value = strtol(input, &endptr, 0);
+
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	ep->locations = value;
+
+	channels = __builtin_popcount(value);
+	/* Automatically set LC3_CHAN_COUNT if only 1 location is supported */
+	if (channels == 1)
+		util_ltv_push(ep->caps, sizeof(channels), LC3_CHAN_COUNT,
+				&channels);
+
+	bt_shell_prompt_input(ep->path, "Supported Context (value):",
+				endpoint_supported_context, ep);
+}
+
+static void endpoint_max_transports(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	char *endptr = NULL;
+	int value;
+
+	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
+		ep->max_transports = UINT8_MAX;
+	} else {
+		value = strtol(input, &endptr, 0);
+
+		if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		ep->max_transports = value;
+	}
+
+	bt_shell_prompt_input(ep->path, "Locations:", endpoint_locations, ep);
+}
+
+static void endpoint_auto_accept(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+
+	if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) {
+		ep->auto_accept = true;
+		bt_shell_prompt_input(ep->path, "Max Transports (auto/value):",
+						endpoint_max_transports, ep);
+		return;
+	} else if (!strcasecmp(input, "n") || !strcasecmp(input, "no")) {
+		ep->auto_accept = false;
+		bt_shell_prompt_input(ep->path, "Max Transports (auto/value):",
+						endpoint_max_transports, ep);
+		return;
+	} else {
+		bt_shell_printf("Invalid input for Auto Accept\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void endpoint_set_metadata(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	struct iovec iov;
+
+	if (!strcasecmp(input, "n") || !strcasecmp(input, "no")) {
+		util_iov_free(ep->meta, 1);
+		ep->meta = NULL;
+		goto done;
+	}
+
+	iov.iov_base = str2bytearray((char *) input, &iov.iov_len);
+	if (iov.iov_base) {
+		util_iov_free(ep->meta, 1);
+		ep->meta = util_iov_dup(&iov, 1);
+	}
+
+done:
+	bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
+					endpoint_auto_accept, ep);
+}
+
+static void endpoint_set_capabilities(const char *input, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	struct iovec iov;
+
+	if (!strcasecmp(input, "n") || !strcasecmp(input, "no")) {
+		util_iov_free(ep->caps, 1);
+		ep->caps = NULL;
+		goto done;
+	}
+
+	iov.iov_base = str2bytearray((char *) input, &iov.iov_len);
+	if (iov.iov_base) {
+		util_iov_free(ep->caps, 1);
+		ep->caps = util_iov_dup(&iov, 1);
+	}
+
+done:
+	bt_shell_prompt_input(ep->path, "Enter Metadata (value/no):",
+					endpoint_set_metadata, ep);
+}
+
+static char *uuid_generator(const char *text, int state)
+{
+	int len = strlen(text);
+	static int index = 0;
+	size_t i;
+
+	if (!state) {
+		index = 0;
+	}
+
+	for (i = index; i < ARRAY_SIZE(caps); i++) {
+		const struct capabilities *cap = &caps[i];
+
+		index++;
+
+		if (!strncasecmp(cap->uuid, text, len))
+			return strdup(cap->uuid);
+	}
+
+	return NULL;
+}
+
+static const struct capabilities *find_capabilities(const char *uuid,
+							uint8_t codec_id)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(caps); i++) {
+		const struct capabilities *cap = &caps[i];
+
+		if (strcasecmp(cap->uuid, uuid))
+			continue;
+
+		if (cap->codec_id == codec_id)
+			return cap;
+	}
+
+	return NULL;
+}
+
+static struct codec_preset *codec_preset_new(const char *name)
+{
+	struct codec_preset *codec;
+
+	codec = new0(struct codec_preset, 1);
+	codec->name = strdup(name);
+	codec->custom = true;
+
+	return codec;
+}
+
+static struct codec_preset *codec_preset_add(struct preset *preset,
+						const char *name)
+{
+	struct codec_preset *codec;
+
+	codec = preset_find_name(preset, name);
+	if (codec)
+		return codec;
+
+	codec = codec_preset_new(name);
+
+	if (!preset->custom)
+		preset->custom = queue_new();
+
+	queue_push_tail(preset->custom, codec);
+
+	return codec;
+}
+
+static void cmd_register_endpoint(int argc, char *argv[])
+{
+	struct endpoint *ep;
+	char *endptr = NULL;
+
+	ep = g_new0(struct endpoint, 1);
+	ep->uuid = g_strdup(argv[1]);
+	ep->codec = strtol(argv[2], &endptr, 0);
+	ep->cid = 0x0000;
+	ep->vid = 0x0000;
+	ep->path = g_strdup_printf("%s/ep%u", BLUEZ_MEDIA_ENDPOINT_PATH,
+					g_list_length(local_endpoints));
+	local_endpoints = g_list_append(local_endpoints, ep);
+
+	if (!strcmp(ep->uuid, BCAA_SERVICE_UUID) ||
+		!strcmp(ep->uuid, BAA_SERVICE_UUID)) {
+		ep->broadcast = true;
+	} else {
+		ep->broadcast = false;
+	}
+
+	if (strrchr(argv[2], ':')) {
+		ep->codec = 0xff;
+		parse_vendor_codec(argv[2], &ep->vid, &ep->cid);
+		ep->preset = new0(struct preset, 1);
+		ep->preset->default_preset = codec_preset_add(ep->preset,
+								"custom");
+	} else {
+		ep->preset = find_presets_name(ep->uuid, argv[2]);
+	}
+
+	if (argc > 3)
+		endpoint_set_capabilities(argv[3], ep);
+	else {
+		const struct capabilities *cap;
+
+		cap = find_capabilities(ep->uuid, ep->codec);
+		if (cap) {
+			/* Copy capabilities */
+			util_iov_free(ep->caps, 1);
+			ep->caps = util_iov_dup(&cap->data, 1);
+
+			/* Copy metadata */
+			util_iov_free(ep->meta, 1);
+			ep->meta = util_iov_dup(&cap->meta, 1);
+
+			bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
+						endpoint_auto_accept, ep);
+		} else
+			bt_shell_prompt_input(ep->path, "Enter capabilities:",
+						endpoint_set_capabilities, ep);
+	}
+}
+
+static void unregister_endpoint_setup(DBusMessageIter *iter, void *user_data)
+{
+	struct endpoint *ep = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &ep->path);
+}
+
+static void unregister_endpoint_reply(DBusMessage *message, void *user_data)
+{
+	struct endpoint *ep = user_data;
+	DBusError error;
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message)) {
+		bt_shell_printf("Failed to unregister endpoint: %s\n",
+				error.name);
+		dbus_error_free(&error);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Endpoint %s unregistered\n", ep->path);
+
+	local_endpoints = g_list_remove(local_endpoints, ep);
+	g_dbus_unregister_interface(dbus_conn, ep->path,
+					BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_unregister_endpoint(int argc, char *argv[])
+{
+	struct endpoint *ep;
+	GList *l;
+
+	ep = endpoint_find(argv[1]);
+	if (!ep) {
+		bt_shell_printf("Unable to find endpoint object: %s\n",
+								argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	for (l = medias; l; l = g_list_next(l)) {
+		if (!g_dbus_proxy_method_call(l->data, "UnregisterEndpoint",
+						unregister_endpoint_setup,
+						unregister_endpoint_reply,
+						ep, NULL)) {
+			bt_shell_printf("Failed unregister endpoint\n");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void config_endpoint_setup(DBusMessageIter *iter, void *user_data)
+{
+	struct endpoint_config *cfg = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+					&cfg->ep->path);
+
+	append_properties(iter, cfg);
+}
+
+static void config_endpoint_reply(DBusMessage *message, void *user_data)
+{
+	struct endpoint_config *cfg = user_data;
+	struct endpoint *ep = cfg->ep;
+	DBusError error;
+
+	free(cfg->caps->iov_base);
+	free(cfg->caps);
+	free(cfg);
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message)) {
+		bt_shell_printf("Failed to config endpoint: %s\n",
+				error.name);
+		dbus_error_free(&error);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Endpoint %s configured\n", ep->path);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void endpoint_set_config(struct endpoint_config *cfg)
+{
+	if (!g_dbus_proxy_method_call(cfg->proxy, "SetConfiguration",
+						config_endpoint_setup,
+						config_endpoint_reply,
+						cfg, NULL)) {
+		bt_shell_printf("Failed to config endpoint\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
+static void endpoint_config(const char *input, void *user_data)
+{
+	struct endpoint_config *cfg = user_data;
+	uint8_t *data;
+	size_t len = 0;
+
+	data = str2bytearray((char *) input, &len);
+
+	util_iov_append(cfg->caps, data, len);
+	free(data);
+
+	endpoint_set_config(cfg);
+}
+
+static struct endpoint *endpoint_new(const struct capabilities *cap);
+
+static void endpoint_set_metadata_cfg(const char *input, void *user_data)
+{
+	struct endpoint_config *cfg = user_data;
+
+	if (!strcasecmp(input, "n") || !strcasecmp(input, "no"))
+		goto done;
+
+	if (!cfg->meta)
+		cfg->meta = g_new0(struct iovec, 1);
+
+	cfg->meta->iov_base = str2bytearray((char *) input,
+				&cfg->meta->iov_len);
+	if (!cfg->meta->iov_base) {
+		free(cfg->meta);
+		cfg->meta = NULL;
+	}
 
+done:
+	endpoint_set_config(cfg);
 }
 
-static void endpoint_cis(const char *input, void *user_data)
+static void config_endpoint_channel_location(const char *input, void *user_data)
 {
-	struct endpoint *ep = user_data;
+	struct endpoint_config *cfg = user_data;
 	char *endptr = NULL;
-	int value;
+	uint32_t location;
+	uint8_t channels = 1;
 
-	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
-		ep->cis = BT_ISO_QOS_CIS_UNSET;
-	} else {
-		value = strtol(input, &endptr, 0);
+	if (!strcasecmp(input, "n") || !strcasecmp(input, "no"))
+		goto add_meta;
 
-		if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
-			bt_shell_printf("Invalid argument: %s\n", input);
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
+	location = strtol(input, &endptr, 0);
 
-		ep->cis = value;
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	endpoint_register(ep);
+	/* Add Channel Allocation LTV in capabilities */
+	location = cpu_to_le32(location);
+	util_ltv_push(cfg->caps, LC3_CONFIG_CHAN_ALLOC_LEN - 1,
+			LC3_CONFIG_CHAN_ALLOC, &location);
+
+	/* Adjust the SDU size based on the number of
+	 * locations/channels that is being requested.
+	 */
+	channels = __builtin_popcount(location);
+	if (channels > 1)
+		cfg->qos.bcast.io_qos.sdu *= channels;
+
+add_meta:
+	/* Add metadata */
+	bt_shell_prompt_input(cfg->ep->path, "Enter Metadata (value/no):",
+			endpoint_set_metadata_cfg, cfg);
 }
 
-static void endpoint_cig(const char *input, void *user_data)
+static void config_endpoint_iso_group(const char *input, void *user_data)
 {
-	struct endpoint *ep = user_data;
+	struct endpoint_config *cfg = user_data;
 	char *endptr = NULL;
 	int value;
+	uint8_t type = LC3_CONFIG_CHAN_ALLOC;
+	bool found = false;
 
 	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
-		ep->cig = BT_ISO_QOS_CIG_UNSET;
+		cfg->ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
 	} else {
 		value = strtol(input, &endptr, 0);
 
@@ -2072,314 +3742,595 @@ static void endpoint_cig(const char *input, void *user_data)
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
-		ep->cig = value;
+		cfg->ep->iso_group = value;
 	}
 
-	bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep);
+	/* Check if Channel Allocation is present in caps */
+	util_ltv_foreach(cfg->caps->iov_base,
+			cfg->caps->iov_len, &type,
+			ltv_find, &found);
+
+	/* Add Channel Allocation if it is not present in caps */
+	if (!found) {
+		bt_shell_prompt_input(cfg->ep->path,
+				"Enter channel location (value/no):",
+				config_endpoint_channel_location, cfg);
+	} else {
+		/* Add metadata */
+		bt_shell_prompt_input(cfg->ep->path,
+				"Enter Metadata (value/no):",
+				endpoint_set_metadata_cfg, cfg);
+	}
 }
 
-static void endpoint_auto_accept(const char *input, void *user_data)
+static void endpoint_set_config_bcast(struct endpoint_config *cfg)
 {
-	struct endpoint *ep = user_data;
+	cfg->ep->bcode = g_new0(struct iovec, 1);
+	util_iov_append(cfg->ep->bcode, bcast_code,
+			sizeof(bcast_code));
 
-	if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) {
-		ep->auto_accept = true;
-	} else if (!strcasecmp(input, "n") || !strcasecmp(input, "no")) {
-		ep->auto_accept = false;
-	} else {
-		bt_shell_printf("Invalid input for Auto Accept\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	if ((strcmp(cfg->ep->uuid, BAA_SERVICE_UUID) == 0)) {
+		/* A broadcast sink endpoint config does not need
+		 * user input.
+		 */
+		endpoint_set_config(cfg);
+		return;
 	}
 
-	bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep);
+	bt_shell_prompt_input(cfg->ep->path,
+		"BIG (auto/value):",
+		config_endpoint_iso_group, cfg);
 }
 
-static void endpoint_set_capabilities(const char *input, void *user_data)
+static void cmd_config_endpoint(int argc, char *argv[])
 {
-	struct endpoint *ep = user_data;
+	struct endpoint_config *cfg;
+	const struct codec_preset *preset;
 
-	if (ep->caps)
-		g_free(ep->caps->iov_base);
-	else
-		ep->caps = g_new0(struct iovec, 1);
+	cfg = new0(struct endpoint_config, 1);
 
-	ep->caps->iov_base = str2bytearray((char *) input, &ep->caps->iov_len);
+	/* Search for the remote endpoint name on DBUS */
+	cfg->proxy = g_dbus_proxy_lookup(endpoints, NULL, argv[1],
+						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+	if (!cfg->proxy) {
+		bt_shell_printf("Endpoint %s not found\n", argv[1]);
+		goto fail;
+	}
 
-	bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
-						endpoint_auto_accept, ep);
+	/* Search for the local endpoint */
+	cfg->ep = endpoint_find(argv[2]);
+	if (!cfg->ep) {
+		bt_shell_printf("Local Endpoint %s not found\n", argv[2]);
+		goto fail;
+	}
+
+	if (argc > 3) {
+		preset = preset_find_name(cfg->ep->preset, argv[3]);
+		if (!preset) {
+			bt_shell_printf("Preset %s not found\n", argv[3]);
+			goto fail;
+		}
+
+		cfg->caps = g_new0(struct iovec, 1);
+		/* Copy capabilities */
+		util_iov_append(cfg->caps, preset->data.iov_base,
+				preset->data.iov_len);
+		cfg->target_latency = preset->target_latency;
+
+		/* Set QoS parameters */
+		cfg->qos = preset->qos;
+
+		if (cfg->ep->broadcast)
+			endpoint_set_config_bcast(cfg);
+		else
+			endpoint_set_config(cfg);
+
+		return;
+	}
+
+	bt_shell_prompt_input(cfg->ep->path, "Enter configuration:",
+					endpoint_config, cfg);
+
+	return;
+
+fail:
+	g_free(cfg);
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
-static char *uuid_generator(const char *text, int state)
+static void custom_delay(const char *input, void *user_data)
 {
-	int len = strlen(text);
-	static int index = 0;
-	size_t i;
+	struct codec_preset *p = user_data;
+	struct bt_bap_qos *qos = (void *)&p->qos;
+	char *endptr = NULL;
 
-	if (!state) {
-		index = 0;
+	if (!p->target_latency)
+		qos->bcast.delay = strtol(input, &endptr, 0);
+	else
+		qos->ucast.delay = strtol(input, &endptr, 0);
+
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	for (i = index; i < ARRAY_SIZE(caps); i++) {
-		const struct capabilities *cap = &caps[i];
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
 
-		index++;
+static void custom_latency(const char *input, void *user_data)
+{
+	struct codec_preset *p = user_data;
+	struct bt_bap_qos *qos = (void *)&p->qos;
+	char *endptr = NULL;
 
-		if (!strncasecmp(cap->uuid, text, len))
-			return strdup(cap->uuid);
+	if (!p->target_latency)
+		qos->bcast.io_qos.latency = strtol(input, &endptr, 0);
+	else
+		qos->ucast.io_qos.latency = strtol(input, &endptr, 0);
+
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	return NULL;
+	bt_shell_prompt_input("QoS", "Enter Presentation Delay (us):",
+					custom_delay, user_data);
 }
 
-static const struct capabilities *find_capabilities(const char *uuid,
-							uint8_t codec_id)
+static void custom_rtn(const char *input, void *user_data)
 {
-	size_t i;
-
-	for (i = 0; i < ARRAY_SIZE(caps); i++) {
-		const struct capabilities *cap = &caps[i];
+	struct codec_preset *p = user_data;
+	struct bt_bap_qos *qos = (void *)&p->qos;
+	char *endptr = NULL;
 
-		if (strcasecmp(cap->uuid, uuid))
-			continue;
+	if (!p->target_latency)
+		qos->bcast.io_qos.rtn = strtol(input, &endptr, 0);
+	else
+		qos->ucast.io_qos.rtn = strtol(input, &endptr, 0);
 
-		if (cap->codec_id == codec_id)
-			return cap;
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	return NULL;
+	bt_shell_prompt_input("QoS", "Enter Max Transport Latency (ms):",
+					custom_latency, user_data);
 }
 
-static void cmd_register_endpoint(int argc, char *argv[])
+static void custom_sdu(const char *input, void *user_data)
 {
-	struct endpoint *ep;
+	struct codec_preset *p = user_data;
+	struct bt_bap_qos *qos = (void *)&p->qos;
 	char *endptr = NULL;
 
-	ep = g_new0(struct endpoint, 1);
-	ep->uuid = g_strdup(argv[1]);
-	ep->codec = strtol(argv[2], &endptr, 0);
-	ep->path = g_strdup_printf("%s/ep%u", BLUEZ_MEDIA_ENDPOINT_PATH,
-					g_list_length(local_endpoints));
-	local_endpoints = g_list_append(local_endpoints, ep);
+	if (!p->target_latency)
+		qos->bcast.io_qos.sdu = strtol(input, &endptr, 0);
+	else
+		qos->ucast.io_qos.sdu = strtol(input, &endptr, 0);
 
-	if (argc > 3)
-		endpoint_set_capabilities(argv[3], ep);
-	else {
-		const struct capabilities *cap;
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 
-		cap = find_capabilities(ep->uuid, ep->codec);
-		if (cap) {
-			if (ep->caps)
-				ep->caps->iov_len = 0;
+	bt_shell_prompt_input("QoS", "Enter RTN:", custom_rtn, user_data);
+}
 
-			/* Copy capabilities */
-			iov_append(&ep->caps, cap->data.iov_base,
-							cap->data.iov_len);
+static void custom_phy(const char *input, void *user_data)
+{
+	struct codec_preset *p = user_data;
+	struct bt_bap_io_qos *qos;
 
-			bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
-						endpoint_auto_accept, ep);
-		} else
-			bt_shell_prompt_input(ep->path, "Enter capabilities:",
-						endpoint_set_capabilities, ep);
+	if (!p->target_latency)
+		qos = &p->qos.bcast.io_qos;
+	else
+		qos = &p->qos.ucast.io_qos;
+
+	if (!strcmp(input, "1M"))
+		qos->phy = 0x01;
+	else if (!strcmp(input, "2M"))
+		qos->phy = 0x02;
+	else {
+		char *endptr = NULL;
+		uint8_t phy = strtol(input, &endptr, 0);
+
+		if (!endptr || *endptr != '\0') {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		switch (phy) {
+		case 0x01:
+		case 0x02:
+			qos->phy = phy;
+			break;
+		default:
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
 	}
+
+	bt_shell_prompt_input("QoS", "Enter Max SDU:", custom_sdu, user_data);
 }
 
-static void unregister_endpoint_setup(DBusMessageIter *iter, void *user_data)
+static void custom_framing(const char *input, void *user_data)
 {
-	struct endpoint *ep = user_data;
+	struct codec_preset *p = user_data;
+	uint8_t *framing;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &ep->path);
+	if (!p->target_latency)
+		framing = &p->qos.bcast.framing;
+	else
+		framing = &p->qos.ucast.framing;
+
+	if (!strcasecmp(input, "Unframed"))
+		*framing = 0x00;
+	else if (!strcasecmp(input, "Framed"))
+		*framing = 0x01;
+	else {
+		char *endptr = NULL;
+
+		*framing = strtol(input, &endptr, 0);
+		if (!endptr || *endptr != '\0') {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	bt_shell_prompt_input("QoS", "Enter PHY (1M, 2M):", custom_phy,
+							user_data);
 }
 
-static void unregister_endpoint_reply(DBusMessage *message, void *user_data)
+static void custom_interval(const char *input, void *user_data)
 {
-	struct endpoint *ep = user_data;
-	DBusError error;
+	struct codec_preset *p = user_data;
+	char *endptr = NULL;
+	struct bt_bap_io_qos *qos;
 
-	dbus_error_init(&error);
+	if (!p->target_latency)
+		qos = &p->qos.bcast.io_qos;
+	else
+		qos = &p->qos.ucast.io_qos;
 
-	if (dbus_set_error_from_message(&error, message)) {
-		bt_shell_printf("Failed to unregister endpoint: %s\n",
-				error.name);
-		dbus_error_free(&error);
+	qos->interval = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	bt_shell_printf("Endpoint %s unregistered\n", ep->path);
+	bt_shell_prompt_input("QoS", "Enter Framing (Unframed, Framed):",
+				custom_framing, user_data);
+}
 
-	local_endpoints = g_list_remove(local_endpoints, ep);
-	g_dbus_unregister_interface(dbus_conn, ep->path,
-					BLUEZ_MEDIA_ENDPOINT_INTERFACE);
+static void custom_target_latency(const char *input, void *user_data)
+{
+	struct codec_preset *p = user_data;
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	if (!strcasecmp(input, "Low"))
+		p->target_latency = 0x01;
+	else if (!strcasecmp(input, "Balance"))
+		p->target_latency = 0x02;
+	else if (!strcasecmp(input, "High"))
+		p->target_latency = 0x03;
+	else {
+		char *endptr = NULL;
+
+		p->target_latency = strtol(input, &endptr, 0);
+		if (!endptr || *endptr != '\0') {
+			bt_shell_printf("Invalid argument: %s\n", input);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
+
+	bt_shell_prompt_input("QoS", "Enter SDU Interval (us):",
+					custom_interval, user_data);
 }
 
-static void cmd_unregister_endpoint(int argc, char *argv[])
+static void custom_length(const char *input, void *user_data)
 {
-	struct endpoint *ep;
-	GList *l;
+	struct codec_preset *p = user_data;
+	struct iovec *iov = (void *)&p->data;
+	uint8_t ltv[4] = { 0x03, LC3_CONFIG_FRAME_LEN };
+	uint16_t len;
+	char *endptr = NULL;
 
-	ep = endpoint_find(argv[1]);
-	if (!ep) {
-		bt_shell_printf("Unable to find endpoint object: %s\n",
-								argv[1]);
+	len = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	for (l = medias; l; l = g_list_next(l)) {
-		if (!g_dbus_proxy_method_call(l->data, "UnregisterEndpoint",
-						unregister_endpoint_setup,
-						unregister_endpoint_reply,
-						ep, NULL)) {
-			bt_shell_printf("Failed unregister endpoint\n");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
+	ltv[2] = len;
+	ltv[3] = len >> 8;
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	util_iov_append(iov, ltv, sizeof(ltv));
+
+	bt_shell_prompt_input("QoS", "Enter Target Latency "
+				"(Low, Balance, High):",
+				custom_target_latency, user_data);
 }
 
-static void config_endpoint_setup(DBusMessageIter *iter, void *user_data)
+static void custom_location(const char *input, void *user_data)
 {
-	struct endpoint_config *cfg = user_data;
+	struct codec_preset *p = user_data;
+	struct iovec *iov = (void *)&p->data;
+	uint32_t location;
+	char *endptr = NULL;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
-					&cfg->ep->path);
+	location = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 
-	append_properties(iter, cfg);
+	/* Only add Channel Allocation if set */
+	if (location) {
+		uint8_t ltv[6] = { 0x05, LC3_CONFIG_CHAN_ALLOC };
+
+		location = cpu_to_le32(location);
+		memcpy(&ltv[2], &location, sizeof(location));
+		util_iov_append(iov, ltv, sizeof(ltv));
+	}
+
+	bt_shell_prompt_input("Codec", "Enter frame length:",
+					custom_length, user_data);
 }
 
-static void config_endpoint_reply(DBusMessage *message, void *user_data)
+static uint8_t val2duration(uint32_t val)
 {
-	struct endpoint_config *cfg = user_data;
-	struct endpoint *ep = cfg->ep;
-	DBusError error;
+	switch (val) {
+	case 7:
+		return 0x00;
+	case 10:
+		return 0x01;
+	default:
+		return 0xff;
+	}
+}
 
-	free(cfg->caps->iov_base);
-	free(cfg->caps);
-	free(cfg);
+static void custom_duration(const char *input, void *user_data)
+{
+	struct codec_preset *p = user_data;
+	struct iovec *iov = (void *)&p->data;
+	uint8_t ltv[3] = { 0x02, LC3_CONFIG_DURATION, 0x00 };
+	char *endptr = NULL;
+	uint32_t val;
 
-	dbus_error_init(&error);
+	val = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 
-	if (dbus_set_error_from_message(&error, message)) {
-		bt_shell_printf("Failed to config endpoint: %s\n",
-				error.name);
-		dbus_error_free(&error);
+	if (strncmp(input, "0x", 2))
+		ltv[2] = val2duration(val);
+	else
+		ltv[2] = val;
+
+	if (ltv[2] == 0xff) {
+		bt_shell_printf("Invalid argument: %s\n", input);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	bt_shell_printf("Endpoint %s configured\n", ep->path);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	util_iov_append(iov, ltv, sizeof(ltv));
+
+	bt_shell_prompt_input("Codec", "Enter channel allocation:",
+					custom_location, user_data);
+}
+
+static uint8_t val2freq(uint32_t val)
+{
+	switch (val) {
+	case 8:
+		return 0x01;
+	case 11:
+		return 0x02;
+	case 16:
+		return 0x03;
+	case 22:
+		return 0x04;
+	case 24:
+		return 0x05;
+	case 32:
+		return 0x06;
+	case 44:
+		return 0x07;
+	case 48:
+		return 0x08;
+	case 88:
+		return 0x09;
+	case 96:
+		return 0x0a;
+	case 174:
+		return 0x0b;
+	case 192:
+		return 0x0c;
+	case 384:
+		return 0x0d;
+	default:
+		return 0x00;
+	}
 }
 
-static void endpoint_set_config(struct endpoint_config *cfg)
+static void custom_frequency(const char *input, void *user_data)
 {
-	if (!g_dbus_proxy_method_call(cfg->proxy, "SetConfiguration",
-						config_endpoint_setup,
-						config_endpoint_reply,
-						cfg, NULL)) {
-		bt_shell_printf("Failed to config endpoint\n");
+	struct codec_preset *p = user_data;
+	struct iovec *iov = (void *)&p->data;
+	uint8_t ltv[3] = { 0x02, LC3_CONFIG_FREQ, 0x00 };
+	uint32_t val;
+	char *endptr = NULL;
+
+	val = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
-}
 
-static void endpoint_config(const char *input, void *user_data)
-{
-	struct endpoint_config *cfg = user_data;
-	uint8_t *data;
-	size_t len = 0;
+	if (strncmp(input, "0x", 2))
+		ltv[2] = val2freq(val);
+	else
+		ltv[2] = val;
 
-	data = str2bytearray((char *) input, &len);
+	if (!ltv[2]) {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 
-	iov_append(&cfg->caps, data, len);
-	free(data);
+	/* Reset iov to start over the codec configuration */
+	free(iov->iov_base);
+	iov->iov_base = NULL;
+	iov->iov_len = 0;
+	util_iov_append(iov, ltv, sizeof(ltv));
 
-	endpoint_set_config(cfg);
+	bt_shell_prompt_input("Codec", "Enter frame duration (ms):",
+				custom_duration, user_data);
 }
 
-static void cmd_config_endpoint(int argc, char *argv[])
+static void foreach_custom_preset_print(void *data, void *user_data)
 {
-	struct endpoint_config *cfg;
-	const struct codec_preset *preset;
+	struct codec_preset *p = data;
+	struct preset *preset = user_data;
 
-	cfg = new0(struct endpoint_config, 1);
+	bt_shell_printf("%s%s\n", p == preset->default_preset ? "*" : "",
+				p->name);
+}
 
-	cfg->proxy = g_dbus_proxy_lookup(endpoints, NULL, argv[1],
-						BLUEZ_MEDIA_ENDPOINT_INTERFACE);
-	if (!cfg->proxy) {
-		bt_shell_printf("Endpoint %s not found\n", argv[1]);
-		goto fail;
-	}
+static void print_presets(struct preset *preset)
+{
+	size_t i;
+	struct codec_preset *p;
 
-	cfg->ep = endpoint_find(argv[2]);
-	if (!cfg->ep) {
-		bt_shell_printf("Local Endpoint %s not found\n", argv[2]);
-		goto fail;
-	}
+	for (i = 0; i < preset->num_presets; i++) {
+		p = &preset->presets[i];
 
-	if (argc > 3) {
-		preset = find_preset(cfg->ep->uuid, argv[3]);
-		if (!preset) {
-			bt_shell_printf("Preset %s not found\n", argv[3]);
-			goto fail;
-		}
+		if (p == preset->default_preset)
+			bt_shell_printf("*%s\n", p->name);
+		else if (preset->default_preset &&
+					p == preset->default_preset->alt_preset)
+			bt_shell_printf("**%s\n", p->name);
+		else
+			bt_shell_printf("%s\n", p->name);
+	}
 
-		/* Copy capabilities */
-		iov_append(&cfg->caps, preset->data.iov_base,
-						preset->data.iov_len);
+	queue_foreach(preset->custom, foreach_custom_preset_print, preset);
+}
 
-		/* Set QoS parameters */
-		cfg->qos = &preset->qos;
+static void custom_chan_alloc(const char *input, void *user_data)
+{
+	struct codec_preset *p = user_data;
+	char *endptr = NULL;
 
-		endpoint_set_config(cfg);
-		return;
+	p->chan_alloc = strtol(input, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		bt_shell_printf("Invalid argument: %s\n", input);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	bt_shell_prompt_input(cfg->ep->path, "Enter configuration:",
-					endpoint_config, cfg);
-
-	return;
-
-fail:
-	g_free(cfg);
-	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	if (p->alt_preset)
+		bt_shell_prompt_input(p->alt_preset->name,
+					"Enter Channel Allocation: ",
+					custom_chan_alloc, p->alt_preset);
+	else
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static void cmd_presets_endpoint(int argc, char *argv[])
 {
-	size_t i;
+	struct preset *preset;
 	struct codec_preset *default_preset = NULL;
+	struct endpoint *ep = NULL;
 
-	if (argc > 2) {
-		default_preset = find_preset(argv[1], argv[2]);
-		if (!default_preset) {
-			bt_shell_printf("Preset %s not found\n", argv[2]);
+	preset = find_presets_name(argv[1], argv[2]);
+	if (!preset) {
+		ep = endpoint_find(argv[1]);
+		if (!ep) {
+			bt_shell_printf("No preset found\n");
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
-
-		default_preset->is_default = true;
+		preset = ep->preset;
+		argv++;
+		argc--;
+	} else {
+		argv += 2;
+		argc -= 2;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(presets); i++) {
-		const struct preset *preset = &presets[i];
+	if (argc > 1) {
+		default_preset = codec_preset_add(preset, argv[1]);
+		if (!default_preset) {
+			bt_shell_printf("Preset %s not found\n", argv[1]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (ep)
+			ep->codec_preset = default_preset;
+		else
+			preset->default_preset = default_preset;
+
+		if (argc > 2) {
+			struct codec_preset *alt_preset;
+			struct iovec *caps = (void *)&default_preset->data;
+			struct iovec *meta = (void *)&default_preset->meta;
+
+			/* Check if and alternative preset was given */
+			alt_preset = preset_find_name(preset, argv[2]);
+			if (alt_preset) {
+				default_preset->alt_preset = alt_preset;
+				bt_shell_prompt_input(default_preset->name,
+						"Enter Channel Allocation: ",
+						custom_chan_alloc,
+						default_preset);
+				return;
+			}
 
-		if (!strcasecmp(preset->uuid, argv[1])) {
-			size_t j;
+			/* Check if Codec Configuration was entered */
+			if (strlen(argv[2])) {
+				caps->iov_base = str2bytearray(argv[2],
+							      &caps->iov_len);
+				if (!caps->iov_base) {
+					bt_shell_printf("Invalid configuration "
+								"%s\n",
+								argv[2]);
+					return bt_shell_noninteractive_quit(
+								EXIT_FAILURE);
+				}
+			}
 
-			for (j = 0; j < preset->num_presets; j++) {
-				struct codec_preset *p;
+			/* Check if metadata was entered */
+			if (argc > 3) {
+				meta->iov_base = str2bytearray(argv[3],
+								&meta->iov_len);
+				if (!meta->iov_base) {
+					bt_shell_printf("Invalid metadata %s\n",
+							argv[5]);
+					return bt_shell_noninteractive_quit(
+								EXIT_FAILURE);
+				}
+			}
 
-				p = &preset->presets[j];
+			/* If configuration was left empty then ask the
+			 * parameters.
+			 */
+			if (!caps->iov_base || !caps->iov_len)
+				goto enter_cc;
 
-				if (default_preset && p != default_preset)
-					p->is_default = false;
+			bt_shell_prompt_input("QoS", "Enter Target Latency "
+						"(Low, Balance, High):",
+						custom_target_latency,
+						default_preset);
 
-				if (p->is_default)
-					bt_shell_printf("*%s\n", p->name);
-				else
-					bt_shell_printf("%s\n", p->name);
-			}
+			return;
 		}
+	} else if (ep && (ep->codec_preset))
+		print_preset(ep->codec_preset, ep->codec);
+	else
+		print_presets(preset);
+
+enter_cc:
+	if (default_preset && default_preset->custom) {
+		bt_shell_prompt_input("Codec", "Enter frequency (Khz):",
+					custom_frequency, default_preset);
+		return;
 	}
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
@@ -2391,26 +4342,74 @@ static const struct bt_shell_menu endpoint_menu = {
 	.entries = {
 	{ "list",         "[local]",    cmd_list_endpoints,
 						"List available endpoints" },
-	{ "show",         "<endpoint>", cmd_show_endpoint,
+	{ "show",         "[endpoint]", cmd_show_endpoint,
 						"Endpoint information",
 						endpoint_generator },
-	{ "register",     "<UUID> <codec> [capabilities...]",
+	{ "register",     "<UUID> <codec[:company]> [capabilities...]",
 						cmd_register_endpoint,
 						"Register Endpoint",
 						uuid_generator },
 	{ "unregister",   "<UUID/object>", cmd_unregister_endpoint,
 						"Register Endpoint",
 						local_endpoint_generator },
-	{ "config",       "<endpoint> <local endpoint> [preset]",
+	{ "config",       "<endpoint> [local endpoint] [preset]",
 						cmd_config_endpoint,
 						"Configure Endpoint",
 						endpoint_generator },
-	{ "presets",      "<UUID> [default]", cmd_presets_endpoint,
-						"List available presets",
+	{ "presets",      "<endpoint>/<UUID> [codec[:company]] [preset] "
+						"[codec config] [metadata]",
+						cmd_presets_endpoint,
+						"List or add presets",
 						uuid_generator },
 	{} },
 };
 
+static void endpoint_init_bcast(struct endpoint *ep)
+{
+	if (!strcmp(ep->uuid, BAA_SERVICE_UUID)) {
+		ep->locations = EP_SNK_LOCATIONS;
+		ep->supported_context = EP_SUPPORTED_SNK_CTXT;
+	} else {
+		ep->locations = EP_SRC_LOCATIONS;
+		ep->supported_context = EP_SUPPORTED_SRC_CTXT;
+	}
+}
+
+static void endpoint_init_ucast(struct endpoint *ep)
+{
+	if (!strcmp(ep->uuid, PAC_SINK_UUID)) {
+		ep->locations = EP_SNK_LOCATIONS;
+		ep->supported_context = EP_SUPPORTED_SNK_CTXT;
+		ep->context = EP_SNK_CTXT;
+	} else if (!strcmp(ep->uuid, PAC_SOURCE_UUID)) {
+		ep->locations = EP_SRC_LOCATIONS;
+		ep->supported_context = EP_SUPPORTED_SRC_CTXT;
+		ep->context = EP_SRC_CTXT;
+	}
+}
+
+static void endpoint_init_defaults(struct endpoint *ep)
+{
+	ep->preset = find_presets(ep->uuid, ep->codec, ep->vid, ep->cid);
+	ep->max_transports = UINT8_MAX;
+	ep->auto_accept = true;
+
+	if (!strcmp(ep->uuid, A2DP_SOURCE_UUID) ||
+			!strcmp(ep->uuid, A2DP_SOURCE_UUID))
+		return;
+
+	ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
+	ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
+
+	ep->broadcast = (strcmp(ep->uuid, BCAA_SERVICE_UUID) &&
+			strcmp(ep->uuid, BAA_SERVICE_UUID)) ? false : true;
+
+	if (ep->broadcast)
+		endpoint_init_bcast(ep);
+	else
+		endpoint_init_ucast(ep);
+}
+
 static struct endpoint *endpoint_new(const struct capabilities *cap)
 {
 	struct endpoint *ep;
@@ -2418,10 +4417,13 @@ static struct endpoint *endpoint_new(const struct capabilities *cap)
 	ep = new0(struct endpoint, 1);
 	ep->uuid = g_strdup(cap->uuid);
 	ep->codec = cap->codec_id;
-	ep->path = g_strdup_printf("%s/ep%u", BLUEZ_MEDIA_ENDPOINT_PATH,
-					g_list_length(local_endpoints));
+	ep->path = g_strdup_printf("%s/%s", BLUEZ_MEDIA_ENDPOINT_PATH,
+				cap->name);
 	/* Copy capabilities */
-	iov_append(&ep->caps, cap->data.iov_base, cap->data.iov_len);
+	ep->caps = util_iov_dup(&cap->data, 1);
+	/* Copy metadata */
+	ep->meta = util_iov_dup(&cap->meta, 1);
+
 	local_endpoints = g_list_append(local_endpoints, ep);
 
 	return ep;
@@ -2430,32 +4432,17 @@ static struct endpoint *endpoint_new(const struct capabilities *cap)
 static void register_endpoints(GDBusProxy *proxy)
 {
 	struct endpoint *ep;
-	DBusMessageIter iter, array;
-
-	if (!g_dbus_proxy_get_property(proxy, "SupportedUUIDs", &iter))
-		return;
-
-	dbus_message_iter_recurse(&iter, &array);
-	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
-		const char *uuid;
-		size_t i;
-
-		dbus_message_iter_get_basic(&array, &uuid);
-
-		for (i = 0; i < ARRAY_SIZE(caps); i++) {
-			const struct capabilities *cap = &caps[i];
+	size_t i;
 
-			if (strcasecmp(cap->uuid, uuid))
-				continue;
+	for (i = 0; i < ARRAY_SIZE(caps); i++) {
+		const struct capabilities *cap = &caps[i];
 
-			ep = endpoint_new(cap);
-			ep->auto_accept = true;
-			ep->cig = BT_ISO_QOS_CIG_UNSET;
-			ep->cis = BT_ISO_QOS_CIS_UNSET;
-			endpoint_register(ep);
-		}
+		if (!media_supports_uuid(proxy, cap->uuid))
+			continue;
 
-		dbus_message_iter_next(&array);
+		ep = endpoint_new(cap);
+		endpoint_init_defaults(ep);
+		endpoint_register(ep);
 	}
 }
 
@@ -2682,14 +4669,14 @@ static struct endpoint *find_ep_by_transport(const char *path)
 	for (l = local_endpoints; l; l = g_list_next(l)) {
 		struct endpoint *ep = l->data;
 
-		if (ep->transport && !strcmp(ep->transport, path))
+		if (queue_find(ep->transports, match_str, path))
 			return ep;
 	}
 
 	return NULL;
 }
 
-static struct endpoint *find_link_by_proxy(GDBusProxy *proxy)
+static GDBusProxy *find_link_by_proxy(GDBusProxy *proxy)
 {
 	DBusMessageIter iter, array;
 
@@ -2701,13 +4688,13 @@ static struct endpoint *find_link_by_proxy(GDBusProxy *proxy)
 	while (dbus_message_iter_get_arg_type(&array) ==
 				DBUS_TYPE_OBJECT_PATH) {
 		const char *transport;
-		struct endpoint *link;
 
 		dbus_message_iter_get_basic(&array, &transport);
 
-		link = find_ep_by_transport(transport);
-		if (link)
-			return link;
+		proxy = g_dbus_proxy_lookup(transports, NULL, transport,
+					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
+		if (proxy)
+			return proxy;
 	}
 
 	return NULL;
@@ -2719,6 +4706,8 @@ static void transport_close(struct transport *transport)
 		return;
 
 	close(transport->fd);
+	transport->fd = -1;
+
 	free(transport->filename);
 }
 
@@ -2726,6 +4715,7 @@ static void transport_free(void *data)
 {
 	struct transport *transport = data;
 
+	io_destroy(transport->timer_io);
 	io_destroy(transport->io);
 	free(transport);
 }
@@ -2748,21 +4738,27 @@ static bool transport_recv(struct io *io, void *user_data)
 	uint8_t buf[1024];
 	int ret, len;
 
-	ret = read(io_get_fd(io), buf, sizeof(buf));
+	ret = io_get_fd(io);
+	if (ret < 0) {
+		bt_shell_printf("io_get_fd() returned %d\n", ret);
+		return true;
+	}
+
+	ret = read(ret, buf, sizeof(buf));
 	if (ret < 0) {
 		bt_shell_printf("Failed to read: %s (%d)\n", strerror(errno),
 								-errno);
 		return true;
 	}
 
-	bt_shell_printf("[seq %d] recv: %u bytes\n", transport->seq, ret);
+	bt_shell_echo("[seq %d] recv: %u bytes", transport->seq, ret);
 
 	transport->seq++;
 
-	if (transport->fd) {
+	if (transport->filename) {
 		len = write(transport->fd, buf, ret);
 		if (len < 0)
-			bt_shell_printf("Unable to write: %s (%d)",
+			bt_shell_printf("Unable to write: %s (%d)\n",
 						strerror(errno), -errno);
 	}
 
@@ -2791,21 +4787,51 @@ static void transport_new(GDBusProxy *proxy, int sk, uint16_t mtu[2])
 	queue_push_tail(ios, transport);
 }
 
+static void ep_set_acquiring(struct endpoint *ep, GDBusProxy *proxy, bool value)
+{
+	bt_shell_printf("Transport %s %s\n", g_dbus_proxy_get_path(proxy),
+			value ? "acquiring" : "acquiring complete");
+
+	if (value && !ep->acquiring)
+		ep->acquiring = queue_new();
+
+	if (value)
+		queue_push_tail(ep->acquiring, proxy);
+	else
+		queue_remove(ep->acquiring, proxy);
+}
+
+static void transport_set_acquiring(GDBusProxy *proxy, bool value)
+{
+	struct endpoint *ep;
+	GDBusProxy *link;
+
+	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
+	if (!ep)
+		return;
+
+	ep_set_acquiring(ep, proxy, value);
+
+	if (!ep->broadcast) {
+		link = find_link_by_proxy(proxy);
+		if (link) {
+			ep = find_ep_by_transport(g_dbus_proxy_get_path(link));
+			if (!ep)
+				return;
+
+			ep_set_acquiring(ep, link, value);
+		}
+	}
+}
+
 static void acquire_reply(DBusMessage *message, void *user_data)
 {
 	GDBusProxy *proxy = user_data;
-	struct endpoint *ep, *link;
 	DBusError error;
 	int sk;
 	uint16_t mtu[2];
 
-	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
-	if (ep) {
-		ep->acquiring = false;
-		link = find_link_by_proxy(proxy);
-		if (link)
-			link->acquiring = false;
-	}
+	transport_set_acquiring(proxy, false);
 
 	dbus_error_init(&error);
 
@@ -2834,33 +4860,98 @@ static void acquire_reply(DBusMessage *message, void *user_data)
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
-static void transport_acquire(const char *input, void *user_data)
+static void select_reply(DBusMessage *message, void *user_data)
+{
+	DBusError error;
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message) == TRUE) {
+		bt_shell_printf("Failed to select: %s\n", error.name);
+		dbus_error_free(&error);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Select successful\n");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void unselect_reply(DBusMessage *message, void *user_data)
+{
+	DBusError error;
+
+	dbus_error_init(&error);
+
+	if (dbus_set_error_from_message(&error, message) == TRUE) {
+		bt_shell_printf("Failed to unselect: %s\n", error.name);
+		dbus_error_free(&error);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Unselect successful\n");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+
+static void prompt_acquire(const char *input, void *user_data)
 {
 	GDBusProxy *proxy = user_data;
-	struct endpoint *ep, *link;
 
 	if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) {
 		if (g_dbus_proxy_method_call(proxy, "Acquire", NULL,
-						acquire_reply, proxy, NULL))
+						acquire_reply, proxy, NULL)) {
+			transport_set_acquiring(proxy, true);
 			return;
+		}
 		bt_shell_printf("Failed acquire transport\n");
 	}
+}
+
+static void transport_acquire(GDBusProxy *proxy, bool prompt)
+{
+	struct endpoint *ep;
+	GDBusProxy *link;
 
-	/* Reset acquiring */
+	/* only attempt to acquire if transport is configured with a local
+	 * endpoint.
+	 */
 	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
-	if (ep) {
-		ep->acquiring = false;
+	if (!ep || queue_find(ep->acquiring, NULL, proxy))
+		return;
+
+	if (!ep->broadcast) {
 		link = find_link_by_proxy(proxy);
-		if (link)
-			link->acquiring = false;
+		if (link) {
+			ep = find_ep_by_transport(g_dbus_proxy_get_path(link));
+			/* if link already acquiring wait it to be complete */
+			if (!ep || queue_find(ep->acquiring, NULL, link))
+				return;
+		}
+	}
+
+	if (ep->auto_accept || !prompt) {
+		if (!prompt)
+			bt_shell_printf("auto acquiring...\n");
+		if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL,
+						acquire_reply, proxy, NULL)) {
+			bt_shell_printf("failed acquire transport\n");
+			return;
+		}
+
+		transport_set_acquiring(proxy, true);
+		return;
 	}
+
+	bt_shell_prompt_input(g_dbus_proxy_get_path(proxy), "acquire (yes/no):",
+					prompt_acquire, proxy);
 }
 
 static void transport_property_changed(GDBusProxy *proxy, const char *name,
 						DBusMessageIter *iter)
 {
 	char *str;
-	struct endpoint *ep, *link;
 
 	str = proxy_description(proxy, "Transport", COLORED_CHG);
 	print_iter(str, name, iter);
@@ -2874,38 +4965,7 @@ static void transport_property_changed(GDBusProxy *proxy, const char *name,
 	if (strcmp(str, "pending"))
 		return;
 
-	/* Only attempt to acquire if transport is configured with a local
-	 * endpoint.
-	 */
-	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
-	if (!ep || ep->acquiring)
-		return;
-
-	ep->acquiring = true;
-
-	link = find_link_by_proxy(proxy);
-	if (link) {
-		bt_shell_printf("Link %s found\n", link->transport);
-		/* If link already acquiring wait it to be complete */
-		if (link->acquiring)
-			return;
-		link->acquiring = true;
-	}
-
-	if (ep->auto_accept) {
-		bt_shell_printf("Auto Acquiring...\n");
-		if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL,
-						acquire_reply, proxy, NULL)) {
-			bt_shell_printf("Failed acquire transport\n");
-			ep->acquiring = false;
-			if (link)
-				link->acquiring = false;
-		}
-		return;
-	}
-
-	bt_shell_prompt_input(g_dbus_proxy_get_path(proxy), "Acquire (yes/no):",
-					transport_acquire, proxy);
+	transport_acquire(proxy, true);
 }
 
 static void property_changed(GDBusProxy *proxy, const char *name,
@@ -2927,27 +4987,103 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 		transport_property_changed(proxy, name, iter);
 }
 
-static char *transport_generator(const char *text, int state)
-{
-	return generic_generator(text, state, transports);
+static char *transport_generator(const char *text, int state)
+{
+	return generic_generator(text, state, transports);
+}
+
+static void cmd_list_transport(int argc, char *argv[])
+{
+	GList *l;
+
+	for (l = transports; l; l = g_list_next(l)) {
+		GDBusProxy *proxy = l->data;
+		print_transport(proxy, NULL);
+	}
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void print_configuration(GDBusProxy *proxy)
+{
+	DBusMessageIter iter, subiter;
+	const char *uuid;
+	uint8_t codec;
+	uint8_t *data;
+	int len;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (!g_dbus_proxy_get_property(proxy, "Codec", &iter))
+		return;
+
+	dbus_message_iter_get_basic(&iter, &codec);
+
+	if (!g_dbus_proxy_get_property(proxy, "Configuration", &iter))
+		return;
+
+	dbus_message_iter_recurse(&iter, &subiter);
+
+	dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+	if (!strcasecmp(uuid, A2DP_SINK_UUID) ||
+			!strcasecmp(uuid, A2DP_SOURCE_UUID)) {
+		print_a2dp_codec(codec, (void *)data, len);
+		return;
+	}
+
+	if (codec != LC3_ID) {
+		print_property(proxy, "Configuration");
+		return;
+	}
+
+	print_lc3_cfg(data, len);
+
+	if (!g_dbus_proxy_get_property(proxy, "Metadata", &iter))
+		return;
+
+	dbus_message_iter_recurse(&iter, &subiter);
+
+	dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+	print_lc3_meta(data, len);
 }
 
-static void cmd_list_transport(int argc, char *argv[])
+static void print_transport_properties(GDBusProxy *proxy)
 {
-	GList *l;
+	bt_shell_printf("Transport %s\n", g_dbus_proxy_get_path(proxy));
 
-	for (l = transports; l; l = g_list_next(l)) {
-		GDBusProxy *proxy = l->data;
-		print_transport(proxy, NULL);
-	}
+	print_property(proxy, "UUID");
+	print_property(proxy, "Codec");
+	print_configuration(proxy);
+	print_property(proxy, "Device");
+	print_property(proxy, "State");
+	print_property(proxy, "Delay");
+	print_property(proxy, "Volume");
+	print_property(proxy, "Endpoint");
+	print_property(proxy, "QoS");
+	print_property(proxy, "Location");
+	print_property(proxy, "Links");
+}
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+static void print_transports(void *data, void *user_data)
+{
+	print_transport_properties(data);
 }
 
 static void cmd_show_transport(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
 
+	/* Show all transports if no argument is given */
+	if (argc != 2) {
+		g_list_foreach(transports, print_transports, NULL);
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
 	proxy = g_dbus_proxy_lookup(transports, NULL, argv[1],
 					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
 	if (!proxy) {
@@ -2955,25 +5091,7 @@ static void cmd_show_transport(int argc, char *argv[])
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	bt_shell_printf("Transport %s\n", g_dbus_proxy_get_path(proxy));
-
-	print_property(proxy, "UUID");
-	print_property(proxy, "Codec");
-	print_property(proxy, "Configuration");
-	print_property(proxy, "Device");
-	print_property(proxy, "State");
-	print_property(proxy, "Delay");
-	print_property(proxy, "Volume");
-	print_property(proxy, "Endpoint");
-
-	print_property(proxy, "Interval");
-	print_property(proxy, "Framing");
-	print_property(proxy, "SDU");
-	print_property(proxy, "Retransmissions");
-	print_property(proxy, "Latency");
-	print_property(proxy, "Location");
-	print_property(proxy, "Metadata");
-	print_property(proxy, "Links");
+	print_transport_properties(proxy);
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
@@ -3010,14 +5128,172 @@ static void cmd_acquire_transport(int argc, char *argv[])
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
-		if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL,
-						acquire_reply, proxy, NULL)) {
-			bt_shell_printf("Failed acquire transport\n");
+		transport_acquire(proxy, false);
+	}
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void set_bcode_cb(const DBusError *error, void *user_data)
+{
+	GDBusProxy *proxy = user_data;
+
+	if (dbus_error_is_set(error)) {
+		bt_shell_printf("Failed to set broadcast code: %s\n",
+								error->name);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Setting broadcast code succeeded\n");
+
+	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
+				select_reply, proxy, NULL))
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+static void set_bcode(const char *input, void *user_data)
+{
+	GDBusProxy *proxy = user_data;
+	char *bcode;
+
+	if (!strcasecmp(input, "n") || !strcasecmp(input, "no"))
+		bcode = g_new0(char, 16);
+	else
+		bcode = g_strdup(input);
+
+	if (g_dbus_proxy_set_property_dict(proxy, "QoS",
+				set_bcode_cb, user_data,
+				NULL, "BCode", DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+				strlen(bcode), bcode, NULL) == FALSE) {
+		bt_shell_printf("Setting broadcast code failed\n");
+		g_free(bcode);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	g_free(bcode);
+}
+
+static void transport_select(void *data, void *user_data)
+{
+	GDBusProxy *proxy = data;
+	DBusMessageIter iter, array, entry, value;
+	unsigned char encryption;
+	const char *key;
+
+	if (g_dbus_proxy_get_property(proxy, "QoS", &iter) == FALSE)
+		return;
+
+	dbus_message_iter_recurse(&iter, &array);
+
+	while (dbus_message_iter_get_arg_type(&array) !=
+						DBUS_TYPE_INVALID) {
+		dbus_message_iter_recurse(&array, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		if (!strcasecmp(key, "Encryption")) {
+			dbus_message_iter_next(&entry);
+			dbus_message_iter_recurse(&entry, &value);
+			dbus_message_iter_get_basic(&value, &encryption);
+			if (encryption == 1) {
+				bt_shell_prompt_input("",
+					"Enter brocast code[value/no]:",
+					set_bcode, proxy);
+				return;
+			}
+			break;
+		}
+		dbus_message_iter_next(&array);
+	}
+
+	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
+					select_reply, proxy, NULL)) {
+		bt_shell_printf("Failed select transport\n");
+		return;
+	}
+}
+
+static void transport_unselect(GDBusProxy *proxy, bool prompt)
+{
+	if (!g_dbus_proxy_method_call(proxy, "Unselect", NULL,
+					unselect_reply, proxy, NULL)) {
+		bt_shell_printf("Failed unselect transport\n");
+		return;
+	}
+}
+
+static void set_links_cb(const DBusError *error, void *user_data)
+{
+	GDBusProxy *link = user_data;
+
+	if (dbus_error_is_set(error)) {
+		bt_shell_printf("Failed to set link %s: %s\n",
+						g_dbus_proxy_get_path(link),
+						error->name);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Successfully linked transport %s\n",
+						g_dbus_proxy_get_path(link));
+}
+
+static void cmd_select_transport(int argc, char *argv[])
+{
+	GDBusProxy *proxy = NULL, *link;
+	struct queue *links = queue_new();
+	const char *path;
+	int i;
+
+	for (i = 1; i < argc; i++) {
+		link = g_dbus_proxy_lookup(transports, NULL, argv[i],
+					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
+		if (!link) {
+			bt_shell_printf("Transport %s not found\n", argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (find_transport(link)) {
+			bt_shell_printf("Transport %s already acquired\n",
+					argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		queue_push_tail(links, link);
+
+		if (!proxy) {
+			proxy = link;
+			continue;
+		}
+
+		path = g_dbus_proxy_get_path(link);
+
+		if (g_dbus_proxy_set_property_array(proxy, "Links",
+					DBUS_TYPE_OBJECT_PATH,
+					&path, 1, set_links_cb,
+					link, NULL) == FALSE) {
+			bt_shell_printf("Linking transport %s failed\n",
+								argv[i]);
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 	}
 
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	queue_foreach(links, transport_select, NULL);
+}
+
+static void cmd_unselect_transport(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+	int i;
+
+	for (i = 1; i < argc; i++) {
+		proxy = g_dbus_proxy_lookup(transports, NULL, argv[i],
+					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
+		if (!proxy) {
+			bt_shell_printf("Transport %s not found\n", argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		transport_unselect(proxy, false);
+	}
 }
 
 static void release_reply(DBusMessage *message, void *user_data)
@@ -3090,145 +5366,253 @@ static int open_file(const char *filename, int flags)
 	return fd;
 }
 
-#define NSEC_USEC(_t) (_t / 1000L)
-#define SEC_USEC(_t)  (_t  * 1000000L)
-#define TS_USEC(_ts)  (SEC_USEC((_ts)->tv_sec) + NSEC_USEC((_ts)->tv_nsec))
-
-static void send_wait(struct timespec *t_start, uint32_t us)
+static int elapsed_time(bool reset, int *secs, int *nsecs)
 {
-	struct timespec t_now;
-	struct timespec t_diff;
-	int64_t delta_us;
+	static struct timespec start;
+	struct timespec curr;
 
-	/* Skip sleep at start */
-	if (!us)
-		return;
+	if (reset) {
+		if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) {
+			bt_shell_printf("clock_gettime: %s (%d)",
+						strerror(errno), errno);
+			return -errno;
+		}
+	}
 
-	if (clock_gettime(CLOCK_MONOTONIC, &t_now) < 0) {
+	if (clock_gettime(CLOCK_MONOTONIC, &curr) < 0) {
 		bt_shell_printf("clock_gettime: %s (%d)", strerror(errno),
-								errno);
-		return;
+						errno);
+		return -errno;
 	}
 
-	t_diff.tv_sec = t_now.tv_sec - t_start->tv_sec;
-	t_diff.tv_nsec = t_now.tv_nsec - t_start->tv_nsec;
-
-	delta_us = us - TS_USEC(&t_diff);
-
-	if (delta_us < 0) {
-		bt_shell_printf("Send is behind: %" PRId64 " us - skip sleep",
-							delta_us);
-		delta_us = 1000;
+	*secs = curr.tv_sec - start.tv_sec;
+	*nsecs = curr.tv_nsec - start.tv_nsec;
+	if (*nsecs < 0) {
+		(*secs)--;
+		*nsecs += 1000000000;
 	}
 
-	usleep(delta_us);
-
-	if (clock_gettime(CLOCK_MONOTONIC, t_start) < 0)
-		bt_shell_printf("clock_gettime: %s (%d)", strerror(errno),
-								errno);
+	return 0;
 }
 
-static int transport_send(struct transport *transport, int fd,
-					struct bt_iso_qos *qos)
+static int transport_send_seq(struct transport *transport, int fd, uint32_t num)
 {
-	struct timespec t_start;
 	uint8_t *buf;
-	uint32_t num = 0;
+	uint32_t i;
 
-	if (qos && clock_gettime(CLOCK_MONOTONIC, &t_start) < 0) {
-		bt_shell_printf("clock_gettime: %s (%d)", strerror(errno),
-								errno);
-		return -errno;
-	}
+	if (!num)
+		return 0;
 
 	buf = malloc(transport->mtu[1]);
-	if (!buf) {
-		bt_shell_printf("malloc: %s (%d)", strerror(errno), errno);
+	if (!buf)
 		return -ENOMEM;
-	}
-
-	/* num of packets = latency (ms) / interval (us) */
-	if (qos)
-		num = (qos->out.latency * 1000 / qos->out.interval);
 
-	for (transport->seq = 0; ; transport->seq++) {
+	for (i = 0; i < num; i++, transport->seq++) {
 		ssize_t ret;
-		int queued;
+		int secs = 0, nsecs = 0;
+		off_t offset;
 
 		ret = read(fd, buf, transport->mtu[1]);
 		if (ret <= 0) {
 			if (ret < 0)
 				bt_shell_printf("read failed: %s (%d)",
 						strerror(errno), errno);
-			close(fd);
+			free(buf);
 			return ret;
 		}
 
 		ret = send(transport->sk, buf, ret, 0);
 		if (ret <= 0) {
-			bt_shell_printf("Send failed: %s (%d)",
+			bt_shell_printf("send failed: %s (%d)",
 							strerror(errno), errno);
+			free(buf);
 			return -errno;
 		}
 
-		ioctl(transport->sk, TIOCOUTQ, &queued);
-
-		bt_shell_printf("[seq %d] send: %zd bytes "
-				"(TIOCOUTQ %d bytes)\n",
-				transport->seq, ret, queued);
+		elapsed_time(!transport->seq, &secs, &nsecs);
 
-		if (qos) {
-			if (transport->seq && !((transport->seq + 1) % num))
-				send_wait(&t_start, num * qos->out.interval);
+		if (!transport->seq && fstat(fd, &transport->stat) < 0) {
+			bt_shell_printf("fstat failed: %s (%d)",
+							strerror(errno), errno);
+			free(buf);
+			return -errno;
 		}
+
+		offset = lseek(fd, 0, SEEK_CUR);
+
+		bt_shell_echo("[seq %d %d.%03ds] send: %zd/%zd bytes",
+				transport->seq, secs,
+				(nsecs + 500000) / 1000000,
+				offset, transport->stat.st_size);
 	}
 
 	free(buf);
+
+	return i;
 }
 
-static void cmd_send_transport(int argc, char *argv[])
+static bool transport_timer_read(struct io *io, void *user_data)
 {
-	GDBusProxy *proxy;
-	struct transport *transport;
-	int fd, err;
+	struct transport *transport = user_data;
 	struct bt_iso_qos qos;
 	socklen_t len;
+	int ret, fd;
+	uint64_t exp;
 
-	proxy = g_dbus_proxy_lookup(transports, NULL, argv[1],
-					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
-	if (!proxy) {
-		bt_shell_printf("Transport %s not found\n", argv[1]);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
+	if (transport->fd < 0)
+		return false;
 
-	transport = find_transport(proxy);
-	if (!transport) {
-		bt_shell_printf("Transport %s not acquired\n", argv[1]);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	fd = io_get_fd(io);
+	if (fd < 0) {
+		bt_shell_printf("io_get_fd() returned %d\n", fd);
+		return false;
 	}
 
-	if (transport->sk < 0) {
-		bt_shell_printf("No Transport Socked found\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	ret = read(fd, &exp, sizeof(exp));
+	if (ret < 0) {
+		bt_shell_printf("Failed to read: %s (%d)\n", strerror(errno),
+								-errno);
+		return false;
 	}
 
-	fd = open_file(argv[2], O_RDONLY);
-
-	bt_shell_printf("Sending ...\n");
-
 	/* Read QoS if available */
 	memset(&qos, 0, sizeof(qos));
 	len = sizeof(qos);
 	if (getsockopt(transport->sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos,
-							&len) < 0)
-		err = transport_send(transport, fd, NULL);
-	else
-		err = transport_send(transport, fd, &qos);
+							&len) < 0) {
+		bt_shell_printf("Failed to getsockopt(BT_ISO_QOS): %s (%d)\n",
+					strerror(errno), -errno);
+		return false;
+	}
+
+	ret = transport_send_seq(transport, transport->fd, transport->num);
+	if (ret < 0) {
+		bt_shell_printf("Unable to send: %s (%d)\n",
+					strerror(-ret), ret);
+		return false;
+	}
 
-	close(fd);
+	if (!ret) {
+		transport_close(transport);
+		return false;
+	}
 
-	if (err < 0)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	return true;
+}
+
+static int transport_send(struct transport *transport, int fd,
+					struct bt_iso_io_qos *qos)
+{
+	struct itimerspec ts;
+	int timer_fd;
+
+	transport->seq = 0;
+
+	if (!qos)
+		return transport_send_seq(transport, fd, UINT32_MAX);
+
+	if (transport->fd >= 0)
+		return -EALREADY;
+
+	timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
+	if (timer_fd < 0)
+		return -errno;
+
+	/* Send data in bursts of
+	 * num = ROUND_CLOSEST(Transport_Latency (ms) / SDU_Interval (us))
+	 * with average data rate = 1 packet / SDU_Interval
+	 */
+	transport->num = ROUND_CLOSEST(qos->latency * 1000, qos->interval);
+	if (!transport->num)
+		transport->num = 1;
+
+	memset(&ts, 0, sizeof(ts));
+	ts.it_value.tv_nsec = 1;
+	ts.it_interval.tv_nsec = transport->num * qos->interval * 1000;
+
+	if (timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &ts, NULL) < 0) {
+		close(timer_fd);
+		return -errno;
+	}
+
+	transport->fd = fd;
+	transport->timer_io = io_new(timer_fd);
+
+	io_set_read_handler(transport->timer_io, transport_timer_read,
+						transport, NULL);
+
+	/* One extra packet to buffers immediately */
+	return transport_send_seq(transport, fd, 1);
+}
+
+static void cmd_send_transport(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+	struct transport *transport;
+	int fd = -1, err;
+	struct bt_iso_qos qos;
+	socklen_t len;
+	int i;
+
+	for (i = 1; i < argc; i++) {
+		proxy = g_dbus_proxy_lookup(transports, NULL, argv[i],
+					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
+		if (!proxy) {
+			bt_shell_printf("Transport %s not found\n", argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		transport = find_transport(proxy);
+		if (!transport) {
+			bt_shell_printf("Transport %s not acquired\n", argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (transport->sk < 0) {
+			bt_shell_printf("No Transport Socked found\n");
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		if (i + 1 < argc) {
+			fd = open_file(argv[++i], O_RDONLY);
+			if (fd < 0)
+				return bt_shell_noninteractive_quit(
+								EXIT_FAILURE);
+		}
+
+		bt_shell_printf("Sending ...\n");
+
+		/* Read QoS if available */
+		memset(&qos, 0, sizeof(qos));
+		len = sizeof(qos);
+		if (getsockopt(transport->sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos,
+							&len) < 0) {
+			bt_shell_printf("Unable to getsockopt(BT_ISO_QOS): %s",
+							strerror(errno));
+			err = transport_send(transport, fd, NULL);
+		} else {
+			struct sockaddr_iso addr;
+			socklen_t optlen = sizeof(addr);
+
+			err = getpeername(transport->sk,
+					(struct sockaddr *)&addr, &optlen);
+			if (!err) {
+				if (!(bacmp(&addr.iso_bdaddr, BDADDR_ANY)))
+					err = transport_send(transport, fd,
+							     &qos.bcast.out);
+				else
+					err = transport_send(transport, fd,
+							     &qos.ucast.out);
+			}
+		}
+
+		if (err < 0) {
+			bt_shell_printf("Unable to send: %s (%d)\n",
+						strerror(-err), -err);
+			close(fd);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+	}
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
@@ -3321,7 +5705,7 @@ static const struct bt_shell_menu transport_menu = {
 	.entries = {
 	{ "list",         NULL,    cmd_list_transport,
 						"List available transports" },
-	{ "show",        "<transport>", cmd_show_transport,
+	{ "show",        "[transport]", cmd_show_transport,
 						"Transport information",
 						transport_generator },
 	{ "acquire",     "<transport> [transport1...]", cmd_acquire_transport,
@@ -3330,13 +5714,22 @@ static const struct bt_shell_menu transport_menu = {
 	{ "release",     "<transport> [transport1...]", cmd_release_transport,
 						"Release Transport",
 						transport_generator },
-	{ "send",        "<transport> <filename>", cmd_send_transport,
-						"Send contents of a file" },
+	{ "send",        "<transport> <filename> [transport1...]",
+						cmd_send_transport,
+						"Send contents of a file",
+						transport_generator },
 	{ "receive",     "<transport> [filename]", cmd_receive_transport,
-						"Get/Set file to receive" },
+						"Get/Set file to receive",
+						transport_generator },
 	{ "volume",      "<transport> [value]",	cmd_volume_transport,
 						"Get/Set transport volume",
 						transport_generator },
+	{ "select",      "<transport> [transport1...]", cmd_select_transport,
+						"Select Transport",
+						transport_generator },
+	{ "unselect",    "<transport> [transport1...]", cmd_unselect_transport,
+						"Unselect Transport",
+						transport_generator },
 	{} },
 };
 
diff --git a/client/print.c b/client/print.c
new file mode 100644
index 0000000..39f8567
--- /dev/null
+++ b/client/print.c
@@ -0,0 +1,238 @@
+
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "gdbus/gdbus.h"
+
+#include "src/shared/util.h"
+#include "src/shared/shell.h"
+#include "print.h"
+
+static void print_fixed_iter(const char *label, const char *name,
+						DBusMessageIter *iter)
+{
+	dbus_bool_t *valbool;
+	dbus_uint32_t *valu32;
+	dbus_uint16_t *valu16;
+	dbus_int16_t *vals16;
+	unsigned char *byte;
+	int len;
+
+	switch (dbus_message_iter_get_arg_type(iter)) {
+	case DBUS_TYPE_BOOLEAN:
+		dbus_message_iter_get_fixed_array(iter, &valbool, &len);
+
+		if (len <= 0)
+			return;
+
+		bt_shell_printf("%s%s:\n", label, name);
+		bt_shell_hexdump((void *)valbool, len * sizeof(*valbool));
+
+		break;
+	case DBUS_TYPE_UINT32:
+		dbus_message_iter_get_fixed_array(iter, &valu32, &len);
+
+		if (len <= 0)
+			return;
+
+		bt_shell_printf("%s%s:\n", label, name);
+		bt_shell_hexdump((void *)valu32, len * sizeof(*valu32));
+
+		break;
+	case DBUS_TYPE_UINT16:
+		dbus_message_iter_get_fixed_array(iter, &valu16, &len);
+
+		if (len <= 0)
+			return;
+
+		bt_shell_printf("%s%s:\n", label, name);
+		bt_shell_hexdump((void *)valu16, len * sizeof(*valu16));
+
+		break;
+	case DBUS_TYPE_INT16:
+		dbus_message_iter_get_fixed_array(iter, &vals16, &len);
+
+		if (len <= 0)
+			return;
+
+		bt_shell_printf("%s%s:\n", label, name);
+		bt_shell_hexdump((void *)vals16, len * sizeof(*vals16));
+
+		break;
+	case DBUS_TYPE_BYTE:
+		dbus_message_iter_get_fixed_array(iter, &byte, &len);
+
+		if (len <= 0)
+			return;
+
+		bt_shell_printf("%s%s:\n", label, name);
+		bt_shell_hexdump((void *)byte, len * sizeof(*byte));
+
+		break;
+	default:
+		return;
+	};
+}
+
+void print_iter(const char *label, const char *name, DBusMessageIter *iter)
+{
+	dbus_bool_t valbool;
+	dbus_uint32_t valu32;
+	dbus_uint16_t valu16;
+	dbus_int16_t vals16;
+	unsigned char byte;
+	const char *valstr;
+	DBusMessageIter subiter;
+	char *entry;
+
+	if (iter == NULL) {
+		bt_shell_printf("%s%s is nil\n", label, name);
+		return;
+	}
+
+	switch (dbus_message_iter_get_arg_type(iter)) {
+	case DBUS_TYPE_INVALID:
+		bt_shell_printf("%s%s is invalid\n", label, name);
+		break;
+	case DBUS_TYPE_STRING:
+		if (!strcasecmp(name, "UUID")) {
+			dbus_message_iter_get_basic(iter, &valstr);
+			print_uuid(label, name, valstr);
+			break;
+		}
+		/* fall through */
+	case DBUS_TYPE_OBJECT_PATH:
+		dbus_message_iter_get_basic(iter, &valstr);
+		bt_shell_printf("%s%s: %s\n", label, name, valstr);
+		break;
+	case DBUS_TYPE_BOOLEAN:
+		dbus_message_iter_get_basic(iter, &valbool);
+		bt_shell_printf("%s%s: %s\n", label, name,
+					valbool == TRUE ? "yes" : "no");
+		break;
+	case DBUS_TYPE_UINT32:
+		dbus_message_iter_get_basic(iter, &valu32);
+		bt_shell_printf("%s%s: 0x%08x (%d)\n", label, name, valu32,
+								valu32);
+		break;
+	case DBUS_TYPE_UINT16:
+		dbus_message_iter_get_basic(iter, &valu16);
+		bt_shell_printf("%s%s: 0x%04x (%d)\n", label, name, valu16,
+								valu16);
+		break;
+	case DBUS_TYPE_INT16:
+		dbus_message_iter_get_basic(iter, &vals16);
+		bt_shell_printf("%s%s: 0x%04x (%d)\n", label, name, vals16,
+								vals16);
+		break;
+	case DBUS_TYPE_BYTE:
+		dbus_message_iter_get_basic(iter, &byte);
+		bt_shell_printf("%s%s: 0x%02x (%d)\n", label, name, byte, byte);
+		break;
+	case DBUS_TYPE_VARIANT:
+		dbus_message_iter_recurse(iter, &subiter);
+		print_iter(label, name, &subiter);
+		break;
+	case DBUS_TYPE_ARRAY:
+		dbus_message_iter_recurse(iter, &subiter);
+
+		if (dbus_type_is_fixed(
+				dbus_message_iter_get_arg_type(&subiter))) {
+			print_fixed_iter(label, name, &subiter);
+			break;
+		}
+
+		while (dbus_message_iter_get_arg_type(&subiter) !=
+							DBUS_TYPE_INVALID) {
+			print_iter(label, name, &subiter);
+			dbus_message_iter_next(&subiter);
+		}
+		break;
+	case DBUS_TYPE_DICT_ENTRY:
+		dbus_message_iter_recurse(iter, &subiter);
+
+		if (dbus_message_iter_get_arg_type(&subiter) ==
+						DBUS_TYPE_STRING) {
+			dbus_message_iter_get_basic(&subiter, &valstr);
+			entry = g_strconcat(name, ".", valstr, NULL);
+		} else {
+			entry = g_strconcat(name, ".Key", NULL);
+			print_iter(label, entry, &subiter);
+			g_free(entry);
+
+			entry = g_strconcat(name, ".Value", NULL);
+		}
+
+		dbus_message_iter_next(&subiter);
+		print_iter(label, entry, &subiter);
+		g_free(entry);
+		break;
+	default:
+		bt_shell_printf("%s%s has unsupported type\n", label, name);
+		break;
+	}
+}
+
+void print_property_with_label(GDBusProxy *proxy, const char *name,
+					const char *label)
+{
+	DBusMessageIter iter;
+
+	if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
+		return;
+
+	print_iter("\t", label ? label : name, &iter);
+}
+
+void print_property(GDBusProxy *proxy, const char *name)
+{
+	print_property_with_label(proxy, name, NULL);
+}
+
+void print_uuid(const char *label, const char *name, const char *uuid)
+{
+	const char *text;
+
+	text = bt_uuidstr_to_str(uuid);
+	if (text) {
+		char str[26];
+		unsigned int n;
+
+		str[sizeof(str) - 1] = '\0';
+
+		n = snprintf(str, sizeof(str), "%s", text);
+		if (n > sizeof(str) - 1) {
+			str[sizeof(str) - 2] = '.';
+			str[sizeof(str) - 3] = '.';
+			if (str[sizeof(str) - 4] == ' ')
+				str[sizeof(str) - 4] = '.';
+
+			n = sizeof(str) - 1;
+		}
+
+		bt_shell_printf("%s%s: %s%*c(%s)\n", label, name, str, 26 - n,
+								' ', uuid);
+	} else
+		bt_shell_printf("%s%s: %*c(%s)\n", label, name, 26, ' ', uuid);
+}
diff --git a/client/print.h b/client/print.h
new file mode 100644
index 0000000..56bcce1
--- /dev/null
+++ b/client/print.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022 Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+void print_property(GDBusProxy *proxy, const char *name);
+void print_property_with_label(GDBusProxy *proxy, const char *name,
+					const char *label);
+void print_iter(const char *label, const char *name, DBusMessageIter *iter);
+void print_uuid(const char *label, const char *name, const char *uuid);
diff --git a/compile b/compile
new file mode 100755
index 0000000..df363c8
--- /dev/null
+++ b/compile
@@ -0,0 +1,348 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.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, 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, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""	$nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+	# lazily determine how to convert abs files
+	case `uname -s` in
+	  MINGW*)
+	    file_conv=mingw
+	    ;;
+	  CYGWIN* | MSYS*)
+	    file_conv=cygwin
+	    ;;
+	  *)
+	    file_conv=wine
+	    ;;
+	esac
+      fi
+      case $file_conv/,$2, in
+	*,$file_conv,*)
+	  ;;
+	mingw/*)
+	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+	  ;;
+	cygwin/* | msys/*)
+	  file=`cygpath -m "$file" || echo "$file"`
+	  ;;
+	wine/*)
+	  file=`winepath -w "$file" || echo "$file"`
+	  ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+	-o)
+	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
+	  eat=1
+	  case $2 in
+	    *.o | *.[oO][bB][jJ])
+	      func_file_conv "$2"
+	      set x "$@" -Fo"$file"
+	      shift
+	      ;;
+	    *)
+	      func_file_conv "$2"
+	      set x "$@" -Fe"$file"
+	      shift
+	      ;;
+	  esac
+	  ;;
+	-I)
+	  eat=1
+	  func_file_conv "$2" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-I*)
+	  func_file_conv "${1#-I}" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-l)
+	  eat=1
+	  func_cl_dashl "$2"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-l*)
+	  func_cl_dashl "${1#-l}"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-L)
+	  eat=1
+	  func_cl_dashL "$2"
+	  ;;
+	-L*)
+	  func_cl_dashL "${1#-L}"
+	  ;;
+	-static)
+	  shared=false
+	  ;;
+	-Wl,*)
+	  arg=${1#-Wl,}
+	  save_ifs="$IFS"; IFS=','
+	  for flag in $arg; do
+	    IFS="$save_ifs"
+	    linker_opts="$linker_opts $flag"
+	  done
+	  IFS="$save_ifs"
+	  ;;
+	-Xlinker)
+	  eat=1
+	  linker_opts="$linker_opts $2"
+	  ;;
+	-*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+	  func_file_conv "$1"
+	  set x "$@" -Tp"$file"
+	  shift
+	  ;;
+	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+	  func_file_conv "$1" mingw
+	  set x "$@" "$file"
+	  shift
+	  ;;
+	*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+  icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as 'compile cc -o foo foo.c'.
+	# So we strip '-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..7f76b62
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1754 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2022 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-09'
+
+# This file 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 3 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, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX.  However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2022 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+# Just in case it came from the environment.
+GUESS=
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+    # prevent multiple calls if $tmp is already set
+    test "$tmp" && return 0
+    : "${TMPDIR=/tmp}"
+    # shellcheck disable=SC2039,SC3028
+    { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+	{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+    dummy=$tmp/dummy
+    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+	,,)    echo "int x;" > "$dummy.c"
+	       for driver in cc gcc c89 c99 ; do
+		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+		       CC_FOR_BUILD=$driver
+		       break
+		   fi
+	       done
+	       if test x"$CC_FOR_BUILD" = x ; then
+		   CC_FOR_BUILD=no_compiler_found
+	       fi
+	       ;;
+	,,*)   CC_FOR_BUILD=$CC ;;
+	,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+    esac
+}
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if test -f /.attbin/uname ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case $UNAME_SYSTEM in
+Linux|GNU|GNU/*)
+	LIBC=unknown
+
+	set_cc_for_build
+	cat <<-EOF > "$dummy.c"
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#elif defined(__GLIBC__)
+	LIBC=gnu
+	#else
+	#include <stdarg.h>
+	/* First heuristic to detect musl libc.  */
+	#ifdef __DEFINED_va_list
+	LIBC=musl
+	#endif
+	#endif
+	EOF
+	cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	eval "$cc_set_libc"
+
+	# Second heuristic to detect musl libc.
+	if [ "$LIBC" = unknown ] &&
+	   command -v ldd >/dev/null &&
+	   ldd --version 2>&1 | grep -q ^musl; then
+		LIBC=musl
+	fi
+
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	if [ "$LIBC" = unknown ]; then
+		LIBC=gnu
+	fi
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+	    /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+	    echo unknown)`
+	case $UNAME_MACHINE_ARCH in
+	    aarch64eb) machine=aarch64_be-unknown ;;
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
+	    *) machine=$UNAME_MACHINE_ARCH-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently (or will in the future) and ABI.
+	case $UNAME_MACHINE_ARCH in
+	    earm*)
+		os=netbsdelf
+		;;
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# Determine ABI tags.
+	case $UNAME_MACHINE_ARCH in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case $UNAME_VERSION in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	GUESS=$machine-${os}${release}${abi-}
+	;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+	;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+	;;
+    *:SecBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+	GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+	;;
+    *:LibertyBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+	;;
+    *:MidnightBSD:*:*)
+	GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+	;;
+    *:ekkoBSD:*:*)
+	GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+	;;
+    *:SolidBSD:*:*)
+	GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+	;;
+    *:OS108:*:*)
+	GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+	;;
+    macppc:MirBSD:*:*)
+	GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+	;;
+    *:MirBSD:*:*)
+	GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+	;;
+    *:Sortix:*:*)
+	GUESS=$UNAME_MACHINE-unknown-sortix
+	;;
+    *:Twizzler:*:*)
+	GUESS=$UNAME_MACHINE-unknown-twizzler
+	;;
+    *:Redox:*:*)
+	GUESS=$UNAME_MACHINE-unknown-redox
+	;;
+    mips:OSF1:*.*)
+	GUESS=mips-dec-osf1
+	;;
+    alpha:OSF1:*:*)
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	trap '' 0
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case $ALPHA_CPU_TYPE in
+	    "EV4 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE=alpha ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE=alphaev5 ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE=alphaev56 ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE=alphapca56 ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE=alphapca57 ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE=alphaev6 ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE=alphaev67 ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE=alphaev69 ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE=alphaev7 ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE=alphaev79 ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+	;;
+    Amiga*:UNIX_System_V:4.0:*)
+	GUESS=m68k-unknown-sysv4
+	;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	GUESS=$UNAME_MACHINE-unknown-amigaos
+	;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	GUESS=$UNAME_MACHINE-unknown-morphos
+	;;
+    *:OS/390:*:*)
+	GUESS=i370-ibm-openedition
+	;;
+    *:z/VM:*:*)
+	GUESS=s390-ibm-zvmoe
+	;;
+    *:OS400:*:*)
+	GUESS=powerpc-ibm-os400
+	;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	GUESS=arm-acorn-riscix$UNAME_RELEASE
+	;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	GUESS=arm-unknown-riscos
+	;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	GUESS=hppa1.1-hitachi-hiuxmpp
+	;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	case `(/bin/universe) 2>/dev/null` in
+	    att) GUESS=pyramid-pyramid-sysv3 ;;
+	    *)   GUESS=pyramid-pyramid-bsd   ;;
+	esac
+	;;
+    NILE*:*:*:dcosx)
+	GUESS=pyramid-pyramid-svr4
+	;;
+    DRS?6000:unix:4.0:6*)
+	GUESS=sparc-icl-nx6
+	;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) GUESS=sparc-icl-nx7 ;;
+	esac
+	;;
+    s390x:SunOS:*:*)
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+	;;
+    sun4H:SunOS:5.*:*)
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-hal-solaris2$SUN_REL
+	;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-sun-solaris2$SUN_REL
+	;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	GUESS=i386-pc-auroraux$UNAME_RELEASE
+	;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	set_cc_for_build
+	SUN_ARCH=i386
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH=x86_64
+	    fi
+	fi
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+	;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-sun-solaris3$SUN_REL
+	;;
+    sun4*:SunOS:*:*)
+	case `/usr/bin/arch -k` in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+	GUESS=sparc-sun-sunos$SUN_REL
+	;;
+    sun3*:SunOS:*:*)
+	GUESS=m68k-sun-sunos$UNAME_RELEASE
+	;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+	case `/bin/arch` in
+	    sun3)
+		GUESS=m68k-sun-sunos$UNAME_RELEASE
+		;;
+	    sun4)
+		GUESS=sparc-sun-sunos$UNAME_RELEASE
+		;;
+	esac
+	;;
+    aushp:SunOS:*:*)
+	GUESS=sparc-auspex-sunos$UNAME_RELEASE
+	;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	GUESS=m68k-milan-mint$UNAME_RELEASE
+	;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	GUESS=m68k-hades-mint$UNAME_RELEASE
+	;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	GUESS=m68k-unknown-mint$UNAME_RELEASE
+	;;
+    m68k:machten:*:*)
+	GUESS=m68k-apple-machten$UNAME_RELEASE
+	;;
+    powerpc:machten:*:*)
+	GUESS=powerpc-apple-machten$UNAME_RELEASE
+	;;
+    RISC*:Mach:*:*)
+	GUESS=mips-dec-mach_bsd4.3
+	;;
+    RISC*:ULTRIX:*:*)
+	GUESS=mips-dec-ultrix$UNAME_RELEASE
+	;;
+    VAX*:ULTRIX*:*:*)
+	GUESS=vax-dec-ultrix$UNAME_RELEASE
+	;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	GUESS=clipper-intergraph-clix$UNAME_RELEASE
+	;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	set_cc_for_build
+	sed 's/^	//' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	GUESS=mips-mips-riscos$UNAME_RELEASE
+	;;
+    Motorola:PowerMAX_OS:*:*)
+	GUESS=powerpc-motorola-powermax
+	;;
+    Motorola:*:4.3:PL8-*)
+	GUESS=powerpc-harris-powermax
+	;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	GUESS=powerpc-harris-powermax
+	;;
+    Night_Hawk:Power_UNIX:*:*)
+	GUESS=powerpc-harris-powerunix
+	;;
+    m88k:CX/UX:7*:*)
+	GUESS=m88k-harris-cxux7
+	;;
+    m88k:*:4*:R4*)
+	GUESS=m88k-motorola-sysv4
+	;;
+    m88k:*:3*:R3*)
+	GUESS=m88k-motorola-sysv3
+	;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
+	then
+	    if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+	       test "$TARGET_BINARY_INTERFACE"x = x
+	    then
+		GUESS=m88k-dg-dgux$UNAME_RELEASE
+	    else
+		GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
+	    fi
+	else
+	    GUESS=i586-dg-dgux$UNAME_RELEASE
+	fi
+	;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	GUESS=m88k-dolphin-sysv3
+	;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	GUESS=m88k-motorola-sysv3
+	;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	GUESS=m88k-tektronix-sysv3
+	;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	GUESS=m68k-tektronix-bsd
+	;;
+    *:IRIX*:*:*)
+	IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+	GUESS=mips-sgi-irix$IRIX_REL
+	;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	GUESS=romp-ibm-aix    # uname -m gives an 8 hex-code CPU id
+	;;                    # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	GUESS=i386-ibm-aix
+	;;
+    ia64:AIX:*:*)
+	if test -x /usr/bin/oslevel ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+	fi
+	GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+	;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		set_cc_for_build
+		sed 's/^		//' << EOF > "$dummy.c"
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+		then
+			GUESS=$SYSTEM_NAME
+		else
+			GUESS=rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		GUESS=rs6000-ibm-aix3.2.4
+	else
+		GUESS=rs6000-ibm-aix3.2
+	fi
+	;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if test -x /usr/bin/lslpp ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+	else
+		IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+	fi
+	GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+	;;
+    *:AIX:*:*)
+	GUESS=rs6000-ibm-aix
+	;;
+    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+	GUESS=romp-ibm-bsd4.4
+	;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	GUESS=romp-ibm-bsd$UNAME_RELEASE    # 4.3 with uname added to
+	;;                                  # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	GUESS=rs6000-bull-bosx
+	;;
+    DPX/2?00:B.O.S.:*:*)
+	GUESS=m68k-bull-sysv3
+	;;
+    9000/[34]??:4.3bsd:1.*:*)
+	GUESS=m68k-hp-bsd
+	;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	GUESS=m68k-hp-bsd4.4
+	;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+	case $UNAME_MACHINE in
+	    9000/31?)            HP_ARCH=m68000 ;;
+	    9000/[34]??)         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if test -x /usr/bin/getconf; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case $sc_cpu_version in
+		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case $sc_kernel_bits in
+			  32) HP_ARCH=hppa2.0n ;;
+			  64) HP_ARCH=hppa2.0w ;;
+			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if test "$HP_ARCH" = ""; then
+		    set_cc_for_build
+		    sed 's/^		//' << EOF > "$dummy.c"
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if test "$HP_ARCH" = hppa2.0w
+	then
+	    set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH=hppa2.0w
+	    else
+		HP_ARCH=hppa64
+	    fi
+	fi
+	GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+	;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+	GUESS=ia64-hp-hpux$HPUX_REV
+	;;
+    3050*:HI-UX:*:*)
+	set_cc_for_build
+	sed 's/^	//' << EOF > "$dummy.c"
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	GUESS=unknown-hitachi-hiuxwe2
+	;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+	GUESS=hppa1.1-hp-bsd
+	;;
+    9000/8??:4.3bsd:*:*)
+	GUESS=hppa1.0-hp-bsd
+	;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	GUESS=hppa1.0-hp-mpeix
+	;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+	GUESS=hppa1.1-hp-osf
+	;;
+    hp8??:OSF1:*:*)
+	GUESS=hppa1.0-hp-osf
+	;;
+    i*86:OSF1:*:*)
+	if test -x /usr/sbin/sysversion ; then
+	    GUESS=$UNAME_MACHINE-unknown-osf1mk
+	else
+	    GUESS=$UNAME_MACHINE-unknown-osf1
+	fi
+	;;
+    parisc*:Lites*:*:*)
+	GUESS=hppa1.1-hp-lites
+	;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	GUESS=c1-convex-bsd
+	;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	GUESS=c34-convex-bsd
+	;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	GUESS=c38-convex-bsd
+	;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	GUESS=c4-convex-bsd
+	;;
+    CRAY*Y-MP:*:*:*)
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=ymp-cray-unicos$CRAY_REL
+	;;
+    CRAY*[A-Z]90:*:*:*)
+	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=t90-cray-unicos$CRAY_REL
+	;;
+    CRAY*T3E:*:*:*)
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=alphaev5-cray-unicosmk$CRAY_REL
+	;;
+    CRAY*SV1:*:*:*)
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=sv1-cray-unicos$CRAY_REL
+	;;
+    *:UNICOS/mp:*:*)
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=craynv-cray-unicosmp$CRAY_REL
+	;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+	GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+	;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+	GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+	;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+	;;
+    sparc*:BSD/OS:*:*)
+	GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+	;;
+    *:BSD/OS:*:*)
+	GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+	;;
+    arm:FreeBSD:*:*)
+	UNAME_PROCESSOR=`uname -p`
+	set_cc_for_build
+	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_PCS_VFP
+	then
+	    FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+	else
+	    FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+	fi
+	;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case $UNAME_PROCESSOR in
+	    amd64)
+		UNAME_PROCESSOR=x86_64 ;;
+	    i386)
+		UNAME_PROCESSOR=i586 ;;
+	esac
+	FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+	;;
+    i*:CYGWIN*:*)
+	GUESS=$UNAME_MACHINE-pc-cygwin
+	;;
+    *:MINGW64*:*)
+	GUESS=$UNAME_MACHINE-pc-mingw64
+	;;
+    *:MINGW*:*)
+	GUESS=$UNAME_MACHINE-pc-mingw32
+	;;
+    *:MSYS*:*)
+	GUESS=$UNAME_MACHINE-pc-msys
+	;;
+    i*:PW*:*)
+	GUESS=$UNAME_MACHINE-pc-pw32
+	;;
+    *:SerenityOS:*:*)
+        GUESS=$UNAME_MACHINE-pc-serenity
+        ;;
+    *:Interix*:*)
+	case $UNAME_MACHINE in
+	    x86)
+		GUESS=i586-pc-interix$UNAME_RELEASE
+		;;
+	    authenticamd | genuineintel | EM64T)
+		GUESS=x86_64-unknown-interix$UNAME_RELEASE
+		;;
+	    IA64)
+		GUESS=ia64-unknown-interix$UNAME_RELEASE
+		;;
+	esac ;;
+    i*:UWIN*:*)
+	GUESS=$UNAME_MACHINE-pc-uwin
+	;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	GUESS=x86_64-pc-cygwin
+	;;
+    prep*:SunOS:5.*:*)
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=powerpcle-unknown-solaris2$SUN_REL
+	;;
+    *:GNU:*:*)
+	# the GNU system
+	GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+	GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+	;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+	;;
+    *:Minix:*:*)
+	GUESS=$UNAME_MACHINE-unknown-minix
+	;;
+    aarch64:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    arm*:Linux:*:*)
+	set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
+	    else
+		GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	;;
+    avr32*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    cris:Linux:*:*)
+	GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+	;;
+    crisv32:Linux:*:*)
+	GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+	;;
+    e2k:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    frv:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    hexagon:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    i*86:Linux:*:*)
+	GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+	;;
+    ia64:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    k1om:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    m32r*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    m68*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	set_cc_for_build
+	IS_GLIBC=0
+	test x"${LIBC}" = xgnu && IS_GLIBC=1
+	sed 's/^	//' << EOF > "$dummy.c"
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#undef mips64
+	#undef mips64el
+	#if ${IS_GLIBC} && defined(_ABI64)
+	LIBCABI=gnuabi64
+	#else
+	#if ${IS_GLIBC} && defined(_ABIN32)
+	LIBCABI=gnuabin32
+	#else
+	LIBCABI=${LIBC}
+	#endif
+	#endif
+
+	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa64r6
+	#else
+	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa32r6
+	#else
+	#if defined(__mips64)
+	CPU=mips64
+	#else
+	CPU=mips
+	#endif
+	#endif
+	#endif
+
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	MIPS_ENDIAN=el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	MIPS_ENDIAN=
+	#else
+	MIPS_ENDIAN=
+	#endif
+	#endif
+EOF
+	cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+	eval "$cc_set_vars"
+	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
+	;;
+    mips64el:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    openrisc*:Linux:*:*)
+	GUESS=or1k-unknown-linux-$LIBC
+	;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    padre:Linux:*:*)
+	GUESS=sparc-unknown-linux-$LIBC
+	;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	GUESS=hppa64-unknown-linux-$LIBC
+	;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+	  PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+	  *)    GUESS=hppa-unknown-linux-$LIBC ;;
+	esac
+	;;
+    ppc64:Linux:*:*)
+	GUESS=powerpc64-unknown-linux-$LIBC
+	;;
+    ppc:Linux:*:*)
+	GUESS=powerpc-unknown-linux-$LIBC
+	;;
+    ppc64le:Linux:*:*)
+	GUESS=powerpc64le-unknown-linux-$LIBC
+	;;
+    ppcle:Linux:*:*)
+	GUESS=powerpcle-unknown-linux-$LIBC
+	;;
+    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+	;;
+    sh64*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    sh*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    tile*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    vax:Linux:*:*)
+	GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+	;;
+    x86_64:Linux:*:*)
+	set_cc_for_build
+	LIBCABI=$LIBC
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_X32 >/dev/null
+	    then
+		LIBCABI=${LIBC}x32
+	    fi
+	fi
+	GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+	;;
+    xtensa*:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	GUESS=i386-sequent-sysv4
+	;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+	;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	GUESS=$UNAME_MACHINE-pc-os2-emx
+	;;
+    i*86:XTS-300:*:STOP)
+	GUESS=$UNAME_MACHINE-unknown-stop
+	;;
+    i*86:atheos:*:*)
+	GUESS=$UNAME_MACHINE-unknown-atheos
+	;;
+    i*86:syllable:*:*)
+	GUESS=$UNAME_MACHINE-pc-syllable
+	;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	GUESS=i386-unknown-lynxos$UNAME_RELEASE
+	;;
+    i*86:*DOS:*:*)
+	GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+	;;
+    i*86:*:4.*:*)
+	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
+	else
+		GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
+	fi
+	;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
+	else
+		GUESS=$UNAME_MACHINE-pc-sysv32
+	fi
+	;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configure will decide that
+	# this is a cross-build.
+	GUESS=i586-pc-msdosdjgpp
+	;;
+    Intel:Mach:3*:*)
+	GUESS=i386-pc-mach3
+	;;
+    paragon:*:*:*)
+	GUESS=i860-intel-osf1
+	;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  GUESS=i860-stardent-sysv$UNAME_RELEASE    # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  GUESS=i860-unknown-sysv$UNAME_RELEASE     # Unknown i860-SVR4
+	fi
+	;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	GUESS=m68010-convergent-sysv
+	;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	GUESS=m68k-convergent-sysv
+	;;
+    M680?0:D-NIX:5.3:*)
+	GUESS=m68k-diab-dnix
+	;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+	;;
+    mc68030:UNIX_System_V:4.*:*)
+	GUESS=m68k-atari-sysv4
+	;;
+    TSUNAMI:LynxOS:2.*:*)
+	GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+	;;
+    rs6000:LynxOS:2.*:*)
+	GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+	;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+	;;
+    SM[BE]S:UNIX_SV:*:*)
+	GUESS=mips-dde-sysv$UNAME_RELEASE
+	;;
+    RM*:ReliantUNIX-*:*:*)
+	GUESS=mips-sni-sysv4
+	;;
+    RM*:SINIX-*:*:*)
+	GUESS=mips-sni-sysv4
+	;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		GUESS=$UNAME_MACHINE-sni-sysv4
+	else
+		GUESS=ns32k-sni-sysv
+	fi
+	;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	GUESS=i586-unisys-sysv4
+	;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	GUESS=hppa1.1-stratus-sysv4
+	;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	GUESS=i860-stratus-sysv4
+	;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	GUESS=$UNAME_MACHINE-stratus-vos
+	;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	GUESS=hppa1.1-stratus-vos
+	;;
+    mc68*:A/UX:*:*)
+	GUESS=m68k-apple-aux$UNAME_RELEASE
+	;;
+    news*:NEWS-OS:6*:*)
+	GUESS=mips-sony-newsos6
+	;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if test -d /usr/nec; then
+		GUESS=mips-nec-sysv$UNAME_RELEASE
+	else
+		GUESS=mips-unknown-sysv$UNAME_RELEASE
+	fi
+	;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	GUESS=powerpc-be-beos
+	;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	GUESS=powerpc-apple-beos
+	;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	GUESS=i586-pc-beos
+	;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	GUESS=i586-pc-haiku
+	;;
+    x86_64:Haiku:*:*)
+	GUESS=x86_64-unknown-haiku
+	;;
+    SX-4:SUPER-UX:*:*)
+	GUESS=sx4-nec-superux$UNAME_RELEASE
+	;;
+    SX-5:SUPER-UX:*:*)
+	GUESS=sx5-nec-superux$UNAME_RELEASE
+	;;
+    SX-6:SUPER-UX:*:*)
+	GUESS=sx6-nec-superux$UNAME_RELEASE
+	;;
+    SX-7:SUPER-UX:*:*)
+	GUESS=sx7-nec-superux$UNAME_RELEASE
+	;;
+    SX-8:SUPER-UX:*:*)
+	GUESS=sx8-nec-superux$UNAME_RELEASE
+	;;
+    SX-8R:SUPER-UX:*:*)
+	GUESS=sx8r-nec-superux$UNAME_RELEASE
+	;;
+    SX-ACE:SUPER-UX:*:*)
+	GUESS=sxace-nec-superux$UNAME_RELEASE
+	;;
+    Power*:Rhapsody:*:*)
+	GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+	;;
+    *:Rhapsody:*:*)
+	GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+	;;
+    arm64:Darwin:*:*)
+	GUESS=aarch64-apple-darwin$UNAME_RELEASE
+	;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p`
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	if command -v xcode-select > /dev/null 2> /dev/null && \
+		! xcode-select --print-path > /dev/null 2> /dev/null ; then
+	    # Avoid executing cc if there is no toolchain installed as
+	    # cc will be a stub that puts up a graphical alert
+	    # prompting the user to install developer tools.
+	    CC_FOR_BUILD=no_compiler_found
+	else
+	    set_cc_for_build
+	fi
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_64BIT_ARCH >/dev/null
+	    then
+		case $UNAME_PROCESSOR in
+		    i386) UNAME_PROCESSOR=x86_64 ;;
+		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		esac
+	    fi
+	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_PPC >/dev/null
+	    then
+		UNAME_PROCESSOR=powerpc
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # uname -m returns i386 or x86_64
+	    UNAME_PROCESSOR=$UNAME_MACHINE
+	fi
+	GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+	;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = x86; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+	;;
+    *:QNX:*:4*)
+	GUESS=i386-pc-qnx
+	;;
+    NEO-*:NONSTOP_KERNEL:*:*)
+	GUESS=neo-tandem-nsk$UNAME_RELEASE
+	;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	GUESS=nse-tandem-nsk$UNAME_RELEASE
+	;;
+    NSR-*:NONSTOP_KERNEL:*:*)
+	GUESS=nsr-tandem-nsk$UNAME_RELEASE
+	;;
+    NSV-*:NONSTOP_KERNEL:*:*)
+	GUESS=nsv-tandem-nsk$UNAME_RELEASE
+	;;
+    NSX-*:NONSTOP_KERNEL:*:*)
+	GUESS=nsx-tandem-nsk$UNAME_RELEASE
+	;;
+    *:NonStop-UX:*:*)
+	GUESS=mips-compaq-nonstopux
+	;;
+    BS2000:POSIX*:*:*)
+	GUESS=bs2000-siemens-sysv
+	;;
+    DS/*:UNIX_System_V:*:*)
+	GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+	;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "${cputype-}" = 386; then
+	    UNAME_MACHINE=i386
+	elif test "x${cputype-}" != x; then
+	    UNAME_MACHINE=$cputype
+	fi
+	GUESS=$UNAME_MACHINE-unknown-plan9
+	;;
+    *:TOPS-10:*:*)
+	GUESS=pdp10-unknown-tops10
+	;;
+    *:TENEX:*:*)
+	GUESS=pdp10-unknown-tenex
+	;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	GUESS=pdp10-dec-tops20
+	;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	GUESS=pdp10-xkl-tops20
+	;;
+    *:TOPS-20:*:*)
+	GUESS=pdp10-unknown-tops20
+	;;
+    *:ITS:*:*)
+	GUESS=pdp10-unknown-its
+	;;
+    SEI:*:*:SEIUX)
+	GUESS=mips-sei-seiux$UNAME_RELEASE
+	;;
+    *:DragonFly:*:*)
+	DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+	;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case $UNAME_MACHINE in
+	    A*) GUESS=alpha-dec-vms ;;
+	    I*) GUESS=ia64-dec-vms ;;
+	    V*) GUESS=vax-dec-vms ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	GUESS=i386-pc-xenix
+	;;
+    i*86:skyos:*:*)
+	SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+	GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+	;;
+    i*86:rdos:*:*)
+	GUESS=$UNAME_MACHINE-pc-rdos
+	;;
+    i*86:Fiwix:*:*)
+	GUESS=$UNAME_MACHINE-pc-fiwix
+	;;
+    *:AROS:*:*)
+	GUESS=$UNAME_MACHINE-unknown-aros
+	;;
+    x86_64:VMkernel:*:*)
+	GUESS=$UNAME_MACHINE-unknown-esx
+	;;
+    amd64:Isilon\ OneFS:*:*)
+	GUESS=x86_64-unknown-onefs
+	;;
+    *:Unleashed:*:*)
+	GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+	;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+    echo "$GUESS"
+    exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+  "4"
+#else
+  ""
+#endif
+  ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+  struct utsname un;
+
+  uname(&un);
+  if (strncmp(un.version, "V2", 2) == 0) {
+    printf ("i386-sequent-ptx2\n"); exit (0);
+  }
+  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+    printf ("i386-sequent-ptx1\n"); exit (0);
+  }
+  printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+  printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+  printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname un;
+  uname (&un);
+  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname *un;
+  uname (&un);
+  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+    mips:Linux | mips64:Linux)
+	# If we got here on MIPS GNU/Linux, output extra information.
+	cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+	;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+and
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+   cat >&2 <<EOF
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM  = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+fi
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..0488e5b
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,145 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Directory for the Android daemon storage files */
+#undef ANDROID_STORAGEDIR
+
+/* Directory for the configuration files */
+#undef CONFIGDIR
+
+/* Define if external plugin support is required */
+#undef EXTERNAL_PLUGINS
+
+/* Define to 1 if you have the backtrace support. */
+#undef HAVE_BACKTRACE_SUPPORT
+
+/* Define to 1 if you have the declaration of 'basename', and to 0 if you
+   don't. */
+#undef HAVE_DECL_BASENAME
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the 'explicit_bzero' function. */
+#undef HAVE_EXPLICIT_BZERO
+
+/* Define to 1 if you have the 'getrandom' function. */
+#undef HAVE_GETRANDOM
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the 'asan' library (-lasan). */
+#undef HAVE_LIBASAN
+
+/* Define to 1 if you have the 'lsan' library (-llsan). */
+#undef HAVE_LIBLSAN
+
+/* Define to 1 if you have the 'ubsan' library (-lubsan). */
+#undef HAVE_LIBUBSAN
+
+/* Define to 1 if you have the <linux/if_alg.h> header file. */
+#undef HAVE_LINUX_IF_ALG_H
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+#undef HAVE_LINUX_TYPES_H
+
+/* Define to 1 if you have the <linux/uhid.h> header file. */
+#undef HAVE_LINUX_UHID_H
+
+/* Define to 1 if you have the <linux/uinput.h> header file. */
+#undef HAVE_LINUX_UINPUT_H
+
+/* Define to 1 if you have the 'rawmemchr' function. */
+#undef HAVE_RAWMEMCHR
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if udev is required */
+#undef HAVE_UDEV
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
+#undef HAVE_VALGRIND_MEMCHECK_H
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Directory for the mesh daemon storage files */
+#undef MESH_STORAGEDIR
+
+/* Define if threading support is required */
+#undef NEED_THREADS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+   required in a freestanding environment). This macro is provided for
+   backward compatibility; new code need not use it. */
+#undef STDC_HEADERS
+
+/* Directory for the storage files */
+#undef STORAGEDIR
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+   nothing if this is not supported.  Do not define if restrict is
+   supported only directly.  */
+#undef restrict
+/* Work around a bug in older versions of Sun C++, which did not
+   #define __restrict__ or support _Restrict or __restrict__
+   even though the corresponding Sun C compiler ended up with
+   "#define restrict _Restrict" or "#define restrict __restrict__"
+   in the previous line.  This workaround can be removed once
+   we assume Oracle Developer Studio 12.5 (2016) or later.  */
+#if defined __SUNPRO_CC && !defined __RESTRICT && !defined __restrict__
+# define _Restrict
+# define __restrict__
+#endif
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..dba16e8
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1890 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2022 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-03'
+
+# This file 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 3 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, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX.  However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2022 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo "$1"
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
+IFS=$saved_IFS
+
+# Separate into logical components for further validation
+case $1 in
+	*-*-*-*-*)
+		echo Invalid configuration \`"$1"\': more than four components >&2
+		exit 1
+		;;
+	*-*-*-*)
+		basic_machine=$field1-$field2
+		basic_os=$field3-$field4
+		;;
+	*-*-*)
+		# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+		# parts
+		maybe_os=$field2-$field3
+		case $maybe_os in
+			nto-qnx* | linux-* | uclinux-uclibc* \
+			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+			| storm-chaos* | os2-emx* | rtmk-nova*)
+				basic_machine=$field1
+				basic_os=$maybe_os
+				;;
+			android-linux)
+				basic_machine=$field1-unknown
+				basic_os=linux-android
+				;;
+			*)
+				basic_machine=$field1-$field2
+				basic_os=$field3
+				;;
+		esac
+		;;
+	*-*)
+		# A lone config we happen to match not fitting any pattern
+		case $field1-$field2 in
+			decstation-3100)
+				basic_machine=mips-dec
+				basic_os=
+				;;
+			*-*)
+				# Second component is usually, but not always the OS
+				case $field2 in
+					# Prevent following clause from handling this valid os
+					sun*os*)
+						basic_machine=$field1
+						basic_os=$field2
+						;;
+					zephyr*)
+						basic_machine=$field1-unknown
+						basic_os=$field2
+						;;
+					# Manufacturers
+					dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+					| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+					| unicom* | ibm* | next | hp | isi* | apollo | altos* \
+					| convergent* | ncr* | news | 32* | 3600* | 3100* \
+					| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+					| ultra | tti* | harris | dolphin | highlevel | gould \
+					| cbm | ns | masscomp | apple | axis | knuth | cray \
+					| microblaze* | sim | cisco \
+					| oki | wec | wrs | winbond)
+						basic_machine=$field1-$field2
+						basic_os=
+						;;
+					*)
+						basic_machine=$field1
+						basic_os=$field2
+						;;
+				esac
+			;;
+		esac
+		;;
+	*)
+		# Convert single-component short-hands not valid as part of
+		# multi-component configurations.
+		case $field1 in
+			386bsd)
+				basic_machine=i386-pc
+				basic_os=bsd
+				;;
+			a29khif)
+				basic_machine=a29k-amd
+				basic_os=udi
+				;;
+			adobe68k)
+				basic_machine=m68010-adobe
+				basic_os=scout
+				;;
+			alliant)
+				basic_machine=fx80-alliant
+				basic_os=
+				;;
+			altos | altos3068)
+				basic_machine=m68k-altos
+				basic_os=
+				;;
+			am29k)
+				basic_machine=a29k-none
+				basic_os=bsd
+				;;
+			amdahl)
+				basic_machine=580-amdahl
+				basic_os=sysv
+				;;
+			amiga)
+				basic_machine=m68k-unknown
+				basic_os=
+				;;
+			amigaos | amigados)
+				basic_machine=m68k-unknown
+				basic_os=amigaos
+				;;
+			amigaunix | amix)
+				basic_machine=m68k-unknown
+				basic_os=sysv4
+				;;
+			apollo68)
+				basic_machine=m68k-apollo
+				basic_os=sysv
+				;;
+			apollo68bsd)
+				basic_machine=m68k-apollo
+				basic_os=bsd
+				;;
+			aros)
+				basic_machine=i386-pc
+				basic_os=aros
+				;;
+			aux)
+				basic_machine=m68k-apple
+				basic_os=aux
+				;;
+			balance)
+				basic_machine=ns32k-sequent
+				basic_os=dynix
+				;;
+			blackfin)
+				basic_machine=bfin-unknown
+				basic_os=linux
+				;;
+			cegcc)
+				basic_machine=arm-unknown
+				basic_os=cegcc
+				;;
+			convex-c1)
+				basic_machine=c1-convex
+				basic_os=bsd
+				;;
+			convex-c2)
+				basic_machine=c2-convex
+				basic_os=bsd
+				;;
+			convex-c32)
+				basic_machine=c32-convex
+				basic_os=bsd
+				;;
+			convex-c34)
+				basic_machine=c34-convex
+				basic_os=bsd
+				;;
+			convex-c38)
+				basic_machine=c38-convex
+				basic_os=bsd
+				;;
+			cray)
+				basic_machine=j90-cray
+				basic_os=unicos
+				;;
+			crds | unos)
+				basic_machine=m68k-crds
+				basic_os=
+				;;
+			da30)
+				basic_machine=m68k-da30
+				basic_os=
+				;;
+			decstation | pmax | pmin | dec3100 | decstatn)
+				basic_machine=mips-dec
+				basic_os=
+				;;
+			delta88)
+				basic_machine=m88k-motorola
+				basic_os=sysv3
+				;;
+			dicos)
+				basic_machine=i686-pc
+				basic_os=dicos
+				;;
+			djgpp)
+				basic_machine=i586-pc
+				basic_os=msdosdjgpp
+				;;
+			ebmon29k)
+				basic_machine=a29k-amd
+				basic_os=ebmon
+				;;
+			es1800 | OSE68k | ose68k | ose | OSE)
+				basic_machine=m68k-ericsson
+				basic_os=ose
+				;;
+			gmicro)
+				basic_machine=tron-gmicro
+				basic_os=sysv
+				;;
+			go32)
+				basic_machine=i386-pc
+				basic_os=go32
+				;;
+			h8300hms)
+				basic_machine=h8300-hitachi
+				basic_os=hms
+				;;
+			h8300xray)
+				basic_machine=h8300-hitachi
+				basic_os=xray
+				;;
+			h8500hms)
+				basic_machine=h8500-hitachi
+				basic_os=hms
+				;;
+			harris)
+				basic_machine=m88k-harris
+				basic_os=sysv3
+				;;
+			hp300 | hp300hpux)
+				basic_machine=m68k-hp
+				basic_os=hpux
+				;;
+			hp300bsd)
+				basic_machine=m68k-hp
+				basic_os=bsd
+				;;
+			hppaosf)
+				basic_machine=hppa1.1-hp
+				basic_os=osf
+				;;
+			hppro)
+				basic_machine=hppa1.1-hp
+				basic_os=proelf
+				;;
+			i386mach)
+				basic_machine=i386-mach
+				basic_os=mach
+				;;
+			isi68 | isi)
+				basic_machine=m68k-isi
+				basic_os=sysv
+				;;
+			m68knommu)
+				basic_machine=m68k-unknown
+				basic_os=linux
+				;;
+			magnum | m3230)
+				basic_machine=mips-mips
+				basic_os=sysv
+				;;
+			merlin)
+				basic_machine=ns32k-utek
+				basic_os=sysv
+				;;
+			mingw64)
+				basic_machine=x86_64-pc
+				basic_os=mingw64
+				;;
+			mingw32)
+				basic_machine=i686-pc
+				basic_os=mingw32
+				;;
+			mingw32ce)
+				basic_machine=arm-unknown
+				basic_os=mingw32ce
+				;;
+			monitor)
+				basic_machine=m68k-rom68k
+				basic_os=coff
+				;;
+			morphos)
+				basic_machine=powerpc-unknown
+				basic_os=morphos
+				;;
+			moxiebox)
+				basic_machine=moxie-unknown
+				basic_os=moxiebox
+				;;
+			msdos)
+				basic_machine=i386-pc
+				basic_os=msdos
+				;;
+			msys)
+				basic_machine=i686-pc
+				basic_os=msys
+				;;
+			mvs)
+				basic_machine=i370-ibm
+				basic_os=mvs
+				;;
+			nacl)
+				basic_machine=le32-unknown
+				basic_os=nacl
+				;;
+			ncr3000)
+				basic_machine=i486-ncr
+				basic_os=sysv4
+				;;
+			netbsd386)
+				basic_machine=i386-pc
+				basic_os=netbsd
+				;;
+			netwinder)
+				basic_machine=armv4l-rebel
+				basic_os=linux
+				;;
+			news | news700 | news800 | news900)
+				basic_machine=m68k-sony
+				basic_os=newsos
+				;;
+			news1000)
+				basic_machine=m68030-sony
+				basic_os=newsos
+				;;
+			necv70)
+				basic_machine=v70-nec
+				basic_os=sysv
+				;;
+			nh3000)
+				basic_machine=m68k-harris
+				basic_os=cxux
+				;;
+			nh[45]000)
+				basic_machine=m88k-harris
+				basic_os=cxux
+				;;
+			nindy960)
+				basic_machine=i960-intel
+				basic_os=nindy
+				;;
+			mon960)
+				basic_machine=i960-intel
+				basic_os=mon960
+				;;
+			nonstopux)
+				basic_machine=mips-compaq
+				basic_os=nonstopux
+				;;
+			os400)
+				basic_machine=powerpc-ibm
+				basic_os=os400
+				;;
+			OSE68000 | ose68000)
+				basic_machine=m68000-ericsson
+				basic_os=ose
+				;;
+			os68k)
+				basic_machine=m68k-none
+				basic_os=os68k
+				;;
+			paragon)
+				basic_machine=i860-intel
+				basic_os=osf
+				;;
+			parisc)
+				basic_machine=hppa-unknown
+				basic_os=linux
+				;;
+			psp)
+				basic_machine=mipsallegrexel-sony
+				basic_os=psp
+				;;
+			pw32)
+				basic_machine=i586-unknown
+				basic_os=pw32
+				;;
+			rdos | rdos64)
+				basic_machine=x86_64-pc
+				basic_os=rdos
+				;;
+			rdos32)
+				basic_machine=i386-pc
+				basic_os=rdos
+				;;
+			rom68k)
+				basic_machine=m68k-rom68k
+				basic_os=coff
+				;;
+			sa29200)
+				basic_machine=a29k-amd
+				basic_os=udi
+				;;
+			sei)
+				basic_machine=mips-sei
+				basic_os=seiux
+				;;
+			sequent)
+				basic_machine=i386-sequent
+				basic_os=
+				;;
+			sps7)
+				basic_machine=m68k-bull
+				basic_os=sysv2
+				;;
+			st2000)
+				basic_machine=m68k-tandem
+				basic_os=
+				;;
+			stratus)
+				basic_machine=i860-stratus
+				basic_os=sysv4
+				;;
+			sun2)
+				basic_machine=m68000-sun
+				basic_os=
+				;;
+			sun2os3)
+				basic_machine=m68000-sun
+				basic_os=sunos3
+				;;
+			sun2os4)
+				basic_machine=m68000-sun
+				basic_os=sunos4
+				;;
+			sun3)
+				basic_machine=m68k-sun
+				basic_os=
+				;;
+			sun3os3)
+				basic_machine=m68k-sun
+				basic_os=sunos3
+				;;
+			sun3os4)
+				basic_machine=m68k-sun
+				basic_os=sunos4
+				;;
+			sun4)
+				basic_machine=sparc-sun
+				basic_os=
+				;;
+			sun4os3)
+				basic_machine=sparc-sun
+				basic_os=sunos3
+				;;
+			sun4os4)
+				basic_machine=sparc-sun
+				basic_os=sunos4
+				;;
+			sun4sol2)
+				basic_machine=sparc-sun
+				basic_os=solaris2
+				;;
+			sun386 | sun386i | roadrunner)
+				basic_machine=i386-sun
+				basic_os=
+				;;
+			sv1)
+				basic_machine=sv1-cray
+				basic_os=unicos
+				;;
+			symmetry)
+				basic_machine=i386-sequent
+				basic_os=dynix
+				;;
+			t3e)
+				basic_machine=alphaev5-cray
+				basic_os=unicos
+				;;
+			t90)
+				basic_machine=t90-cray
+				basic_os=unicos
+				;;
+			toad1)
+				basic_machine=pdp10-xkl
+				basic_os=tops20
+				;;
+			tpf)
+				basic_machine=s390x-ibm
+				basic_os=tpf
+				;;
+			udi29k)
+				basic_machine=a29k-amd
+				basic_os=udi
+				;;
+			ultra3)
+				basic_machine=a29k-nyu
+				basic_os=sym1
+				;;
+			v810 | necv810)
+				basic_machine=v810-nec
+				basic_os=none
+				;;
+			vaxv)
+				basic_machine=vax-dec
+				basic_os=sysv
+				;;
+			vms)
+				basic_machine=vax-dec
+				basic_os=vms
+				;;
+			vsta)
+				basic_machine=i386-pc
+				basic_os=vsta
+				;;
+			vxworks960)
+				basic_machine=i960-wrs
+				basic_os=vxworks
+				;;
+			vxworks68)
+				basic_machine=m68k-wrs
+				basic_os=vxworks
+				;;
+			vxworks29k)
+				basic_machine=a29k-wrs
+				basic_os=vxworks
+				;;
+			xbox)
+				basic_machine=i686-pc
+				basic_os=mingw32
+				;;
+			ymp)
+				basic_machine=ymp-cray
+				basic_os=unicos
+				;;
+			*)
+				basic_machine=$1
+				basic_os=
+				;;
+		esac
+		;;
+esac
+
+# Decode 1-component or ad-hoc basic machines
+case $basic_machine in
+	# Here we handle the default manufacturer of certain CPU types.  It is in
+	# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		cpu=hppa1.1
+		vendor=winbond
+		;;
+	op50n)
+		cpu=hppa1.1
+		vendor=oki
+		;;
+	op60c)
+		cpu=hppa1.1
+		vendor=oki
+		;;
+	ibm*)
+		cpu=i370
+		vendor=ibm
+		;;
+	orion105)
+		cpu=clipper
+		vendor=highlevel
+		;;
+	mac | mpw | mac-mpw)
+		cpu=m68k
+		vendor=apple
+		;;
+	pmac | pmac-mpw)
+		cpu=powerpc
+		vendor=apple
+		;;
+
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		cpu=m68000
+		vendor=att
+		;;
+	3b*)
+		cpu=we32k
+		vendor=att
+		;;
+	bluegene*)
+		cpu=powerpc
+		vendor=ibm
+		basic_os=cnk
+		;;
+	decsystem10* | dec10*)
+		cpu=pdp10
+		vendor=dec
+		basic_os=tops10
+		;;
+	decsystem20* | dec20*)
+		cpu=pdp10
+		vendor=dec
+		basic_os=tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		cpu=m68k
+		vendor=motorola
+		;;
+	dpx2*)
+		cpu=m68k
+		vendor=bull
+		basic_os=sysv3
+		;;
+	encore | umax | mmax)
+		cpu=ns32k
+		vendor=encore
+		;;
+	elxsi)
+		cpu=elxsi
+		vendor=elxsi
+		basic_os=${basic_os:-bsd}
+		;;
+	fx2800)
+		cpu=i860
+		vendor=alliant
+		;;
+	genix)
+		cpu=ns32k
+		vendor=ns
+		;;
+	h3050r* | hiux*)
+		cpu=hppa1.1
+		vendor=hitachi
+		basic_os=hiuxwe2
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		cpu=hppa1.0
+		vendor=hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		cpu=m68000
+		vendor=hp
+		;;
+	hp9k3[2-9][0-9])
+		cpu=m68k
+		vendor=hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		cpu=hppa1.0
+		vendor=hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		cpu=hppa1.1
+		vendor=hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		cpu=hppa1.1
+		vendor=hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		cpu=hppa1.1
+		vendor=hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		cpu=hppa1.1
+		vendor=hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		cpu=hppa1.0
+		vendor=hp
+		;;
+	i*86v32)
+		cpu=`echo "$1" | sed -e 's/86.*/86/'`
+		vendor=pc
+		basic_os=sysv32
+		;;
+	i*86v4*)
+		cpu=`echo "$1" | sed -e 's/86.*/86/'`
+		vendor=pc
+		basic_os=sysv4
+		;;
+	i*86v)
+		cpu=`echo "$1" | sed -e 's/86.*/86/'`
+		vendor=pc
+		basic_os=sysv
+		;;
+	i*86sol2)
+		cpu=`echo "$1" | sed -e 's/86.*/86/'`
+		vendor=pc
+		basic_os=solaris2
+		;;
+	j90 | j90-cray)
+		cpu=j90
+		vendor=cray
+		basic_os=${basic_os:-unicos}
+		;;
+	iris | iris4d)
+		cpu=mips
+		vendor=sgi
+		case $basic_os in
+		    irix*)
+			;;
+		    *)
+			basic_os=irix4
+			;;
+		esac
+		;;
+	miniframe)
+		cpu=m68000
+		vendor=convergent
+		;;
+	*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		cpu=m68k
+		vendor=atari
+		basic_os=mint
+		;;
+	news-3600 | risc-news)
+		cpu=mips
+		vendor=sony
+		basic_os=newsos
+		;;
+	next | m*-next)
+		cpu=m68k
+		vendor=next
+		case $basic_os in
+		    openstep*)
+		        ;;
+		    nextstep*)
+			;;
+		    ns2*)
+		      basic_os=nextstep2
+			;;
+		    *)
+		      basic_os=nextstep3
+			;;
+		esac
+		;;
+	np1)
+		cpu=np1
+		vendor=gould
+		;;
+	op50n-* | op60c-*)
+		cpu=hppa1.1
+		vendor=oki
+		basic_os=proelf
+		;;
+	pa-hitachi)
+		cpu=hppa1.1
+		vendor=hitachi
+		basic_os=hiuxwe2
+		;;
+	pbd)
+		cpu=sparc
+		vendor=tti
+		;;
+	pbb)
+		cpu=m68k
+		vendor=tti
+		;;
+	pc532)
+		cpu=ns32k
+		vendor=pc532
+		;;
+	pn)
+		cpu=pn
+		vendor=gould
+		;;
+	power)
+		cpu=power
+		vendor=ibm
+		;;
+	ps2)
+		cpu=i386
+		vendor=ibm
+		;;
+	rm[46]00)
+		cpu=mips
+		vendor=siemens
+		;;
+	rtpc | rtpc-*)
+		cpu=romp
+		vendor=ibm
+		;;
+	sde)
+		cpu=mipsisa32
+		vendor=sde
+		basic_os=${basic_os:-elf}
+		;;
+	simso-wrs)
+		cpu=sparclite
+		vendor=wrs
+		basic_os=vxworks
+		;;
+	tower | tower-32)
+		cpu=m68k
+		vendor=ncr
+		;;
+	vpp*|vx|vx-*)
+		cpu=f301
+		vendor=fujitsu
+		;;
+	w65)
+		cpu=w65
+		vendor=wdc
+		;;
+	w89k-*)
+		cpu=hppa1.1
+		vendor=winbond
+		basic_os=proelf
+		;;
+	none)
+		cpu=none
+		vendor=none
+		;;
+	leon|leon[3-9])
+		cpu=sparc
+		vendor=$basic_machine
+		;;
+	leon-*|leon[3-9]-*)
+		cpu=sparc
+		vendor=`echo "$basic_machine" | sed 's/-.*//'`
+		;;
+
+	*-*)
+		# shellcheck disable=SC2162
+		saved_IFS=$IFS
+		IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
+		IFS=$saved_IFS
+		;;
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+		cpu=$basic_machine
+		vendor=pc
+		;;
+	# These rules are duplicated from below for sake of the special case above;
+	# i.e. things that normalized to x86 arches should also default to "pc"
+	pc98)
+		cpu=i386
+		vendor=pc
+		;;
+	x64 | amd64)
+		cpu=x86_64
+		vendor=pc
+		;;
+	# Recognize the basic CPU types without company name.
+	*)
+		cpu=$basic_machine
+		vendor=unknown
+		;;
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+	# Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+	# some cases the only manufacturer, in others, it is the most popular.
+	craynv-unknown)
+		vendor=cray
+		basic_os=${basic_os:-unicosmp}
+		;;
+	c90-unknown | c90-cray)
+		vendor=cray
+		basic_os=${Basic_os:-unicos}
+		;;
+	fx80-unknown)
+		vendor=alliant
+		;;
+	romp-unknown)
+		vendor=ibm
+		;;
+	mmix-unknown)
+		vendor=knuth
+		;;
+	microblaze-unknown | microblazeel-unknown)
+		vendor=xilinx
+		;;
+	rs6000-unknown)
+		vendor=ibm
+		;;
+	vax-unknown)
+		vendor=dec
+		;;
+	pdp11-unknown)
+		vendor=dec
+		;;
+	we32k-unknown)
+		vendor=att
+		;;
+	cydra-unknown)
+		vendor=cydrome
+		;;
+	i370-ibm*)
+		vendor=ibm
+		;;
+	orion-unknown)
+		vendor=highlevel
+		;;
+	xps-unknown | xps100-unknown)
+		cpu=xps100
+		vendor=honeywell
+		;;
+
+	# Here we normalize CPU types with a missing or matching vendor
+	armh-unknown | armh-alt)
+		cpu=armv7l
+		vendor=alt
+		basic_os=${basic_os:-linux-gnueabihf}
+		;;
+	dpx20-unknown | dpx20-bull)
+		cpu=rs6000
+		vendor=bull
+		basic_os=${basic_os:-bosx}
+		;;
+
+	# Here we normalize CPU types irrespective of the vendor
+	amd64-*)
+		cpu=x86_64
+		;;
+	blackfin-*)
+		cpu=bfin
+		basic_os=linux
+		;;
+	c54x-*)
+		cpu=tic54x
+		;;
+	c55x-*)
+		cpu=tic55x
+		;;
+	c6x-*)
+		cpu=tic6x
+		;;
+	e500v[12]-*)
+		cpu=powerpc
+		basic_os=${basic_os}"spe"
+		;;
+	mips3*-*)
+		cpu=mips64
+		;;
+	ms1-*)
+		cpu=mt
+		;;
+	m68knommu-*)
+		cpu=m68k
+		basic_os=linux
+		;;
+	m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+		cpu=s12z
+		;;
+	openrisc-*)
+		cpu=or32
+		;;
+	parisc-*)
+		cpu=hppa
+		basic_os=linux
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		cpu=i586
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+		cpu=i686
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		cpu=i686
+		;;
+	pentium4-*)
+		cpu=i786
+		;;
+	pc98-*)
+		cpu=i386
+		;;
+	ppc-* | ppcbe-*)
+		cpu=powerpc
+		;;
+	ppcle-* | powerpclittle-*)
+		cpu=powerpcle
+		;;
+	ppc64-*)
+		cpu=powerpc64
+		;;
+	ppc64le-* | powerpc64little-*)
+		cpu=powerpc64le
+		;;
+	sb1-*)
+		cpu=mipsisa64sb1
+		;;
+	sb1el-*)
+		cpu=mipsisa64sb1el
+		;;
+	sh5e[lb]-*)
+		cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
+		;;
+	spur-*)
+		cpu=spur
+		;;
+	strongarm-* | thumb-*)
+		cpu=arm
+		;;
+	tx39-*)
+		cpu=mipstx39
+		;;
+	tx39el-*)
+		cpu=mipstx39el
+		;;
+	x64-*)
+		cpu=x86_64
+		;;
+	xscale-* | xscalee[bl]-*)
+		cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
+		;;
+	arm64-* | aarch64le-*)
+		cpu=aarch64
+		;;
+
+	# Recognize the canonical CPU Types that limit and/or modify the
+	# company names they are paired with.
+	cr16-*)
+		basic_os=${basic_os:-elf}
+		;;
+	crisv32-* | etraxfs*-*)
+		cpu=crisv32
+		vendor=axis
+		;;
+	cris-* | etrax*-*)
+		cpu=cris
+		vendor=axis
+		;;
+	crx-*)
+		basic_os=${basic_os:-elf}
+		;;
+	neo-tandem)
+		cpu=neo
+		vendor=tandem
+		;;
+	nse-tandem)
+		cpu=nse
+		vendor=tandem
+		;;
+	nsr-tandem)
+		cpu=nsr
+		vendor=tandem
+		;;
+	nsv-tandem)
+		cpu=nsv
+		vendor=tandem
+		;;
+	nsx-tandem)
+		cpu=nsx
+		vendor=tandem
+		;;
+	mipsallegrexel-sony)
+		cpu=mipsallegrexel
+		vendor=sony
+		;;
+	tile*-*)
+		basic_os=${basic_os:-linux-gnu}
+		;;
+
+	*)
+		# Recognize the canonical CPU types that are allowed with any
+		# company name.
+		case $cpu in
+			1750a | 580 \
+			| a29k \
+			| aarch64 | aarch64_be \
+			| abacus \
+			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+			| alphapca5[67] | alpha64pca5[67] \
+			| am33_2.0 \
+			| amdgcn \
+			| arc | arceb | arc32 | arc64 \
+			| arm | arm[lb]e | arme[lb] | armv* \
+			| avr | avr32 \
+			| asmjs \
+			| ba \
+			| be32 | be64 \
+			| bfin | bpf | bs2000 \
+			| c[123]* | c30 | [cjt]90 | c4x \
+			| c8051 | clipper | craynv | csky | cydra \
+			| d10v | d30v | dlx | dsp16xx \
+			| e2k | elxsi | epiphany \
+			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+			| h8300 | h8500 \
+			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+			| hexagon \
+			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
+			| ip2k | iq2000 \
+			| k1om \
+			| le32 | le64 \
+			| lm32 \
+			| loongarch32 | loongarch64 | loongarchx32 \
+			| m32c | m32r | m32rle \
+			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+			| m88110 | m88k | maxq | mb | mcore | mep | metag \
+			| microblaze | microblazeel \
+			| mips | mipsbe | mipseb | mipsel | mipsle \
+			| mips16 \
+			| mips64 | mips64eb | mips64el \
+			| mips64octeon | mips64octeonel \
+			| mips64orion | mips64orionel \
+			| mips64r5900 | mips64r5900el \
+			| mips64vr | mips64vrel \
+			| mips64vr4100 | mips64vr4100el \
+			| mips64vr4300 | mips64vr4300el \
+			| mips64vr5000 | mips64vr5000el \
+			| mips64vr5900 | mips64vr5900el \
+			| mipsisa32 | mipsisa32el \
+			| mipsisa32r2 | mipsisa32r2el \
+			| mipsisa32r3 | mipsisa32r3el \
+			| mipsisa32r5 | mipsisa32r5el \
+			| mipsisa32r6 | mipsisa32r6el \
+			| mipsisa64 | mipsisa64el \
+			| mipsisa64r2 | mipsisa64r2el \
+			| mipsisa64r3 | mipsisa64r3el \
+			| mipsisa64r5 | mipsisa64r5el \
+			| mipsisa64r6 | mipsisa64r6el \
+			| mipsisa64sb1 | mipsisa64sb1el \
+			| mipsisa64sr71k | mipsisa64sr71kel \
+			| mipsr5900 | mipsr5900el \
+			| mipstx39 | mipstx39el \
+			| mmix \
+			| mn10200 | mn10300 \
+			| moxie \
+			| mt \
+			| msp430 \
+			| nds32 | nds32le | nds32be \
+			| nfp \
+			| nios | nios2 | nios2eb | nios2el \
+			| none | np1 | ns16k | ns32k | nvptx \
+			| open8 \
+			| or1k* \
+			| or32 \
+			| orion \
+			| picochip \
+			| pdp10 | pdp11 | pj | pjl | pn | power \
+			| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+			| pru \
+			| pyramid \
+			| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
+			| rl78 | romp | rs6000 | rx \
+			| s390 | s390x \
+			| score \
+			| sh | shl \
+			| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+			| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+			| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+			| sparclite \
+			| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+			| spu \
+			| tahoe \
+			| thumbv7* \
+			| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+			| tron \
+			| ubicom32 \
+			| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+			| vax \
+			| visium \
+			| w65 \
+			| wasm32 | wasm64 \
+			| we32k \
+			| x86 | x86_64 | xc16x | xgate | xps100 \
+			| xstormy16 | xtensa* \
+			| ymp \
+			| z8k | z80)
+				;;
+
+			*)
+				echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+				exit 1
+				;;
+		esac
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $vendor in
+	digital*)
+		vendor=dec
+		;;
+	commodore*)
+		vendor=cbm
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if test x$basic_os != x
+then
+
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+	gnu/linux*)
+		kernel=linux
+		os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+		;;
+	os2-emx)
+		kernel=os2
+		os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+		;;
+	nto-qnx*)
+		kernel=nto
+		os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+		;;
+	*-*)
+		# shellcheck disable=SC2162
+		saved_IFS=$IFS
+		IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+		IFS=$saved_IFS
+		;;
+	# Default OS when just kernel was specified
+	nto*)
+		kernel=nto
+		os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
+		;;
+	linux*)
+		kernel=linux
+		os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
+		;;
+	*)
+		kernel=
+		os=$basic_os
+		;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
+case $os in
+	# First match some system type aliases that might get confused
+	# with valid system types.
+	# solaris* is a basic system type, with this one exception.
+	auroraux)
+		os=auroraux
+		;;
+	bluegene*)
+		os=cnk
+		;;
+	solaris1 | solaris1.*)
+		os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
+		;;
+	solaris)
+		os=solaris2
+		;;
+	unixware*)
+		os=sysv4.2uw
+		;;
+	# es1800 is here to avoid being matched by es* (a different OS)
+	es1800*)
+		os=ose
+		;;
+	# Some version numbers need modification
+	chorusos*)
+		os=chorusos
+		;;
+	isc)
+		os=isc2.2
+		;;
+	sco6)
+		os=sco5v6
+		;;
+	sco5)
+		os=sco3.2v5
+		;;
+	sco4)
+		os=sco3.2v4
+		;;
+	sco3.2.[4-9]*)
+		os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
+		;;
+	sco*v* | scout)
+		# Don't match below
+		;;
+	sco*)
+		os=sco3.2v2
+		;;
+	psos*)
+		os=psos
+		;;
+	qnx*)
+		os=qnx
+		;;
+	hiux*)
+		os=hiuxwe2
+		;;
+	lynx*178)
+		os=lynxos178
+		;;
+	lynx*5)
+		os=lynxos5
+		;;
+	lynxos*)
+		# don't get caught up in next wildcard
+		;;
+	lynx*)
+		os=lynxos
+		;;
+	mac[0-9]*)
+		os=`echo "$os" | sed -e 's|mac|macos|'`
+		;;
+	opened*)
+		os=openedition
+		;;
+	os400*)
+		os=os400
+		;;
+	sunos5*)
+		os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+		;;
+	sunos6*)
+		os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+		;;
+	wince*)
+		os=wince
+		;;
+	utek*)
+		os=bsd
+		;;
+	dynix*)
+		os=bsd
+		;;
+	acis*)
+		os=aos
+		;;
+	atheos*)
+		os=atheos
+		;;
+	syllable*)
+		os=syllable
+		;;
+	386bsd)
+		os=bsd
+		;;
+	ctix* | uts*)
+		os=sysv
+		;;
+	nova*)
+		os=rtmk-nova
+		;;
+	ns2)
+		os=nextstep2
+		;;
+	# Preserve the version number of sinix5.
+	sinix5.*)
+		os=`echo "$os" | sed -e 's|sinix|sysv|'`
+		;;
+	sinix*)
+		os=sysv4
+		;;
+	tpf*)
+		os=tpf
+		;;
+	triton*)
+		os=sysv3
+		;;
+	oss*)
+		os=sysv3
+		;;
+	svr4*)
+		os=sysv4
+		;;
+	svr3)
+		os=sysv3
+		;;
+	sysvr4)
+		os=sysv4
+		;;
+	ose*)
+		os=ose
+		;;
+	*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+		os=mint
+		;;
+	dicos*)
+		os=dicos
+		;;
+	pikeos*)
+		# Until real need of OS specific support for
+		# particular features comes up, bare metal
+		# configurations are quite functional.
+		case $cpu in
+		    arm*)
+			os=eabi
+			;;
+		    *)
+			os=elf
+			;;
+		esac
+		;;
+	*)
+		# No normalization, but not necessarily accepted, that comes below.
+		;;
+esac
+
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+kernel=
+case $cpu-$vendor in
+	score-*)
+		os=elf
+		;;
+	spu-*)
+		os=elf
+		;;
+	*-acorn)
+		os=riscix1.2
+		;;
+	arm*-rebel)
+		kernel=linux
+		os=gnu
+		;;
+	arm*-semi)
+		os=aout
+		;;
+	c4x-* | tic4x-*)
+		os=coff
+		;;
+	c8051-*)
+		os=elf
+		;;
+	clipper-intergraph)
+		os=clix
+		;;
+	hexagon-*)
+		os=elf
+		;;
+	tic54x-*)
+		os=coff
+		;;
+	tic55x-*)
+		os=coff
+		;;
+	tic6x-*)
+		os=coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=tops20
+		;;
+	pdp11-*)
+		os=none
+		;;
+	*-dec | vax-*)
+		os=ultrix4.2
+		;;
+	m68*-apollo)
+		os=domain
+		;;
+	i386-sun)
+		os=sunos4.0.2
+		;;
+	m68000-sun)
+		os=sunos3
+		;;
+	m68*-cisco)
+		os=aout
+		;;
+	mep-*)
+		os=elf
+		;;
+	mips*-cisco)
+		os=elf
+		;;
+	mips*-*)
+		os=elf
+		;;
+	or32-*)
+		os=coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=sysv3
+		;;
+	sparc-* | *-sun)
+		os=sunos4.1.1
+		;;
+	pru-*)
+		os=elf
+		;;
+	*-be)
+		os=beos
+		;;
+	*-ibm)
+		os=aix
+		;;
+	*-knuth)
+		os=mmixware
+		;;
+	*-wec)
+		os=proelf
+		;;
+	*-winbond)
+		os=proelf
+		;;
+	*-oki)
+		os=proelf
+		;;
+	*-hp)
+		os=hpux
+		;;
+	*-hitachi)
+		os=hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=sysv
+		;;
+	*-cbm)
+		os=amigaos
+		;;
+	*-dg)
+		os=dgux
+		;;
+	*-dolphin)
+		os=sysv3
+		;;
+	m68k-ccur)
+		os=rtu
+		;;
+	m88k-omron*)
+		os=luna
+		;;
+	*-next)
+		os=nextstep
+		;;
+	*-sequent)
+		os=ptx
+		;;
+	*-crds)
+		os=unos
+		;;
+	*-ns)
+		os=genix
+		;;
+	i370-*)
+		os=mvs
+		;;
+	*-gould)
+		os=sysv
+		;;
+	*-highlevel)
+		os=bsd
+		;;
+	*-encore)
+		os=bsd
+		;;
+	*-sgi)
+		os=irix
+		;;
+	*-siemens)
+		os=sysv4
+		;;
+	*-masscomp)
+		os=rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=uxpv
+		;;
+	*-rom68k)
+		os=coff
+		;;
+	*-*bug)
+		os=coff
+		;;
+	*-apple)
+		os=macos
+		;;
+	*-atari*)
+		os=mint
+		;;
+	*-wrs)
+		os=vxworks
+		;;
+	*)
+		os=none
+		;;
+esac
+
+fi
+
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+	# Sometimes we do "kernel-libc", so those need to count as OSes.
+	musl* | newlib* | relibc* | uclibc*)
+		;;
+	# Likewise for "kernel-abi"
+	eabi* | gnueabi*)
+		;;
+	# VxWorks passes extra cpu info in the 4th filed.
+	simlinux | simwindows | spe)
+		;;
+	# Now accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST end in a * to match a version number.
+	gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
+	     | hiux* | abug | nacl* | netware* | windows* \
+	     | os9* | macos* | osx* | ios* \
+	     | mpw* | magic* | mmixware* | mon960* | lnews* \
+	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
+	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+	     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
+	     | chorusrdb* | cegcc* | glidix* | serenity* \
+	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+	     | midipix* | mingw32* | mingw64* | mint* \
+	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+	     | interix* | uwin* | mks* | rhapsody* | darwin* \
+	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
+	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
+	     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+	     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+	     | fiwix* )
+		;;
+	# This one is extra strict with allowed versions
+	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		;;
+	none)
+		;;
+	*)
+		echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+		   | linux-musl* | linux-relibc* | linux-uclibc* )
+		;;
+	uclinux-uclibc* )
+		;;
+	-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+		# These are just libc implementations, not actual OSes, and thus
+		# require a kernel.
+		echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+		exit 1
+		;;
+	kfreebsd*-gnu* | kopensolaris*-gnu*)
+		;;
+	vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+		;;
+	nto-qnx*)
+		;;
+	os2-emx)
+		;;
+	*-eabi* | *-gnueabi*)
+		;;
+	-*)
+		# Blank kernel with real OS is always fine.
+		;;
+	*-*)
+		echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+		exit 1
+		;;
+esac
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+case $vendor in
+	unknown)
+		case $cpu-$os in
+			*-riscix*)
+				vendor=acorn
+				;;
+			*-sunos*)
+				vendor=sun
+				;;
+			*-cnk* | *-aix*)
+				vendor=ibm
+				;;
+			*-beos*)
+				vendor=be
+				;;
+			*-hpux*)
+				vendor=hp
+				;;
+			*-mpeix*)
+				vendor=hp
+				;;
+			*-hiux*)
+				vendor=hitachi
+				;;
+			*-unos*)
+				vendor=crds
+				;;
+			*-dgux*)
+				vendor=dg
+				;;
+			*-luna*)
+				vendor=omron
+				;;
+			*-genix*)
+				vendor=ns
+				;;
+			*-clix*)
+				vendor=intergraph
+				;;
+			*-mvs* | *-opened*)
+				vendor=ibm
+				;;
+			*-os400*)
+				vendor=ibm
+				;;
+			s390-* | s390x-*)
+				vendor=ibm
+				;;
+			*-ptx*)
+				vendor=sequent
+				;;
+			*-tpf*)
+				vendor=ibm
+				;;
+			*-vxsim* | *-vxworks* | *-windiss*)
+				vendor=wrs
+				;;
+			*-aux*)
+				vendor=apple
+				;;
+			*-hms*)
+				vendor=hitachi
+				;;
+			*-mpw* | *-macos*)
+				vendor=apple
+				;;
+			*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
+				vendor=atari
+				;;
+			*-vos*)
+				vendor=stratus
+				;;
+		esac
+		;;
+esac
+
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..410616f
--- /dev/null
+++ b/configure
@@ -0,0 +1,19902 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.72 for bluez 5.79.
+#
+#
+# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
+# Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else case e in #(
+  e) case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" ""	$as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed 'exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else case e in #(
+  e) case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
+
+else case e in #(
+  e) exitcode=1; echo positional parameters were not saved. ;;
+esac
+fi
+test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null
+then :
+  as_have_required=yes
+else case e in #(
+  e) as_have_required=no ;;
+esac
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
+
+else case e in #(
+  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else case e in #(
+  e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi ;;
+esac
+fi
+
+
+      if test "x$CONFIG_SHELL" != x
+then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed 'exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno
+then :
+  printf "%s\n" "$0: This script requires a shell more modern than all"
+  printf "%s\n" "$0: the shells that I found on your system."
+  if test ${ZSH_VERSION+y} ; then
+    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi ;;
+esac
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else case e in #(
+  e) as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  } ;;
+esac
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else case e in #(
+  e) as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  } ;;
+esac
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  printf "%s\n" "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      t clear
+      :clear
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n.  New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+    # In both cases, we have to default to 'cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+
+# Sed expression to map a string onto a valid variable name.
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='bluez'
+PACKAGE_TARNAME='bluez'
+PACKAGE_VERSION='5.79'
+PACKAGE_STRING='bluez 5.79'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_default_prefix=/usr/local
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_c_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+PLUGIN_PHONEBOOK
+LIBEDATESERVER_LIBS
+LIBEDATESERVER_CFLAGS
+LIBEBOOK_LIBS
+LIBEBOOK_CFLAGS
+SPEEXDSP_LIBS
+SPEEXDSP_CFLAGS
+SBC_LIBS
+SBC_CFLAGS
+ANDROID_FALSE
+ANDROID_TRUE
+MESH_STORAGEDIR
+CONFIGDIR
+PKGLIBEXECDIR
+PKGBINDIR
+ADMIN_FALSE
+ADMIN_TRUE
+LOGGER_FALSE
+LOGGER_TRUE
+HID2HCI_FALSE
+HID2HCI_TRUE
+SIXAXIS_FALSE
+SIXAXIS_TRUE
+EXTERNAL_PLUGINS_FALSE
+EXTERNAL_PLUGINS_TRUE
+DEPRECATED_FALSE
+DEPRECATED_TRUE
+EXPERIMENTAL_FALSE
+EXPERIMENTAL_TRUE
+TESTING_FALSE
+TESTING_TRUE
+RUN_RST2MAN_FALSE
+RUN_RST2MAN_TRUE
+MANPAGES_FALSE
+MANPAGES_TRUE
+RST2MAN
+DATAFILES_FALSE
+DATAFILES_TRUE
+SYSTEMD_USERUNITDIR
+SYSTEMD_SYSTEMUNITDIR
+SYSTEMD_FALSE
+SYSTEMD_TRUE
+READLINE_FALSE
+READLINE_TRUE
+CLIENT_FALSE
+CLIENT_TRUE
+LIBSHARED_ELL_FALSE
+LIBSHARED_ELL_TRUE
+EXTERNAL_ELL_FALSE
+EXTERNAL_ELL_TRUE
+ELL_LIBS
+ELL_CFLAGS
+BTPCLIENT_FALSE
+BTPCLIENT_TRUE
+OBEX_FALSE
+OBEX_TRUE
+ICAL_LIBS
+ICAL_CFLAGS
+ALSA_LIBS
+ALSA_CFLAGS
+MIDI_FALSE
+MIDI_TRUE
+JSONC_LIBS
+JSONC_CFLAGS
+MESH_FALSE
+MESH_TRUE
+CUPS_SERVERBIN
+CUPS_SERVERBIN_FALSE
+CUPS_SERVERBIN_TRUE
+CUPS_FALSE
+CUPS_TRUE
+UDEV_DIR
+UDEV_LIBS
+UDEV_CFLAGS
+MONITOR_FALSE
+MONITOR_TRUE
+TOOLS_FALSE
+TOOLS_TRUE
+ASHA_FALSE
+ASHA_TRUE
+CSIP_FALSE
+CSIP_TRUE
+MICP_FALSE
+MICP_TRUE
+VCP_FALSE
+VCP_TRUE
+CCP_FALSE
+CCP_TRUE
+MCP_FALSE
+MCP_TRUE
+BASS_FALSE
+BASS_TRUE
+BAP_FALSE
+BAP_TRUE
+HEALTH_FALSE
+HEALTH_TRUE
+HOG_FALSE
+HOG_TRUE
+HID_FALSE
+HID_TRUE
+NETWORK_FALSE
+NETWORK_TRUE
+AVRCP_FALSE
+AVRCP_TRUE
+A2DP_FALSE
+A2DP_TRUE
+SAP_FALSE
+SAP_TRUE
+NFC_FALSE
+NFC_TRUE
+TEST_FALSE
+TEST_TRUE
+LIBRARY_FALSE
+LIBRARY_TRUE
+BACKTRACE_LIBS
+BACKTRACE_CFLAGS
+ZSH_COMPLETIONS_FALSE
+ZSH_COMPLETIONS_TRUE
+ZSH_COMPLETIONDIR
+DBUS_SESSIONBUSDIR
+DBUS_SYSTEMBUSDIR
+DBUS_CONFDIR
+DBUS_LIBS
+DBUS_CFLAGS
+GTHREAD_LIBS
+GTHREAD_CFLAGS
+GLIB_LIBS
+GLIB_CFLAGS
+VALGRIND_FALSE
+VALGRIND_TRUE
+MISC_LDFLAGS
+MISC_CFLAGS
+ASAN_LIB
+DBUS_RUN_SESSION_FALSE
+DBUS_RUN_SESSION_TRUE
+COVERAGE_FALSE
+COVERAGE_TRUE
+enable_valgrind
+enable_dbus_run_session
+enable_coverage
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+ac_ct_AR
+AR
+DLLTOOL
+OBJDUMP
+FILECMD
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+WARNING_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+CSCOPE
+ETAGS
+CTAGS
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_maintainer_mode
+enable_dependency_tracking
+enable_static
+enable_shared
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_optimization
+enable_asan
+enable_lsan
+enable_ubsan
+enable_debug
+enable_pie
+enable_threads
+with_dbusconfdir
+with_dbussystembusdir
+with_dbussessionbusdir
+with_zsh_completion_dir
+enable_backtrace
+enable_library
+enable_test
+enable_nfc
+enable_sap
+enable_a2dp
+enable_avrcp
+enable_network
+enable_hid
+enable_hog
+enable_health
+enable_bap
+enable_bass
+enable_mcp
+enable_ccp
+enable_vcp
+enable_micp
+enable_csip
+enable_asha
+enable_tools
+enable_monitor
+enable_udev
+with_udevdir
+enable_cups
+enable_mesh
+enable_midi
+enable_obex
+enable_btpclient
+enable_external_ell
+enable_client
+enable_systemd
+with_systemdsystemunitdir
+with_systemduserunitdir
+enable_datafiles
+enable_manpages
+enable_testing
+enable_experimental
+enable_deprecated
+enable_external_plugins
+enable_sixaxis
+enable_hid2hci
+enable_logger
+enable_admin
+enable_android
+with_phonebook
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+LT_SYS_LIBRARY_PATH
+GLIB_CFLAGS
+GLIB_LIBS
+GTHREAD_CFLAGS
+GTHREAD_LIBS
+DBUS_CFLAGS
+DBUS_LIBS
+UDEV_CFLAGS
+UDEV_LIBS
+JSONC_CFLAGS
+JSONC_LIBS
+ALSA_CFLAGS
+ALSA_LIBS
+ICAL_CFLAGS
+ICAL_LIBS
+ELL_CFLAGS
+ELL_LIBS
+SBC_CFLAGS
+SBC_LIBS
+SPEEXDSP_CFLAGS
+SPEEXDSP_LIBS
+LIBEBOOK_CFLAGS
+LIBEBOOK_LIBS
+LIBEDATESERVER_CFLAGS
+LIBEDATESERVER_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: '$ac_useropt'"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: '$ac_useropt'"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: '$ac_useropt'"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: '$ac_useropt'"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: '$ac_option'
+Try '$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir runstatedir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: '$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+'configure' configures bluez 5.79 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print 'checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for '--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or '..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, 'make install' will install all the files in
+'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than '$ac_default_prefix' using '--prefix',
+for instance '--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/bluez]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of bluez 5.79:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-maintainer-mode
+                          enable make rules and dependencies not useful (and
+                          sometimes confusing) to the casual installer
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --enable-static[=PKGS]  build static libraries [default=no]
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --disable-optimization  disable code optimization through compiler
+  --enable-asan           enable linking with address sanitizer
+  --enable-lsan           enable linking with address sanitizer
+  --enable-ubsan          enable linking with address sanitizer
+  --enable-debug          enable compiling with debugging information
+  --enable-pie            enable position independent executables flag
+  --enable-threads        enable threading support
+  --enable-backtrace      compile backtrace support
+  --enable-library        install Bluetooth library
+  --enable-test           enable test/example scripts
+  --enable-nfc            enable NFC paring
+  --enable-sap            enable SAP profile
+  --disable-a2dp          disable A2DP profile
+  --disable-avrcp         disable AVRCP profile
+  --disable-network       disable network profiles
+  --disable-hid           disable HID profile
+  --disable-hog           disable HoG profile
+  --enable-health         enable health profiles
+  --disable-bap           disable BAP profile
+  --disable-bass          disable BASS service
+  --disable-mcp           disable MCP profile
+  --disable-ccp           disable CCP profile
+  --disable-vcp           disable VCP profile
+  --disable-micp          disable MICP profile
+  --disable-csip          disable CSIP profile
+  --disable-asha          disable ASHA support
+  --disable-tools         disable Bluetooth tools
+  --disable-monitor       disable Bluetooth monitor
+  --disable-udev          disable udev device support
+  --disable-cups          disable CUPS printer support
+  --enable-mesh           enable Mesh profile support
+  --enable-midi           enable MIDI support
+  --disable-obex          disable OBEX profile support
+  --enable-btpclient      enable BTP client
+  --enable-external-ell   enable external Embedded Linux library
+  --disable-client        disable command line client
+  --disable-systemd       disable systemd integration
+  --disable-datafiles     do not install configuration and data files
+  --disable-manpages      disable building of manual pages
+  --enable-testing        enable testing tools
+  --enable-experimental   enable experimental tools
+  --enable-deprecated     enable deprecated tools
+  --enable-external-plugins
+                          enable support for external plugins
+  --enable-sixaxis        enable sixaxis plugin
+  --enable-hid2hci        enable hid2hci tool
+  --enable-logger         enable HCI logger service
+  --enable-admin          enable admin policy plugin
+  --enable-android        enable BlueZ for Android
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-aix-soname=aix|svr4|both
+                          shared library versioning (aka "SONAME") variant to
+                          provide on AIX, [default=aix].
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot[=DIR]    Search for dependent libraries within DIR (or the
+                          compiler's sysroot if not specified).
+  --with-dbusconfdir=DIR  path to D-Bus configuration directory
+  --with-dbussystembusdir=DIR
+                          path to D-Bus system bus services directory
+  --with-dbussessionbusdir=DIR
+                          path to D-Bus session bus services directory
+  --with-zsh-completion-dir=DIR
+                          path to install zsh completions
+  --with-udevdir=DIR      path to udev directory
+  --with-systemdsystemunitdir=DIR
+                          path to systemd system unit directory
+  --with-systemduserunitdir=DIR
+                          path to systemd user unit directory
+  --with-phonebook=PLUGIN obexd phonebook plugin (default=dummy)
+
+Some influential environment variables:
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  LT_SYS_LIBRARY_PATH
+              User-defined run-time library search path.
+  GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config
+  GLIB_LIBS   linker flags for GLIB, overriding pkg-config
+  GTHREAD_CFLAGS
+              C compiler flags for GTHREAD, overriding pkg-config
+  GTHREAD_LIBS
+              linker flags for GTHREAD, overriding pkg-config
+  DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
+  DBUS_LIBS   linker flags for DBUS, overriding pkg-config
+  UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
+  UDEV_LIBS   linker flags for UDEV, overriding pkg-config
+  JSONC_CFLAGS
+              C compiler flags for JSONC, overriding pkg-config
+  JSONC_LIBS  linker flags for JSONC, overriding pkg-config
+  ALSA_CFLAGS C compiler flags for ALSA, overriding pkg-config
+  ALSA_LIBS   linker flags for ALSA, overriding pkg-config
+  ICAL_CFLAGS C compiler flags for ICAL, overriding pkg-config
+  ICAL_LIBS   linker flags for ICAL, overriding pkg-config
+  ELL_CFLAGS  C compiler flags for ELL, overriding pkg-config
+  ELL_LIBS    linker flags for ELL, overriding pkg-config
+  SBC_CFLAGS  C compiler flags for SBC, overriding pkg-config
+  SBC_LIBS    linker flags for SBC, overriding pkg-config
+  SPEEXDSP_CFLAGS
+              C compiler flags for SPEEXDSP, overriding pkg-config
+  SPEEXDSP_LIBS
+              linker flags for SPEEXDSP, overriding pkg-config
+  LIBEBOOK_CFLAGS
+              C compiler flags for LIBEBOOK, overriding pkg-config
+  LIBEBOOK_LIBS
+              linker flags for LIBEBOOK, overriding pkg-config
+  LIBEDATESERVER_CFLAGS
+              C compiler flags for LIBEDATESERVER, overriding pkg-config
+  LIBEDATESERVER_LIBS
+              linker flags for LIBEDATESERVER, overriding pkg-config
+
+Use these variables to override the choices made by 'configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for configure.gnu first; this name is used for a wrapper for
+    # Metaconfig's "Configure" on case-insensitive file systems.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+bluez configure 5.79
+generated by GNU Autoconf 2.72
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest.beam
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext
+then :
+  ac_retval=0
+else case e in #(
+  e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1 ;;
+esac
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }
+then :
+  ac_retval=0
+else case e in #(
+  e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1 ;;
+esac
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  eval "$3=yes"
+else case e in #(
+  e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$3
+	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+   which can conflict with char $2 (void); below.  */
+
+#include <limits.h>
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 (void);
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main (void)
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  eval "$3=yes"
+else case e in #(
+  e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$3
+	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  eval ac_save_FLAGS=\$$6
+  as_fn_append $6 " $5"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main (void)
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  eval "$3=yes"
+else case e in #(
+  e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+  eval $6=\$ac_save_FLAGS
+ ;;
+esac
+fi
+eval ac_res=\$$3
+	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_check_decl
+ac_configure_args_raw=
+for ac_arg
+do
+  case $ac_arg in
+  *\'*)
+    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+  esac
+  as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+  *$as_nl*)
+    ac_safe_unquote= ;;
+  *)
+    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
+    ac_unsafe_a="$ac_unsafe_z#~"
+    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by bluez $as_me 5.79, which was
+generated by GNU Autoconf 2.72.  Invocation command line was
+
+  $ $0$ac_configure_args_raw
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    printf "%s\n" "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Sanitize IFS.
+  IFS=" ""	$as_nl"
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    printf "%s\n" "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    printf "%s\n" "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      printf "%s\n" "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      printf "%s\n" "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	printf "%s\n" "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      printf "%s\n" "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      printf "%s\n" "$as_me: caught signal $ac_signal"
+    printf "%s\n" "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+printf "%s\n" "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  ac_site_files="$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
+else
+  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+fi
+
+for ac_site_file in $ac_site_files
+do
+  case $ac_site_file in #(
+  */*) :
+     ;; #(
+  *) :
+    ac_site_file=./$ac_site_file ;;
+esac
+  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See 'config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+   Do not test the value of __STDC__, because some compilers set it to 0
+   while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (char **p, int i)
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* C89 style stringification. */
+#define noexpand_stringify(a) #a
+const char *stringified = noexpand_stringify(arbitrary+token=sequence);
+
+/* C89 style token pasting.  Exercises some of the corner cases that
+   e.g. old MSVC gets wrong, but not very hard. */
+#define noexpand_concat(a,b) a##b
+#define expand_concat(a,b) noexpand_concat(a,b)
+extern int vA;
+extern int vbee;
+#define aye A
+#define bee B
+int *pvA = &expand_concat(v,aye);
+int *pvbee = &noexpand_concat(v,bee);
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not \xHH hex character constants.
+   These do not provoke an error unfortunately, instead are silently treated
+   as an "x".  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
+   array size at least.  It is necessary to write \x00 == 0 to get something
+   that is true only with -std.  */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+               int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+/* Does the compiler advertise C99 conformance? */
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+// See if C++-style comments work.
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+extern void free (void *);
+
+// Check varargs macros.  These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+  int x = 1234;
+  int y = 5678;
+  debug ("Flag");
+  debug ("X = %d\n", x);
+  showlist (The first, second, and third items.);
+  report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+  #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+  #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+  int datasize;
+  double data[];
+};
+
+struct named_init {
+  int number;
+  const wchar_t *name;
+  double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+  // Iterate through items via the restricted pointer.
+  // Also check for declarations in for loops.
+  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+    continue;
+  return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  va_list args_copy;
+  va_copy (args_copy, args);
+
+  const char *str = "";
+  int number = 0;
+  float fnumber = 0;
+
+  while (*format)
+    {
+      switch (*format++)
+	{
+	case '\''s'\'': // string
+	  str = va_arg (args_copy, const char *);
+	  break;
+	case '\''d'\'': // int
+	  number = va_arg (args_copy, int);
+	  break;
+	case '\''f'\'': // float
+	  fnumber = va_arg (args_copy, double);
+	  break;
+	default:
+	  break;
+	}
+    }
+  va_end (args_copy);
+  va_end (args);
+
+  return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+  // Check bool.
+  _Bool success = false;
+  success |= (argc != 0);
+
+  // Check restrict.
+  if (test_restrict ("String literal") == 0)
+    success = true;
+  char *restrict newvar = "Another string";
+
+  // Check varargs.
+  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+  test_varargs_macros ();
+
+  // Check flexible array members.
+  struct incomplete_array *ia =
+    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+  ia->datasize = 10;
+  for (int i = 0; i < ia->datasize; ++i)
+    ia->data[i] = i * 1.234;
+  // Work around memory leak warnings.
+  free (ia);
+
+  // Check named initializers.
+  struct named_init ni = {
+    .number = 34,
+    .name = L"Test wide string",
+    .average = 543.34343,
+  };
+
+  ni.number = 58;
+
+  int dynamic_array[ni.number];
+  dynamic_array[0] = argv[0][0];
+  dynamic_array[ni.number - 1] = 543;
+
+  // work around unused variable warnings
+  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+	 || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+/* Does the compiler advertise C11 conformance? */
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+  int_alignment = _Alignof (int),
+  int_array_alignment = _Alignof (int[100]),
+  char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+  int x;
+  _Static_assert (sizeof (int) <= sizeof (long int),
+                  "_Static_assert does not work in struct");
+  long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+  union {
+    struct { int i; int j; };
+    struct { int k; long int l; } w;
+  };
+  int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+  _Static_assert ((offsetof (struct anonymous, i)
+		   == offsetof (struct anonymous, w.k)),
+		  "Anonymous union alignment botch");
+  v1.i = 2;
+  v1.w.k = 5;
+  ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+  int ok = 0;
+  ${ac_c_conftest_c89_main}
+  ${ac_c_conftest_c99_main}
+  ${ac_c_conftest_c11_main}
+  return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+  int ok = 0;
+  ${ac_c_conftest_c89_main}
+  ${ac_c_conftest_c99_main}
+  return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+  int ok = 0;
+  ${ac_c_conftest_c89_main}
+  return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub ltmain.sh compile missing install-sh"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+  as_found=:
+
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}:  trying $as_dir" >&5
+  ac_aux_dir_found=yes
+  ac_install_sh=
+  for ac_aux in $ac_aux_files
+  do
+    # As a special case, if "install-sh" is required, that requirement
+    # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+    # and $ac_install_sh is set appropriately for whichever one is found.
+    if test x"$ac_aux" = x"install-sh"
+    then
+      if test -f "${as_dir}install-sh"; then
+        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install-sh found" >&5
+        ac_install_sh="${as_dir}install-sh -c"
+      elif test -f "${as_dir}install.sh"; then
+        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install.sh found" >&5
+        ac_install_sh="${as_dir}install.sh -c"
+      elif test -f "${as_dir}shtool"; then
+        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}shtool found" >&5
+        ac_install_sh="${as_dir}shtool install -c"
+      else
+        ac_aux_dir_found=no
+        if $ac_first_candidate; then
+          ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+        else
+          break
+        fi
+      fi
+    else
+      if test -f "${as_dir}${ac_aux}"; then
+        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}${ac_aux} found" >&5
+      else
+        ac_aux_dir_found=no
+        if $ac_first_candidate; then
+          ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+        else
+          break
+        fi
+      fi
+    fi
+  done
+  if test "$ac_aux_dir_found" = yes; then
+    ac_aux_dir="$as_dir"
+    break
+  fi
+  ac_first_candidate=false
+
+  as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else case e in #(
+  e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;;
+esac
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+  ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+  ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+  ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'" >&5
+printf "%s\n" "$as_me:   former value:  '$ac_old_val'" >&2;}
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'" >&5
+printf "%s\n" "$as_me:   current value: '$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
+	    and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+am__api_version='1.16'
+
+
+
+  # Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test ${ac_cv_path_install+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+  ./ | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+ ;;
+esac
+fi
+  if test ${ac_cv_path_install+y}; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+printf %s "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+	&& test "$*" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was 's,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
+
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+
+  if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
+printf %s "checking for a race-free mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test ${ac_cv_path_mkdir+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
+	   case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir ('*'coreutils) '* | \
+	     *'BusyBox '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+ ;;
+esac
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test ${ac_cv_path_mkdir+y}; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use plain mkdir -p,
+    # in the hope it doesn't have the bugs of ancient mkdir.
+    MKDIR_P='mkdir -p'
+  fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+printf "%s\n" "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AWK+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+printf "%s\n" "$AWK" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval test \${ac_cv_prog_make_${ac_make}_set+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make ;;
+esac
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+  SET_MAKE=
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test ${enable_silent_rules+y}
+then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+printf %s "checking whether $am_make supports nested variables... " >&6; }
+if test ${am_cv_make_support_nested_variables+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if printf "%s\n" 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='bluez'
+ VERSION='5.79'
+
+
+printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
+
+
+printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5
+printf %s "checking how to create a pax tar archive... " >&6; }
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_pax-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        { echo "$as_me:$LINENO: $_am_tar --version" >&5
+   ($_am_tar --version) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && break
+      done
+      am__tar="$_am_tar --format=posix -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=posix -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x pax -w "$$tardir"'
+      am__tar_='pax -L -x pax -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H pax -L'
+      am__tar_='find "$tardir" -print | cpio -o -H pax -L'
+      am__untar='cpio -i -H pax -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_pax}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+   (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+   ($am__untar <conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+      { echo "$as_me:$LINENO: cat conftest.dir/file" >&5
+   (cat conftest.dir/file) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  if test ${am_cv_prog_tar_pax+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) am_cv_prog_tar_pax=$_am_tool ;;
+esac
+fi
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5
+printf "%s\n" "$am_cv_prog_tar_pax" >&6; }
+
+
+
+
+
+# Variables for tags utilities; see am/tags.am
+if test -z "$CTAGS"; then
+  CTAGS=ctags
+fi
+
+if test -z "$ETAGS"; then
+  ETAGS=etags
+fi
+
+if test -z "$CSCOPE"; then
+  CSCOPE=cscope
+fi
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Check whether --enable-silent-rules was given.
+if test ${enable_silent_rules+y}
+then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+printf %s "checking whether $am_make supports nested variables... " >&6; }
+if test ${am_cv_make_support_nested_variables+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if printf "%s\n" 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test ${enable_maintainer_mode+y}
+then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else case e in #(
+  e) USE_MAINTAINER_MODE=no ;;
+esac
+fi
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+printf "%s\n" "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PKG_CONFIG+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+printf "%s\n" "$PKG_CONFIG" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_PKG_CONFIG+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+	else
+		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+		PKG_CONFIG=""
+	fi
+fi
+
+
+	with_cflags=""
+	if (test "$USE_MAINTAINER_MODE" = "yes"); then
+		with_cflags="$with_cflags -Wall -Werror -Wextra"
+		with_cflags="$with_cflags -Wno-unused-parameter"
+		with_cflags="$with_cflags -Wno-missing-field-initializers"
+		with_cflags="$with_cflags -Wdeclaration-after-statement"
+		with_cflags="$with_cflags -Wmissing-declarations"
+		with_cflags="$with_cflags -Wredundant-decls"
+		with_cflags="$with_cflags -Wcast-align"
+		with_cflags="$with_cflags -Wswitch-enum"
+		with_cflags="$with_cflags -Wformat -Wformat-security"
+		with_cflags="$with_cflags -DG_DISABLE_DEPRECATED"
+		with_cflags="$with_cflags -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28"
+		with_cflags="$with_cflags -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32"
+	fi
+	WARNING_CFLAGS=$with_cflags
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+   (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+  case $?:`cat confinc.out 2>/dev/null` in #(
+  '0:this is the am__doit target') :
+    case $s in #(
+  BSD) :
+    am__include='.include' am__quote='"' ;; #(
+  *) :
+    am__include='include' am__quote='' ;;
+esac ;; #(
+  *) :
+     ;;
+esac
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+printf "%s\n" "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test ${enable_dependency_tracking+y}
+then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
+  fi
+fi
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}clang"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="clang"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See 'config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
+# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an '-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else case e in #(
+  e) ac_file='' ;;
+esac
+fi
+if test -z "$ac_file"
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See 'config.log' for more details" "$LINENO" 5; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; } ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+then :
+  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
+# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will
+# work properly (i.e., refer to 'conftest.exe'), while it won't with
+# 'rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else case e in #(
+  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main (void)
+{
+FILE *f = fopen ("conftest.out", "w");
+ if (!f)
+  return 1;
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
+If you meant to cross compile, use '--host'.
+See 'config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext \
+  conftest.o conftest.obj conftest.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else case e in #(
+  e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_compiler_gnu=yes
+else case e in #(
+  e) ac_compiler_gnu=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+y}
+ac_save_CFLAGS=$CFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_g=yes
+else case e in #(
+  e) CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+  e) ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c11" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+     CC="$CC $ac_cv_prog_cc_c11" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+  ac_prog_cc_stdc=c11 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c99" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+     CC="$CC $ac_cv_prog_cc_c99" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+  ac_prog_cc_stdc=c99 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c89" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+     CC="$CC $ac_cv_prog_cc_c89" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+  ac_prog_cc_stdc=c89 ;;
+esac
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+printf %s "checking whether $CC understands -c and -o together... " >&6; }
+if test ${am_cv_prog_cc_c_o+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+printf %s "checking dependency style of $depcc... " >&6; }
+if test ${am_cv_CC_dependencies_compiler_type+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
+printf %s "checking for C/C++ restrict keyword... " >&6; }
+if test ${ac_cv_c_restrict+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_c_restrict=no
+   # Put '__restrict__' first, to avoid problems with glibc and non-GCC; see:
+   # https://lists.gnu.org/archive/html/bug-autoconf/2016-02/msg00006.html
+   # Put 'restrict' last, because C++ lacks it.
+   for ac_kw in __restrict__ __restrict _Restrict restrict; do
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+typedef int *int_ptr;
+	   int foo (int_ptr $ac_kw ip) { return ip[0]; }
+	   int bar (int [$ac_kw]); /* Catch GCC bug 14050.  */
+	   int bar (int ip[$ac_kw]) { return ip[0]; }
+
+int
+main (void)
+{
+int s[1];
+	   int *$ac_kw t = s;
+	   t[0] = 0;
+	   return foo (t) + bar (t);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+     test "$ac_cv_c_restrict" != no && break
+   done
+   ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+printf "%s\n" "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+   restrict) ;;
+   no) printf "%s\n" "#define restrict /**/" >>confdefs.h
+ ;;
+   *)  printf "%s\n" "#define restrict $ac_cv_c_restrict" >>confdefs.h
+ ;;
+ esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
+  fi
+fi
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}clang"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="clang"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See 'config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_compiler_gnu=yes
+else case e in #(
+  e) ac_compiler_gnu=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+y}
+ac_save_CFLAGS=$CFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_g=yes
+else case e in #(
+  e) CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+  e) ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c11" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+     CC="$CC $ac_cv_prog_cc_c11" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+  ac_prog_cc_stdc=c11 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c99" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+     CC="$CC $ac_cv_prog_cc_c99" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+  ac_prog_cc_stdc=c99 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"
+then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+  e) if test "x$ac_cv_prog_cc_c89" = x
+then :
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+     CC="$CC $ac_cv_prog_cc_c89" ;;
+esac
+fi
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+  ac_prog_cc_stdc=c89 ;;
+esac
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+printf %s "checking whether $CC understands -c and -o together... " >&6; }
+if test ${am_cv_prog_cc_c_o+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+printf %s "checking dependency style of $depcc... " >&6; }
+if test ${am_cv_CC_dependencies_compiler_type+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fPIE" >&5
+printf %s "checking whether ${CC-cc} accepts -fPIE... " >&6; }
+if test ${ac_cv_prog_cc_pie+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+		echo 'void f(){}' > conftest.c
+		if test -z "`${CC-cc} -fPIE -pie -c conftest.c 2>&1`"; then
+			ac_cv_prog_cc_pie=yes
+		else
+			ac_cv_prog_cc_pie=no
+		fi
+		rm -rf conftest*
+	 ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_pie" >&5
+printf "%s\n" "$ac_cv_prog_cc_pie" >&6; }
+
+
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fsanitize=address" >&5
+printf %s "checking whether ${CC-cc} accepts -fsanitize=address... " >&6; }
+if test ${ac_cv_prog_cc_asan+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+		echo 'void f(){}' > asan.c
+		if test -z "`${CC-cc} -fsanitize=address -c asan.c 2>&1`"; then
+			ac_cv_prog_cc_asan=yes
+		else
+			ac_cv_prog_cc_asan=no
+		fi
+		rm -rf asan*
+        ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_asan" >&5
+printf "%s\n" "$ac_cv_prog_cc_asan" >&6; }
+
+
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fsanitize=leak" >&5
+printf %s "checking whether ${CC-cc} accepts -fsanitize=leak... " >&6; }
+if test ${ac_cv_prog_cc_lsan+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+		echo 'void f(){}' > lsan.c
+		if test -z "`${CC-cc} -fsanitize=leak -c lsan.c 2>&1`"; then
+			ac_cv_prog_cc_lsan=yes
+		else
+			ac_cv_prog_cc_lsan=no
+		fi
+		rm -rf lsan*
+	 ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_lsan" >&5
+printf "%s\n" "$ac_cv_prog_cc_lsan" >&6; }
+
+
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fsanitize=undefined" >&5
+printf %s "checking whether ${CC-cc} accepts -fsanitize=undefined... " >&6; }
+if test ${ac_cv_prog_cc_ubsan+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+		echo 'void f(){}' > ubsan.c
+		if test -z "`${CC-cc} -fsanitize=undefined -c ubsan.c 2>&1`"; then
+			ac_cv_prog_cc_ubsan=yes
+		else
+			ac_cv_prog_cc_ubsan=no
+		fi
+		rm -rf ubsan*
+	 ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_ubsan" >&5
+printf "%s\n" "$ac_cv_prog_cc_ubsan" >&6; }
+
+
+
+
+
+
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.7'
+macro_revision='2.4.7'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+
+  # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+printf %s "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case $ECHO in
+  printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+printf "%s\n" "printf" >&6; } ;;
+  print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+printf "%s\n" "print -r" >&6; } ;;
+  *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+printf "%s\n" "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+printf %s "checking for a sed that does not truncate output... " >&6; }
+if test ${ac_cv_path_SED+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)           ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in sed gsed
+   do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in #(
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+#(
+*)
+  ac_count=0
+  printf %s 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    printf "%s\n" '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+printf "%s\n" "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in grep ggrep
+   do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in #(
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+#(
+*)
+  ac_count=0
+  printf %s 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    printf "%s\n" 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in egrep
+   do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in #(
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+#(
+*)
+  ac_count=0
+  printf %s 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    printf "%s\n" 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+         EGREP_TRADITIONAL=$EGREP
+ ac_cv_path_EGREP_TRADITIONAL=$EGREP
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+printf %s "checking for fgrep... " >&6; }
+if test ${ac_cv_path_FGREP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in fgrep
+   do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in #(
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+#(
+*)
+  ac_count=0
+  printf %s 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    printf "%s\n" 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+printf "%s\n" "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test ${with_gnu_ld+y}
+then :
+  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else case e in #(
+  e) with_gnu_ld=no ;;
+esac
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+printf %s "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return, which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD=$ac_prog
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test yes = "$with_gnu_ld"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+printf %s "checking for GNU ld... " >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+printf %s "checking for non-GNU ld... " >&6; }
+fi
+if test ${lt_cv_path_LD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -z "$LD"; then
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD=$ac_dir/$ac_prog
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test no != "$with_gnu_ld" && break
+	;;
+      *)
+	test yes != "$with_gnu_ld" && break
+	;;
+      esac
+    fi
+  done
+  IFS=$lt_save_ifs
+else
+  lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi ;;
+esac
+fi
+
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
+if test ${lt_cv_prog_gnu_ld+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test ${lt_cv_path_NM+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM=$NM
+else
+  lt_nm_to_check=${ac_tool_prefix}nm
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS=$lt_save_ifs
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm=$ac_dir/$lt_tmp_nm
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+	case $build_os in
+	mingw*) lt_bad_file=conftest.nm/nofile ;;
+	*) lt_bad_file=/dev/null ;;
+	esac
+	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+	*$lt_bad_file* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break 2
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break 2
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS=$lt_save_ifs
+  done
+  : ${lt_cv_path_NM=no}
+fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+printf "%s\n" "$lt_cv_path_NM" >&6; }
+if test no != "$lt_cv_path_NM"; then
+  NM=$lt_cv_path_NM
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DUMPBIN+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+printf "%s\n" "$DUMPBIN" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols -headers"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test : != "$DUMPBIN"; then
+    NM=$DUMPBIN
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+printf %s "checking the name lister ($NM) interface... " >&6; }
+if test ${lt_cv_nm_interface+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+printf "%s\n" "$lt_cv_nm_interface" >&6; }
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+printf %s "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+printf "%s\n" "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+printf %s "checking the maximum length of command line arguments... " >&6; }
+if test ${lt_cv_sys_max_cmd_len+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)   i=0
+  teststring=ABCD
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test 17 != "$i" # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+ ;;
+esac
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
+printf "%s\n" "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+printf %s "checking how to convert $build file names to $host format... " >&6; }
+if test ${lt_cv_to_host_file_cmd+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+ ;;
+esac
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+printf %s "checking how to convert $build file names to toolchain format... " >&6; }
+if test ${lt_cv_to_tool_file_cmd+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+ ;;
+esac
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+printf %s "checking for $LD option to reload object files... " >&6; }
+if test ${lt_cv_ld_reload_flag+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_ld_reload_flag='-r' ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test yes != "$GCC"; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test yes = "$GCC"; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
+set dummy ${ac_tool_prefix}file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_FILECMD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$FILECMD"; then
+  ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_FILECMD="${ac_tool_prefix}file"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+FILECMD=$ac_cv_prog_FILECMD
+if test -n "$FILECMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
+printf "%s\n" "$FILECMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_FILECMD"; then
+  ac_ct_FILECMD=$FILECMD
+  # Extract the first word of "file", so it can be a program name with args.
+set dummy file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_FILECMD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_FILECMD"; then
+  ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_FILECMD="file"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
+if test -n "$ac_ct_FILECMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
+printf "%s\n" "$ac_ct_FILECMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_FILECMD" = x; then
+    FILECMD=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    FILECMD=$ac_ct_FILECMD
+  fi
+else
+  FILECMD="$ac_cv_prog_FILECMD"
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OBJDUMP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+printf "%s\n" "$OBJDUMP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+printf %s "checking how to recognize dependent libraries... " >&6; }
+if test ${lt_cv_deplibs_check_method+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='$FILECMD -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=$FILECMD
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=$FILECMD
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=$FILECMD
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd* | bitrig*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+os2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DLLTOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+printf "%s\n" "$DLLTOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+printf %s "checking how to associate runtime and link libraries... " >&6; }
+if test ${lt_cv_sharedlib_from_linklib_cmd+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh;
+  # decide which one to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd=$ECHO
+  ;;
+esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+
+
+
+
+
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+
+
+
+
+
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+printf %s "checking for archiver @FILE support... " >&6; }
+if test ${lt_cv_ar_at_file+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test 0 -eq "$ac_status"; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	if test 0 -ne "$ac_status"; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+   ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+printf "%s\n" "$lt_cv_ar_at_file" >&6; }
+
+if test no = "$lt_cv_ar_at_file"; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  bitrig* | openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+printf %s "checking command to parse $NM output from $compiler object... " >&6; }
+if test ${lt_cv_sys_global_symbol_pipe+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test ia64 = "$host_cpu"; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  # Gets list of data symbols to import.
+  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+  # Adjust the below global symbol transforms to fixup imported variables.
+  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+  lt_c_name_lib_hook="\
+  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+else
+  # Disable hooks by default.
+  lt_cv_sys_global_symbol_to_import=
+  lt_cdecl_hook=
+  lt_c_name_hook=
+  lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function,
+    # D for any global variable and I for any imported variable.
+    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
+	  LIBS=conftstm.$ac_objext
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest$ac_exeext; then
+	    pipe_works=yes
+	  fi
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test yes = "$pipe_works"; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+ ;;
+esac
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+printf "%s\n" "failed" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+printf "%s\n" "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+printf %s "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test ${with_sysroot+y}
+then :
+  withval=$with_sysroot;
+else case e in #(
+  e) with_sysroot=no ;;
+esac
+fi
+
+
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+   if test yes = "$GCC"; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+printf "%s\n" "$with_sysroot" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+printf "%s\n" "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+printf %s "checking for a working dd... " >&6; }
+if test ${ac_cv_path_lt_DD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+  ac_path_lt_DD_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_prog in dd
+   do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+      $ac_path_lt_DD_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_lt_DD"; then
+    :
+  fi
+else
+  ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+printf %s "checking how to truncate binary pipes... " >&6; }
+if test ${lt_cv_truncate_bin+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+printf "%s\n" "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in $*""; do
+      case $cc_temp in
+        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test ${enable_libtool_lock+y}
+then :
+  enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out what ABI is being produced by ac_compile, and set mode
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `$FILECMD conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE=32
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE=64
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test yes = "$lt_cv_prog_gnu_ld"; then
+      case `$FILECMD conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `$FILECMD conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+mips64*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    emul=elf
+    case `$FILECMD conftest.$ac_objext` in
+      *32-bit*)
+	emul="${emul}32"
+	;;
+      *64-bit*)
+	emul="${emul}64"
+	;;
+    esac
+    case `$FILECMD conftest.$ac_objext` in
+      *MSB*)
+	emul="${emul}btsmip"
+	;;
+      *LSB*)
+	emul="${emul}ltsmip"
+	;;
+    esac
+    case `$FILECMD conftest.$ac_objext` in
+      *N32*)
+	emul="${emul}n32"
+	;;
+    esac
+    LD="${LD-ld} -m $emul"
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.  Note that the listed cases only cover the
+  # situations where additional linker options are needed (such as when
+  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+  # vice versa); the common cases where no linker options are needed do
+  # not appear in the list.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `$FILECMD conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `$FILECMD conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS -belf"
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+printf %s "checking whether the C compiler needs -belf... " >&6; }
+if test ${lt_cv_cc_needs_belf+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  lt_cv_cc_needs_belf=yes
+else case e in #(
+  e) lt_cv_cc_needs_belf=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
+  if test yes != "$lt_cv_cc_needs_belf"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS=$SAVE_CFLAGS
+  fi
+  ;;
+*-*solaris*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `$FILECMD conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*|x86_64-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD=${LD-ld}_sol2
+        fi
+        ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks=$enable_libtool_lock
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_MANIFEST_TOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+printf "%s\n" "$MANIFEST_TOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+  fi
+else
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if test ${lt_cv_path_mainfest_tool+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; }
+if test yes != "$lt_cv_path_mainfest_tool"; then
+  MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DSYMUTIL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+printf "%s\n" "$DSYMUTIL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_NMEDIT+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+printf "%s\n" "$NMEDIT" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_NMEDIT+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+printf "%s\n" "$ac_ct_NMEDIT" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LIPO+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+printf "%s\n" "$LIPO" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LIPO+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+printf "%s\n" "$ac_ct_LIPO" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+printf "%s\n" "$OTOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+printf "%s\n" "$ac_ct_OTOOL" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL64+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+printf "%s\n" "$OTOOL64" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL64+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+printf "%s\n" "$ac_ct_OTOOL64" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+printf %s "checking for -single_module linker flag... " >&6; }
+if test ${lt_cv_apple_cc_single_mod+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_apple_cc_single_mod=no
+      if test -z "$LT_MULTI_MODULE"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	# If there is a non-empty error log, and "single_module"
+	# appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+	  cat conftest.err >&5
+	# Otherwise, if the output was created with a 0 exit code from
+	# the compiler, it worked.
+	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
+
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+printf %s "checking for -exported_symbols_list linker flag... " >&6; }
+if test ${lt_cv_ld_exported_symbols_list+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  lt_cv_ld_exported_symbols_list=yes
+else case e in #(
+  e) lt_cv_ld_exported_symbols_list=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS=$save_LDFLAGS
+     ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
+
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+printf %s "checking for -force_load linker flag... " >&6; }
+if test ${lt_cv_ld_force_load+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
+      $AR $AR_FLAGS libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+	cat conftest.err >&5
+      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+     ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+printf "%s\n" "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+    darwin*)
+      case $MACOSX_DEPLOYMENT_TARGET,$host in
+        10.[012],*|,*powerpc*-darwin[5-8]*)
+          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+        *)
+          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test yes = "$lt_cv_apple_cc_single_mod"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+    fi
+    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x$2 in
+    x)
+        ;;
+    *:)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+        ;;
+    x:*)
+        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+        ;;
+    *)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+  if test $ac_cache; then
+    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+      printf "%s\n" "#define $ac_item 1" >> confdefs.h
+    fi
+    ac_header= ac_cache=
+  elif test $ac_header; then
+    ac_cache=$ac_item
+  else
+    ac_header=$ac_item
+  fi
+done
+
+
+
+
+
+
+
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
+
+fi
+
+
+
+
+
+# Set options
+# Check whether --enable-static was given.
+if test ${enable_static+y}
+then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else case e in #(
+  e) enable_static=no ;;
+esac
+fi
+
+
+
+
+
+
+
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test ${enable_shared+y}
+then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else case e in #(
+  e) enable_shared=yes ;;
+esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test ${with_pic+y}
+then :
+  withval=$with_pic; lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for lt_pkg in $withval; do
+	IFS=$lt_save_ifs
+	if test "X$lt_pkg" = "X$lt_p"; then
+	  pic_mode=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else case e in #(
+  e) pic_mode=default ;;
+esac
+fi
+
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test ${enable_fast_install+y}
+then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else case e in #(
+  e) enable_fast_install=yes ;;
+esac
+fi
+
+
+
+
+
+
+
+
+  shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+printf %s "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test ${with_aix_soname+y}
+then :
+  withval=$with_aix_soname; case $withval in
+    aix|svr4|both)
+      ;;
+    *)
+      as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+      ;;
+    esac
+    lt_cv_with_aix_soname=$with_aix_soname
+else case e in #(
+  e) if test ${lt_cv_with_aix_soname+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_with_aix_soname=aix ;;
+esac
+fi
+
+    with_aix_soname=$lt_cv_with_aix_soname ;;
+esac
+fi
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+printf "%s\n" "$with_aix_soname" >&6; }
+  if test aix != "$with_aix_soname"; then
+    # For the AIX way of multilib, we name the shared archive member
+    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+    if test 64 = "${OBJECT_MODE-32}"; then
+      shared_archive_member_spec=shr_64
+    else
+      shared_archive_member_spec=shr
+    fi
+  fi
+  ;;
+*)
+  with_aix_soname=aix
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+printf %s "checking for objdir... " >&6; }
+if test ${lt_cv_objdir+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+printf "%s\n" "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test set != "${COLLECT_NAMES+set}"; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+printf %s "checking for ${ac_tool_prefix}file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/${ac_tool_prefix}file"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+printf %s "checking for file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/file"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC=$CC
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test yes = "$GCC"; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test ${lt_cv_prog_compiler_rtti_exceptions+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+  if test yes = "$GCC"; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      case $host_os in
+      os2*)
+	lt_prog_compiler_static='$wl-static'
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      if test -n "$lt_prog_compiler_pic"; then
+        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      case $cc_basename in
+      nagfor*)
+        # NAG Fortran compiler
+        lt_prog_compiler_wl='-Wl,-Wl,,'
+        lt_prog_compiler_pic='-PIC'
+        lt_prog_compiler_static='-Bstatic'
+        ;;
+      esac
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      case $host_os in
+      os2*)
+	lt_prog_compiler_static='$wl-static'
+	;;
+      esac
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='$wl-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64, which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # flang / f18. f95 an alias for gfortran or flang on Debian
+      flang* | f18* | f95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      nagfor*)
+	# NAG Fortran compiler
+	lt_prog_compiler_wl='-Wl,-Wl,,'
+	lt_prog_compiler_pic='-PIC'
+	lt_prog_compiler_static='-Bstatic'
+	;;
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | $SED 5q` in
+	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ F* | *Sun*Fortran*)
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Qoption ld '
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+        *Intel*\ [CF]*Compiler*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fPIC'
+	  lt_prog_compiler_static='-static'
+	  ;;
+	*Portland\ Group*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fpic'
+	  lt_prog_compiler_static='-Bstatic'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms that do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+printf %s "checking for $compiler option to produce PIC... " >&6; }
+if test ${lt_cv_prog_compiler_pic+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_pic=$lt_prog_compiler_pic ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test ${lt_cv_prog_compiler_pic_works+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works"; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test ${lt_cv_prog_compiler_static_works+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works"; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
+  # do not overwrite the value of need_locks provided by the user
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+printf %s "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+printf "%s\n" "$hard_links" >&6; }
+  if test no = "$hard_links"; then
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+  # as well as any symbol that contains 'd'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++ or Intel C++ Compiler.
+    if test yes != "$GCC"; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+    with_gnu_ld=yes
+    ;;
+  openbsd* | bitrig*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    link_all_deplibs=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test yes = "$with_gnu_ld"; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test yes = "$lt_use_gnu_ld_interface"; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='$wl'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+    export_dynamic_flag_spec='$wl--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test ia64 != "$host_cpu"; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='$wl--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file, use it as
+	# is; otherwise, prepend EXPORTS...
+	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+          cp $export_symbols $output_objdir/$soname.def;
+        else
+          echo EXPORTS > $output_objdir/$soname.def;
+          cat $export_symbols >> $output_objdir/$soname.def;
+        fi~
+        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      shrext_cmds=.dll
+      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      enable_shared_with_static_runtimes=yes
+      file_list_spec='@'
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+      export_dynamic_flag_spec='$wl-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test linux-dietlibc = "$host_os"; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test no = "$tmp_diet"
+      then
+	tmp_addflag=' $pic_flag'
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+        nagfor*)                        # NAGFOR 5.3
+          tmp_sharedflag='-Wl,-shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | $SED 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+        if test yes = "$supports_anon_versioning"; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            echo "local: *; };" >> $output_objdir/$libname.ver~
+            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	tcc*)
+	  hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	  export_dynamic_flag_spec='-rdynamic'
+	  ;;
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+	  if test yes = "$supports_anon_versioning"; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              echo "local: *; };" >> $output_objdir/$libname.ver~
+              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test no = "$ld_shlibs"; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test ia64 = "$host_cpu"; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
+	# Without the "-l" option, or with the "-B" option, AIX nm treats
+	# weak defined symbols like other global defined symbols, whereas
+	# GNU nm marks them as "W".
+	# While the 'weak' keyword is ignored in the Export File, we need
+	# it in the Import File for the 'aix-soname' feature, so we have
+	# to replace the "-B" option with "-P" for AIX nm.
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# have runtime linking enabled, and use it for executables.
+	# For shared libraries, we enable/disable runtime linking
+	# depending on the kind of the shared library created -
+	# when "with_aix_soname,aix_use_runtimelinking" is:
+	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "aix,yes"  lib.so          shared, rtl:yes, for executables
+	#            lib.a           static archive
+	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
+	#            lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a(lib.so.V) shared, rtl:no
+	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a           static archive
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
+	    # so we don't have lib.a shared libs to link our executables.
+	    # We have to force runtime linking in this case.
+	    aix_use_runtimelinking=yes
+	    LDFLAGS="$LDFLAGS -Wl,-brtl"
+	  fi
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='$wl-f,'
+      case $with_aix_soname,$aix_use_runtimelinking in
+      aix,*) ;; # traditional, no import file
+      svr4,* | *,yes) # use import file
+	# The Import File defines what to hardcode.
+	hardcode_direct=no
+	hardcode_direct_absolute=no
+	;;
+      esac
+
+      if test yes = "$GCC"; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`$CC -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test yes = "$aix_use_runtimelinking"; then
+	  shared_flag="$shared_flag "'$wl-G'
+	fi
+	# Need to ensure runtime linking is disabled for the traditional
+	# shared library, or the linker may eventually find shared libraries
+	# /with/ Import File - we do not want to mix them.
+	shared_flag_aix='-shared'
+	shared_flag_svr4='-shared $wl-G'
+      else
+	# not using gcc
+	if test ia64 = "$host_cpu"; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test yes = "$aix_use_runtimelinking"; then
+	    shared_flag='$wl-G'
+	  else
+	    shared_flag='$wl-bM:SRE'
+	  fi
+	  shared_flag_aix='$wl-bM:SRE'
+	  shared_flag_svr4='$wl-G'
+	fi
+      fi
+
+      export_dynamic_flag_spec='$wl-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if test ${lt_cv_aix_libpath_+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=/usr/lib:/lib
+  fi
+   ;;
+esac
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+      else
+	if test ia64 = "$host_cpu"; then
+	  hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if test ${lt_cv_aix_libpath_+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=/usr/lib:/lib
+  fi
+   ;;
+esac
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+	 hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' $wl-bernotok'
+	  allow_undefined_flag=' $wl-berok'
+	  if test yes = "$with_gnu_ld"; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+	  # -brtl affects multiple linker settings, -berok does not and is overridden later
+	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+	  if test svr4 != "$with_aix_soname"; then
+	    # This is similar to how AIX traditionally builds its shared libraries.
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+	  fi
+	  if test aix != "$with_aix_soname"; then
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+	  else
+	    # used by -dlpreopen to get the symbols
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+	  fi
+	  archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++ or Intel C++ Compiler.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl* | icl*)
+	# Native MSVC or ICC
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	always_export_symbols=yes
+	file_list_spec='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+            cp "$export_symbols" "$output_objdir/$soname.def";
+            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+          else
+            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+          fi~
+          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+          linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+	enable_shared_with_static_runtimes=yes
+	exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	old_postinstall_cmds='chmod 644 $oldlib'
+	postlink_cmds='lt_outputfile="@OUTPUT@"~
+          lt_tool_outputfile="@TOOL_OUTPUT@"~
+          case $lt_outputfile in
+            *.exe|*.EXE) ;;
+            *)
+              lt_outputfile=$lt_outputfile.exe
+              lt_tool_outputfile=$lt_tool_outputfile.exe
+              ;;
+          esac~
+          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+            $RM "$lt_outputfile.manifest";
+          fi'
+	;;
+      *)
+	# Assume MSVC and ICC wrapper
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	old_archive_from_new_cmds='true'
+	# FIXME: Should let the user specify the lib program.
+	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	enable_shared_with_static_runtimes=yes
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test yes = "$lt_cv_ld_force_load"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag=$_lt_dar_allow_undefined
+  case $cc_basename in
+     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test yes = "$_lt_dar_can_shared"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+    archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly* | midnightbsd*)
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test yes = "$GCC"; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='$wl-E'
+      ;;
+
+    hpux10*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test no = "$with_gnu_ld"; then
+	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='$wl-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+printf %s "checking if $CC understands -b... " >&6; }
+if test ${lt_cv_prog_compiler__b+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_prog_compiler__b=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
+
+if test yes = "$lt_cv_prog_compiler__b"; then
+    archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test no = "$with_gnu_ld"; then
+	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='$wl-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+	# This should be the same for all languages, so no per-tag cache variable.
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if test ${lt_cv_irix_exported_symbol+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) save_LDFLAGS=$LDFLAGS
+	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  lt_cv_irix_exported_symbol=yes
+else case e in #(
+  e) lt_cv_irix_exported_symbol=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+           LDFLAGS=$save_LDFLAGS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+	if test yes = "$lt_cv_irix_exported_symbol"; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+	fi
+	link_all_deplibs=no
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    linux*)
+      case $cc_basename in
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	ld_shlibs=yes
+	archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	;;
+      esac
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd* | bitrig*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+	  export_dynamic_flag_spec='$wl-E'
+	else
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      shrext_cmds=.dll
+      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      enable_shared_with_static_runtimes=yes
+      file_list_spec='@'
+      ;;
+
+    osf3*)
+      if test yes = "$GCC"; then
+	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test yes = "$GCC"; then
+	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+	archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test yes = "$GCC"; then
+	wlarc='$wl'
+	archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='$wl'
+	  archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands '-z linker_flag'.  GCC discards it without '$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test yes = "$GCC"; then
+	  whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test sequent = "$host_vendor"; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='$wl-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We CANNOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='$wl-z,text'
+      allow_undefined_flag='$wl-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='$wl-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='$wl-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test sni = "$host_vendor"; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='$wl-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+printf "%s\n" "$ld_shlibs" >&6; }
+test no = "$ld_shlibs" && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test yes,yes = "$GCC,$enable_shared"; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+printf %s "checking whether -lc should be explicitly linked in... " >&6; }
+if test ${lt_cv_archive_cmds_need_lc+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+	 ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+printf %s "checking dynamic linker characteristics... " >&6; }
+
+if test yes = "$GCC"; then
+  case $host_os in
+    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+    *) lt_awk_arg='/^libraries:/' ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+    *) lt_sed_strip_eq='s|=/|/|g' ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary...
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  # ...but if some path component already ends with the multilib dir we assume
+  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+  case "$lt_multi_os_dir; $lt_search_path_spec " in
+  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+    lt_multi_os_dir=
+    ;;
+  esac
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+    elif test -n "$lt_multi_os_dir"; then
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+  lt_foo = "";
+  lt_count = 0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo = "/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='$libname$release$shared_ext$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test ia64 = "$host_cpu"; then
+    # AIX 5 supports IA64
+    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line '#! .'.  This would cause the generated library to
+    # depend on '.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # Using Import Files as archive members, it is possible to support
+    # filename-based versioning of shared library archives on AIX. While
+    # this would work for both with and without runtime linking, it will
+    # prevent static linking of such archives. So we do filename-based
+    # shared library versioning with .so extension only, which is used
+    # when both runtime linking and shared linking is enabled.
+    # Unfortunately, runtime linking may impact performance, so we do
+    # not want this to be the default eventually. Also, we use the
+    # versioned .so libs for executables only if there is the -brtl
+    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+    # To allow for filename-based versioning support, we need to create
+    # libNAME.so.V as an archive file, containing:
+    # *) an Import File, referring to the versioned filename of the
+    #    archive as well as the shared archive member, telling the
+    #    bitwidth (32 or 64) of that shared object, and providing the
+    #    list of exported symbols of that shared object, eventually
+    #    decorated with the 'weak' keyword
+    # *) the shared object with the F_LOADONLY flag set, to really avoid
+    #    it being seen by the linker.
+    # At run time we better use the real file rather than another symlink,
+    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+    case $with_aix_soname,$aix_use_runtimelinking in
+    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    aix,yes) # traditional libtool
+      dynamic_linker='AIX unversionable lib.so'
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      ;;
+    aix,no) # traditional AIX only
+      dynamic_linker='AIX lib.a(lib.so.V)'
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      ;;
+    svr4,*) # full svr4 only
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,yes) # both, prefer svr4
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # unpreferred sharedlib libNAME.a needs extra handling
+      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,no) # both, prefer aix
+      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+      ;;
+    esac
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='$libname$shared_ext'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl* | *,icl*)
+    # Native MSVC or ICC
+    libname_spec='$name'
+    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+    library_names_spec='$libname.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec=$LIB
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC and ICC wrapper
+    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$major$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      soname_spec='$libname$release$shared_ext$major'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    if test 32 = "$HPUX_IA64_MODE"; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+    fi
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test yes = "$lt_cv_prog_gnu_ld"; then
+		version_type=linux # correct to gnu/linux during the next big refactor
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+linux*android*)
+  version_type=none # Android doesn't support versioned libraries.
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext'
+  soname_spec='$libname$release$shared_ext'
+  finish_cmds=
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  dynamic_linker='Android linker'
+  # Don't embed -rpath directories since the linker doesn't support them.
+  hardcode_libdir_flag_spec='-L$libdir'
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if test ${lt_cv_shlibpath_overrides_runpath+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
+then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+     ;;
+esac
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Ideally, we could use ldconfig to report *all* directores which are
+  # searched for libraries, however this is still not possible.  Aside from not
+  # being certain /sbin/ldconfig is available, command
+  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+  # even though it is searched at run-time.  Try to do the best guess by
+  # appending ld.so.conf contents (and includes) to the search path.
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd* | bitrig*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec=/usr/lib
+  need_lib_prefix=no
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    need_version=no
+  else
+    need_version=yes
+  fi
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+os2*)
+  libname_spec='$name'
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+  # OS/2 can only load a DLL with a base name of 8 characters or less.
+  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+    v=$($ECHO $release$versuffix | tr -d .-);
+    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+    $ECHO $n$v`$shared_ext'
+  library_names_spec='${libname}_dll.$libext'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=BEGINLIBPATH
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  postinstall_cmds='base_file=`basename \$file`~
+    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+    dldir=$destdir/`dirname \$dlpath`~
+    test -d \$dldir || mkdir -p \$dldir~
+    $install_prog $dir/$dlname \$dldir/$dlname~
+    chmod a+x \$dldir/$dlname~
+    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+    fi'
+  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+    dlpath=$dir/\$dldll~
+    $RM \$dlpath'
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test yes = "$with_gnu_ld"; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec; then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+    soname_spec='$libname$shared_ext.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=sco
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test yes = "$with_gnu_ld"; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+printf "%s\n" "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+printf %s "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test yes = "$hardcode_automatic"; then
+
+  # We can hardcode non-existent directories.
+  if test no != "$hardcode_direct" &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+     test no != "$hardcode_minus_L"; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+printf "%s\n" "$hardcode_action" >&6; }
+
+if test relink = "$hardcode_action" ||
+   test yes = "$inherit_rpath"; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+     test no = "$enable_shared"; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test yes != "$enable_dlopen"; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen=load_add_on
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen=LoadLibrary
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+    # if libdl is installed we need to link against it
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_dl_dlopen=yes
+else case e in #(
+  e) ac_cv_lib_dl_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else case e in #(
+  e)
+    lt_cv_dlopen=dyld
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+     ;;
+esac
+fi
+
+    ;;
+
+  tpf*)
+    # Don't try to run any link tests for TPF.  We know it's impossible
+    # because TPF is a cross-compiler, and we know how we open DSOs.
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=no
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes
+then :
+  lt_cv_dlopen=shl_load
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+printf %s "checking for shl_load in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_shl_load+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load (void);
+int
+main (void)
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_dld_shl_load=yes
+else case e in #(
+  e) ac_cv_lib_dld_shl_load=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes
+then :
+  lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+else case e in #(
+  e) ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes
+then :
+  lt_cv_dlopen=dlopen
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_dl_dlopen=yes
+else case e in #(
+  e) ac_cv_lib_dl_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+printf %s "checking for dlopen in -lsvld... " >&6; }
+if test ${ac_cv_lib_svld_dlopen+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_svld_dlopen=yes
+else case e in #(
+  e) ac_cv_lib_svld_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes
+then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+printf %s "checking for dld_link in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_dld_link+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link (void);
+int
+main (void)
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_dld_dld_link=yes
+else case e in #(
+  e) ac_cv_lib_dld_dld_link=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes
+then :
+  lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
+fi
+
+	       ;;
+esac
+fi
+
+	     ;;
+esac
+fi
+
+	   ;;
+esac
+fi
+
+	 ;;
+esac
+fi
+
+       ;;
+esac
+fi
+
+    ;;
+  esac
+
+  if test no = "$lt_cv_dlopen"; then
+    enable_dlopen=no
+  else
+    enable_dlopen=yes
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS=$CPPFLAGS
+    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS=$LDFLAGS
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS=$LIBS
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+printf %s "checking whether a program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) 	  if test yes = "$cross_compiling"; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+     ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+printf "%s\n" "$lt_cv_dlopen_self" >&6; }
+
+    if test yes = "$lt_cv_dlopen_self"; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self_static+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) 	  if test yes = "$cross_compiling"; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+       ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS=$save_CPPFLAGS
+    LDFLAGS=$save_LDFLAGS
+    LIBS=$save_LIBS
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+printf %s "checking whether stripping libraries is possible... " >&6; }
+if test -z "$STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+else
+  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+    old_striplib="$STRIP --strip-debug"
+    striplib="$STRIP --strip-unneeded"
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+  else
+    case $host_os in
+    darwin*)
+      # FIXME - insert some real tests, host_os isn't really good enough
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+      ;;
+    freebsd*)
+      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+        old_striplib="$STRIP --strip-debug"
+        striplib="$STRIP --strip-unneeded"
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+      else
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+      fi
+      ;;
+    *)
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+      ;;
+    esac
+  fi
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report what library types will actually be built
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+printf %s "checking if libtool supports shared libraries... " >&6; }
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+printf "%s\n" "$can_build_shared" >&6; }
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+printf %s "checking whether to build shared libraries... " >&6; }
+  test no = "$can_build_shared" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test yes = "$enable_shared" && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test ia64 != "$host_cpu"; then
+      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+      yes,aix,yes) ;;			# shared object as lib.so file only
+      yes,svr4,*) ;;			# shared object as lib.so archive member only
+      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+      esac
+    fi
+    ;;
+  esac
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+printf "%s\n" "$enable_shared" >&6; }
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+printf %s "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test yes = "$enable_shared" || enable_static=yes
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+printf "%s\n" "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+if (test "$USE_MAINTAINER_MODE" = "yes"); then
+	# Extract the first word of "lcov", so it can be a program name with args.
+set dummy lcov; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_enable_coverage+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$enable_coverage"; then
+  ac_cv_prog_enable_coverage="$enable_coverage" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_enable_coverage="yes"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_enable_coverage" && ac_cv_prog_enable_coverage="no"
+fi ;;
+esac
+fi
+enable_coverage=$ac_cv_prog_enable_coverage
+if test -n "$enable_coverage"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_coverage" >&5
+printf "%s\n" "$enable_coverage" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+	# Extract the first word of "dbus-run-session", so it can be a program name with args.
+set dummy dbus-run-session; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_enable_dbus_run_session+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$enable_dbus_run_session"; then
+  ac_cv_prog_enable_dbus_run_session="$enable_dbus_run_session" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_enable_dbus_run_session="yes"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+enable_dbus_run_session=$ac_cv_prog_enable_dbus_run_session
+if test -n "$enable_dbus_run_session"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_dbus_run_session" >&5
+printf "%s\n" "$enable_dbus_run_session" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+	# Extract the first word of "valgrind", so it can be a program name with args.
+set dummy valgrind; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_enable_valgrind+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$enable_valgrind"; then
+  ac_cv_prog_enable_valgrind="$enable_valgrind" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_enable_valgrind="yes"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+enable_valgrind=$ac_cv_prog_enable_valgrind
+if test -n "$enable_valgrind"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_valgrind" >&5
+printf "%s\n" "$enable_valgrind" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+	ac_fn_c_check_header_compile "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default"
+if test "x$ac_cv_header_valgrind_memcheck_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h
+
+fi
+
+fi
+ if test "${enable_coverage}" = "yes"; then
+  COVERAGE_TRUE=
+  COVERAGE_FALSE='#'
+else
+  COVERAGE_TRUE='#'
+  COVERAGE_FALSE=
+fi
+
+ if test "${enable_dbus_run_session}" = "yes"; then
+  DBUS_RUN_SESSION_TRUE=
+  DBUS_RUN_SESSION_FALSE='#'
+else
+  DBUS_RUN_SESSION_TRUE='#'
+  DBUS_RUN_SESSION_FALSE=
+fi
+
+
+
+	misc_cflags=""
+	misc_ldflags=""
+	# Check whether --enable-optimization was given.
+if test ${enable_optimization+y}
+then :
+  enableval=$enable_optimization;
+		if (test "${enableval}" = "no"); then
+			misc_cflags="$misc_cflags -O0"
+		fi
+
+fi
+
+	# Check whether --enable-asan was given.
+if test ${enable_asan+y}
+then :
+  enableval=$enable_asan;
+		save_LIBS=$LIBS
+		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _init in -lasan" >&5
+printf %s "checking for _init in -lasan... " >&6; }
+if test ${ac_cv_lib_asan__init+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lasan  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _init (void);
+int
+main (void)
+{
+return _init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_asan__init=yes
+else case e in #(
+  e) ac_cv_lib_asan__init=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_asan__init" >&5
+printf "%s\n" "$ac_cv_lib_asan__init" >&6; }
+if test "x$ac_cv_lib_asan__init" = xyes
+then :
+  printf "%s\n" "#define HAVE_LIBASAN 1" >>confdefs.h
+
+  LIBS="-lasan $LIBS"
+
+fi
+
+		LIBS=$save_LIBS
+		if (test "${enableval}" = "yes" &&
+				test "${ac_cv_lib_asan__init}" = "yes" &&
+				test "${ac_cv_prog_cc_asan}" = "yes"); then
+			misc_cflags="$misc_cflags -fsanitize=address";
+			misc_ldflags="$misc_ldflags -fsanitize=address"
+			ASAN_LIB=${ac_cv_lib_asan__init}
+
+		fi
+
+fi
+
+	# Check whether --enable-lsan was given.
+if test ${enable_lsan+y}
+then :
+  enableval=$enable_lsan;
+		save_LIBS=$LIBS
+		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _init in -llsan" >&5
+printf %s "checking for _init in -llsan... " >&6; }
+if test ${ac_cv_lib_lsan__init+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-llsan  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _init (void);
+int
+main (void)
+{
+return _init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_lsan__init=yes
+else case e in #(
+  e) ac_cv_lib_lsan__init=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lsan__init" >&5
+printf "%s\n" "$ac_cv_lib_lsan__init" >&6; }
+if test "x$ac_cv_lib_lsan__init" = xyes
+then :
+  printf "%s\n" "#define HAVE_LIBLSAN 1" >>confdefs.h
+
+  LIBS="-llsan $LIBS"
+
+fi
+
+		LIBS=$save_LIBS
+		if (test "${enableval}" = "yes" &&
+				test "${ac_cv_lib_lsan__init}" = "yes" &&
+				test "${ac_cv_prog_cc_lsan}" = "yes"); then
+			misc_cflags="$misc_cflags -fsanitize=leak";
+			misc_ldflags="$misc_ldflags -fsanitize=leak"
+			ASAN_LIB=${ac_cv_lib_lsan__init}
+
+		fi
+
+fi
+
+	# Check whether --enable-ubsan was given.
+if test ${enable_ubsan+y}
+then :
+  enableval=$enable_ubsan;
+		save_LIBS=$LIBS
+		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _init in -lubsan" >&5
+printf %s "checking for _init in -lubsan... " >&6; }
+if test ${ac_cv_lib_ubsan__init+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lubsan  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _init (void);
+int
+main (void)
+{
+return _init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_ubsan__init=yes
+else case e in #(
+  e) ac_cv_lib_ubsan__init=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ubsan__init" >&5
+printf "%s\n" "$ac_cv_lib_ubsan__init" >&6; }
+if test "x$ac_cv_lib_ubsan__init" = xyes
+then :
+  printf "%s\n" "#define HAVE_LIBUBSAN 1" >>confdefs.h
+
+  LIBS="-lubsan $LIBS"
+
+fi
+
+		LIBS=$save_LIBS
+		if (test "${enableval}" = "yes" &&
+				test "${ac_cv_lib_ubsan__init}" = "yes" &&
+				test "${ac_cv_prog_cc_ubsan}" = "yes"); then
+			misc_cflags="$misc_cflags -fsanitize=undefined";
+			misc_ldflags="$misc_ldflags -fsanitize=undefined";
+		fi
+
+fi
+
+	# Check whether --enable-debug was given.
+if test ${enable_debug+y}
+then :
+  enableval=$enable_debug;
+		if (test "${enableval}" = "yes" &&
+				test "${ac_cv_prog_cc_g}" = "yes"); then
+			misc_cflags="$misc_cflags -g"
+		fi
+
+fi
+
+	# Check whether --enable-pie was given.
+if test ${enable_pie+y}
+then :
+  enableval=$enable_pie;
+		if (test "${enableval}" = "yes" &&
+				test "${ac_cv_prog_cc_pie}" = "yes"); then
+			misc_cflags="$misc_cflags -fPIC"
+			misc_ldflags="$misc_ldflags -pie -Wl,-z,now"
+		fi
+
+fi
+
+	if (test "$enable_coverage" = "yes"); then
+		misc_cflags="$misc_cflags --coverage"
+		misc_ldflags="$misc_ldflags --coverage"
+	fi
+	misc_cflags="$misc_cflags -ffunction-sections -fdata-sections"
+	misc_ldflags="$misc_ldflags -Wl,--gc-sections"
+	MISC_CFLAGS=$misc_cflags
+
+	MISC_LDFLAGS=$misc_ldflags
+
+
+
+ if test "${enable_valgrind}" = "yes" &&
+		test "$ASAN_LIB" != "yes" && test "LSAN_LIB" != "yes"; then
+  VALGRIND_TRUE=
+  VALGRIND_FALSE='#'
+else
+  VALGRIND_TRUE='#'
+  VALGRIND_FALSE=
+fi
+
+
+# Check whether --enable-threads was given.
+if test ${enable_threads+y}
+then :
+  enableval=$enable_threads; enable_threads=${enableval}
+fi
+
+
+ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
+if test "x$ac_cv_func_explicit_bzero" = xyes
+then :
+  printf "%s\n" "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "getrandom" "ac_cv_func_getrandom"
+if test "x$ac_cv_func_getrandom" = xyes
+then :
+  printf "%s\n" "#define HAVE_GETRANDOM 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "rawmemchr" "ac_cv_func_rawmemchr"
+if test "x$ac_cv_func_rawmemchr" = xyes
+then :
+  printf "%s\n" "#define HAVE_RAWMEMCHR 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "signalfd" "ac_cv_func_signalfd"
+if test "x$ac_cv_func_signalfd" = xyes
+then :
+  dummy=yes
+else case e in #(
+  e) as_fn_error $? "signalfd support is required" "$LINENO" 5 ;;
+esac
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime (void);
+int
+main (void)
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_rt_clock_gettime=yes
+else case e in #(
+  e) ac_cv_lib_rt_clock_gettime=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
+  dummy=yes
+else case e in #(
+  e) as_fn_error $? "realtime clock support is required" "$LINENO" 5 ;;
+esac
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create (void);
+int
+main (void)
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_pthread_pthread_create=yes
+else case e in #(
+  e) ac_cv_lib_pthread_pthread_create=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
+  dummy=yes
+else case e in #(
+  e) as_fn_error $? "posix thread support is required" "$LINENO" 5 ;;
+esac
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_dl_dlopen=yes
+else case e in #(
+  e) ac_cv_lib_dl_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+  dummy=yes
+else case e in #(
+  e) as_fn_error $? "dynamic linking loader is required" "$LINENO" 5 ;;
+esac
+fi
+
+
+ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
+if test "x$ac_cv_header_string_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_types_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_LINUX_TYPES_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "linux/if_alg.h" "ac_cv_header_linux_if_alg_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_if_alg_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_LINUX_IF_ALG_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "linux/uinput.h" "ac_cv_header_linux_uinput_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_uinput_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_LINUX_UINPUT_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "linux/uhid.h" "ac_cv_header_linux_uhid_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_uhid_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_LINUX_UHID_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_random_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h
+
+fi
+
+
+# basename may be only available in libgen.h with the POSIX behavior,
+# not desired here
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_save_CFLAGS=$CFLAGS
+   ac_cv_c_undeclared_builtin_options='cannot detect'
+   for ac_arg in '' -fno-builtin; do
+     CFLAGS="$ac_save_CFLAGS $ac_arg"
+     # This test program should *not* compile successfully.
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+(void) strchr;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+  e) # This test program should compile successfully.
+        # No library function is consistently available on
+        # freestanding implementations, so test against a dummy
+        # declaration.  Include always-available headers on the
+        # off chance that they somehow elicit warnings.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
+
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+  (void) ac_decl;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  if test x"$ac_arg" = x
+then :
+  ac_cv_c_undeclared_builtin_options='none needed'
+else case e in #(
+  e) ac_cv_c_undeclared_builtin_options=$ac_arg ;;
+esac
+fi
+          break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+    done
+    CFLAGS=$ac_save_CFLAGS
+   ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+  case $ac_cv_c_undeclared_builtin_options in #(
+  'cannot detect') :
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See 'config.log' for more details" "$LINENO" 5; } ;; #(
+  'none needed') :
+    ac_c_undeclared_builtin_options='' ;; #(
+  *) :
+    ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_check_decl "$LINENO" "basename" "ac_cv_have_decl_basename" "#define _GNU_SOURCE 1
+				 #include <string.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_basename" = xyes
+then :
+  ac_have_decl=1
+else case e in #(
+  e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_BASENAME $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: GNU basename extension not found" >&5
+printf "%s\n" "$as_me: WARNING: GNU basename extension not found" >&2;} ;;
+esac
+fi
+
+
+
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glib-2.0 >= 2.28" >&5
+printf %s "checking for glib-2.0 >= 2.28... " >&6; }
+
+if test -n "$GLIB_CFLAGS"; then
+    pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.28\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.28") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.28" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GLIB_LIBS"; then
+    pkg_cv_GLIB_LIBS="$GLIB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.28\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.28") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.28" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.28" 2>&1`
+        else
+                GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.28" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$GLIB_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (glib-2.0 >= 2.28) were not met:
+
+$GLIB_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
+        GLIB_LIBS=$pkg_cv_GLIB_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+
+if (test "${enable_threads}" = "yes"); then
+
+printf "%s\n" "#define NEED_THREADS 1" >>confdefs.h
+
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gthread-2.0 >= 2.16" >&5
+printf %s "checking for gthread-2.0 >= 2.16... " >&6; }
+
+if test -n "$GTHREAD_CFLAGS"; then
+    pkg_cv_GTHREAD_CFLAGS="$GTHREAD_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0 >= 2.16\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gthread-2.0 >= 2.16") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags "gthread-2.0 >= 2.16" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GTHREAD_LIBS"; then
+    pkg_cv_GTHREAD_LIBS="$GTHREAD_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0 >= 2.16\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gthread-2.0 >= 2.16") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GTHREAD_LIBS=`$PKG_CONFIG --libs "gthread-2.0 >= 2.16" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                GTHREAD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gthread-2.0 >= 2.16" 2>&1`
+        else
+                GTHREAD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gthread-2.0 >= 2.16" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$GTHREAD_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (gthread-2.0 >= 2.16) were not met:
+
+$GTHREAD_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GTHREAD_CFLAGS
+and GTHREAD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GTHREAD_CFLAGS
+and GTHREAD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        GTHREAD_CFLAGS=$pkg_cv_GTHREAD_CFLAGS
+        GTHREAD_LIBS=$pkg_cv_GTHREAD_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+	GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+	GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+fi
+
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dbus-1 >= 1.10" >&5
+printf %s "checking for dbus-1 >= 1.10... " >&6; }
+
+if test -n "$DBUS_CFLAGS"; then
+    pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.10\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.10") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1 >= 1.10" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$DBUS_LIBS"; then
+    pkg_cv_DBUS_LIBS="$DBUS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.10\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.10") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1 >= 1.10" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1 >= 1.10" 2>&1`
+        else
+                DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1 >= 1.10" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$DBUS_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (dbus-1 >= 1.10) were not met:
+
+$DBUS_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables DBUS_CFLAGS
+and DBUS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables DBUS_CFLAGS
+and DBUS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS
+        DBUS_LIBS=$pkg_cv_DBUS_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+
+
+# Check whether --with-dbusconfdir was given.
+if test ${with_dbusconfdir+y}
+then :
+  withval=$with_dbusconfdir; path_dbusconfdir=${withval}
+fi
+
+if (test -z "${path_dbusconfdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking D-Bus configuration directory" >&5
+printf %s "checking D-Bus configuration directory... " >&6; }
+	path_dbusconfdir="`$PKG_CONFIG --variable=datadir dbus-1`"
+	if (test -z "${path_dbusconfdir}"); then
+		as_fn_error $? "D-Bus configuration directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_dbusconfdir}" >&5
+printf "%s\n" "${path_dbusconfdir}" >&6; }
+fi
+DBUS_CONFDIR=${path_dbusconfdir}
+
+
+
+# Check whether --with-dbussystembusdir was given.
+if test ${with_dbussystembusdir+y}
+then :
+  withval=$with_dbussystembusdir; path_dbussystembusdir=${withval}
+fi
+
+if (test -z "${path_dbussystembusdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking D-Bus system bus services dir" >&5
+printf %s "checking D-Bus system bus services dir... " >&6; }
+	path_dbussystembusdir="`$PKG_CONFIG --variable=system_bus_services_dir dbus-1`"
+	if (test -z "${path_dbussystembusdir}"); then
+		as_fn_error $? "D-Bus system bus services directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_dbussystembusdir}" >&5
+printf "%s\n" "${path_dbussystembusdir}" >&6; }
+fi
+DBUS_SYSTEMBUSDIR=${path_dbussystembusdir}
+
+
+
+# Check whether --with-dbussessionbusdir was given.
+if test ${with_dbussessionbusdir+y}
+then :
+  withval=$with_dbussessionbusdir; path_dbussessionbusdir=${withval}
+fi
+
+if (test -z "${path_dbussessionbusdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking D-Bus session bus services dir" >&5
+printf %s "checking D-Bus session bus services dir... " >&6; }
+	path_dbussessionbusdir="`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`"
+	if (test -z "${path_dbussessionbusdir}"); then
+		as_fn_error $? "D-Bus session bus services directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_dbussessionbusdir}" >&5
+printf "%s\n" "${path_dbussessionbusdir}" >&6; }
+fi
+DBUS_SESSIONBUSDIR=${path_dbussessionbusdir}
+
+
+
+# Check whether --with-zsh-completion-dir was given.
+if test ${with_zsh_completion_dir+y}
+then :
+  withval=$with_zsh_completion_dir; path_zshcompletiondir=${withval}
+else case e in #(
+  e) path_zshcompletiondir="yes" ;;
+esac
+fi
+
+
+if (test "${path_zshcompletiondir}" = "yes"); then
+	path_zshcompletiondir="$datarootdir/zsh/site-functions"
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_zshcompletiondir}" >&5
+printf "%s\n" "${path_zshcompletiondir}" >&6; }
+fi
+ZSH_COMPLETIONDIR=${path_zshcompletiondir}
+
+ if test "${path_zshcompletiondir}" != "no"; then
+  ZSH_COMPLETIONS_TRUE=
+  ZSH_COMPLETIONS_FALSE='#'
+else
+  ZSH_COMPLETIONS_TRUE='#'
+  ZSH_COMPLETIONS_FALSE=
+fi
+
+
+# Check whether --enable-backtrace was given.
+if test ${enable_backtrace+y}
+then :
+  enableval=$enable_backtrace; enable_backtrace=${enableval}
+fi
+
+
+if (test "${enable_backtrace}" = "yes"); then
+	ac_fn_c_check_header_compile "$LINENO" "elfutils/libdwfl.h" "ac_cv_header_elfutils_libdwfl_h" "$ac_includes_default"
+if test "x$ac_cv_header_elfutils_libdwfl_h" = xyes
+then :
+  dummy=yes
+else case e in #(
+  e) as_fn_error $? "elfutils support is required" "$LINENO" 5 ;;
+esac
+fi
+
+
+printf "%s\n" "#define HAVE_BACKTRACE_SUPPORT 1" >>confdefs.h
+
+	BACKTRACE_CFLAGS=""
+	BACKTRACE_LIBS="-ldw"
+
+
+fi
+
+# Check whether --enable-library was given.
+if test ${enable_library+y}
+then :
+  enableval=$enable_library; enable_library=${enableval}
+fi
+
+ if test "${enable_library}" = "yes"; then
+  LIBRARY_TRUE=
+  LIBRARY_FALSE='#'
+else
+  LIBRARY_TRUE='#'
+  LIBRARY_FALSE=
+fi
+
+
+# Check whether --enable-test was given.
+if test ${enable_test+y}
+then :
+  enableval=$enable_test; enable_test=${enableval}
+fi
+
+ if test "${enable_test}" = "yes"; then
+  TEST_TRUE=
+  TEST_FALSE='#'
+else
+  TEST_TRUE='#'
+  TEST_FALSE=
+fi
+
+
+# Check whether --enable-nfc was given.
+if test ${enable_nfc+y}
+then :
+  enableval=$enable_nfc; enable_nfc=${enableval}
+fi
+
+ if test "${enable_nfc}" = "yes"; then
+  NFC_TRUE=
+  NFC_FALSE='#'
+else
+  NFC_TRUE='#'
+  NFC_FALSE=
+fi
+
+
+# Check whether --enable-sap was given.
+if test ${enable_sap+y}
+then :
+  enableval=$enable_sap; enable_sap=${enableval}
+fi
+
+ if test "${enable_sap}" = "yes"; then
+  SAP_TRUE=
+  SAP_FALSE='#'
+else
+  SAP_TRUE='#'
+  SAP_FALSE=
+fi
+
+
+# Check whether --enable-a2dp was given.
+if test ${enable_a2dp+y}
+then :
+  enableval=$enable_a2dp; enable_a2dp=${enableval}
+fi
+
+ if test "${enable_a2dp}" != "no"; then
+  A2DP_TRUE=
+  A2DP_FALSE='#'
+else
+  A2DP_TRUE='#'
+  A2DP_FALSE=
+fi
+
+
+# Check whether --enable-avrcp was given.
+if test ${enable_avrcp+y}
+then :
+  enableval=$enable_avrcp; enable_avrcp=${enableval}
+fi
+
+ if test "${enable_avrcp}" != "no"; then
+  AVRCP_TRUE=
+  AVRCP_FALSE='#'
+else
+  AVRCP_TRUE='#'
+  AVRCP_FALSE=
+fi
+
+
+# Check whether --enable-network was given.
+if test ${enable_network+y}
+then :
+  enableval=$enable_network; enable_network=${enableval}
+fi
+
+ if test "${enable_network}" != "no"; then
+  NETWORK_TRUE=
+  NETWORK_FALSE='#'
+else
+  NETWORK_TRUE='#'
+  NETWORK_FALSE=
+fi
+
+
+# Check whether --enable-hid was given.
+if test ${enable_hid+y}
+then :
+  enableval=$enable_hid; enable_hid=${enableval}
+fi
+
+ if test "${enable_hid}" != "no"; then
+  HID_TRUE=
+  HID_FALSE='#'
+else
+  HID_TRUE='#'
+  HID_FALSE=
+fi
+
+
+# Check whether --enable-hog was given.
+if test ${enable_hog+y}
+then :
+  enableval=$enable_hog; enable_hog=${enableval}
+fi
+
+ if test "${enable_hog}" != "no"; then
+  HOG_TRUE=
+  HOG_FALSE='#'
+else
+  HOG_TRUE='#'
+  HOG_FALSE=
+fi
+
+
+# Check whether --enable-health was given.
+if test ${enable_health+y}
+then :
+  enableval=$enable_health; enable_health=${enableval}
+fi
+
+ if test "${enable_health}" = "yes"; then
+  HEALTH_TRUE=
+  HEALTH_FALSE='#'
+else
+  HEALTH_TRUE='#'
+  HEALTH_FALSE=
+fi
+
+
+# Check whether --enable-bap was given.
+if test ${enable_bap+y}
+then :
+  enableval=$enable_bap; enable_bap=${enableval}
+fi
+
+ if test "${enable_bap}" != "no"; then
+  BAP_TRUE=
+  BAP_FALSE='#'
+else
+  BAP_TRUE='#'
+  BAP_FALSE=
+fi
+
+
+# Check whether --enable-bass was given.
+if test ${enable_bass+y}
+then :
+  enableval=$enable_bass; enable_bass=${enableval}
+fi
+
+ if test "${enable_bass}" != "no"; then
+  BASS_TRUE=
+  BASS_FALSE='#'
+else
+  BASS_TRUE='#'
+  BASS_FALSE=
+fi
+
+
+# Check whether --enable-mcp was given.
+if test ${enable_mcp+y}
+then :
+  enableval=$enable_mcp; enable_mcp=${enableval}
+fi
+
+ if test "${enable_mcp}" != "no"; then
+  MCP_TRUE=
+  MCP_FALSE='#'
+else
+  MCP_TRUE='#'
+  MCP_FALSE=
+fi
+
+
+# Check whether --enable-ccp was given.
+if test ${enable_ccp+y}
+then :
+  enableval=$enable_ccp; enable_ccp=${enableval}
+fi
+
+ if test "${enable_ccp}" != "no"; then
+  CCP_TRUE=
+  CCP_FALSE='#'
+else
+  CCP_TRUE='#'
+  CCP_FALSE=
+fi
+
+
+# Check whether --enable-vcp was given.
+if test ${enable_vcp+y}
+then :
+  enableval=$enable_vcp; enable_vcp=${enableval}
+fi
+
+ if test "${enable_vcp}" != "no"; then
+  VCP_TRUE=
+  VCP_FALSE='#'
+else
+  VCP_TRUE='#'
+  VCP_FALSE=
+fi
+
+
+# Check whether --enable-micp was given.
+if test ${enable_micp+y}
+then :
+  enableval=$enable_micp; enable_micp=${enableval}
+fi
+
+ if test "${enable_micp}" != "no"; then
+  MICP_TRUE=
+  MICP_FALSE='#'
+else
+  MICP_TRUE='#'
+  MICP_FALSE=
+fi
+
+
+# Check whether --enable-csip was given.
+if test ${enable_csip+y}
+then :
+  enableval=$enable_csip; enable_csip=${enableval}
+fi
+
+ if test "${enable_csip}" != "no"; then
+  CSIP_TRUE=
+  CSIP_FALSE='#'
+else
+  CSIP_TRUE='#'
+  CSIP_FALSE=
+fi
+
+
+# Check whether --enable-asha was given.
+if test ${enable_asha+y}
+then :
+  enableval=$enable_asha; enable_asha=${enableval}
+fi
+
+ if test "${enable_asha}" != "no"; then
+  ASHA_TRUE=
+  ASHA_FALSE='#'
+else
+  ASHA_TRUE='#'
+  ASHA_FALSE=
+fi
+
+
+# Check whether --enable-tools was given.
+if test ${enable_tools+y}
+then :
+  enableval=$enable_tools; enable_tools=${enableval}
+fi
+
+ if test "${enable_tools}" != "no"; then
+  TOOLS_TRUE=
+  TOOLS_FALSE='#'
+else
+  TOOLS_TRUE='#'
+  TOOLS_FALSE=
+fi
+
+
+# Check whether --enable-monitor was given.
+if test ${enable_monitor+y}
+then :
+  enableval=$enable_monitor; enable_monitor=${enableval}
+fi
+
+ if test "${enable_monitor}" != "no"; then
+  MONITOR_TRUE=
+  MONITOR_FALSE='#'
+else
+  MONITOR_TRUE='#'
+  MONITOR_FALSE=
+fi
+
+
+# Check whether --enable-udev was given.
+if test ${enable_udev+y}
+then :
+  enableval=$enable_udev; enable_udev=${enableval}
+fi
+
+if (test "${enable_udev}" != "no"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libudev >= 196" >&5
+printf %s "checking for libudev >= 196... " >&6; }
+
+if test -n "$UDEV_CFLAGS"; then
+    pkg_cv_UDEV_CFLAGS="$UDEV_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libudev >= 196\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libudev >= 196") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_UDEV_CFLAGS=`$PKG_CONFIG --cflags "libudev >= 196" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$UDEV_LIBS"; then
+    pkg_cv_UDEV_LIBS="$UDEV_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libudev >= 196\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libudev >= 196") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_UDEV_LIBS=`$PKG_CONFIG --libs "libudev >= 196" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                UDEV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libudev >= 196" 2>&1`
+        else
+                UDEV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libudev >= 196" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$UDEV_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (libudev >= 196) were not met:
+
+$UDEV_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables UDEV_CFLAGS
+and UDEV_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables UDEV_CFLAGS
+and UDEV_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        UDEV_CFLAGS=$pkg_cv_UDEV_CFLAGS
+        UDEV_LIBS=$pkg_cv_UDEV_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+
+printf "%s\n" "#define HAVE_UDEV 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-udevdir was given.
+if test ${with_udevdir+y}
+then :
+  withval=$with_udevdir; path_udevdir=${withval}
+fi
+
+if (test "${enable_udev}" != "no" && test -z "${path_udevdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking udev directory" >&5
+printf %s "checking udev directory... " >&6; }
+	path_udevdir="`$PKG_CONFIG --variable=udevdir udev`"
+	if (test -z "${path_udevdir}"); then
+		as_fn_error $? "udev directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_udevdir}" >&5
+printf "%s\n" "${path_udevdir}" >&6; }
+fi
+UDEV_DIR=${path_udevdir}
+
+
+# Check whether --enable-cups was given.
+if test ${enable_cups+y}
+then :
+  enableval=$enable_cups; enable_cups=${enableval}
+fi
+
+ if test "${enable_cups}" != "no"; then
+  CUPS_TRUE=
+  CUPS_FALSE='#'
+else
+  CUPS_TRUE='#'
+  CUPS_FALSE=
+fi
+
+if (test "${enable_cups}" != "no"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking cups directory" >&5
+printf %s "checking cups directory... " >&6; }
+	cups_serverbin=`$PKG_CONFIG cups --variable=cups_serverbin`
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${cups_serverbin}" >&5
+printf "%s\n" "${cups_serverbin}" >&6; }
+fi
+ if test "${cups_serverbin}" != ""; then
+  CUPS_SERVERBIN_TRUE=
+  CUPS_SERVERBIN_FALSE='#'
+else
+  CUPS_SERVERBIN_TRUE='#'
+  CUPS_SERVERBIN_FALSE=
+fi
+
+if test "${cups_serverbin}" != ""
+then :
+
+	CUPS_SERVERBIN=${cups_serverbin}
+
+
+fi
+
+# Check whether --enable-mesh was given.
+if test ${enable_mesh+y}
+then :
+  enableval=$enable_mesh; enable_mesh=${enableval}
+fi
+
+ if test "${enable_mesh}" = "yes"; then
+  MESH_TRUE=
+  MESH_FALSE='#'
+else
+  MESH_TRUE='#'
+  MESH_FALSE=
+fi
+
+
+if (test "${enable_mesh}" = "yes"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for json-c >= 0.13" >&5
+printf %s "checking for json-c >= 0.13... " >&6; }
+
+if test -n "$JSONC_CFLAGS"; then
+    pkg_cv_JSONC_CFLAGS="$JSONC_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json-c >= 0.13\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "json-c >= 0.13") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_JSONC_CFLAGS=`$PKG_CONFIG --cflags "json-c >= 0.13" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$JSONC_LIBS"; then
+    pkg_cv_JSONC_LIBS="$JSONC_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json-c >= 0.13\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "json-c >= 0.13") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_JSONC_LIBS=`$PKG_CONFIG --libs "json-c >= 0.13" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                JSONC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "json-c >= 0.13" 2>&1`
+        else
+                JSONC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "json-c >= 0.13" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$JSONC_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (json-c >= 0.13) were not met:
+
+$JSONC_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables JSONC_CFLAGS
+and JSONC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables JSONC_CFLAGS
+and JSONC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        JSONC_CFLAGS=$pkg_cv_JSONC_CFLAGS
+        JSONC_LIBS=$pkg_cv_JSONC_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+
+# Check whether --enable-midi was given.
+if test ${enable_midi+y}
+then :
+  enableval=$enable_midi; enable_midi=${enableval}
+fi
+
+ if test "${enable_midi}" = "yes"; then
+  MIDI_TRUE=
+  MIDI_FALSE='#'
+else
+  MIDI_TRUE='#'
+  MIDI_FALSE=
+fi
+
+
+if (test "${enable_midi}" = "yes"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for alsa" >&5
+printf %s "checking for alsa... " >&6; }
+
+if test -n "$ALSA_CFLAGS"; then
+    pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$ALSA_LIBS"; then
+    pkg_cv_ALSA_LIBS="$ALSA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "alsa" 2>&1`
+        else
+                ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "alsa" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$ALSA_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (alsa) were not met:
+
+$ALSA_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables ALSA_CFLAGS
+and ALSA_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables ALSA_CFLAGS
+and ALSA_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS
+        ALSA_LIBS=$pkg_cv_ALSA_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+
+# Check whether --enable-obex was given.
+if test ${enable_obex+y}
+then :
+  enableval=$enable_obex; enable_obex=${enableval}
+fi
+
+if (test "${enable_obex}" != "no"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libical" >&5
+printf %s "checking for libical... " >&6; }
+
+if test -n "$ICAL_CFLAGS"; then
+    pkg_cv_ICAL_CFLAGS="$ICAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libical\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libical") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ICAL_CFLAGS=`$PKG_CONFIG --cflags "libical" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$ICAL_LIBS"; then
+    pkg_cv_ICAL_LIBS="$ICAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libical\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libical") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ICAL_LIBS=`$PKG_CONFIG --libs "libical" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                ICAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libical" 2>&1`
+        else
+                ICAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libical" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$ICAL_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (libical) were not met:
+
+$ICAL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables ICAL_CFLAGS
+and ICAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables ICAL_CFLAGS
+and ICAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        ICAL_CFLAGS=$pkg_cv_ICAL_CFLAGS
+        ICAL_LIBS=$pkg_cv_ICAL_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+ if test "${enable_obex}" != "no"; then
+  OBEX_TRUE=
+  OBEX_FALSE='#'
+else
+  OBEX_TRUE='#'
+  OBEX_FALSE=
+fi
+
+
+# Check whether --enable-btpclient was given.
+if test ${enable_btpclient+y}
+then :
+  enableval=$enable_btpclient; enable_btpclient=${enableval}
+fi
+
+ if test "${enable_btpclient}" = "yes"; then
+  BTPCLIENT_TRUE=
+  BTPCLIENT_FALSE='#'
+else
+  BTPCLIENT_TRUE='#'
+  BTPCLIENT_FALSE=
+fi
+
+
+# Check whether --enable-external_ell was given.
+if test ${enable_external_ell+y}
+then :
+  enableval=$enable_external_ell; enable_external_ell=${enableval}
+fi
+
+if (test "${enable_external_ell}" = "yes"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ell >= 0.39" >&5
+printf %s "checking for ell >= 0.39... " >&6; }
+
+if test -n "$ELL_CFLAGS"; then
+    pkg_cv_ELL_CFLAGS="$ELL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ell >= 0.39\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "ell >= 0.39") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ELL_CFLAGS=`$PKG_CONFIG --cflags "ell >= 0.39" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$ELL_LIBS"; then
+    pkg_cv_ELL_LIBS="$ELL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ell >= 0.39\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "ell >= 0.39") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ELL_LIBS=`$PKG_CONFIG --libs "ell >= 0.39" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                ELL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ell >= 0.39" 2>&1`
+        else
+                ELL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ell >= 0.39" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$ELL_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (ell >= 0.39) were not met:
+
+$ELL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables ELL_CFLAGS
+and ELL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables ELL_CFLAGS
+and ELL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        ELL_CFLAGS=$pkg_cv_ELL_CFLAGS
+        ELL_LIBS=$pkg_cv_ELL_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+if (test "${enable_external_ell}" != "yes" &&
+		(test "${enable_btpclient}" = "yes" || test "${enable_mesh}" = "yes")); then
+	if (test ! -f ${srcdir}/ell/ell.h) &&
+			(test ! -f ${srcdir}/../ell/ell/ell.h); then
+				as_fn_error $? "ELL source is required or use --enable-external-ell" "$LINENO" 5
+	fi
+fi
+ if test "${enable_external_ell}" = "yes" ||
+				(test "${enable_btpclient}" != "yes" &&
+						test "${enable_mesh}" != "yes"); then
+  EXTERNAL_ELL_TRUE=
+  EXTERNAL_ELL_FALSE='#'
+else
+  EXTERNAL_ELL_TRUE='#'
+  EXTERNAL_ELL_FALSE=
+fi
+
+ if test "${enable_btpclient}" = "yes" ||
+						test "${enable_mesh}" = "yes"; then
+  LIBSHARED_ELL_TRUE=
+  LIBSHARED_ELL_FALSE='#'
+else
+  LIBSHARED_ELL_TRUE='#'
+  LIBSHARED_ELL_FALSE=
+fi
+
+
+# Check whether --enable-client was given.
+if test ${enable_client+y}
+then :
+  enableval=$enable_client; enable_client=${enableval}
+fi
+
+ if test "${enable_client}" != "no"; then
+  CLIENT_TRUE=
+  CLIENT_FALSE='#'
+else
+  CLIENT_TRUE='#'
+  CLIENT_FALSE=
+fi
+
+
+if (test "${enable_client}" != "no" || test "${enable_mesh}" = "yes"); then
+               for ac_header in readline/readline.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default"
+if test "x$ac_cv_header_readline_readline_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_READLINE_READLINE_H 1" >>confdefs.h
+ enable_readline=yes
+else case e in #(
+  e) as_fn_error $? "readline header files are required" "$LINENO" 5 ;;
+esac
+fi
+
+done
+fi
+ if test "${enable_readline}" = "yes"; then
+  READLINE_TRUE=
+  READLINE_FALSE='#'
+else
+  READLINE_TRUE='#'
+  READLINE_FALSE=
+fi
+
+
+# Check whether --enable-systemd was given.
+if test ${enable_systemd+y}
+then :
+  enableval=$enable_systemd; enable_systemd=${enableval}
+fi
+
+ if test "${enable_systemd}" != "no"; then
+  SYSTEMD_TRUE=
+  SYSTEMD_FALSE='#'
+else
+  SYSTEMD_TRUE='#'
+  SYSTEMD_FALSE=
+fi
+
+
+
+# Check whether --with-systemdsystemunitdir was given.
+if test ${with_systemdsystemunitdir+y}
+then :
+  withval=$with_systemdsystemunitdir; path_systemunitdir=${withval}
+fi
+
+if (test "${enable_systemd}" != "no" && test -z "${path_systemunitdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking systemd system unit dir" >&5
+printf %s "checking systemd system unit dir... " >&6; }
+	path_systemunitdir="`$PKG_CONFIG --variable=systemdsystemunitdir systemd`"
+	if (test -z "${path_systemunitdir}"); then
+		as_fn_error $? "systemd system unit directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_systemunitdir}" >&5
+printf "%s\n" "${path_systemunitdir}" >&6; }
+fi
+SYSTEMD_SYSTEMUNITDIR=${path_systemunitdir}
+
+
+
+# Check whether --with-systemduserunitdir was given.
+if test ${with_systemduserunitdir+y}
+then :
+  withval=$with_systemduserunitdir; path_userunitdir=${withval}
+fi
+
+if (test "${enable_systemd}" != "no" && test -z "${path_userunitdir}"); then
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking systemd user unit dir" >&5
+printf %s "checking systemd user unit dir... " >&6; }
+	path_userunitdir="`$PKG_CONFIG --variable=systemduserunitdir systemd`"
+	if (test -z "${path_userunitdir}"); then
+		as_fn_error $? "systemd user unit directory is required" "$LINENO" 5
+	fi
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${path_userunitdir}" >&5
+printf "%s\n" "${path_userunitdir}" >&6; }
+fi
+SYSTEMD_USERUNITDIR=${path_userunitdir}
+
+
+# Check whether --enable-datafiles was given.
+if test ${enable_datafiles+y}
+then :
+  enableval=$enable_datafiles; enable_datafiles=${enableval}
+fi
+
+ if test "${enable_datafiles}" != "no"; then
+  DATAFILES_TRUE=
+  DATAFILES_FALSE='#'
+else
+  DATAFILES_TRUE='#'
+  DATAFILES_FALSE=
+fi
+
+
+# Check whether --enable-manpages was given.
+if test ${enable_manpages+y}
+then :
+  enableval=$enable_manpages; enable_manpages=${enableval}
+fi
+
+if (test "${enable_manpages}" != "no"); then
+	for ac_prog in rst2man rst2man.py
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RST2MAN+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) if test -n "$RST2MAN"; then
+  ac_cv_prog_RST2MAN="$RST2MAN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RST2MAN="$ac_prog"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+RST2MAN=$ac_cv_prog_RST2MAN
+if test -n "$RST2MAN"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RST2MAN" >&5
+printf "%s\n" "$RST2MAN" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+  test -n "$RST2MAN" && break
+done
+test -n "$RST2MAN" || RST2MAN=""no""
+
+	if (test "${RST2MAN}" = "no" ); then
+		as_fn_error $? "rst2man is required" "$LINENO" 5
+	fi
+fi
+ if test "${enable_manpages}" != "no"; then
+  MANPAGES_TRUE=
+  MANPAGES_FALSE='#'
+else
+  MANPAGES_TRUE='#'
+  MANPAGES_FALSE=
+fi
+
+ if test "${enable_manpages}" != "no" &&
+				test "${RST2MAN}" != "no"; then
+  RUN_RST2MAN_TRUE=
+  RUN_RST2MAN_FALSE='#'
+else
+  RUN_RST2MAN_TRUE='#'
+  RUN_RST2MAN_FALSE=
+fi
+
+
+# Check whether --enable-testing was given.
+if test ${enable_testing+y}
+then :
+  enableval=$enable_testing; enable_testing=${enableval}
+fi
+
+ if test "${enable_testing}" = "yes"; then
+  TESTING_TRUE=
+  TESTING_FALSE='#'
+else
+  TESTING_TRUE='#'
+  TESTING_FALSE=
+fi
+
+
+# Check whether --enable-experimental was given.
+if test ${enable_experimental+y}
+then :
+  enableval=$enable_experimental; enable_experimental=${enableval}
+fi
+
+ if test "${enable_experimental}" = "yes"; then
+  EXPERIMENTAL_TRUE=
+  EXPERIMENTAL_FALSE='#'
+else
+  EXPERIMENTAL_TRUE='#'
+  EXPERIMENTAL_FALSE=
+fi
+
+
+# Check whether --enable-deprecated was given.
+if test ${enable_deprecated+y}
+then :
+  enableval=$enable_deprecated; enable_deprecated=${enableval}
+fi
+
+ if test "${enable_deprecated}" = "yes"; then
+  DEPRECATED_TRUE=
+  DEPRECATED_FALSE='#'
+else
+  DEPRECATED_TRUE='#'
+  DEPRECATED_FALSE=
+fi
+
+
+# Check whether --enable-external-plugins was given.
+if test ${enable_external_plugins+y}
+then :
+  enableval=$enable_external_plugins; enable_external_plugins=${enableval}
+fi
+
+ if test "${enable_external_plugins}" = "yes"; then
+  EXTERNAL_PLUGINS_TRUE=
+  EXTERNAL_PLUGINS_FALSE='#'
+else
+  EXTERNAL_PLUGINS_TRUE='#'
+  EXTERNAL_PLUGINS_FALSE=
+fi
+
+if (test "${enable_external_plugins}" = "yes"); then
+
+printf "%s\n" "#define EXTERNAL_PLUGINS 1" >>confdefs.h
+
+else
+
+printf "%s\n" "#define EXTERNAL_PLUGINS 0" >>confdefs.h
+
+fi
+
+# Check whether --enable-sixaxis was given.
+if test ${enable_sixaxis+y}
+then :
+  enableval=$enable_sixaxis; enable_sixaxis=${enableval}
+fi
+
+ if test "${enable_sixaxis}" = "yes" &&
+					 test "${enable_udev}" != "no"; then
+  SIXAXIS_TRUE=
+  SIXAXIS_FALSE='#'
+else
+  SIXAXIS_TRUE='#'
+  SIXAXIS_FALSE=
+fi
+
+
+# Check whether --enable-hid2hci was given.
+if test ${enable_hid2hci+y}
+then :
+  enableval=$enable_hid2hci; enable_hid2hci=${enableval}
+fi
+
+ if test "${enable_hid2hci}" = "yes" &&
+					test "${enable_udev}" != "no"; then
+  HID2HCI_TRUE=
+  HID2HCI_FALSE='#'
+else
+  HID2HCI_TRUE='#'
+  HID2HCI_FALSE=
+fi
+
+
+# Check whether --enable-logger was given.
+if test ${enable_logger+y}
+then :
+  enableval=$enable_logger; enable_logger=${enableval}
+fi
+
+ if test "${enable_logger}" = "yes"; then
+  LOGGER_TRUE=
+  LOGGER_FALSE='#'
+else
+  LOGGER_TRUE='#'
+  LOGGER_FALSE=
+fi
+
+
+# Check whether --enable-admin was given.
+if test ${enable_admin+y}
+then :
+  enableval=$enable_admin; enable_admin=${enableval}
+fi
+
+ if test "${enable_admin}" = "yes"; then
+  ADMIN_TRUE=
+  ADMIN_FALSE='#'
+else
+  ADMIN_TRUE='#'
+  ADMIN_FALSE=
+fi
+
+
+if (test "${prefix}" = "NONE"); then
+		if (test "$localstatedir" = '${prefix}/var'); then
+		localstatedir='/var'
+
+	fi
+
+	prefix="${ac_default_prefix}"
+fi
+
+if (test "${exec_prefix}" = "NONE"); then
+	# exec_prefix defaults to prefix, although our manual handling of the
+	# latter (above) confuses autoconf. Manually set the exec_prefix.
+	exec_prefix="${prefix}"
+fi
+
+# Expand any variables containing relative references like ${prefix} and co.
+#
+# Otherwise we'll end up with literal references in the final binaries or
+# manuals, which is not something we really want.
+#
+pkgbindir="${bindir}"
+if (test "$bindir" = '${exec_prefix}/bin'); then
+	pkgbindir="${exec_prefix}/bin"
+else
+	pkgbindir="${bindir}"
+fi
+PKGBINDIR="${pkgbindir}"
+
+
+if (test "$libexecdir" = '${exec_prefix}/libexec'); then
+	pkglibexecdir="${exec_prefix}/libexec/bluetooth"
+else
+	pkglibexecdir="${libexecdir}/bluetooth"
+fi
+PKGLIBEXECDIR="${pkglibexecdir}"
+
+
+if (test "$localstatedir" = '${prefix}/var'); then
+	storagedir="${prefix}/var/lib/bluetooth"
+else
+	storagedir="${localstatedir}/lib/bluetooth"
+fi
+
+printf "%s\n" "#define STORAGEDIR \"${storagedir}\"" >>confdefs.h
+
+
+if (test "$sysconfdir" = '${prefix}/etc'); then
+	configdir="${prefix}/etc/bluetooth"
+else
+	configdir="${sysconfdir}/bluetooth"
+fi
+
+printf "%s\n" "#define CONFIGDIR \"${configdir}\"" >>confdefs.h
+
+CONFIGDIR="${configdir}"
+
+
+
+printf "%s\n" "#define MESH_STORAGEDIR \"${storagedir}/mesh\"" >>confdefs.h
+
+MESH_STORAGEDIR="${storagedir}/mesh"
+
+
+# Check whether --enable-android was given.
+if test ${enable_android+y}
+then :
+  enableval=$enable_android; enable_android=${enableval}
+fi
+
+ if test "${enable_android}" = "yes"; then
+  ANDROID_TRUE=
+  ANDROID_FALSE='#'
+else
+  ANDROID_TRUE='#'
+  ANDROID_FALSE=
+fi
+
+
+if (test "${enable_android}" = "yes"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sbc >= 1.2" >&5
+printf %s "checking for sbc >= 1.2... " >&6; }
+
+if test -n "$SBC_CFLAGS"; then
+    pkg_cv_SBC_CFLAGS="$SBC_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sbc >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sbc >= 1.2") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SBC_CFLAGS=`$PKG_CONFIG --cflags "sbc >= 1.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$SBC_LIBS"; then
+    pkg_cv_SBC_LIBS="$SBC_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sbc >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sbc >= 1.2") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SBC_LIBS=`$PKG_CONFIG --libs "sbc >= 1.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                SBC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sbc >= 1.2" 2>&1`
+        else
+                SBC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sbc >= 1.2" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$SBC_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (sbc >= 1.2) were not met:
+
+$SBC_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables SBC_CFLAGS
+and SBC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables SBC_CFLAGS
+and SBC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        SBC_CFLAGS=$pkg_cv_SBC_CFLAGS
+        SBC_LIBS=$pkg_cv_SBC_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+
+if (test "${enable_android}" = "yes"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for speexdsp >= 1.2" >&5
+printf %s "checking for speexdsp >= 1.2... " >&6; }
+
+if test -n "$SPEEXDSP_CFLAGS"; then
+    pkg_cv_SPEEXDSP_CFLAGS="$SPEEXDSP_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"speexdsp >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "speexdsp >= 1.2") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SPEEXDSP_CFLAGS=`$PKG_CONFIG --cflags "speexdsp >= 1.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$SPEEXDSP_LIBS"; then
+    pkg_cv_SPEEXDSP_LIBS="$SPEEXDSP_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"speexdsp >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "speexdsp >= 1.2") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SPEEXDSP_LIBS=`$PKG_CONFIG --libs "speexdsp >= 1.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                SPEEXDSP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "speexdsp >= 1.2" 2>&1`
+        else
+                SPEEXDSP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "speexdsp >= 1.2" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$SPEEXDSP_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (speexdsp >= 1.2) were not met:
+
+$SPEEXDSP_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables SPEEXDSP_CFLAGS
+and SPEEXDSP_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables SPEEXDSP_CFLAGS
+and SPEEXDSP_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        SPEEXDSP_CFLAGS=$pkg_cv_SPEEXDSP_CFLAGS
+        SPEEXDSP_LIBS=$pkg_cv_SPEEXDSP_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+
+
+printf "%s\n" "#define ANDROID_STORAGEDIR \"${storagedir}/android\"" >>confdefs.h
+
+
+
+# Check whether --with-phonebook was given.
+if test ${with_phonebook+y}
+then :
+  withval=$with_phonebook; plugin_phonebook=${withval}
+fi
+
+if (test -z "${plugin_phonebook}"); then
+	plugin_phonebook=dummy
+fi
+
+if (test "${plugin_phonebook}" = "ebook"); then
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libebook-1.2 >= 3.3" >&5
+printf %s "checking for libebook-1.2 >= 3.3... " >&6; }
+
+if test -n "$LIBEBOOK_CFLAGS"; then
+    pkg_cv_LIBEBOOK_CFLAGS="$LIBEBOOK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libebook-1.2 >= 3.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libebook-1.2 >= 3.3") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBEBOOK_CFLAGS=`$PKG_CONFIG --cflags "libebook-1.2 >= 3.3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBEBOOK_LIBS"; then
+    pkg_cv_LIBEBOOK_LIBS="$LIBEBOOK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libebook-1.2 >= 3.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libebook-1.2 >= 3.3") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBEBOOK_LIBS=`$PKG_CONFIG --libs "libebook-1.2 >= 3.3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                LIBEBOOK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libebook-1.2 >= 3.3" 2>&1`
+        else
+                LIBEBOOK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libebook-1.2 >= 3.3" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$LIBEBOOK_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (libebook-1.2 >= 3.3) were not met:
+
+$LIBEBOOK_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBEBOOK_CFLAGS
+and LIBEBOOK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables LIBEBOOK_CFLAGS
+and LIBEBOOK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        LIBEBOOK_CFLAGS=$pkg_cv_LIBEBOOK_CFLAGS
+        LIBEBOOK_LIBS=$pkg_cv_LIBEBOOK_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libedataserver-1.2 >= 3.3" >&5
+printf %s "checking for libedataserver-1.2 >= 3.3... " >&6; }
+
+if test -n "$LIBEDATESERVER_CFLAGS"; then
+    pkg_cv_LIBEDATESERVER_CFLAGS="$LIBEDATESERVER_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedataserver-1.2 >= 3.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libedataserver-1.2 >= 3.3") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBEDATESERVER_CFLAGS=`$PKG_CONFIG --cflags "libedataserver-1.2 >= 3.3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBEDATESERVER_LIBS"; then
+    pkg_cv_LIBEDATESERVER_LIBS="$LIBEDATESERVER_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedataserver-1.2 >= 3.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libedataserver-1.2 >= 3.3") 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBEDATESERVER_LIBS=`$PKG_CONFIG --libs "libedataserver-1.2 >= 3.3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+                LIBEDATESERVER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libedataserver-1.2 >= 3.3" 2>&1`
+        else
+                LIBEDATESERVER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libedataserver-1.2 >= 3.3" 2>&1`
+        fi
+        # Put the nasty error message in config.log where it belongs
+        echo "$LIBEDATESERVER_PKG_ERRORS" >&5
+
+        as_fn_error $? "Package requirements (libedataserver-1.2 >= 3.3) were not met:
+
+$LIBEDATESERVER_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBEDATESERVER_CFLAGS
+and LIBEDATESERVER_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables LIBEDATESERVER_CFLAGS
+and LIBEDATESERVER_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See 'config.log' for more details" "$LINENO" 5; }
+else
+        LIBEDATESERVER_CFLAGS=$pkg_cv_LIBEDATESERVER_CFLAGS
+        LIBEDATESERVER_LIBS=$pkg_cv_LIBEDATESERVER_LIBS
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+PLUGIN_PHONEBOOK=${plugin_phonebook}
+
+
+ac_config_files="$ac_config_files lib/bluez.pc Makefile mesh/bluetooth-meshd.rst mesh/bluetooth-mesh.service obexd/src/obex.service obexd/src/org.bluez.obex.service src/bluetoothd.rst src/bluetooth.service tools/bluetooth-logger.service tools/mpris-proxy.service"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# 'ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* 'ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # 'set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # 'set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+printf %s "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5
+printf "%s\n" "done" >&6; }
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${COVERAGE_TRUE}" && test -z "${COVERAGE_FALSE}"; then
+  as_fn_error $? "conditional \"COVERAGE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DBUS_RUN_SESSION_TRUE}" && test -z "${DBUS_RUN_SESSION_FALSE}"; then
+  as_fn_error $? "conditional \"DBUS_RUN_SESSION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${VALGRIND_TRUE}" && test -z "${VALGRIND_FALSE}"; then
+  as_fn_error $? "conditional \"VALGRIND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ZSH_COMPLETIONS_TRUE}" && test -z "${ZSH_COMPLETIONS_FALSE}"; then
+  as_fn_error $? "conditional \"ZSH_COMPLETIONS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBRARY_TRUE}" && test -z "${LIBRARY_FALSE}"; then
+  as_fn_error $? "conditional \"LIBRARY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TEST_TRUE}" && test -z "${TEST_FALSE}"; then
+  as_fn_error $? "conditional \"TEST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${NFC_TRUE}" && test -z "${NFC_FALSE}"; then
+  as_fn_error $? "conditional \"NFC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SAP_TRUE}" && test -z "${SAP_FALSE}"; then
+  as_fn_error $? "conditional \"SAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${A2DP_TRUE}" && test -z "${A2DP_FALSE}"; then
+  as_fn_error $? "conditional \"A2DP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AVRCP_TRUE}" && test -z "${AVRCP_FALSE}"; then
+  as_fn_error $? "conditional \"AVRCP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${NETWORK_TRUE}" && test -z "${NETWORK_FALSE}"; then
+  as_fn_error $? "conditional \"NETWORK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HID_TRUE}" && test -z "${HID_FALSE}"; then
+  as_fn_error $? "conditional \"HID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HOG_TRUE}" && test -z "${HOG_FALSE}"; then
+  as_fn_error $? "conditional \"HOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HEALTH_TRUE}" && test -z "${HEALTH_FALSE}"; then
+  as_fn_error $? "conditional \"HEALTH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BAP_TRUE}" && test -z "${BAP_FALSE}"; then
+  as_fn_error $? "conditional \"BAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BASS_TRUE}" && test -z "${BASS_FALSE}"; then
+  as_fn_error $? "conditional \"BASS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MCP_TRUE}" && test -z "${MCP_FALSE}"; then
+  as_fn_error $? "conditional \"MCP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CCP_TRUE}" && test -z "${CCP_FALSE}"; then
+  as_fn_error $? "conditional \"CCP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${VCP_TRUE}" && test -z "${VCP_FALSE}"; then
+  as_fn_error $? "conditional \"VCP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MICP_TRUE}" && test -z "${MICP_FALSE}"; then
+  as_fn_error $? "conditional \"MICP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CSIP_TRUE}" && test -z "${CSIP_FALSE}"; then
+  as_fn_error $? "conditional \"CSIP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ASHA_TRUE}" && test -z "${ASHA_FALSE}"; then
+  as_fn_error $? "conditional \"ASHA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TOOLS_TRUE}" && test -z "${TOOLS_FALSE}"; then
+  as_fn_error $? "conditional \"TOOLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MONITOR_TRUE}" && test -z "${MONITOR_FALSE}"; then
+  as_fn_error $? "conditional \"MONITOR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CUPS_TRUE}" && test -z "${CUPS_FALSE}"; then
+  as_fn_error $? "conditional \"CUPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CUPS_SERVERBIN_TRUE}" && test -z "${CUPS_SERVERBIN_FALSE}"; then
+  as_fn_error $? "conditional \"CUPS_SERVERBIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MESH_TRUE}" && test -z "${MESH_FALSE}"; then
+  as_fn_error $? "conditional \"MESH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MIDI_TRUE}" && test -z "${MIDI_FALSE}"; then
+  as_fn_error $? "conditional \"MIDI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OBEX_TRUE}" && test -z "${OBEX_FALSE}"; then
+  as_fn_error $? "conditional \"OBEX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BTPCLIENT_TRUE}" && test -z "${BTPCLIENT_FALSE}"; then
+  as_fn_error $? "conditional \"BTPCLIENT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${EXTERNAL_ELL_TRUE}" && test -z "${EXTERNAL_ELL_FALSE}"; then
+  as_fn_error $? "conditional \"EXTERNAL_ELL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBSHARED_ELL_TRUE}" && test -z "${LIBSHARED_ELL_FALSE}"; then
+  as_fn_error $? "conditional \"LIBSHARED_ELL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CLIENT_TRUE}" && test -z "${CLIENT_FALSE}"; then
+  as_fn_error $? "conditional \"CLIENT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${READLINE_TRUE}" && test -z "${READLINE_FALSE}"; then
+  as_fn_error $? "conditional \"READLINE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SYSTEMD_TRUE}" && test -z "${SYSTEMD_FALSE}"; then
+  as_fn_error $? "conditional \"SYSTEMD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DATAFILES_TRUE}" && test -z "${DATAFILES_FALSE}"; then
+  as_fn_error $? "conditional \"DATAFILES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MANPAGES_TRUE}" && test -z "${MANPAGES_FALSE}"; then
+  as_fn_error $? "conditional \"MANPAGES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${RUN_RST2MAN_TRUE}" && test -z "${RUN_RST2MAN_FALSE}"; then
+  as_fn_error $? "conditional \"RUN_RST2MAN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TESTING_TRUE}" && test -z "${TESTING_FALSE}"; then
+  as_fn_error $? "conditional \"TESTING\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${EXPERIMENTAL_TRUE}" && test -z "${EXPERIMENTAL_FALSE}"; then
+  as_fn_error $? "conditional \"EXPERIMENTAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DEPRECATED_TRUE}" && test -z "${DEPRECATED_FALSE}"; then
+  as_fn_error $? "conditional \"DEPRECATED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${EXTERNAL_PLUGINS_TRUE}" && test -z "${EXTERNAL_PLUGINS_FALSE}"; then
+  as_fn_error $? "conditional \"EXTERNAL_PLUGINS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SIXAXIS_TRUE}" && test -z "${SIXAXIS_FALSE}"; then
+  as_fn_error $? "conditional \"SIXAXIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HID2HCI_TRUE}" && test -z "${HID2HCI_FALSE}"; then
+  as_fn_error $? "conditional \"HID2HCI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LOGGER_TRUE}" && test -z "${LOGGER_FALSE}"; then
+  as_fn_error $? "conditional \"LOGGER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ADMIN_TRUE}" && test -z "${ADMIN_FALSE}"; then
+  as_fn_error $? "conditional \"ADMIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ANDROID_TRUE}" && test -z "${ANDROID_FALSE}"; then
+  as_fn_error $? "conditional \"ANDROID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else case e in #(
+  e) case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" ""	$as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  printf "%s\n" "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else case e in #(
+  e) as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  } ;;
+esac
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else case e in #(
+  e) as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  } ;;
+esac
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n.  New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+    # In both cases, we have to default to 'cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+
+# Sed expression to map a string onto a valid variable name.
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by bluez $as_me 5.79, which was
+generated by GNU Autoconf 2.72.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+'$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config='$ac_cs_config_escaped'
+ac_cs_version="\\
+bluez config.status 5.79
+configured by $0, generated by GNU Autoconf 2.72,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    printf "%s\n" "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    printf "%s\n" "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: '$1'
+Try '$0 --help' for more information.";;
+  --help | --hel | -h )
+    printf "%s\n" "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: '$1'
+Try '$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  printf "%s\n" "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+FILECMD \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+DLLTOOL \
+sharedlib_from_linklib_cmd \
+AR \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "lib/bluez.pc") CONFIG_FILES="$CONFIG_FILES lib/bluez.pc" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "mesh/bluetooth-meshd.rst") CONFIG_FILES="$CONFIG_FILES mesh/bluetooth-meshd.rst" ;;
+    "mesh/bluetooth-mesh.service") CONFIG_FILES="$CONFIG_FILES mesh/bluetooth-mesh.service" ;;
+    "obexd/src/obex.service") CONFIG_FILES="$CONFIG_FILES obexd/src/obex.service" ;;
+    "obexd/src/org.bluez.obex.service") CONFIG_FILES="$CONFIG_FILES obexd/src/org.bluez.obex.service" ;;
+    "src/bluetoothd.rst") CONFIG_FILES="$CONFIG_FILES src/bluetoothd.rst" ;;
+    "src/bluetooth.service") CONFIG_FILES="$CONFIG_FILES src/bluetooth.service" ;;
+    "tools/bluetooth-logger.service") CONFIG_FILES="$CONFIG_FILES tools/bluetooth-logger.service" ;;
+    "tools/mpris-proxy.service") CONFIG_FILES="$CONFIG_FILES tools/mpris-proxy.service" ;;
+
+  *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+  test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to '$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with './config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with './config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script 'defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain ':'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is 'configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when '$srcdir' = '.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      printf "%s\n" "/* $configure_input  */" >&1 \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    printf "%s\n" "/* $configure_input  */" >&1 \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  case $CONFIG_FILES in #(
+  *\'*) :
+    eval set x "$CONFIG_FILES" ;; #(
+  *) :
+    set x $CONFIG_FILES ;; #(
+  *) :
+     ;;
+esac
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$am_mf" : 'X\(//\)[^/]' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$am_mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$am_mf" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    { echo "$as_me:$LINENO: cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles" >&5
+   (cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE=\"gmake\" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).
+See 'config.log' for more details" "$LINENO" 5; }
+  fi
+  { am_dirpart=; unset am_dirpart;}
+  { am_filepart=; unset am_filepart;}
+  { am_mf=; unset am_mf;}
+  { am_rc=; unset am_rc;}
+  rm -f conftest-deps.mk
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options that allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}"; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile=${ofile}T
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool 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 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the  same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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, see <http://www.gnu.org/licenses/>.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# A file(cmd) program that detects file types.
+FILECMD=$lt_FILECMD
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive (by configure).
+lt_ar_flags=$lt_ar_flags
+
+# Flags to create an archive.
+AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+    cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x$2 in
+    x)
+        ;;
+    *:)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+        ;;
+    x:*)
+        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+        ;;
+    *)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+
+
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in $*""; do
+      case $cc_temp in
+        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  $SED '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/configure.ac b/configure.ac
index f9f0faf..01f0f2b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 AC_PREREQ(2.60)
-AC_INIT(bluez, 5.66)
+AC_INIT(bluez, 5.79)
 
 AM_INIT_AUTOMAKE([foreign subdir-objects color-tests silent-rules
 					tar-pax no-dist-gzip dist-xz])
@@ -32,8 +32,8 @@ AC_PROG_MKDIR_P
 m4_define([_LT_AC_TAGCONFIG], [])
 m4_ifdef([AC_LIBTOOL_TAGS], [AC_LIBTOOL_TAGS([])])
 
-AC_DISABLE_STATIC
-AC_PROG_LIBTOOL
+LT_PREREQ(2.2)
+LT_INIT([disable-static])
 
 if (test "$USE_MAINTAINER_MODE" = "yes"); then
 	AC_CHECK_PROG(enable_coverage, [lcov], [yes], [no])
@@ -70,32 +70,34 @@ AC_CHECK_LIB(pthread, pthread_create, dummy=yes,
 AC_CHECK_LIB(dl, dlopen, dummy=yes,
 			AC_MSG_ERROR(dynamic linking loader is required))
 
-AC_CHECK_HEADERS(linux/types.h linux/if_alg.h linux/uinput.h linux/uhid.h sys/random.h)
+AC_CHECK_HEADERS(string.h linux/types.h linux/if_alg.h linux/uinput.h linux/uhid.h sys/random.h)
 
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
-				AC_MSG_ERROR(GLib >= 2.28 is required))
-AC_SUBST(GLIB_CFLAGS)
-AC_SUBST(GLIB_LIBS)
+# basename may be only available in libgen.h with the POSIX behavior,
+# not desired here
+AC_CHECK_DECLS([basename], [],
+				AC_MSG_WARN([GNU basename extension not found]),
+				[#define _GNU_SOURCE 1
+				 #include <string.h>
+				 ])
+
+
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28)
 
 if (test "${enable_threads}" = "yes"); then
 	AC_DEFINE(NEED_THREADS, 1, [Define if threading support is required])
-	PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
-				AC_MSG_ERROR(GThread >= 2.16 is required))
+	PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16)
 	GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
 	GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
 fi
 
-PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.6, dummy=yes,
-				AC_MSG_ERROR(D-Bus >= 1.6 is required))
-AC_SUBST(DBUS_CFLAGS)
-AC_SUBST(DBUS_LIBS)
+PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.10)
 
 AC_ARG_WITH([dbusconfdir], AS_HELP_STRING([--with-dbusconfdir=DIR],
 				[path to D-Bus configuration directory]),
 					[path_dbusconfdir=${withval}])
 if (test -z "${path_dbusconfdir}"); then
 	AC_MSG_CHECKING([D-Bus configuration directory])
-	path_dbusconfdir="`$PKG_CONFIG --variable=sysconfdir dbus-1`"
+	path_dbusconfdir="`$PKG_CONFIG --variable=datadir dbus-1`"
 	if (test -z "${path_dbusconfdir}"); then
 		AC_MSG_ERROR([D-Bus configuration directory is required])
 	fi
@@ -199,14 +201,34 @@ AC_ARG_ENABLE(bap, AS_HELP_STRING([--disable-bap],
 		[disable BAP profile]), [enable_bap=${enableval}])
 AM_CONDITIONAL(BAP, test "${enable_bap}" != "no")
 
+AC_ARG_ENABLE(bass, AS_HELP_STRING([--disable-bass],
+		[disable BASS service]), [enable_bass=${enableval}])
+AM_CONDITIONAL(BASS, test "${enable_bass}" != "no")
+
 AC_ARG_ENABLE(mcp, AS_HELP_STRING([--disable-mcp],
         [disable MCP profile]), [enable_mcp=${enableval}])
 AM_CONDITIONAL(MCP, test "${enable_mcp}" != "no")
 
+AC_ARG_ENABLE(ccp, AS_HELP_STRING([--disable-ccp],
+        [disable CCP profile]), [enable_ccp=${enableval}])
+AM_CONDITIONAL(CCP, test "${enable_ccp}" != "no")
+
 AC_ARG_ENABLE(vcp, AS_HELP_STRING([--disable-vcp],
 		[disable VCP profile]), [enable_vcp=${enableval}])
 AM_CONDITIONAL(VCP, test "${enable_vcp}" != "no")
 
+AC_ARG_ENABLE(micp, AS_HELP_STRING([--disable-micp],
+		[disable MICP profile]), [enable_micp=${enableval}])
+AM_CONDITIONAL(MICP, test "${enable_micp}" != "no")
+
+AC_ARG_ENABLE(csip, AS_HELP_STRING([--disable-csip],
+		[disable CSIP profile]), [enable_csip=${enableval}])
+AM_CONDITIONAL(CSIP, test "${enable_csip}" != "no")
+
+AC_ARG_ENABLE(asha, AS_HELP_STRING([--disable-asha],
+		[disable ASHA support]), [enable_asha=${enableval}])
+AM_CONDITIONAL(ASHA, test "${enable_asha}" != "no")
+
 AC_ARG_ENABLE(tools, AS_HELP_STRING([--disable-tools],
 		[disable Bluetooth tools]), [enable_tools=${enableval}])
 AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no")
@@ -217,16 +239,10 @@ AM_CONDITIONAL(MONITOR, test "${enable_monitor}" != "no")
 
 AC_ARG_ENABLE(udev, AS_HELP_STRING([--disable-udev],
 		[disable udev device support]), [enable_udev=${enableval}])
-if (test "${enable_tools}" != "no" && test "${enable_udev}" != "no"); then
-	PKG_CHECK_MODULES(UDEV, libudev >= 172, dummy=yes,
-				AC_MSG_ERROR(libudev >= 172 is required))
-	AC_SUBST(UDEV_CFLAGS)
-	AC_SUBST(UDEV_LIBS)
-	AC_CHECK_LIB(udev, udev_hwdb_new,
-		AC_DEFINE(HAVE_UDEV_HWDB_NEW, 1,
-			[Define to 1 if you have the udev_hwdb_new() function.]))
+if (test "${enable_udev}" != "no"); then
+	PKG_CHECK_MODULES(UDEV, libudev >= 196)
+	AC_DEFINE(HAVE_UDEV, 1, [Define to 1 if udev is required])
 fi
-AM_CONDITIONAL(UDEV, test "${enable_udev}" != "no")
 
 AC_ARG_WITH([udevdir], AS_HELP_STRING([--with-udevdir=DIR],
 			[path to udev directory]), [path_udevdir=${withval}])
@@ -243,16 +259,22 @@ AC_SUBST(UDEV_DIR, [${path_udevdir}])
 AC_ARG_ENABLE(cups, AS_HELP_STRING([--disable-cups],
                 [disable CUPS printer support]), [enable_cups=${enableval}])
 AM_CONDITIONAL(CUPS, test "${enable_cups}" != "no")
+if (test "${enable_cups}" != "no"); then
+	AC_MSG_CHECKING([cups directory])
+	cups_serverbin=`$PKG_CONFIG cups --variable=cups_serverbin`
+	AC_MSG_RESULT([${cups_serverbin}])
+fi
+AM_CONDITIONAL(CUPS_SERVERBIN, test "${cups_serverbin}" != "")
+AS_IF([test "${cups_serverbin}" != ""],[
+	AC_SUBST(CUPS_SERVERBIN, ${cups_serverbin})
+])
 
 AC_ARG_ENABLE(mesh, AS_HELP_STRING([--enable-mesh],
 		[enable Mesh profile support]), [enable_mesh=${enableval}])
 AM_CONDITIONAL(MESH, test "${enable_mesh}" = "yes")
 
 if (test "${enable_mesh}" = "yes"); then
-	PKG_CHECK_MODULES(JSONC, json-c >= 0.13, dummy=yes,
-				AC_MSG_ERROR(json-c >= 0.13 is required))
-	AC_SUBST(JSON_CFLAGS)
-	AC_SUBST(JSON_LIBS)
+	PKG_CHECK_MODULES(JSONC, json-c >= 0.13)
 fi
 
 AC_ARG_ENABLE(midi, AS_HELP_STRING([--enable-midi],
@@ -260,19 +282,13 @@ AC_ARG_ENABLE(midi, AS_HELP_STRING([--enable-midi],
 AM_CONDITIONAL(MIDI, test "${enable_midi}" = "yes")
 
 if (test "${enable_midi}" = "yes"); then
-	PKG_CHECK_MODULES(ALSA, alsa, dummy=yes,
-			AC_MSG_ERROR(ALSA lib is required for MIDI support))
-	AC_SUBST(ALSA_CFLAGS)
-	AC_SUBST(ALSA_LIBS)
+	PKG_CHECK_MODULES(ALSA, alsa)
 fi
 
 AC_ARG_ENABLE(obex, AS_HELP_STRING([--disable-obex],
 		[disable OBEX profile support]), [enable_obex=${enableval}])
 if (test "${enable_obex}" != "no"); then
-	PKG_CHECK_MODULES(ICAL, libical, dummy=yes,
-					AC_MSG_ERROR(libical is required))
-	AC_SUBST(ICAL_CFLAGS)
-	AC_SUBST(ICAL_LIBS)
+	PKG_CHECK_MODULES(ICAL, libical)
 fi
 AM_CONDITIONAL(OBEX, test "${enable_obex}" != "no")
 
@@ -284,10 +300,14 @@ AC_ARG_ENABLE([external_ell], AS_HELP_STRING([--enable-external-ell],
 				[enable external Embedded Linux library]),
 					[enable_external_ell=${enableval}])
 if (test "${enable_external_ell}" = "yes"); then
-	PKG_CHECK_MODULES(ELL, ell >= 0.39, dummy=yes,
-		AC_MSG_ERROR(Embedded Linux library >= 0.39 is required))
-	AC_SUBST(ELL_CFLAGS)
-	AC_SUBST(ELL_LIBS)
+	PKG_CHECK_MODULES(ELL, ell >= 0.39)
+fi
+if (test "${enable_external_ell}" != "yes" &&
+		(test "${enable_btpclient}" = "yes" || test "${enable_mesh}" = "yes")); then
+	if (test ! -f ${srcdir}/ell/ell.h) &&
+			(test ! -f ${srcdir}/../ell/ell/ell.h); then
+				AC_MSG_ERROR(ELL source is required or use --enable-external-ell)
+	fi
 fi
 AM_CONDITIONAL(EXTERNAL_ELL, test "${enable_external_ell}" = "yes" ||
 				(test "${enable_btpclient}" != "yes" &&
@@ -370,6 +390,16 @@ AC_ARG_ENABLE(deprecated, AS_HELP_STRING([--enable-deprecated],
 					[enable_deprecated=${enableval}])
 AM_CONDITIONAL(DEPRECATED, test "${enable_deprecated}" = "yes")
 
+AC_ARG_ENABLE(external-plugins, AS_HELP_STRING([--enable-external-plugins],
+			[enable support for external plugins]),
+					[enable_external_plugins=${enableval}])
+AM_CONDITIONAL(EXTERNAL_PLUGINS, test "${enable_external_plugins}" = "yes")
+if (test "${enable_external_plugins}" = "yes"); then
+	AC_DEFINE(EXTERNAL_PLUGINS, 1, [Define if external plugin support is required])
+else
+	AC_DEFINE(EXTERNAL_PLUGINS, 0, [Define if external plugin support is required])
+fi
+
 AC_ARG_ENABLE(sixaxis, AS_HELP_STRING([--enable-sixaxis],
 		[enable sixaxis plugin]), [enable_sixaxis=${enableval}])
 AM_CONDITIONAL(SIXAXIS, test "${enable_sixaxis}" = "yes" &&
@@ -397,6 +427,32 @@ if (test "${prefix}" = "NONE"); then
 	prefix="${ac_default_prefix}"
 fi
 
+if (test "${exec_prefix}" = "NONE"); then
+	# exec_prefix defaults to prefix, although our manual handling of the
+	# latter (above) confuses autoconf. Manually set the exec_prefix.
+	exec_prefix="${prefix}"
+fi
+
+# Expand any variables containing relative references like ${prefix} and co.
+#
+# Otherwise we'll end up with literal references in the final binaries or
+# manuals, which is not something we really want.
+#
+pkgbindir="${bindir}"
+if (test "$bindir" = '${exec_prefix}/bin'); then
+	pkgbindir="${exec_prefix}/bin"
+else
+	pkgbindir="${bindir}"
+fi
+AC_SUBST(PKGBINDIR, "${pkgbindir}")
+
+if (test "$libexecdir" = '${exec_prefix}/libexec'); then
+	pkglibexecdir="${exec_prefix}/libexec/bluetooth"
+else
+	pkglibexecdir="${libexecdir}/bluetooth"
+fi
+AC_SUBST(PKGLIBEXECDIR, "${pkglibexecdir}")
+
 if (test "$localstatedir" = '${prefix}/var'); then
 	storagedir="${prefix}/var/lib/bluetooth"
 else
@@ -424,17 +480,11 @@ AC_ARG_ENABLE(android, AS_HELP_STRING([--enable-android],
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
 if (test "${enable_android}" = "yes"); then
-	PKG_CHECK_MODULES(SBC, sbc >= 1.2, dummy=yes,
-			AC_MSG_ERROR(SBC library >= 1.2 is required))
-	AC_SUBST(SBC_CFLAGS)
-	AC_SUBST(SBC_LIBS)
+	PKG_CHECK_MODULES(SBC, sbc >= 1.2)
 fi
 
 if (test "${enable_android}" = "yes"); then
-	PKG_CHECK_MODULES(SPEEXDSP, speexdsp >= 1.2, dummy=yes,
-			AC_MSG_ERROR(SPEEXDSP library >= 1.2 is required))
-	AC_SUBST(SPEEXDSP_CFLAGS)
-	AC_SUBST(SPEEXDSP_LIBS)
+	PKG_CHECK_MODULES(SPEEXDSP, speexdsp >= 1.2)
 fi
 
 AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
@@ -448,17 +498,21 @@ if (test -z "${plugin_phonebook}"); then
 fi
 
 if (test "${plugin_phonebook}" = "ebook"); then
-	PKG_CHECK_MODULES(LIBEBOOK, [libebook-1.2 >= 3.3], dummy=yes,
-			AC_MSG_ERROR(libebook >= 3.3 is required))
-	AC_SUBST(LIBEBOOK_CFLAGS)
-	AC_SUBST(LIBEBOOK_LIBS)
-	PKG_CHECK_MODULES(LIBEDATESERVER, [libedataserver-1.2 >= 3.3],
-			dummy=yes,
-			AC_MSG_ERROR(libedataserver >= 3.3 is required))
-	AC_SUBST(LIBEDATESERVER_CFLAGS)
-	AC_SUBST(LIBEDATESERVER_LIBS)
+	PKG_CHECK_MODULES(LIBEBOOK, libebook-1.2 >= 3.3)
+	PKG_CHECK_MODULES(LIBEDATESERVER, libedataserver-1.2 >= 3.3)
 fi
 AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}])
 
-AC_CONFIG_FILES(Makefile src/bluetoothd.rst lib/bluez.pc mesh/bluetooth-meshd.rst)
+AC_CONFIG_FILES(
+	lib/bluez.pc
+	Makefile
+	mesh/bluetooth-meshd.rst
+	mesh/bluetooth-mesh.service
+	obexd/src/obex.service
+	obexd/src/org.bluez.obex.service
+	src/bluetoothd.rst
+	src/bluetooth.service
+	tools/bluetooth-logger.service
+	tools/mpris-proxy.service
+)
 AC_OUTPUT
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..715e343
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+
+# 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, 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, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputting dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='	'
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'.  On the theory
+## that the space means something, we add a space to the output as
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like '#:fec' to the end of the
+    # dependency line.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+      | tr "$nl" ' ' >> "$depfile"
+    echo >> "$depfile"
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+      >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  set_dir_from "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using '\' :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
+
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  set_dir_from  "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
+    sed -ne '2,${
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
+
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
+
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for ':'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+  "$@" $dashmflag |
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+        set fnord "$@"
+        shift
+        shift
+        ;;
+    *)
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
deleted file mode 100644
index 9b2721c..0000000
--- a/doc/adapter-api.txt
+++ /dev/null
@@ -1,361 +0,0 @@
-BlueZ D-Bus Adapter API description
-***********************************
-
-
-Adapter hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.Adapter1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		void StartDiscovery()
-
-			This method starts the device discovery session. This
-			includes an inquiry procedure and remote device name
-			resolving. Use StopDiscovery to release the sessions
-			acquired.
-
-			This process will start creating Device objects as
-			new devices are discovered.
-
-			During discovery RSSI delta-threshold is imposed.
-
-			Each client can request a single device discovery session
-			per adapter.
-
-			Possible errors: org.bluez.Error.NotReady
-					 org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-
-		void StopDiscovery()
-
-			This method will cancel any previous StartDiscovery
-			transaction.
-
-			Note that a discovery procedure is shared between all
-			discovery sessions thus calling StopDiscovery will only
-			release a single session and discovery will stop when
-			all sessions from all clients have finished.
-
-			Possible errors: org.bluez.Error.NotReady
-					 org.bluez.Error.Failed
-					 org.bluez.Error.NotAuthorized
-
-		void RemoveDevice(object device)
-
-			This removes the remote device object at the given
-			path. It will remove also the pairing information.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.Failed
-
-		void SetDiscoveryFilter(dict filter)
-
-			This method sets the device discovery filter for the
-			caller. When this method is called with no filter
-			parameter, filter is removed.
-
-			Parameters that may be set in the filter dictionary
-			include the following:
-
-			array{string} UUIDs
-
-				Filter by service UUIDs, empty means match
-				_any_ UUID.
-
-				When a remote device is found that advertises
-				any UUID from UUIDs, it will be reported if:
-				- Pathloss and RSSI are both empty.
-				- only Pathloss param is set, device advertise
-				  TX pwer, and computed pathloss is less than
-				  Pathloss param.
-				- only RSSI param is set, and received RSSI is
-				  higher than RSSI param.
-
-			int16 RSSI
-
-				RSSI threshold value.
-
-				PropertiesChanged signals will be emitted
-				for already existing Device objects, with
-				updated RSSI value. If one or more discovery
-				filters have been set, the RSSI delta-threshold,
-				that is imposed by StartDiscovery by default,
-				will not be applied.
-
-			uint16 Pathloss
-
-				Pathloss threshold value.
-
-				PropertiesChanged signals will be emitted
-				for already existing Device objects, with
-				updated Pathloss value.
-
-			string Transport (Default "auto")
-
-				Transport parameter determines the type of
-				scan.
-
-				Possible values:
-					"auto"	- interleaved scan
-					"bredr"	- BR/EDR inquiry
-					"le"	- LE scan only
-
-				If "le" or "bredr" Transport is requested,
-				and the controller doesn't support it,
-				org.bluez.Error.Failed error will be returned.
-				If "auto" transport is requested, scan will use
-				LE, BREDR, or both, depending on what's
-				currently enabled on the controller.
-
-			bool DuplicateData (Default: true)
-
-				Disables duplicate detection of advertisement
-				data.
-
-				When enabled PropertiesChanged signals will be
-				generated for either ManufacturerData and
-				ServiceData everytime they are discovered.
-
-			bool Discoverable (Default: false)
-
-				Make adapter discoverable while discovering,
-				if the adapter is already discoverable setting
-				this filter won't do anything.
-
-			string Pattern (Default: none)
-
-				Discover devices where the pattern matches
-				either the prefix of the address or
-				device name which is convenient way to limited
-				the number of device objects created during a
-				discovery.
-
-				When set disregards device discoverable flags.
-
-				Note: The pattern matching is ignored if there
-				are other client that don't set any pattern as
-				it work as a logical OR, also setting empty
-				string "" pattern will match any device found.
-
-			When discovery filter is set, Device objects will be
-			created as new devices with matching criteria are
-			discovered regardless of they are connectable or
-			discoverable which enables listening to
-			non-connectable and non-discoverable devices.
-
-			When multiple clients call SetDiscoveryFilter, their
-			filters are internally merged, and notifications about
-			new devices are sent to all clients. Therefore, each
-			client must check that device updates actually match
-			its filter.
-
-			When SetDiscoveryFilter is called multiple times by the
-			same client, last filter passed will be active for
-			given client.
-
-			SetDiscoveryFilter can be called before StartDiscovery.
-			It is useful when client will create first discovery
-			session, to ensure that proper scan will be started
-			right after call to StartDiscovery.
-
-			Possible errors: org.bluez.Error.NotReady
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		array{string} GetDiscoveryFilters()
-
-			Return available filters that can be given to
-			SetDiscoveryFilter.
-
-			Possible errors: None
-
-		object ConnectDevice(dict properties) [experimental]
-
-			This method connects to device without need of
-			performing General Discovery. Connection mechanism is
-			similar to Connect method from Device1 interface with
-			exception that this method returns success when physical
-			connection is established. After this method returns,
-			services discovery will continue and any supported
-			profile will be connected. There is no need for calling
-			Connect on Device1 after this call. If connection was
-			successful this method returns object path to created
-			device object.
-
-			Parameters that may be set in the filter dictionary
-			include the following:
-
-			string Address
-
-				The Bluetooth device address of the remote
-				device. This parameter is mandatory.
-
-			string AddressType
-
-				The Bluetooth device Address Type. This is
-				address type that should be used for initial
-				connection. If this parameter is not present
-				BR/EDR device is created.
-
-				Possible values:
-					"public" - Public address
-					"random" - Random address
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.NotReady
-					 org.bluez.Error.Failed
-
-Properties	string Address [readonly]
-
-			The Bluetooth device address.
-
-		string AddressType [readonly]
-
-			The Bluetooth  Address Type. For dual-mode and BR/EDR
-			only adapter this defaults to "public". Single mode LE
-			adapters may have either value. With privacy enabled
-			this contains type of Identity Address and not type of
-			address used for connection.
-
-			Possible values:
-				"public" - Public address
-				"random" - Random address
-
-		string Name [readonly]
-
-			The Bluetooth system name (pretty hostname).
-
-			This property is either a static system default
-			or controlled by an external daemon providing
-			access to the pretty hostname configuration.
-
-		string Alias [readwrite]
-
-			The Bluetooth friendly name. This value can be
-			changed.
-
-			In case no alias is set, it will return the system
-			provided name. Setting an empty string as alias will
-			convert it back to the system provided name.
-
-			When resetting the alias with an empty string, the
-			property will default back to system name.
-
-			On a well configured system, this property never
-			needs to be changed since it defaults to the system
-			name and provides the pretty hostname. Only if the
-			local name needs to be different from the pretty
-			hostname, this property should be used as last
-			resort.
-
-		uint32 Class [readonly]
-
-			The Bluetooth class of device.
-
-			This property represents the value that is either
-			automatically configured by DMI/ACPI information
-			or provided as static configuration.
-
-		boolean Powered [readwrite]
-
-			Switch an adapter on or off. This will also set the
-			appropriate connectable state of the controller.
-
-			The value of this property is not persistent. After
-			restart or unplugging of the adapter it will reset
-			back to false.
-
-		string PowerState [readonly, experimental]
-
-			The power state of an adapter.
-
-			The power state will show whether the adapter is
-			turning off, or turning on, as well as being on
-			or off.
-
-			Possible values:
-				"on" - powered on
-				"off" - powered off
-				"off-enabling" - transitioning from "off" to "on"
-				"on-disabling" - transitioning from "on" to "off"
-				"off-blocked" - blocked by rfkill
-
-		boolean Discoverable [readwrite]
-
-			Switch an adapter to discoverable or non-discoverable
-			to either make it visible or hide it. This is a global
-			setting and should only be used by the settings
-			application.
-
-			If the DiscoverableTimeout is set to a non-zero
-			value then the system will set this value back to
-			false after the timer expired.
-
-			In case the adapter is switched off, setting this
-			value will fail.
-
-			When changing the Powered property the new state of
-			this property will be updated via a PropertiesChanged
-			signal.
-
-			For any new adapter this settings defaults to false.
-
-		boolean Pairable [readwrite]
-
-			Switch an adapter to pairable or non-pairable. This is
-			a global setting and should only be used by the
-			settings application.
-
-			Note that this property only affects incoming pairing
-			requests.
-
-			For any new adapter this settings defaults to true.
-
-		uint32 PairableTimeout [readwrite]
-
-			The pairable timeout in seconds. A value of zero
-			means that the timeout is disabled and it will stay in
-			pairable mode forever.
-
-			The default value for pairable timeout should be
-			disabled (value 0).
-
-		uint32 DiscoverableTimeout [readwrite]
-
-			The discoverable timeout in seconds. A value of zero
-			means that the timeout is disabled and it will stay in
-			discoverable/limited mode forever.
-
-			The default value for the discoverable timeout should
-			be 180 seconds (3 minutes).
-
-		boolean Discovering [readonly]
-
-			Indicates that a device discovery procedure is active.
-
-		array{string} UUIDs [readonly]
-
-			List of 128-bit UUIDs that represents the available
-			local services.
-
-		string Modalias [readonly, optional]
-
-			Local Device ID information in modalias format
-			used by the kernel and udev.
-
-		array{string} Roles [readonly]
-
-			List of supported roles. Possible values:
-				"central": Supports the central role.
-				"peripheral": Supports the peripheral role.
-				"central-peripheral": Supports both roles
-						      concurrently.
-
-		array{string} ExperimentalFeatures [readonly, optional]
-
-			List of 128-bit UUIDs that represents the experimental
-			features currently enabled.
diff --git a/doc/admin-policy-api.txt b/doc/admin-policy-api.txt
deleted file mode 100644
index 3f11690..0000000
--- a/doc/admin-policy-api.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-BlueZ D-Bus Admin Policy API description
-***********************************
-
-This API provides methods to control the behavior of bluez as an administrator.
-
-Interface AdminPolicySet1 provides methods to set policies. Once the policy is
-set successfully, it will affect all clients and stay persistently even after
-restarting Bluetooth Daemon. The only way to clear it is to overwrite the
-policy with the same method.
-
-Interface AdminPolicyStatus1 provides readonly properties to indicate the
-current values of admin policy.
-
-
-Admin Policy Set hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.AdminPolicySet1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		void SetServiceAllowList(array{string} UUIDs)
-
-			This method sets the service allowlist by specifying
-			service UUIDs.
-
-			When SetServiceAllowList is called, bluez will block
-			incoming and outgoing connections to the service not in
-			UUIDs for all of the clients.
-
-			Any subsequent calls to this method will supersede any
-			previously set allowlist values.  Calling this method
-			with an empty array will allow any service UUIDs to be
-			used.
-
-			The default value is an empty array.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.Failed
-
-
-Admin Policy Status hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.AdminPolicyStatus1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Properties	array{string} ServiceAllowList [readonly]
-
-			Current value of service allow list.
-
-
-
-Admin Policy Status hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.AdminPolicyStatus1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Properties	bool IsAffectedByPolicy [readonly]
-
-			Indicate if there is any auto-connect profile in this
-			device is not allowed by admin policy.
diff --git a/doc/advertisement-monitor-api.txt b/doc/advertisement-monitor-api.txt
deleted file mode 100644
index 9189f2c..0000000
--- a/doc/advertisement-monitor-api.txt
+++ /dev/null
@@ -1,187 +0,0 @@
-BlueZ D-Bus Advertisement Monitor API Description
-*************************************************
-
-This API allows an client to specify a job of monitoring advertisements by
-registering the root of hierarchy and then exposing advertisement monitors
-under the root with filtering conditions, thresholds of RSSI and timers
-of RSSI thresholds.
-
-Once a monitoring job is activated by BlueZ, the client can expect to get
-notified on the targeted advertisements no matter if there is an ongoing
-discovery session (a discovery session is started/stopped with methods in
-org.bluez.Adapter1 interface).
-
-Advertisement Monitor hierarchy
-===============================
-Service		org.bluez
-Interface	org.bluez.AdvertisementMonitor1 [experimental]
-Object path	freely definable
-
-Methods		void Release() [noreply]
-
-			This gets called as a signal for a client to perform
-			clean-up when (1)a monitor cannot be activated after it
-			was exposed or (2)a monitor has been deactivated.
-
-		void Activate() [noreply]
-
-			After a monitor was exposed, this gets called as a
-			signal for client to get acknowledged when a monitor
-			has been activated, so the client can expect to receive
-			calls on DeviceFound() or DeviceLost().
-
-		void DeviceFound(object device) [noreply]
-
-			This gets called to notify the client of finding the
-			targeted device. Once receiving the call, the client
-			should start to monitor the corresponding device to
-			retrieve the changes on RSSI and advertisement content.
-
-		void DeviceLost(object device) [noreply]
-
-			This gets called to notify the client of losing the
-			targeted device. Once receiving this call, the client
-			should stop monitoring the corresponding device.
-
-Properties	string Type [read-only]
-
-			The type of the monitor. See SupportedMonitorTypes in
-			org.bluez.AdvertisementMonitorManager1 for the available
-			options.
-
-		Int16 RSSILowThreshold [read-only, optional]
-
-			Used in conjunction with RSSILowTimeout to determine
-			whether a device becomes out-of-range. Valid range is
-			-127 to 20 (dBm), while 127 indicates unset.
-
-		Int16 RSSIHighThreshold [read-only, optional]
-
-			Used in conjunction with RSSIHighTimeout to determine
-			whether a device becomes in-range. Valid range is
-			-127 to 20 (dBm), while 127 indicates unset.
-
-		Uint16 RSSILowTimeout [read-only, optional]
-
-			The time it takes to consider a device as out-of-range.
-			If this many seconds elapses without receiving any
-			signal at least as strong as RSSILowThreshold, a
-			currently in-range device will be considered as
-			out-of-range (lost). Valid range is 1 to 300 (seconds),
-			while 0 indicates unset.
-
-		Uint16 RSSIHighTimeout [read-only, optional]
-
-			The time it takes to consider a device as in-range.
-			If this many seconds elapses while we continuously
-			receive signals at least as strong as RSSIHighThreshold,
-			a currently out-of-range device will be considered as
-			in-range (found). Valid range is 1 to 300 (seconds),
-			while 0 indicates unset.
-
-		Uint16 RSSISamplingPeriod [read-only, optional]
-
-			Grouping rules on how to propagate the received
-			advertisement packets to the client. Valid range is 0 to
-			255 while 256 indicates unset.
-
-			The meaning of this property is as follows:
-			0:
-				All advertisement packets from in-range devices
-				would be propagated.
-			255:
-				Only the first advertisement packet of in-range
-				devices would be propagated. If the device
-				becomes lost, then the first packet when it is
-				found again will also be propagated.
-			1 to 254:
-				Advertisement packets would be grouped into
-				100ms * N time period. Packets in the same group
-				will only be reported once, with the RSSI value
-				being averaged out.
-
-			Currently this is unimplemented in user space, so the
-			value is only used to be forwarded to the kernel.
-
-		array{(uint8, uint8, array{byte})} Patterns [read-only, optional]
-
-			If the Type property is set to "or_patterns", then this
-			property must exist and have at least one entry in the
-			array.
-
-			The structure of a pattern contains the following:
-			uint8 start_position
-				The index in an AD data field where the search
-				should start. The beginning of an AD data field
-				is index 0.
-			uint8 AD_data_type
-				See https://www.bluetooth.com/specifications/
-				assigned-numbers/generic-access-profile/ for
-				the possible allowed value.
-			array{byte} content_of_pattern
-				This is the value of the pattern. The maximum
-				length of the bytes is 31.
-
-Advertisement Monitor Manager hierarchy
-=======================================
-Service		org.bluez
-Interface	org.bluez.AdvertisementMonitorManager1 [experimental]
-Object path	/org/bluez/{hci0,hci1,...}
-
-Methods		void RegisterMonitor(object application)
-
-			This registers the root path of a hierarchy of
-			advertisement monitors.
-			The application object path together with the D-Bus
-			system bus connection ID define the identification of
-			the application registering advertisement monitors.
-			Once a root path is registered by a client via this
-			method, the client can freely expose/unexpose
-			advertisement monitors without re-registering the root
-			path again. After use, the client should call
-			UnregisterMonitor() method to invalidate the
-			advertisement monitors.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-					 org.bluez.Error.Failed
-
-		void UnregisterMonitor(object application)
-
-			This unregisters a hierarchy of advertisement monitors
-			that has been previously registered. The object path
-			parameter must match the same value that has been used
-			on registration. Upon unregistration, the advertisement
-			monitor(s) should expect to receive Release() method as
-			the signal that the advertisement monitor(s) has been
-			deactivated.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.DoesNotExist
-
-Properties	array{string} SupportedMonitorTypes [read-only]
-
-			This lists the supported types of advertisement
-			monitors. An application should check this before
-			instantiate and expose an object of
-			org.bluez.AdvertisementMonitor1.
-
-			Possible values for monitor types:
-
-			"or_patterns"
-				Patterns with logic OR applied. With this type,
-				property "Patterns" must exist and has at least
-				one pattern.
-
-		array{string} SupportedFeatures [read-only]
-
-			This lists the features of advertisement monitoring
-			supported by BlueZ.
-
-			Possible values for features:
-
-			"controller-patterns"
-				If the controller is capable of performing
-				advertisement monitoring by patterns, BlueZ
-				would offload the patterns to the controller to
-				reduce power consumption.
diff --git a/doc/advertising-api.txt b/doc/advertising-api.txt
deleted file mode 100644
index c6ee934..0000000
--- a/doc/advertising-api.txt
+++ /dev/null
@@ -1,277 +0,0 @@
-BlueZ D-Bus LE Advertising API Description
-******************************************
-
-Advertising packets are structured data which is broadcast on the LE Advertising
-channels and available for all devices in range.  Because of the limited space
-available in LE Advertising packets (31 bytes), each packet's contents must be
-carefully controlled.
-
-BlueZ acts as a store for the Advertisement Data which is meant to be sent.
-It constructs the correct Advertisement Data from the structured
-data and configured the kernel to send the correct advertisement.
-
-Advertisement Data objects are registered freely and then referenced by BlueZ
-when constructing the data sent to the kernel.
-
-LE Advertisement Data hierarchy
-===============================
-
-Specifies the Advertisement Data to be broadcast and some advertising
-parameters.  Properties which are not present will not be included in the
-data.  Required advertisement data types will always be included.
-All UUIDs are 128-bit versions in the API, and 16 or 32-bit
-versions of the same UUID will be used in the advertising data as appropriate.
-
-Service		org.bluez
-Interface	org.bluez.LEAdvertisement1
-Object path	freely definable
-
-Methods		void Release() [noreply]
-
-			This method gets called when the service daemon
-			removes the Advertisement. A client can use it to do
-			cleanup tasks. There is no need to call
-			UnregisterAdvertisement because when this method gets
-			called it has already been unregistered.
-
-Properties	string Type
-
-			Determines the type of advertising packet requested.
-
-			Possible values: "broadcast" or "peripheral"
-
-		array{string} ServiceUUIDs
-
-			List of UUIDs to include in the "Service UUID" field of
-			the Advertising Data.
-
-		dict ManufacturerData
-
-			Manufactuer Data fields to include in
-			the Advertising Data.  Keys are the Manufacturer ID
-			to associate with the data.
-
-		array{string} SolicitUUIDs
-
-			Array of UUIDs to include in "Service Solicitation"
-			Advertisement Data.
-
-		dict ServiceData
-
-			Service Data elements to include. The keys are the
-			UUID to associate with the data.
-
-		dict Data [Experimental]
-
-			Advertising Type to include in the Advertising
-			Data. Key is the advertising type and value is the
-			data as byte array.
-
-			Note: Types already handled by other properties shall
-			not be used.
-
-			Possible values:
-				<type> <byte array>
-				...
-
-			Example:
-				<Transport Discovery> <Organization Flags...>
-				0x26                   0x01         0x01...
-
-		bool Discoverable [Experimental]
-
-			Advertise as general discoverable. When present this
-			will override adapter Discoverable property.
-
-			Note: This property shall not be set when Type is set
-			to broadcast.
-
-		uint16 DiscoverableTimeout [Experimental]
-
-			The discoverable timeout in seconds. A value of zero
-			means that the timeout is disabled and it will stay in
-			discoverable/limited mode forever.
-
-			Note: This property shall not be set when Type is set
-			to broadcast.
-
-		array{string} Includes
-
-			List of features to be included in the advertising
-			packet.
-
-			Possible values: as found on
-					LEAdvertisingManager.SupportedIncludes
-
-		string LocalName
-
-			Local name to be used in the advertising report. If the
-			string is too big to fit into the packet it will be
-			truncated.
-
-			If this property is available 'local-name' cannot be
-			present in the Includes.
-
-		uint16 Appearance
-
-			Appearance to be used in the advertising report.
-
-			Possible values: as found on GAP Service.
-
-		uint16_t Duration
-
-			Rotation duration of the advertisement in seconds. If
-			there are other applications advertising no duration is
-			set the default is 2 seconds.
-
-		uint16_t Timeout
-
-			Timeout of the advertisement in seconds. This defines
-			the lifetime of the advertisement.
-
-		string SecondaryChannel [Experimental]
-
-			Secondary channel to be used. Primary channel is
-			always set to "1M" except when "Coded" is set.
-
-			Possible value: "1M" (default)
-					"2M"
-					"Coded"
-
-		uint32 MinInterval [Experimental]
-
-			Minimum advertising interval to be used by the
-			advertising set, in milliseconds. Acceptable values
-			are in the range [20ms, 10,485s]. If the provided
-			MinInterval is larger than the provided MaxInterval,
-			the registration will return failure.
-
-		uint32 MaxInterval [Experimental]
-
-			Maximum advertising interval to be used by the
-			advertising set, in milliseconds. Acceptable values
-			are in the range [20ms, 10,485s]. If the provided
-			MinInterval is larger than the provided MaxInterval,
-			the registration will return failure.
-
-		int16 TxPower [Experimental]
-
-			Requested transmission power of this advertising set.
-			The provided value is used only if the "CanSetTxPower"
-			feature is enabled on the Advertising Manager. The
-			provided value must be in range [-127 to +20], where
-			units are in dBm.
-
-
-LE Advertising Manager hierarchy
-================================
-
-The Advertising Manager allows external applications to register Advertisement
-Data which should be broadcast to devices.  Advertisement Data elements must
-follow the API for LE Advertisement Data described above.
-
-Service		org.bluez
-Interface	org.bluez.LEAdvertisingManager1
-Object path	/org/bluez/{hci0,hci1,...}
-
-Methods		RegisterAdvertisement(object advertisement, dict options)
-
-			Registers an advertisement object to be sent over the LE
-			Advertising channel.  The service must be exported
-			under interface LEAdvertisement1.
-
-			InvalidArguments error indicates that the object has
-			invalid or conflicting properties.
-
-			InvalidLength error indicates that the data
-			provided generates a data packet which is too long.
-
-			The properties of this object are parsed when it is
-			registered, and any changes are ignored.
-
-			If the same object is registered twice it will result in
-			an AlreadyExists error.
-
-			If the maximum number of advertisement instances is
-			reached it will result in NotPermitted error.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-					 org.bluez.Error.InvalidLength
-					 org.bluez.Error.NotPermitted
-
-		UnregisterAdvertisement(object advertisement)
-
-			This unregisters an advertisement that has been
-			previously registered.  The object path parameter must
-			match the same value that has been used on registration.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.DoesNotExist
-
-Properties	byte ActiveInstances
-
-			Number of active advertising instances.
-
-		byte SupportedInstances
-
-			Number of available advertising instances.
-
-		array{string} SupportedIncludes
-
-			List of supported system includes.
-
-			Possible values: "tx-power"
-					 "appearance"
-					 "local-name"
-
-		array{string} SupportedSecondaryChannels [Experimental]
-
-			List of supported Secondary channels. Secondary
-			channels can be used to advertise with the
-			corresponding PHY.
-
-			Possible values: "1M"
-					 "2M"
-					 "Coded"
-
-		dict SupportedCapabilities [Experimental]
-
-			Enumerates Advertising-related controller capabilities
-			useful to the client.
-
-			Possible Values:
-
-				byte MaxAdvLen
-
-					Max advertising data length
-
-				byte MaxScnRspLen
-
-					Max advertising scan response length
-
-				int16 MinTxPower
-
-					Min advertising tx power (dBm)
-
-				int16 MaxTxPower
-
-					Max advertising tx power (dBm)
-
-		array{string} SupportedFeatures [readonly,optional,Experimental]
-
-			List of supported platform features. If no features
-			are available on the platform, the SupportedFeatures
-			array will be empty.
-
-			Possible values: "CanSetTxPower"
-
-						Indicates whether platform can
-						specify tx power on each
-						advertising instance.
-
-					 "HardwareOffload"
-
-						Indicates whether multiple
-						advertising will be offloaded
-						to the controller.
diff --git a/doc/agent-api.txt b/doc/agent-api.txt
deleted file mode 100644
index 0d9347c..0000000
--- a/doc/agent-api.txt
+++ /dev/null
@@ -1,185 +0,0 @@
-BlueZ D-Bus Agent API description
-**********************************
-
-
-Agent Manager hierarchy
-=======================
-
-Service		org.bluez
-Interface	org.bluez.AgentManager1
-Object path	/org/bluez
-
-		void RegisterAgent(object agent, string capability)
-
-			This registers an agent handler.
-
-			The object path defines the path of the agent
-			that will be called when user input is needed.
-
-			Every application can register its own agent and
-			for all actions triggered by that application its
-			agent is used.
-
-			It is not required by an application to register
-			an agent. If an application does chooses to not
-			register an agent, the default agent is used. This
-			is on most cases a good idea. Only application
-			like a pairing wizard should register their own
-			agent.
-
-			An application can only register one agent. Multiple
-			agents per application is not supported.
-
-			The capability parameter can have the values
-			"DisplayOnly", "DisplayYesNo", "KeyboardOnly",
-			"NoInputNoOutput" and "KeyboardDisplay" which
-			reflects the input and output capabilities of the
-			agent.
-
-			If an empty string is used it will fallback to
-			"KeyboardDisplay".
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-
-		void UnregisterAgent(object agent)
-
-			This unregisters the agent that has been previously
-			registered. The object path parameter must match the
-			same value that has been used on registration.
-
-			Possible errors: org.bluez.Error.DoesNotExist
-
-		void RequestDefaultAgent(object agent)
-
-			This requests is to make the application agent
-			the default agent. The application is required
-			to register an agent.
-
-			Special permission might be required to become
-			the default agent.
-
-			Possible errors: org.bluez.Error.DoesNotExist
-
-
-Agent hierarchy
-===============
-
-Service		unique name
-Interface	org.bluez.Agent1
-Object path	freely definable
-
-Methods		void Release()
-
-			This method gets called when the service daemon
-			unregisters the agent. An agent can use it to do
-			cleanup tasks. There is no need to unregister the
-			agent, because when this method gets called it has
-			already been unregistered.
-
-		string RequestPinCode(object device)
-
-			This method gets called when the service daemon
-			needs to get the passkey for an authentication.
-
-			The return value should be a string of 1-16 characters
-			length. The string can be alphanumeric.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void DisplayPinCode(object device, string pincode)
-
-			This method gets called when the service daemon
-			needs to display a pincode for an authentication.
-
-			An empty reply should be returned. When the pincode
-			needs no longer to be displayed, the Cancel method
-			of the agent will be called.
-
-			This is used during the pairing process of keyboards
-			that don't support Bluetooth 2.1 Secure Simple Pairing,
-			in contrast to DisplayPasskey which is used for those
-			that do.
-
-			This method will only ever be called once since
-			older keyboards do not support typing notification.
-
-			Note that the PIN will always be a 6-digit number,
-			zero-padded to 6 digits. This is for harmony with
-			the later specification.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		uint32 RequestPasskey(object device)
-
-			This method gets called when the service daemon
-			needs to get the passkey for an authentication.
-
-			The return value should be a numeric value
-			between 0-999999.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void DisplayPasskey(object device, uint32 passkey,
-								uint16 entered)
-
-			This method gets called when the service daemon
-			needs to display a passkey for an authentication.
-
-			The entered parameter indicates the number of already
-			typed keys on the remote side.
-
-			An empty reply should be returned. When the passkey
-			needs no longer to be displayed, the Cancel method
-			of the agent will be called.
-
-			During the pairing process this method might be
-			called multiple times to update the entered value.
-
-			Note that the passkey will always be a 6-digit number,
-			so the display should be zero-padded at the start if
-			the value contains less than 6 digits.
-
-		void RequestConfirmation(object device, uint32 passkey)
-
-			This method gets called when the service daemon
-			needs to confirm a passkey for an authentication.
-
-			To confirm the value it should return an empty reply
-			or an error in case the passkey is invalid.
-
-			Note that the passkey will always be a 6-digit number,
-			so the display should be zero-padded at the start if
-			the value contains less than 6 digits.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void RequestAuthorization(object device)
-
-			This method gets called to request the user to
-			authorize an incoming pairing attempt which
-			would in other circumstances trigger the just-works
-			model, or when the user plugged in a device that
-			implements cable pairing. In the latter case, the
-			device would not be connected to the adapter via
-			Bluetooth yet.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void AuthorizeService(object device, string uuid)
-
-			This method gets called when the service daemon
-			needs to authorize a connection/service request.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void Cancel()
-
-			This method gets called to indicate that the agent
-			request failed before a reply was returned.
diff --git a/doc/battery-api.txt b/doc/battery-api.txt
deleted file mode 100644
index 9a6b4fd..0000000
--- a/doc/battery-api.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-BlueZ D-Bus Battery API description
-***********************************
-
-
-Battery hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.Battery1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Properties	byte Percentage [readonly]
-
-			The percentage of battery left as an unsigned 8-bit integer.
-
-		string Source [readonly, optional, experimental]
-
-			Describes where the battery information comes from
-			This property is informational only and may be useful
-			for debugging purposes.
-			Providers from BatteryProvider1 may make use of this
-			property to indicate where the battery report comes from
-			(e.g. "HFP 1.7", "HID", or the profile UUID).
-
-
-Battery Provider Manager hierarchy
-==================================
-A battery provider starts by registering itself as a battery provider with the
-RegisterBatteryProvider method passing an object path as the provider ID. Then,
-it can start exposing org.bluez.BatteryProvider1 objects having the path
-starting with the given provider ID. It can also remove objects at any time.
-The objects and their properties exposed by battery providers will be reflected
-on org.bluez.Battery1 interface.
-
-BlueZ will stop monitoring these exposed and removed objects after
-UnregisterBatteryProvider is called for that provider ID.
-
-Service		org.bluez
-Interface	org.bluez.BatteryProviderManager1 [experimental]
-Object path	/org/bluez/{hci0,hci1,...}
-
-Methods		void RegisterBatteryProvider(object provider)
-
-			This registers a battery provider. A registered
-			battery provider can then expose objects with
-			org.bluez.BatteryProvider1 interface described below.
-
-		void UnregisterBatteryProvider(object provider)
-
-			This unregisters a battery provider. After
-			unregistration, the BatteryProvider1 objects provided
-			by this client are ignored by BlueZ.
-
-
-Battery Provider hierarchy
-==========================
-
-Service		<client D-Bus address>
-Interface	org.bluez.BatteryProvider1 [experimental]
-Object path	{provider_root}/{unique battery object path}
-
-Properties	Objects provided on this interface contain the same properties
-		as org.bluez.Battery1 interface. Additionally, this interface
-		needs to have the Device property indicating the object path
-		of the device this battery provides.
-
-		object Device [readonly]
-
-			The object path of the device that has this battery.
diff --git a/doc/ci.config b/doc/ci.config
deleted file mode 100644
index 31e49ba..0000000
--- a/doc/ci.config
+++ /dev/null
@@ -1,122 +0,0 @@
-#############################################################
-#                                                           #
-#   This config file is for testing bluetooth build only.   #
-#                                                           #
-#############################################################
-
-CONFIG_VIRTIO=y
-CONFIG_VIRTIO_PCI=y
-
-CONFIG_NET=y
-CONFIG_INET=y
-
-CONFIG_NET_9P=y
-CONFIG_NET_9P_VIRTIO=y
-
-CONFIG_9P_FS=y
-CONFIG_9P_FS_POSIX_ACL=y
-
-CONFIG_GPIOLIB=y
-
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-
-CONFIG_SERIAL_DEV_BUS=y
-
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_TMPFS_XATTR=y
-
-CONFIG_DEVTMPFS=y
-CONFIG_DEBUG_FS=y
-
-CONFIG_MMC=y
-
-CONFIG_RPMSG=y
-CONFIG_QCOM_WCNSS_CTRL=y
-
-CONFIG_PCMCIA=y
-
-CONFIG_ISDN_CAPI=y
-
-CONFIG_6LOWPAN=y
-
-CONFIG_LEDS_CLASS=y
-
-CONFIG_USB=y
-
-CONFIG_BT=y
-CONFIG_BT_BREDR=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_LE=y
-CONFIG_BT_MSFTEXT=y
-CONFIG_BT_HS=y
-CONFIG_BT_CMTP=y
-CONFIG_BT_6LOWPAN=y
-CONFIG_BT_LEDS=y
-CONFIG_BT_FEATURE_DEBUG=y
-
-CONFIG_BT_HCIVHCI=y
-
-CONFIG_BT_HCIBTUSB=y
-CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y
-CONFIG_BT_HCIBTUSB_MTK=y
-CONFIG_BT_HCIBCM203X=y
-CONFIG_BT_HCIBPA10X=y
-CONFIG_BT_MRVL=y
-CONFIG_BT_ATH3K=y
-
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_SERDEV=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_ATH3K=y
-CONFIG_BT_HCIUART_AG6XX=y
-CONFIG_BT_HCIUART_NOKIA=y
-CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIUART_3WIRE=y
-CONFIG_BT_HCIUART_INTEL=y
-CONFIG_BT_HCIUART_BCM=y
-CONFIG_BT_HCIUART_RTL=y
-CONFIG_BT_HCIUART_QCA=y
-CONFIG_BT_HCIUART_MRVL=y
-CONFIG_BT_MTKUART=y
-
-CONFIG_BT_HCIBFUSB=y
-
-CONFIG_BT_HCIBTSDIO=y
-CONFIG_BT_MRVL_SDIO=y
-CONFIG_BT_MTKSDIO=y
-
-CONFIG_BT_HCIDTL1=y
-CONFIG_BT_HCIBT3C=y
-CONFIG_BT_HCIBLUECARD=y
-
-CONFIG_BT_QCOMSMD=y
-
-CONFIG_BT_VIRTIO=y
-
-CONFIG_CRYPTO_CMAC=y
-CONFIG_CRYPTO_USER_API=y
-CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_USER_API_SKCIPHER=y
-
-CONFIG_UNIX=y
-
-CONFIG_UHID=y
-
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_LOCKDEP=y
-CONFIG_DEBUG_MUTEXES=y
-
-CONFIG_OF=y
diff --git a/doc/coding-style.txt b/doc/coding-style.txt
deleted file mode 100644
index e731588..0000000
--- a/doc/coding-style.txt
+++ /dev/null
@@ -1,279 +0,0 @@
-BlueZ coding style
-******************
-
-Every project has its coding style, and BlueZ is not an exception. This
-document describes the preferred coding style for BlueZ code, in order to keep
-some level of consistency among developers so that code can be easily
-understood and maintained.
-
-First of all, BlueZ coding style must follow every rule for Linux kernel
-(https://www.kernel.org/doc/Documentation/process/coding-style.rst). There also
-exists a tool named checkpatch.pl to help you check the compliance with it.
-Just type "checkpatch.pl --no-tree patch_name" to check your patch. In theory,
-you need to clean up all the warnings and errors except this one: "ERROR:
-Missing Signed-off-by: line(s)". BlueZ does not used Signed-Off lines, so
-including them is actually an error.  In certain circumstances one can ignore
-the 80 character per line limit.  This is generally only allowed if the
-alternative would make the code even less readable.
-
-Besides the kernel coding style above, BlueZ has special flavors for its own.
-Some of them are mandatory (marked as 'M'), while some others are optional
-(marked as 'O'), but generally preferred.
-
-M1: Blank line before and after an if/while/do/for statement
-============================================================
-
-There should be a blank line before if statement unless the if is nested and
-not preceded by an expression or variable declaration.
-
-Example:
-1)
-a = 1;
-if (b) {  // wrong
-
-2)
-a = 1
-
-if (b) {
-}
-a = 2;	// wrong
-
-3)
-if (a) {
-	if (b)  // correct
-
-4)
-b = 2;
-
-if (a) {	// correct
-
-}
-
-b = 3;
-
-The only exception to this rule applies when a variable is being checked for
-errors as such:
-
-err = stat(filename, &st);
-if (err || !S_ISDIR(st.st_mode))
-	return;
-
-M2: Multiple line comment
-=========================
-
-If your comment has more than one line, please start it from the second line.
-
-Example:
-/*
- * first line comment	// correct
- * ...
- * last line comment
- */
-
-
-M3: Space before and after operator
-===================================
-
-There should be a space before and after each operator.
-
-Example:
-a + b;  // correct
-
-
-M4: Wrap long lines
-===================
-
-If your condition in if, while, for statement or a function declaration is too
-long to fit in one line, the new line needs to be indented not aligned with the
-body.
-
-Example:
-1)
-if ((adapter->supported_settings & MGMT_SETTING_SSP) &&
-	!(adapter->current_settings & MGMT_SETTING_SSP)) // wrong
-
-2)
-if ((adapter->supported_settings & MGMT_SETTING_SSP) &&
-				!(adapter->current_settings & MGMT_SETTING_SSP))
-
-3)
-void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
-				 btd_adapter_pin_cb_t cb) // wrong
-
-4)
-void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
-							btd_adapter_pin_cb_t cb)
-
-The referred style for line wrapping is to indent as far as possible to the
-right without hitting the 80 columns limit.
-
-M5: Space when doing type casting
-=================================
-
-There should be a space between new type and variable.
-
-Example:
-1)
-a = (int *)b;  // wrong
-2)
-a = (int *) b;  // correct
-
-
-M6: Don't initialize variable unnecessarily
-===========================================
-
-When declaring a variable, try not to initialize it unless necessary.
-
-Example:
-int i = 1;  // wrong
-
-for (i = 0; i < 3; i++) {
-}
-
-M7: Follow the order of include header elements
-===============================================
-
-When writing an include header the various elements should be in the following
-order:
-	- #includes
-	- forward declarations
-	- #defines
-	- enums
-	- typedefs
-	- function declarations and inline function definitions
-
-M8: Internal headers must not use include guards
-================================================
-
-Any time when creating a new header file with non-public API, that header
-must not contain include guards.
-
-M9: Naming of enums
-===================
-
-Enums must have a descriptive name.  The enum type should be small caps and
-it should not be typedef-ed.  Enum contents should be in CAPITAL letters and
-prefixed by the enum type name.
-
-Example:
-
-enum animal_type {
-	ANIMAL_TYPE_FOUR_LEGS,
-	ANIMAL_TYPE_EIGHT_LEGS,
-	ANIMAL_TYPE_TWO_LEGS,
-};
-
-If the enum contents have values (e.g. from specification) the formatting
-should be as follows:
-
-enum animal_type {
-	ANIMAL_TYPE_FOUR_LEGS =		4,
-	ANIMAL_TYPE_EIGHT_LEGS =	8,
-	ANIMAL_TYPE_TWO_LEGS =		2,
-};
-
-M10: Enum as switch variable
-============================
-
-If the variable of a switch is an enum, you must include all values in
-switch body even if providing default. This is enforced by compiler option
-enabling extra warning in such case. The reason for this is to ensure that if
-later on enum is modified and one forget to change the switch accordingly, the
-compiler will complain the new added type hasn't been handled.
-
-Example:
-
-enum animal_type {
-	ANIMAL_TYPE_FOUR_LEGS =		4,
-	ANIMAL_TYPE_EIGHT_LEGS =	8,
-	ANIMAL_TYPE_TWO_LEGS =		2,
-};
-
-enum animal_type t;
-
-switch (t) { // OK
-case ANIMAL_TYPE_FOUR_LEGS:
-	...
-	break;
-case ANIMAL_TYPE_EIGHT_LEGS:
-	...
-	break;
-case ANIMAL_TYPE_TWO_LEGS:
-	...
-	break;
-default:
-	break;
-}
-
-switch (t) { // Wrong
-case ANIMAL_TYPE_FOUR_LEGS:
-	...
-	break;
-case ANIMAL_TYPE_TWO_LEGS:
-	...
-	break;
-default:
-	break;
-}
-
-However if the enum comes from an external header file outside BlueZ, such as
-Android headers, we cannot make any assumption of how the enum is defined and
-this rule might not apply.
-
-M11: Always use parenthesis with sizeof
-=======================================
-
-The expression argument to the sizeof operator should always be in
-parenthesis, too.
-
-Example:
-1)
-memset(stuff, 0, sizeof(*stuff));
-
-2)
-memset(stuff, 0, sizeof *stuff); // Wrong
-
-M12: Use void if function has no parameters
-===========================================
-
-A function with no parameters must use void in the parameter list.
-
-Example:
-1)
-void foo(void)
-{
-}
-
-2)
-void foo()	// Wrong
-{
-}
-
-O1: Try to avoid complex if body
-================================
-
-It's better not to have a complicated statement for if. You may judge its
-contrary condition and return | break | continue | goto ASAP.
-
-Example:
-1)
-if (device) {  // worse
-	memset(&eir_data, 0, sizeof(eir_data));
-	if (eir_len > 0)
-		eir_parse(&eir_data, ev->eir, eir_len);
-	...
-} else {
-	error("Unable to get device object for %s", addr);
-	return;
-}
-
-2)
-if (!device) {
-	error("Unable to get device object for %s", addr);
-	return;
-}
-
-memset(&eir_data, 0, sizeof(eir_data));
-if (eir_len > 0)
-	eir_parse(&eir_data, ev->eir, eir_len);
-...
diff --git a/doc/device-api.txt b/doc/device-api.txt
deleted file mode 100644
index 628accb..0000000
--- a/doc/device-api.txt
+++ /dev/null
@@ -1,283 +0,0 @@
-BlueZ D-Bus Device API description
-**********************************
-
-
-Device hierarchy
-================
-
-Service		org.bluez
-Interface	org.bluez.Device1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Methods		void Connect()
-
-			This is a generic method to connect any profiles
-			the remote device supports that can be connected
-			to and have been flagged as auto-connectable on
-			our side. If only subset of profiles is already
-			connected it will try to connect currently disconnected
-			ones.
-
-			If at least one profile was connected successfully this
-			method will indicate success.
-
-			For dual-mode devices only one bearer is connected at
-			time, the conditions are in the following order:
-
-				1. Connect the disconnected bearer if already
-				connected.
-
-				2. Connect first the bonded bearer. If no
-				bearers are bonded or both are skip and check
-				latest seen bearer.
-
-				3. Connect last seen bearer, in case the
-				timestamps are the same BR/EDR takes
-				precedence.
-
-			Possible errors: org.bluez.Error.NotReady
-					 org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.AlreadyConnected
-
-		void Disconnect()
-
-			This method gracefully disconnects all connected
-			profiles and then terminates low-level ACL connection.
-
-			ACL connection will be terminated even if some profiles
-			were not disconnected properly e.g. due to misbehaving
-			device.
-
-			This method can be also used to cancel a preceding
-			Connect call before a reply to it has been received.
-
-			For non-trusted devices connected over LE bearer calling
-			this method will disable incoming connections until
-			Connect method is called again.
-
-			Possible errors: org.bluez.Error.NotConnected
-
-		void ConnectProfile(string uuid)
-
-			This method connects a specific profile of this
-			device. The UUID provided is the remote service
-			UUID for the profile.
-
-			Possible errors: org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotAvailable
-					 org.bluez.Error.NotReady
-
-		void DisconnectProfile(string uuid)
-
-			This method disconnects a specific profile of
-			this device. The profile needs to be registered
-			client profile.
-
-			There is no connection tracking for a profile, so
-			as long as the profile is registered this will always
-			succeed.
-
-			Possible errors: org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-
-		void Pair()
-
-			This method will connect to the remote device,
-			initiate pairing and then retrieve all SDP records
-			(or GATT primary services).
-
-			If the application has registered its own agent,
-			then that specific agent will be used. Otherwise
-			it will use the default agent.
-
-			Only for applications like a pairing wizard it
-			would make sense to have its own agent. In almost
-			all other cases the default agent will handle
-			this just fine.
-
-			In case there is no application agent and also
-			no default agent present, this method will fail.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.Failed
-					 org.bluez.Error.AlreadyExists
-					 org.bluez.Error.AuthenticationCanceled
-					 org.bluez.Error.AuthenticationFailed
-					 org.bluez.Error.AuthenticationRejected
-					 org.bluez.Error.AuthenticationTimeout
-					 org.bluez.Error.ConnectionAttemptFailed
-
-		void CancelPairing()
-
-			This method can be used to cancel a pairing
-			operation initiated by the Pair method.
-
-			Possible errors: org.bluez.Error.DoesNotExist
-					 org.bluez.Error.Failed
-
-Properties	string Address [readonly]
-
-			The Bluetooth device address of the remote device.
-
-		string AddressType [readonly]
-
-			The Bluetooth device Address Type. For dual-mode and
-			BR/EDR only devices this defaults to "public". Single
-			mode LE devices may have either value. If remote device
-			uses privacy than before pairing this represents address
-			type used for connection and Identity Address after
-			pairing.
-
-			Possible values:
-				"public" - Public address
-				"random" - Random address
-
-		string Name [readonly, optional]
-
-			The Bluetooth remote name. This value can not be
-			changed. Use the Alias property instead.
-
-			This value is only present for completeness. It is
-			better to always use the Alias property when
-			displaying the devices name.
-
-			If the Alias property is unset, it will reflect
-			this value which makes it more convenient.
-
-		string Icon [readonly, optional]
-
-			Proposed icon name according to the freedesktop.org
-			icon naming specification.
-
-		uint32 Class [readonly, optional]
-
-			The Bluetooth class of device of the remote device.
-
-		uint16 Appearance [readonly, optional]
-
-			External appearance of device, as found on GAP service.
-
-		array{string} UUIDs [readonly, optional]
-
-			List of 128-bit UUIDs that represents the available
-			remote services.
-
-		boolean Paired [readonly]
-
-			Indicates if the remote device is paired. Paired means
-			the pairing process where devices exchange the
-			information to establish an encrypted connection has
-			been completed.
-
-		boolean Bonded [readonly]
-
-			Indicates if the remote device is bonded. Bonded means
-			the information exchanged on pairing process has been
-			stored and will be persisted.
-
-		boolean Connected [readonly]
-
-			Indicates if the remote device is currently connected.
-			A PropertiesChanged signal indicate changes to this
-			status.
-
-		boolean Trusted [readwrite]
-
-			Indicates if the remote is seen as trusted. This
-			setting can be changed by the application.
-
-		boolean Blocked [readwrite]
-
-			If set to true any incoming connections from the
-			device will be immediately rejected. Any device
-			drivers will also be removed and no new ones will
-			be probed as long as the device is blocked.
-
-		boolean WakeAllowed [readwrite]
-
-			If set to true this device will be allowed to wake the
-			host from system suspend.
-
-		string Alias [readwrite]
-
-			The name alias for the remote device. The alias can
-			be used to have a different friendly name for the
-			remote device.
-
-			In case no alias is set, it will return the remote
-			device name. Setting an empty string as alias will
-			convert it back to the remote device name.
-
-			When resetting the alias with an empty string, the
-			property will default back to the remote name.
-
-		object Adapter [readonly]
-
-			The object path of the adapter the device belongs to.
-
-		boolean LegacyPairing [readonly]
-
-			Set to true if the device only supports the pre-2.1
-			pairing mechanism. This property is useful during
-			device discovery to anticipate whether legacy or
-			simple pairing will occur if pairing is initiated.
-
-			Note that this property can exhibit false-positives
-			in the case of Bluetooth 2.1 (or newer) devices that
-			have disabled Extended Inquiry Response support.
-
-		string Modalias [readonly, optional]
-
-			Remote Device ID information in modalias format
-			used by the kernel and udev.
-
-		int16 RSSI [readonly, optional]
-
-			Received Signal Strength Indicator of the remote
-			device (inquiry or advertising).
-
-		int16 TxPower [readonly, optional]
-
-			Advertised transmitted power level (inquiry or
-			advertising).
-
-		dict ManufacturerData [readonly, optional]
-
-			Manufacturer specific advertisement data. Keys are
-			16 bits Manufacturer ID followed by its byte array
-			value.
-
-		dict ServiceData [readonly, optional]
-
-			Service advertisement data. Keys are the UUIDs in
-			string format followed by its byte array value.
-
-		bool ServicesResolved [readonly]
-
-			Indicate whether or not service discovery has been
-			resolved.
-
-		array{byte} AdvertisingFlags [readonly, experimental]
-
-			The Advertising Data Flags of the remote device.
-
-		dict AdvertisingData [readonly, experimental]
-
-			The Advertising Data of the remote device. Keys are
-			are 8 bits AD Type followed by data as byte array.
-
-			Note: Only types considered safe to be handled by
-			application are exposed.
-
-			Possible values:
-				<type> <byte array>
-				...
-
-			Example:
-				<Transport Discovery> <Organization Flags...>
-				0x26                   0x01         0x01...
diff --git a/doc/errors.txt b/doc/errors.txt
deleted file mode 100644
index 047610c..0000000
--- a/doc/errors.txt
+++ /dev/null
@@ -1,233 +0,0 @@
-D-Bus Method Return Error Codes
-===============================
-
-The motivation of having detailed error is to provide context-based failure
-reasons along with D-Bus method return so that D-Bus clients can build metrics
-and optimize their application based on these failure reasons. For instance, a
-client can build retry mechanism for a connection failure or improve the
-bottleneck of use scenario based on actionable metrics.
-
-These error codes are context-based but not necessarily tied to interface or
-method calls. For instance, if a pairing request failed due to connection
-failure, connection error would be attached to the method return of Pair().
-
-BR/EDR connection already connected
-===================================
-	errno:	EALREADY, EISCONN
-
-	Either the profile is already connected or ACL connection is in place.
-
-BR/EDR connection page timeout
-==============================
-	errno:	EHOSTDOWN
-
-	Failed due to page timeout.
-
-BR/EDR connection profile unavailable
-=====================================
-	errno:	ENOPROTOOPT
-
-	Failed to find connectable services or the target service.
-
-BR/EDR connection SDP search
-============================
-	errno:	none
-
-	Failed to complete the SDP search.
-
-BR/EDR connection create socket
-===============================
-	errno:	EIO
-
-	Failed to create or connect to BT IO socket. This can also indicate
-	hardware failure in the controller.
-
-BR/EDR connection invalid arguments
-===================================
-	errno:	EHOSTUNREACH
-
-	Failed due to invalid arguments.
-
-BR/EDR connection not powered
-=============================
-	errno:	EHOSTUNREACH
-
-	Failed due to adapter not powered.
-
-BR/EDR connection not supported
-===============================
-	errno:	EOPNOTSUPP, EPROTONOSUPPORT
-
-	Failed due to unsupported state transition of L2CAP channel or other
-	features either by the local host or the remote.
-
-BR/EDR connection bad socket
-============================
-	errno:	EBADFD
-
-	Failed due to the socket is in bad state.
-
-BR/EDR connection memory allocation
-===================================
-	errno:	ENOMEM
-
-	Failed to allocate memory in either host stack or controller.
-
-BR/EDR connection busy
-======================
-	errno:	EBUSY
-
-	Failed due to other ongoing operations, such as pairing, busy L2CAP
-	channel or the operation disallowed by the controller.
-
-BR/EDR connection concurrent connection limit
-=============================================
-	errno:	EMLINK
-
-	Failed due to reaching the concurrent connection limit to a device.
-
-BR/EDR connection timeout
-=========================
-	errno:	ETIMEDOUT
-
-	Failed due to connection timeout
-
-BR/EDR connection refused
-=========================
-	errno:	ECONNREFUSED
-
-	Refused by the remote device due to limited resource, security reason
-	or unacceptable address type.
-
-BR/EDR connection aborted by remote
-===================================
-	errno:	ECONNRESET
-
-	Terminated by the remote device due to limited resource or power off.
-
-BR/EDR connection aborted by local
-==================================
-	errno:	ECONNABORTED
-
-	Aborted by the local host.
-
-BR/EDR connection LMP protocol error
-====================================
-	errno:	EPROTO
-
-	Failed due to LMP protocol error.
-
-BR/EDR connection canceled
-==========================
-	errno:	none
-
-	Failed due to cancellation caused by adapter drop, unexpected device
-	drop, orincoming disconnection request before connection request is
-	completed.
-
-BR/EDR connection unknown error
-===============================
-	errno:	ENOSYS
-
-	Failed due to unknown reason.
-
-LE connection invalid arguments
-===============================
-	errno:	EINVAL
-
-	Failed due to invalid arguments.
-
-LE connection not powered
-=========================
-	errno:	EHOSTUNREACH
-
-	Failed due to adapter not powered.
-
-LE connection not supported
-===========================
-	errno:	EOPNOTSUPP, EPROTONOSUPPORT
-
-	Failed due to unsupported state transition of L2CAP channel or other
-	features (e.g. LE features) either by the local host or the remote.
-
-LE connection already connected
-===============================
-	errno: EALREADY, EISCONN
-
-	Either the BT IO is already connected or LE link connection in place.
-
-LE connection bad socket
-========================
-	errno: EBADFD
-
-	Failed due to the socket is in bad state.
-
-LE connection memory allocation
-===============================
-	errno: ENOMEM
-
-	Failed to allocate memory in either host stack or controller.
-
-LE connection busy
-==================
-	errno:	EBUSY
-
-	Failed due to other ongoing operations, such as pairing, connecting,
-	busy L2CAP channel or the operation disallowed by the controller.
-
-LE connection refused
-=====================
-	errno:	ECONNREFUSED
-
-	Failed due to that LE is not enabled or the attempt is refused by the
-	remote device due to limited resource, security reason or unacceptable
-	address type.
-
-LE connection create socket
-===========================
-	errno:	EIO
-
-	Failed to create or connect to BT IO socket. This can also indicate
-	hardware failure in the controller.
-
-LE connection timeout
-=====================
-	errno:	ETIMEDOUT
-
-	Failed due to connection timeout
-
-LE connection concurrent connection limit
-=========================================
-	errno:	EMLINK
-
-	Failed due to reaching the synchronous connection limit to a device.
-
-LE connection abort by remote
-=============================
-	errno:	ECONNRESET
-
-	Aborted by the remote device due to limited resource or power off.
-
-LE connection abort by local
-============================
-	errno:	ECONNABORTED
-
-	Aborted by the local host.
-
-LE connection link layer protocol error
-=======================================
-	errno:	EPROTO
-
-	Failed due to link layer protocol error.
-
-LE connection GATT browsing
-===========================
-	errno:	none
-
-	Failed to complete the GATT browsing.
-
-LE connection unknown error
-===========================
-	errno:	ENOSYS
-
-	Failed due to unknown reason.
diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
deleted file mode 100644
index 5042c54..0000000
--- a/doc/gatt-api.txt
+++ /dev/null
@@ -1,509 +0,0 @@
-BlueZ D-Bus GATT API description
-********************************
-
-GATT local and remote services share the same high-level D-Bus API. Local
-refers to GATT based service exported by a BlueZ plugin or an external
-application. Remote refers to GATT services exported by the peer.
-
-BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
-Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
-external services to allow seamless GATT declarations (Service, Characteristic
-and Descriptors) discovery. Each GATT service tree is required to export a D-Bus
-Object Manager at its root that is solely responsible for the objects that
-belong to that service.
-
-Releasing a registered GATT service is not defined yet. Any API extension
-should avoid breaking the defined API, and if possible keep an unified GATT
-remote and local services representation.
-
-Service hierarchy
-=================
-
-GATT remote and local service representation. Object path for local services
-is freely definable.
-
-External applications implementing local services must register the services
-using GattManager1 registration method and must implement the methods and
-properties defined in GattService1 interface.
-
-Service		org.bluez
-Interface	org.bluez.GattService1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
-
-Properties	string UUID [read-only]
-
-			128-bit service UUID.
-
-		boolean Primary [read-only]
-
-			Indicates whether or not this GATT service is a
-			primary service. If false, the service is secondary.
-
-		object Device [read-only, optional]
-
-			Object path of the Bluetooth device the service
-			belongs to. Only present on services from remote
-			devices.
-
-		array{object} Includes [read-only, optional]
-
-			Array of object paths representing the included
-			services of this service.
-
-		uint16 Handle [read-write, optional] (Server Only)
-
-			Service handle. When available in the server it
-			would attempt to use to allocate into the database
-			which may fail, to auto allocate the value 0x0000
-			shall be used which will cause the allocated handle to
-			be set once registered.
-
-
-Characteristic hierarchy
-========================
-
-For local GATT defined services, the object paths need to follow the service
-path hierarchy and are freely definable.
-
-Service		org.bluez
-Interface	org.bluez.GattCharacteristic1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
-
-Methods		array{byte} ReadValue(dict options)
-
-			Issues a request to read the value of the
-			characteristic and returns the value if the
-			operation was successful.
-
-			Possible options: "offset": uint16 offset
-					  "mtu": Exchanged MTU (Server only)
-					  "device": Object Device (Server only)
-
-			Possible Errors: org.bluez.Error.Failed(string ecode)
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.NotPermitted
-					 org.bluez.Error.NotAuthorized
-					 org.bluez.Error.InvalidOffset
-					 org.bluez.Error.NotSupported
-
-			Possible Error Code: string 0x80 - 0x9f
-
-		void WriteValue(array{byte} value, dict options)
-
-			Issues a request to write the value of the
-			characteristic.
-
-			Possible options: "offset": Start offset
-					  "type": string
-						Possible values:
-						"command": Write without
-						response
-						"request": Write with response
-						"reliable": Reliable Write
-					  "mtu": Exchanged MTU (Server only)
-					  "device": Device path (Server only)
-					  "link": Link type (Server only)
-					  "prepare-authorize": True if prepare
-							       authorization
-							       request
-
-			Possible Errors: org.bluez.Error.Failed(string ecode)
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.NotPermitted
-					 org.bluez.Error.InvalidValueLength
-					 org.bluez.Error.NotAuthorized
-					 org.bluez.Error.NotSupported
-
-			Possible Error Code: string 0x80 - 0x9f
-
-		fd, uint16 AcquireWrite(dict options) [optional]
-
-			Acquire file descriptor and MTU for writing. Only
-			sockets are supported. Usage of WriteValue will be
-			locked causing it to return NotPermitted error.
-
-			For server the MTU returned shall be equal or smaller
-			than the negotiated MTU.
-
-			For client it only works with characteristic that has
-			WriteAcquired property which relies on
-			write-without-response Flag.
-
-			To release the lock the client shall close the file
-			descriptor, a HUP is generated in case the device
-			is disconnected.
-
-			Note: the MTU can only be negotiated once and is
-			symmetric therefore this method may be delayed in
-			order to have the exchange MTU completed, because of
-			that the file descriptor is closed during
-			reconnections as the MTU has to be renegotiated.
-
-			Possible options: "device": Object Device (Server only)
-					  "mtu": Exchanged MTU (Server only)
-					  "link": Link type (Server only)
-
-			Possible Errors: org.bluez.Error.Failed
-					 org.bluez.Error.NotSupported
-
-		fd, uint16 AcquireNotify(dict options) [optional]
-
-			Acquire file descriptor and MTU for notify. Only
-			sockets are support. Usage of StartNotify will be locked
-			causing it to return NotPermitted error.
-
-			For server the MTU returned shall be equal or smaller
-			than the negotiated MTU.
-
-			Only works with characteristic that has NotifyAcquired
-			which relies on notify Flag and no other client have
-			called StartNotify.
-
-			Notification are enabled during this procedure so
-			StartNotify shall not be called, any notification
-			will be dispatched via file descriptor therefore the
-			Value property is not affected during the time where
-			notify has been acquired.
-
-			To release the lock the client shall close the file
-			descriptor, a HUP is generated in case the device
-			is disconnected.
-
-			Note: the MTU can only be negotiated once and is
-			symmetric therefore this method may be delayed in
-			order to have the exchange MTU completed, because of
-			that the file descriptor is closed during
-			reconnections as the MTU has to be renegotiated.
-
-			Possible options: "device": Object Device (Server only)
-					  "mtu": Exchanged MTU (Server only)
-					  "link": Link type (Server only)
-
-			Possible Errors: org.bluez.Error.Failed
-					 org.bluez.Error.NotSupported
-
-		void StartNotify()
-
-			Starts a notification session from this characteristic
-			if it supports value notifications or indications.
-
-			Possible Errors: org.bluez.Error.Failed
-					 org.bluez.Error.NotPermitted
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.NotConnected
-					 org.bluez.Error.NotSupported
-
-		void StopNotify()
-
-			This method will cancel any previous StartNotify
-			transaction. Note that notifications from a
-			characteristic are shared between sessions thus
-			calling StopNotify will release a single session.
-
-			Possible Errors: org.bluez.Error.Failed
-
-		void Confirm() [optional] (Server only)
-
-			This method doesn't expect a reply so it is just a
-			confirmation that value was received.
-
-			Possible Errors: org.bluez.Error.Failed
-
-Properties	string UUID [read-only]
-
-			128-bit characteristic UUID.
-
-		object Service [read-only]
-
-			Object path of the GATT service the characteristic
-			belongs to.
-
-		array{byte} Value [read-only, optional]
-
-			The cached value of the characteristic. This property
-			gets updated only after a successful read request and
-			when a notification or indication is received, upon
-			which a PropertiesChanged signal will be emitted.
-
-		boolean WriteAcquired [read-only, optional]
-
-			True, if this characteristic has been acquired by any
-			client using AcquireWrite.
-
-			For client properties is ommited in case
-			'write-without-response' flag is not set.
-
-			For server the presence of this property indicates
-			that AcquireWrite is supported.
-
-		boolean NotifyAcquired [read-only, optional]
-
-			True, if this characteristic has been acquired by any
-			client using AcquireNotify.
-
-			For client this properties is ommited in case 'notify'
-			flag is not set.
-
-			For server the presence of this property indicates
-			that AcquireNotify is supported.
-
-		boolean Notifying [read-only, optional]
-
-			True, if notifications or indications on this
-			characteristic are currently enabled.
-
-		array{string} Flags [read-only]
-
-			Defines how the characteristic value can be used. See
-			Core spec "Table 3.5: Characteristic Properties bit
-			field", and "Table 3.8: Characteristic Extended
-			Properties bit field".
-
-			The "x-notify" and "x-indicate" flags restrict access
-			to notifications and indications by imposing write
-			restrictions on a characteristic's client
-			characteristic configuration descriptor.
-
-			Allowed values:
-
-				"broadcast"
-				"read"
-				"write-without-response"
-				"write"
-				"notify"
-				"indicate"
-				"authenticated-signed-writes"
-				"extended-properties"
-				"reliable-write"
-				"writable-auxiliaries"
-				"encrypt-read"
-				"encrypt-write"
-				"encrypt-notify" (Server only)
-				"encrypt-indicate" (Server only)
-				"encrypt-authenticated-read"
-				"encrypt-authenticated-write"
-				"encrypt-authenticated-notify" (Server only)
-				"encrypt-authenticated-indicate" (Server only)
-				"secure-read" (Server only)
-				"secure-write" (Server only)
-				"secure-notify" (Server only)
-				"secure-indicate" (Server only)
-				"authorize"
-
-		uint16 Handle [read-write, optional] (Server Only)
-
-			Characteristic handle. When available in the server it
-			would attempt to use to allocate into the database
-			which may fail, to auto allocate the value 0x0000
-			shall be used which will cause the allocated handle to
-			be set once registered.
-
-		uint16 MTU [read-only]
-
-			Characteristic MTU, this is valid both for ReadValue
-			and WriteValue but either method can use long
-			procedures when supported.
-
-Characteristic Descriptors hierarchy
-====================================
-
-Local or remote GATT characteristic descriptors hierarchy.
-
-Service		org.bluez
-Interface	org.bluez.GattDescriptor1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
-
-Methods		array{byte} ReadValue(dict flags)
-
-			Issues a request to read the value of the
-			characteristic and returns the value if the
-			operation was successful.
-
-			Possible options: "offset": Start offset
-					  "device": Device path (Server only)
-					  "link": Link type (Server only)
-
-			Possible Errors: org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.NotPermitted
-					 org.bluez.Error.NotAuthorized
-					 org.bluez.Error.NotSupported
-
-		void WriteValue(array{byte} value, dict flags)
-
-			Issues a request to write the value of the
-			characteristic.
-
-			Possible options: "offset": Start offset
-					  "device": Device path (Server only)
-					  "link": Link type (Server only)
-					  "prepare-authorize": boolean Is prepare
-							       authorization
-							       request
-
-			Possible Errors: org.bluez.Error.Failed
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.NotPermitted
-					 org.bluez.Error.InvalidValueLength
-					 org.bluez.Error.NotAuthorized
-					 org.bluez.Error.NotSupported
-
-Properties	string UUID [read-only]
-
-			128-bit descriptor UUID.
-
-		object Characteristic [read-only]
-
-			Object path of the GATT characteristic the descriptor
-			belongs to.
-
-		array{byte} Value [read-only, optional]
-
-			The cached value of the descriptor. This property
-			gets updated only after a successful read request, upon
-			which a PropertiesChanged signal will be emitted.
-
-		array{string} Flags [read-only]
-
-			Defines how the descriptor value can be used.
-
-			Possible values:
-
-				"read"
-				"write"
-				"encrypt-read"
-				"encrypt-write"
-				"encrypt-authenticated-read"
-				"encrypt-authenticated-write"
-				"secure-read" (Server Only)
-				"secure-write" (Server Only)
-				"authorize"
-
-		uint16 Handle [read-write, optional] (Server Only)
-
-			Characteristic handle. When available in the server it
-			would attempt to use to allocate into the database
-			which may fail, to auto allocate the value 0x0000
-			shall be used which will cause the allocated handle to
-			be set once registered.
-
-GATT Profile hierarchy
-=====================
-
-Local profile (GATT client) instance. By registering this type of object
-an application effectively indicates support for a specific GATT profile
-and requests automatic connections to be established to devices
-supporting it.
-
-Service		<application dependent>
-Interface	org.bluez.GattProfile1
-Object path	<application dependent>
-
-Methods		void Release()
-
-			This method gets called when the service daemon
-			unregisters the profile. The profile can use it to
-			do cleanup tasks. There is no need to unregister the
-			profile, because when this method gets called it has
-			already been unregistered.
-
-Properties	array{string} UUIDs [read-only]
-
-			128-bit GATT service UUIDs to auto connect.
-
-
-GATT Manager hierarchy
-======================
-
-GATT Manager allows external applications to register GATT services and
-profiles.
-
-Registering a profile allows applications to subscribe to *remote* services.
-These must implement the GattProfile1 interface defined above.
-
-Registering a service allows applications to publish a *local* GATT service,
-which then becomes available to remote devices. A GATT service is represented by
-a D-Bus object hierarchy where the root node corresponds to a service and the
-child nodes represent characteristics and descriptors that belong to that
-service. Each node must implement one of GattService1, GattCharacteristic1,
-or GattDescriptor1 interfaces described above, based on the attribute it
-represents. Each node must also implement the standard D-Bus Properties
-interface to expose their properties. These objects collectively represent a
-GATT service definition.
-
-To make service registration simple, BlueZ requires that all objects that belong
-to a GATT service be grouped under a D-Bus Object Manager that solely manages
-the objects of that service. Hence, the standard DBus.ObjectManager interface
-must be available on the root service path. An example application hierarchy
-containing two separate GATT services may look like this:
-
--> /com/example
-  |   - org.freedesktop.DBus.ObjectManager
-  |
-  -> /com/example/service0
-  | |   - org.freedesktop.DBus.Properties
-  | |   - org.bluez.GattService1
-  | |
-  | -> /com/example/service0/char0
-  | |     - org.freedesktop.DBus.Properties
-  | |     - org.bluez.GattCharacteristic1
-  | |
-  | -> /com/example/service0/char1
-  |   |   - org.freedesktop.DBus.Properties
-  |   |   - org.bluez.GattCharacteristic1
-  |   |
-  |   -> /com/example/service0/char1/desc0
-  |       - org.freedesktop.DBus.Properties
-  |       - org.bluez.GattDescriptor1
-  |
-  -> /com/example/service1
-    |   - org.freedesktop.DBus.Properties
-    |   - org.bluez.GattService1
-    |
-    -> /com/example/service1/char0
-        - org.freedesktop.DBus.Properties
-        - org.bluez.GattCharacteristic1
-
-When a service is registered, BlueZ will automatically obtain information about
-all objects using the service's Object Manager. Once a service has been
-registered, the objects of a service should not be removed. If BlueZ receives an
-InterfacesRemoved signal from a service's Object Manager, it will immediately
-unregister the service. Similarly, if the application disconnects from the bus,
-all of its registered services will be automatically unregistered.
-InterfacesAdded signals will be ignored.
-
-Examples:
-	- Client
-		test/example-gatt-client
-		client/bluetoothctl
-	- Server
-		test/example-gatt-server
-		tools/gatt-service
-
-
-Service		org.bluez
-Interface	org.bluez.GattManager1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		void RegisterApplication(object application, dict options)
-
-			Registers a local GATT services hierarchy as described
-			above (GATT Server) and/or GATT profiles (GATT Client).
-
-			The application object path together with the D-Bus
-			system bus connection ID define the identification of
-			the application registering a GATT based
-			service or profile.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-
-		void UnregisterApplication(object application)
-
-			This unregisters the services that has been
-			previously registered. The object path parameter
-			must match the same value that has been used
-			on registration.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.DoesNotExist
diff --git a/doc/hci.7 b/doc/hci.7
new file mode 100644
index 0000000..06e377b
--- /dev/null
+++ b/doc/hci.7
@@ -0,0 +1,225 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HCI" "7" "October 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+hci \- Bluetooth HCI protocol
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+hci_socket = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+.EE
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+Bluetooth Host Controller Interface (HCI) is the standard protocol to
+communicate with Bluetooth adapters. HCI protocol provides a uniform command
+method for the Host to access Controller capabilities and to control connections
+to other Controllers.
+.SH SOCKET ADDRESS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct sockaddr_hci {
+    sa_family_t    hci_family;
+    unsigned short hci_dev;
+    unsigned short hci_channel;
+};
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+Possible values for hci_channel:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBHCI_CHANNEL_RAW\fP
+T}	T{
+0x00
+T}	T{
+Raw channel \- Used for raw HCI communication
+T}
+_
+T{
+\fBHCI_CHANNEL_USER\fP
+T}	T{
+0x01
+T}	T{
+User channel \- Used for userspace HCI communication (disables kernel processing)
+T}
+_
+T{
+\fBHCI_CHANNEL_MONITOR\fP
+T}	T{
+0x02
+T}	T{
+Monitor channel \- Used for monitoring HCI traffic (btmon(1))
+T}
+_
+T{
+\fBHCI_CHANNEL_CONTROL\fP
+T}	T{
+0x03
+T}	T{
+Control channel \- Used to manage local adapters (bluetoothd(7))
+T}
+_
+T{
+\fBHCI_CHANNEL_LOGGING\fP
+T}	T{
+0x04
+T}	T{
+Logging channel \- Used to inject logging messages (bluetoothd(7))
+T}
+.TE
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct sockaddr_hci addr;
+
+memset(&addr, 0, sizeof(addr));
+addr.hci_family = AF_BLUETOOTH;
+addr.hci_dev = HCI_DEV_NONE;
+addr.hci_channel = HCI_CHANNEL_CONTROL;
+.EE
+.UNINDENT
+.UNINDENT
+.SH SOCKET OPTIONS
+.sp
+The socket options listed below can be set by using \fBsetsockopt(2)\fP and read
+with \fBgetsockopt(2)\fP with the socket level set to SOL_BLUETOOTH or SOL_HCI
+(HCI_FILTER).
+.SS HCI_FILTER (since Linux 2.6)
+.sp
+Filter by HCI events, requires hci_channel to be set to HCI_CHANNEL_RAW,
+possible values:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct hci_filter {
+    uint32_t type_mask;
+    uint32_t event_mask[2];
+    uint16_t opcode;
+};
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct hci_filter flt;
+
+memset(&flt, 0, sizeof(flt));
+flt.type_mask = 1 << BT_H4_EVT_PKT;
+flt.event_mask[0] = 0xffffffff;
+flt.event_mask[1] = 0xffffffff;
+
+setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt));
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_SNDBUF (since Linux 5.16)
+.sp
+Set send buffer size, requires hci_channel to be set to HCI_CHANNEL_MONITOR,
+HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.
+.sp
+Default value is 1028.
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+uint16_t mtu = UINT16_MAX;
+int err;
+
+err = setsockopt(fd, SOL_BLUETOOTH, BT_SNDMTU, &mtu, sizeof(mtu));
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_RCVBUF (since Linux 5.16)
+.sp
+Set receive buffer size, requires hci_channel to be set to HCI_CHANNEL_MONITOR,
+HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.
+.sp
+Default value is 1028.
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+uint16_t mtu;
+socklen_t len;
+int err;
+
+len = sizeof(mtu);
+err = getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU, mtu, &len);
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH SEE ALSO
+.sp
+socket(7)
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/hci.rst b/doc/hci.rst
new file mode 100644
index 0000000..d7f192a
--- /dev/null
+++ b/doc/hci.rst
@@ -0,0 +1,152 @@
+===
+hci
+===
+
+----------------------
+Bluetooth HCI protocol
+----------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: October 2024
+:Manual section: 7
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+.. code-block::
+
+    #include <sys/socket.h>
+    #include <bluetooth/bluetooth.h>
+    #include <bluetooth/hci.h>
+
+    hci_socket = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+
+DESCRIPTION
+===========
+
+Bluetooth Host Controller Interface (HCI) is the standard protocol to
+communicate with Bluetooth adapters. HCI protocol provides a uniform command
+method for the Host to access Controller capabilities and to control connections
+to other Controllers.
+
+SOCKET ADDRESS
+==============
+
+.. code-block::
+
+    struct sockaddr_hci {
+        sa_family_t    hci_family;
+        unsigned short hci_dev;
+        unsigned short hci_channel;
+    };
+
+Possible values for hci_channel:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **HCI_CHANNEL_RAW**, 0x00, Raw channel - Used for raw HCI communication
+    **HCI_CHANNEL_USER**, 0x01, User channel - Used for userspace HCI communication (disables kernel processing)
+    **HCI_CHANNEL_MONITOR**, 0x02, Monitor channel - Used for monitoring HCI traffic (btmon(1))
+    **HCI_CHANNEL_CONTROL**, 0x03, Control channel - Used to manage local adapters (bluetoothd(7))
+    **HCI_CHANNEL_LOGGING**, 0x04, Logging channel - Used to inject logging messages (bluetoothd(7))
+
+Example:
+
+.. code-block::
+
+    struct sockaddr_hci addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.hci_family = AF_BLUETOOTH;
+    addr.hci_dev = HCI_DEV_NONE;
+    addr.hci_channel = HCI_CHANNEL_CONTROL;
+
+SOCKET OPTIONS
+==============
+
+The socket options listed below can be set by using **setsockopt(2)** and read
+with **getsockopt(2)** with the socket level set to SOL_BLUETOOTH or SOL_HCI
+(HCI_FILTER).
+
+HCI_FILTER (since Linux 2.6)
+----------------------------
+
+Filter by HCI events, requires hci_channel to be set to HCI_CHANNEL_RAW,
+possible values:
+
+.. code-block::
+
+    struct hci_filter {
+        uint32_t type_mask;
+        uint32_t event_mask[2];
+        uint16_t opcode;
+    };
+
+Example:
+
+.. code-block::
+
+    struct hci_filter flt;
+
+    memset(&flt, 0, sizeof(flt));
+    flt.type_mask = 1 << BT_H4_EVT_PKT;
+    flt.event_mask[0] = 0xffffffff;
+    flt.event_mask[1] = 0xffffffff;
+
+    setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt));
+
+BT_SNDBUF (since Linux 5.16)
+----------------------------
+
+Set send buffer size, requires hci_channel to be set to HCI_CHANNEL_MONITOR,
+HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.
+
+Default value is 1028.
+
+Example:
+
+.. code-block::
+
+    uint16_t mtu = UINT16_MAX;
+    int err;
+
+    err = setsockopt(fd, SOL_BLUETOOTH, BT_SNDMTU, &mtu, sizeof(mtu));
+
+BT_RCVBUF (since Linux 5.16)
+----------------------------
+
+Set receive buffer size, requires hci_channel to be set to HCI_CHANNEL_MONITOR,
+HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.
+
+Default value is 1028.
+
+Example:
+
+.. code-block::
+
+    uint16_t mtu;
+    socklen_t len;
+    int err;
+
+    len = sizeof(mtu);
+    err = getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU, mtu, &len);
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
+
+SEE ALSO
+========
+
+socket(7)
diff --git a/doc/input-api.txt b/doc/input-api.txt
deleted file mode 100644
index 67da08b..0000000
--- a/doc/input-api.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-BlueZ D-Bus Input API description
-*********************************
-
-Input hierarchy
-===============
-
-Service		org.bluez
-Interface	org.bluez.Input1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Properties	string ReconnectMode [readonly]
-
-			Determines the Connectability mode of the HID device as
-			defined by the HID Profile specification, Section 5.4.2.
-
-			This mode is based in the two properties
-			HIDReconnectInitiate (see Section 5.3.4.6) and
-			HIDNormallyConnectable (see Section 5.3.4.14) which
-			define the following four possible values:
-
-			"none"		Device and host are not required to
-					automatically restore the connection.
-
-			"host"		Bluetooth HID host restores connection.
-
-			"device"	Bluetooth HID device restores
-					connection.
-
-			"any"		Bluetooth HID device shall attempt to
-					restore the lost connection, but
-					Bluetooth HID Host may also restore the
-					connection.
diff --git a/doc/intel-variants.txt b/doc/intel-variants.txt
deleted file mode 100644
index 4f51ca9..0000000
--- a/doc/intel-variants.txt
+++ /dev/null
@@ -1,159 +0,0 @@
-Intel Hardware Varaints
-=======================
-
-These are the list of Intel Bluetooth devices and its information.
-
-Some of devices were tested the following test cases:
-	Firmware loading after cold boot
-	Firmware loading after restart
-	Device discovery
-	Connection to LE Mouse
-	A2DP
-	HFP
-	Update to new firmware if available
-
-All Intel firmware can be found from linux-firmware git repo.
-https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
-
-
-Device List
------------
-
-Wilkins Peak (WP)
-- HW ID:	USB(0x8087:0x07dc)
-- Device Type:	Legacy ROM device
-- Driver flag:	BTUSB_INTEL_BROKEN_INITIAL_NCMD
-- HW variant:	0x07
-- FW files:
-	WP2 B3
-	intel/ibt-hw-37.7.10-fw-1.80.2.3.d.bseq
-		tested: Patch Version: 87    Release Version: 20.60.0.2
-			70353356f ("linux-firmware: Update firmware patch for Intel Bluetooth 7260 (B3/B4)")
-	WP2 B5
-	intel/ibt-hw-37.7.10-fw-1.80.1.2d.d.bseq
-		tested: Patch Version: 42    Release Version: 20.60.0.2
-			629a5e089 ("linux-firmware: Update firmware patch for Intel Bluetooth 7260 (B5/B6)")
-
-	WP1 B3
-	intel/ibt-hw-37.7.10-fw-1.0.1.2d.d.bseq
-
-	WP1 B3
-	intel/ibt-hw-37.7.10-fw-1.0.2.3.d.bseq
-
-
-Stone Peak (StP)
-- HW ID:	USB(0x8087:0x0a2a)
-- Device Type:	Legacy ROM device
-- HW variant:	0x08
-- FW files:
-	StP
-	intel/ibt-hw-37.8.10-fw-1.10.2.27.d.bseq
-
-	StP D1
-	intel/ibt-hw-37.8.10-fw-1.10.3.11.e.bseq
-		tested: FW Build: REL_50_0002    Release Version: 20.60.0.2
-			9489f5524 ("linux-firmware: Update firmware patch for Intel Bluetooth 7265 (D0)")
-
-
-Sandy Peak (SdP)
-- HW ID:	USB(0x8087:0x0aa7)
-- Device Type:	Legacy ROM device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-- HW variant:	0x08
-	intel/ibt-hw-37.8.10-fw-22.50.19.14.f.bseq
-		tested: FW Patch Version: 0x42(66)
-			195ecf149 ("linux-firmware: Intel BT 7265: Fix Security Issues")
-
-
-Snow Field Peak (SfP) / Windstorm Peak (WsP)
-- HW ID:	USB(0x8087:0x0a2b)
-- Device Type:	Legacy Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-- HW variant:	0x0b
-	SfP
-	intel/ibt-11-5.sfi
-		tested: FW Build: REL0522    Release Version: 20.100.0.3
-			f0896585b ("linux-firmware: Update firmware patch for Intel Bluetooth 8260")
-- HW variant:	0x0c
-	WsP
-	intel/ibt-12-16.sfi
-		tested: FW Build: REL1221    Release Version: 22.50.0.4
-			4116d72b9 ("linux-firmware: Update firmware file for Intel Bluetooth 8265")
-		tested: FW Build: REL0306    Release Version: 21.10.0.6
-			1f8ebdfc2 ("linux-firmware: Update firmware file for Intel Bluetooth 8265")
-
-
-Jefferson Peak (JfP)
-- HW ID:	USB(0x8087:0x0aaa)
-- Device Type:	Legacy Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-		HCI_QUIRK_VALID_LE_STATES
-- HW variant:	0x11
-	intel/ibt-17-0-1.sfi
-	intel/ibt-17-16-1.sfi
-
-
-Thunder Peak (ThP)
-- HW ID:	USB(0x8087:0x0025)
-- Device Type:	Legacy Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-		HCI_QUIRK_VALID_LE_STATES
-- HW variant:	0x12
-	intel/ibt-18-0-1.sfi
-	intel/ibt-18-16-1.sfi
-		tested: FW Build: REL19718    Release Version: 22.50.0.4
-			687d64a4d ("linux-firmware: Update firmware file for Intel Bluetooth 9260")
-		tested: FW Build: REL13313    Release Version: 21.120.0.4
-			db3038082 ("linux-firmware: Update firmware file for Intel Bluetooth 9260")
-
-
-Quasar(QsR) / Harrison Peak (HrP)
-- HW ID:	USB(0x8087:0x0026)
-- Device Type:	Legacy Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-- HW variant: 	0x13
-	Quasar with JfP
-	intel/ibt-19-0-1.sfi
-	intel/ibt-19-240-1.sfi
-
-	Quasar with HrP
-	intel/ibt-19-0-4.sfi
-	intel/ibt-19-240-4.sfi
-
-	intel/ibt-19-0-0.sfi
-	intel/ibt-19-16-4.sfi
-	intel/ibt-19-32-0.sfi
-	intel/ibt-19-32-1.sfi
-	intel/ibt-19-32-4.sfi
-
-
-Cyclone Peak (CcP)
-- HW ID:	USB(0x8087:0x0029)
-- Device Type:	Legacy Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-- HW variant:	0x14
-	intel/ibt-20-0-3.sfi
-	intel/ibt-20-1-3.sfi
-		tested: FW Build: REL25791    Release Version: 22.60.0.3
-			34803c20f ("linux-firmware: Update firmware file for Intel Bluetooth AX200")
-	intel/ibt-20-1-4.sfi
-
-
-Typhon Peak (TyP)
-- HW ID:	USB(0x8087:0x0032)
-- Device Type:	TLV based Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-- HW variant:	0x17
-	intel/ibt-0041-0041.sfi
-		tested: FW Build: REL25171    Release Version: 22.60.0.3
-			25ddc612f ("linux-firmware: Update firmware file for Intel Bluetooth AX210")
-		tested: FW Build: REL17510    Release Version: 22.20.0.3
-			28185ecdc ("linux-firmware: Update firmware file for Intel Bluetooth AX210")
-
-
-Garfield Peak (GfP)
-- HW ID:	USB(0x8087:0x0033)
-- Device Type:	TLV based Bootloader device
-- HCI Quirks:	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED
-		HCI_QUIRK_VALID_LE_STATES
-- HW variant:	0x18
diff --git a/doc/l2cap.7 b/doc/l2cap.7
new file mode 100644
index 0000000..4117f6b
--- /dev/null
+++ b/doc/l2cap.7
@@ -0,0 +1,578 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "L2CAP" "7" "May 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+l2cap \- L2CAP protocol
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+
+l2cap_socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+.EE
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+L2CAP is a protocol that provides an interface for higher\-level protocols to
+send and receive data over a Bluetooth connection. L2CAP sits on top of the
+Bluetooth Host Controller Interface (HCI) and provides a set of channels that
+can be used by higher\-level protocols to transmit data.
+.sp
+L2CAP provides a number of services to higher\-level protocols, including
+segmentation and reassembly of large data packets and flow control to prevent
+overloading of the receiver. L2CAP also supports multiple channels per
+connection, allowing for concurrent data transmission using different protocols.
+.SH SOCKET ADDRESS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+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;
+};
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct sockaddr_l2 addr;
+
+memset(&addr, 0, sizeof(addr));
+addr.l2_family = AF_BLUETOOTH;
+bacpy(&addr.l2_bdaddr, bdaddr);
+
+if (cid)
+    addr.l2_cid = htobs(cid);
+else
+    addr.l2_psm = htobs(psm);
+
+addr.l2_bdaddr_type = bdaddr_type;
+.EE
+.UNINDENT
+.UNINDENT
+.SH SOCKET OPTIONS
+.sp
+The socket options listed below can be set by using \fBsetsockopt(2)\fP and read
+with \fBgetsockopt(2)\fP with the socket level set to SOL_BLUETOOTH.
+.SS BT_SECURITY (since Linux 2.6.30)
+.sp
+Channel security level, possible values:
+.TS
+box center;
+l|l|l|l.
+T{
+Value
+T}	T{
+Security Level
+T}	T{
+Link Key Type
+T}	T{
+Encryption
+T}
+_
+T{
+\fBBT_SECURITY_SDP\fP
+T}	T{
+0 (SDP Only)
+T}	T{
+None
+T}	T{
+Not required
+T}
+_
+T{
+\fBBT_SECURITY_LOW\fP
+T}	T{
+1 (Low)
+T}	T{
+Unauthenticated
+T}	T{
+Not required
+T}
+_
+T{
+\fBBT_SECURITY_MEDIUM\fP
+T}	T{
+2 (Medium \- default)
+T}	T{
+Unauthenticated
+T}	T{
+Desired
+T}
+_
+T{
+\fBBT_SECURITY_HIGH\fP
+T}	T{
+3 (High)
+T}	T{
+Authenticated
+T}	T{
+Required
+T}
+_
+T{
+\fBBT_SECURITY_FIPS\fP (since Linux 3.15)
+T}	T{
+4 (Secure Only)
+T}	T{
+Authenticated (P\-256 based Secure Simple Pairing and Secure Authentication)
+T}	T{
+Required
+T}
+.TE
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+int level = BT_SECURITY_HIGH;
+int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
+                     sizeof(level));
+if (err == \-1) {
+    perror(\(dqsetsockopt\(dq);
+    return 1;
+}
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_DEFER_SETUP (since Linux 2.6.30)
+.sp
+Channel defer connection setup, this control if the connection procedure
+needs to be authorized by userspace before responding which allows
+authorization at profile level, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Value
+T}	T{
+Description
+T}	T{
+Authorization
+T}
+_
+T{
+\fB0\fP
+T}	T{
+Disable (default)
+T}	T{
+Not required
+T}
+_
+T{
+\fB1\fP
+T}	T{
+Enable
+T}	T{
+Required
+T}
+.TE
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+int defer_setup = 1;
+int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_DEFER_SETUP,
+                     &defer_setup, sizeof(defer_setup));
+if (err == \-1) {
+    perror(\(dqsetsockopt\(dq);
+    return err;
+}
+
+err = listen(l2cap_socket, 5);
+if (err) {
+    perror(\(dqlisten\(dq);
+    return err;
+}
+
+struct sockaddr_l2 remote_addr = {0};
+socklen_t addr_len = sizeof(remote_addr);
+int new_socket = accept(l2cap_socket, (struct sockaddr*)&remote_addr,
+                        &addr_len);
+if (new_socket < 0) {
+    perror(\(dqaccept\(dq);
+    return new_socket;
+}
+
+/* To complete the connection setup of new_socket read 1 byte */
+char c;
+struct pollfd pfd;
+
+memset(&pfd, 0, sizeof(pfd));
+pfd.fd = new_socket;
+pfd.events = POLLOUT;
+
+err = poll(&pfd, 1, 0);
+if (err) {
+    perror(\(dqpoll\(dq);
+    return err;
+}
+
+if (!(pfd.revents & POLLOUT)) {
+    err = read(sk, &c, 1);
+    if (err < 0) {
+        perror(\(dqread\(dq);
+        return err;
+    }
+}
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_FLUSHABLE (since Linux 2.6.39)
+.sp
+Channel flushable flag, this control if the channel data can be flushed or
+not, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_FLUSHABLE_OFF\fP
+T}	T{
+0x00 (default)
+T}	T{
+Do not flush data
+T}
+_
+T{
+\fBBT_FLUSHABLE_ON\fP
+T}	T{
+0x01
+T}	T{
+Flush data
+T}
+.TE
+.SS BT_POWER (since Linux 3.1)
+.sp
+Channel power policy, this control if the channel shall force exit of sniff
+mode or not, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_POWER_FORCE_ACTIVE_OFF\fP
+T}	T{
+0x00 (default)
+T}	T{
+Don\(aqt force exit of sniff mode
+T}
+_
+T{
+\fBBT_POWER_FORCE_ACTIVE_ON\fP
+T}	T{
+0x01
+T}	T{
+Force exit of sniff mode
+T}
+.TE
+.SS BT_CHANNEL_POLICY (since Linux 3.10)
+.sp
+High\-speed (AMP) channel policy, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_ONLY\fP
+T}	T{
+0 (default)
+T}	T{
+BR/EDR only
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_PREFERRED\fP
+T}	T{
+1
+T}	T{
+BR/EDR Preferred
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_PREFERRED\fP
+T}	T{
+2
+T}	T{
+AMP Preferred
+T}
+.TE
+.SS BT_PHY (since Linux 5.10)
+.sp
+Channel supported PHY(s), possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_PHY_BR_1M_1SLOT\fP
+T}	T{
+BIT 0
+T}	T{
+BR 1Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_1M_3SLOT\fP
+T}	T{
+BIT 1
+T}	T{
+BR 1Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_1M_5SLOT\fP
+T}	T{
+BIT 2
+T}	T{
+BR 1Mbps 5SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_1SLOT\fP
+T}	T{
+BIT 3
+T}	T{
+EDR 2Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_3SLOT\fP
+T}	T{
+BIT 4
+T}	T{
+EDR 2Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_5SLOT\fP
+T}	T{
+BIT 5
+T}	T{
+EDR 2Mbps 5SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_1SLOT\fP
+T}	T{
+BIT 6
+T}	T{
+EDR 3Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_3SLOT\fP
+T}	T{
+BIT 7
+T}	T{
+EDR 3Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_5SLOT\fP
+T}	T{
+BIT 8
+T}	T{
+EDR 3Mbps 5SLOT
+T}
+_
+T{
+\fBBT_PHY_LE_1M_TX\fP
+T}	T{
+BIT 9
+T}	T{
+LE 1Mbps TX
+T}
+_
+T{
+\fBBT_PHY_LE_1M_RX\fP
+T}	T{
+BIT 10
+T}	T{
+LE 1Mbps RX
+T}
+_
+T{
+\fBBT_PHY_LE_2M_TX\fP
+T}	T{
+BIT 11
+T}	T{
+LE 2Mbps TX
+T}
+_
+T{
+\fBBT_PHY_LE_2M_RX\fP
+T}	T{
+BIT 12
+T}	T{
+LE 2Mbps RX
+T}
+_
+T{
+\fBBT_PHY_LE_CODED_TX\fP
+T}	T{
+BIT 13
+T}	T{
+LE Coded TX
+T}
+_
+T{
+\fBBT_PHY_LE_CODED_RX\fP
+T}	T{
+BIT 14
+T}	T{
+LE Coded RX
+T}
+.TE
+.SS BT_MODE (since Linux 5.10)
+.sp
+Channel Mode, possible values:
+.TS
+box center;
+l|l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}	T{
+Link
+T}
+_
+T{
+\fBBT_MODE_BASIC\fP
+T}	T{
+0x00 (default)
+T}	T{
+Basic mode
+T}	T{
+Any
+T}
+_
+T{
+\fBBT_MODE_ERTM\fP
+T}	T{
+0x01
+T}	T{
+Enhanced Retransmission mode
+T}	T{
+BR/EDR
+T}
+_
+T{
+\fBBT_MODE_STREAM\fP
+T}	T{
+0x02
+T}	T{
+Stream mode
+T}	T{
+BR/EDR
+T}
+_
+T{
+\fBBT_MODE_LE_FLOWCTL\fP
+T}	T{
+0x03
+T}	T{
+Credit based flow control mode
+T}	T{
+LE
+T}
+_
+T{
+\fBBT_MODE_EXT_FLOWCTL\fP
+T}	T{
+0x04
+T}	T{
+Extended Credit based flow control mode
+T}	T{
+Any
+T}
+.TE
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH SEE ALSO
+.sp
+socket(7), l2test(1)
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/l2cap.rst b/doc/l2cap.rst
new file mode 100644
index 0000000..f90f882
--- /dev/null
+++ b/doc/l2cap.rst
@@ -0,0 +1,258 @@
+=====
+l2cap
+=====
+
+--------------
+L2CAP protocol
+--------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: May 2024
+:Manual section: 7
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+.. code-block::
+
+    #include <sys/socket.h>
+    #include <bluetooth/bluetooth.h>
+    #include <bluetooth/l2cap.h>
+
+    l2cap_socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+
+DESCRIPTION
+===========
+
+L2CAP is a protocol that provides an interface for higher-level protocols to
+send and receive data over a Bluetooth connection. L2CAP sits on top of the
+Bluetooth Host Controller Interface (HCI) and provides a set of channels that
+can be used by higher-level protocols to transmit data.
+
+L2CAP provides a number of services to higher-level protocols, including
+segmentation and reassembly of large data packets and flow control to prevent
+overloading of the receiver. L2CAP also supports multiple channels per
+connection, allowing for concurrent data transmission using different protocols.
+
+SOCKET ADDRESS
+==============
+
+.. code-block::
+
+    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;
+    };
+
+Example:
+
+.. code-block::
+
+    struct sockaddr_l2 addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.l2_family = AF_BLUETOOTH;
+    bacpy(&addr.l2_bdaddr, bdaddr);
+
+    if (cid)
+        addr.l2_cid = htobs(cid);
+    else
+        addr.l2_psm = htobs(psm);
+
+    addr.l2_bdaddr_type = bdaddr_type;
+
+SOCKET OPTIONS
+==============
+
+The socket options listed below can be set by using **setsockopt(2)** and read
+with **getsockopt(2)** with the socket level set to SOL_BLUETOOTH.
+
+BT_SECURITY (since Linux 2.6.30)
+--------------------------------
+
+Channel security level, possible values:
+
+.. csv-table::
+    :header: "Value", "Security Level", "Link Key Type", "Encryption"
+    :widths: auto
+
+    **BT_SECURITY_SDP**, 0 (SDP Only), None, Not required
+    **BT_SECURITY_LOW**, 1 (Low), Unauthenticated, Not required
+    **BT_SECURITY_MEDIUM**, 2 (Medium - default), Unauthenticated, Desired
+    **BT_SECURITY_HIGH**, 3 (High), Authenticated, Required
+    **BT_SECURITY_FIPS** (since Linux 3.15), 4 (Secure Only), Authenticated (P-256 based Secure Simple Pairing and Secure Authentication), Required
+
+Example:
+
+.. code-block::
+
+    int level = BT_SECURITY_HIGH;
+    int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
+                         sizeof(level));
+    if (err == -1) {
+        perror("setsockopt");
+        return 1;
+    }
+
+BT_DEFER_SETUP (since Linux 2.6.30)
+-----------------------------------
+
+Channel defer connection setup, this control if the connection procedure
+needs to be authorized by userspace before responding which allows
+authorization at profile level, possible values:
+
+.. csv-table::
+    :header: "Value", "Description", "Authorization"
+    :widths: auto
+
+    **0**, Disable (default), Not required
+    **1**, Enable, Required
+
+Example:
+
+.. code-block::
+
+    int defer_setup = 1;
+    int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_DEFER_SETUP,
+                         &defer_setup, sizeof(defer_setup));
+    if (err == -1) {
+        perror("setsockopt");
+        return err;
+    }
+
+    err = listen(l2cap_socket, 5);
+    if (err) {
+        perror("listen");
+        return err;
+    }
+
+    struct sockaddr_l2 remote_addr = {0};
+    socklen_t addr_len = sizeof(remote_addr);
+    int new_socket = accept(l2cap_socket, (struct sockaddr*)&remote_addr,
+                            &addr_len);
+    if (new_socket < 0) {
+        perror("accept");
+        return new_socket;
+    }
+
+    /* To complete the connection setup of new_socket read 1 byte */
+    char c;
+    struct pollfd pfd;
+
+    memset(&pfd, 0, sizeof(pfd));
+    pfd.fd = new_socket;
+    pfd.events = POLLOUT;
+
+    err = poll(&pfd, 1, 0);
+    if (err) {
+        perror("poll");
+        return err;
+    }
+
+    if (!(pfd.revents & POLLOUT)) {
+        err = read(sk, &c, 1);
+        if (err < 0) {
+            perror("read");
+            return err;
+        }
+    }
+
+BT_FLUSHABLE (since Linux 2.6.39)
+---------------------------------
+
+Channel flushable flag, this control if the channel data can be flushed or
+not, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_FLUSHABLE_OFF**, 0x00 (default), Do not flush data
+    **BT_FLUSHABLE_ON**, 0x01, Flush data
+
+BT_POWER (since Linux 3.1)
+--------------------------
+
+Channel power policy, this control if the channel shall force exit of sniff
+mode or not, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_POWER_FORCE_ACTIVE_OFF**, 0x00 (default), Don't force exit of sniff mode
+    **BT_POWER_FORCE_ACTIVE_ON**, 0x01, Force exit of sniff mode
+
+BT_CHANNEL_POLICY (since Linux 3.10)
+------------------------------------
+
+High-speed (AMP) channel policy, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_CHANNEL_POLICY_BREDR_ONLY**, 0 (default), BR/EDR only
+    **BT_CHANNEL_POLICY_BREDR_PREFERRED**, 1, BR/EDR Preferred
+    **BT_CHANNEL_POLICY_BREDR_PREFERRED**, 2, AMP Preferred
+
+BT_PHY (since Linux 5.10)
+-------------------------
+
+Channel supported PHY(s), possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_PHY_BR_1M_1SLOT**, BIT 0, BR 1Mbps 1SLOT
+    **BT_PHY_BR_1M_3SLOT**, BIT 1, BR 1Mbps 3SLOT
+    **BT_PHY_BR_1M_5SLOT**, BIT 2, BR 1Mbps 5SLOT
+    **BT_PHY_BR_2M_1SLOT**, BIT 3, EDR 2Mbps 1SLOT
+    **BT_PHY_BR_2M_3SLOT**, BIT 4, EDR 2Mbps 3SLOT
+    **BT_PHY_BR_2M_5SLOT**, BIT 5, EDR 2Mbps 5SLOT
+    **BT_PHY_BR_3M_1SLOT**, BIT 6, EDR 3Mbps 1SLOT
+    **BT_PHY_BR_3M_3SLOT**, BIT 7, EDR 3Mbps 3SLOT
+    **BT_PHY_BR_3M_5SLOT**, BIT 8, EDR 3Mbps 5SLOT
+    **BT_PHY_LE_1M_TX**, BIT 9, LE 1Mbps TX
+    **BT_PHY_LE_1M_RX**, BIT 10, LE 1Mbps RX
+    **BT_PHY_LE_2M_TX**, BIT 11, LE 2Mbps TX
+    **BT_PHY_LE_2M_RX**, BIT 12, LE 2Mbps RX
+    **BT_PHY_LE_CODED_TX**, BIT 13, LE Coded TX
+    **BT_PHY_LE_CODED_RX**, BIT 14, LE Coded RX
+
+BT_MODE (since Linux 5.10)
+--------------------------
+
+Channel Mode, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description", "Link"
+    :widths: auto
+
+    **BT_MODE_BASIC**, 0x00 (default), Basic mode, Any
+    **BT_MODE_ERTM**, 0x01, Enhanced Retransmission mode, BR/EDR
+    **BT_MODE_STREAM**, 0x02, Stream mode, BR/EDR
+    **BT_MODE_LE_FLOWCTL**, 0x03, Credit based flow control mode, LE
+    **BT_MODE_EXT_FLOWCTL**, 0x04, Extended Credit based flow control mode, Any
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
+
+SEE ALSO
+========
+
+socket(7), l2test(1)
diff --git a/doc/maintainer-guidelines.txt b/doc/maintainer-guidelines.txt
deleted file mode 100644
index 21162d4..0000000
--- a/doc/maintainer-guidelines.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-Maintainer guidelines
-*********************
-
-This document is intended for the maintainers of the BlueZ project. It
-serves as basic guidelines for handling patch review and commit access.
-
-
-Rule 1: Keep the GIT tree clean and linear
-==========================================
-
-The bluetooth.git, bluetooth-next.git and bluez.git trees are not your
-private playground. The history is meant to be clean and linear.
-
-	- NO merges
-	- NO branches
-	- NO tags
-
-If anyone needs testing or work on a feature, clone the tree and do
-it in your own copy. The master trees are off limits.
-
-One advise to avoid any accidental errors in this area to set proper
-options in global ~/.gitconfig or local .git/config files.
-
-	[merge]
-		ff = only
-
-Violations of this rule are not acceptable. This rule is enforced. If
-in doubt ask one of the seasoned maintainers.
-
-
-Rule 2: Enforce clean commit messages
-=====================================
-
-The commit messages are required to be clean and follow style guidelines
-to be consistent.
-
-Commit messages should adhere to a 72 characters by line limit. That
-makes it easy to read them via git log in a terminal window. Exceptions
-to this rule are logs, trace or other verbatim copied information.
-
-Every commit requires full names and email addresses. No synonyms or
-nicknames are allowed. It is also important that the Outlook style
-names with lastname, firstname are not allowed. It is the maintainers
-job to ensure we get proper firstname lastname <email> authorship.
-
-It is also important that the committer itself uses a valid name and
-email address when committing patches. So ensure that either the
-global ~/.gitconfig or local .git/config provides proper values.
-
-	[user]
-		name = Peter Mustermann
-		email = peter@mustermann.de
-
-Commit messages for bluez.git shall not contain Signed-off-by
-signatures. They are not used in userspace and with that it is the
-maintainers job to ensure they do not get committed to the repository.
-
-For bluetooth.git and bluetooth-next.git The Signed-off-by process is
-used and the signatures are required.
-
-Tags like Change-Id generated from Gerrit are never acceptable. It is
-the maintainers job to ensure that these are not committed into the
-repositories.
-
-Violations of this rule create a mess in the tree that can not be
-reversed. If in doubt ask one of the seasoned maintainers.
-
-
-Rule 3: Enforce correct coding style
-====================================
-
-The coding style follows roughly the kernel coding style with any
-exceptions documented in doc/coding-style.txt.
-
-To ensure trivial white-space errors don't get committed, have the
-following in your .gitconfig:
-
-	[apply]
-		whitespace = error
-
-It can also be helpful to use the checkpatch.pl script coming with the
-Linux kernel to do some automated checking. Adding the following to your
-.git/hooks/pre-commit and .git/hooks/pre-applypatch is a simple way to
-do this:
-
-	exec git diff --cached | ~/src/linux/scripts/checkpatch.pl -q \
-		--no-tree --no-signoff --show-types \
-		--ignore CAMELCASE,NEW_TYPEDEFS,INITIALISED_STATIC -
-
-The above assumes that a kernel tree resides in ~/src/linux/.
-
-
-Rule 4: Pay extra attention to adding new files to the tree
-===========================================================
-
-New files that are added to the tree require several things to be
-verified first:
-
-	- Check that the names are acceptible with other maintainers
-	- Ensure that the file modes are correct
-	- Verify that the license & copyright headers are correct
-	- If the file is supposed to be part of the release tarball,
-	  make sure that it gets picked up by 'make dist' (particularly
-	  important for documentation or other files that are not code)
-
-
-Rule 5: Keep the mailing list in sync with the commit process
-=============================================================
-
-When applying patches, be sure to send a response to the mailing list as
-soon as the code has been pushed to the upstream tree. Usually this
-means one email per patch, however patch-sets may only have one response
-covering the entire set. If applying a subset of a patch-set clearly
-state what was applied in your response.
diff --git a/doc/media-api.txt b/doc/media-api.txt
deleted file mode 100644
index 847f8be..0000000
--- a/doc/media-api.txt
+++ /dev/null
@@ -1,779 +0,0 @@
-BlueZ D-Bus Media API description
-*********************************
-
-
-Media hierarchy
-===============
-
-Service		org.bluez
-Interface	org.bluez.Media1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		void RegisterEndpoint(object endpoint, dict properties)
-
-			Register a local end point to sender, the sender can
-			register as many end points as it likes.
-
-			Note: If the sender disconnects the end points are
-			automatically unregistered.
-
-			possible properties:
-
-				string UUID:
-
-					UUID of the profile which the endpoint
-					is for.
-
-					UUID must be in the list of
-					SupportedUUIDS.
-
-				byte Codec:
-
-					Assigned number of codec that the
-					endpoint implements. The values should
-					match the profile specification which
-					is indicated by the UUID.
-
-				array{byte} Capabilities:
-
-					Capabilities blob, it is used as it is
-					so the size and byte order must match.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported - emitted
-					 when interface for the end-point is
-					 disabled.
-
-		void UnregisterEndpoint(object endpoint)
-
-			Unregister sender end point.
-
-		void RegisterPlayer(object player, dict properties)
-
-			Register a media player object to sender, the sender
-			can register as many objects as it likes.
-
-			Object must implement at least
-			org.mpris.MediaPlayer2.Player as defined in MPRIS 2.2
-			spec:
-
-			http://specifications.freedesktop.org/mpris-spec/latest/
-
-			Note: If the sender disconnects its objects are
-			automatically unregistered.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-
-		void UnregisterPlayer(object player)
-
-			Unregister sender media player.
-
-		void RegisterApplication(object root, dict options)
-
-			Register endpoints an player objects within root
-			object which must implement ObjectManager.
-
-			The application object path together with the D-Bus
-			system bus connection ID define the identification of
-			the application.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-
-		void UnregisterApplication(object application)
-
-			This unregisters the services that has been
-			previously registered. The object path parameter
-			must match the same value that has been used
-			on registration.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.DoesNotExist
-
-Properties	array{string} SupportedUUIDs [readonly]:
-
-			List of 128-bit UUIDs that represents the supported
-			Endpoint registration.
-
-Media Control hierarchy
-=======================
-
-Service		org.bluez
-Interface	org.bluez.MediaControl1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Methods		void Play() [Deprecated]
-
-			Resume playback.
-
-		void Pause() [Deprecated]
-
-			Pause playback.
-
-		void Stop() [Deprecated]
-
-			Stop playback.
-
-		void Next() [Deprecated]
-
-			Next item.
-
-		void Previous() [Deprecated]
-
-			Previous item.
-
-		void VolumeUp() [Deprecated]
-
-			Adjust remote volume one step up
-
-		void VolumeDown() [Deprecated]
-
-			Adjust remote volume one step down
-
-		void FastForward() [Deprecated]
-
-			Fast forward playback, this action is only stopped
-			when another method in this interface is called.
-
-		void Rewind() [Deprecated]
-
-			Rewind playback, this action is only stopped
-			when another method in this interface is called.
-
-Properties
-
-		boolean Connected [readonly]
-
-		object Player [readonly, optional]
-
-			Addressed Player object path.
-
-
-MediaPlayer1 hierarchy
-======================
-
-Service		org.bluez (Controller role)
-Interface	org.bluez.MediaPlayer1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
-
-Methods		void Play()
-
-			Resume playback.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Pause()
-
-			Pause playback.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Stop()
-
-			Stop playback.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Next()
-
-			Next item.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Previous()
-
-			Previous item.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void FastForward()
-
-			Fast forward playback, this action is only stopped
-			when another method in this interface is called.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Rewind()
-
-			Rewind playback, this action is only stopped
-			when another method in this interface is called.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Press(byte avc_key)
-
-			Press a specific key to send as passthrough command.
-			The key will be released automatically. Use Hold()
-			instead if the intention is to hold down the key.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Hold(byte avc_key)
-
-			Press and hold a specific key to send as passthrough
-			command. It is your responsibility to make sure that
-			Release() is called after calling this method. The held
-			key will also be released when any other method in this
-			interface is called.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void Release()
-
-			Release the previously held key invoked using Hold().
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-Properties	string Equalizer [readwrite]
-
-			Possible values: "off" or "on"
-
-		string Repeat [readwrite]
-
-			Possible values: "off", "singletrack", "alltracks" or
-					"group"
-
-		string Shuffle [readwrite]
-
-			Possible values: "off", "alltracks" or "group"
-
-		string Scan [readwrite]
-
-			Possible values: "off", "alltracks" or "group"
-
-		string Status [readonly]
-
-			Possible status: "playing", "stopped", "paused",
-					"forward-seek", "reverse-seek"
-					or "error"
-
-		uint32 Position [readonly]
-
-			Playback position in milliseconds. Changing the
-			position may generate additional events that will be
-			sent to the remote device. When position is 0 it means
-			the track is starting and when it's greater than or
-			equal to track's duration the track has ended. Note
-			that even if duration is not available in metadata it's
-			possible to signal its end by setting position to the
-			maximum uint32 value.
-
-		dict Track [readonly]
-
-			Track metadata.
-
-			Possible values:
-
-				string Title:
-
-					Track title name
-
-				string Artist:
-
-					Track artist name
-
-				string Album:
-
-					Track album name
-
-				string Genre:
-
-					Track genre name
-
-				uint32 NumberOfTracks:
-
-					Number of tracks in total
-
-				uint32 TrackNumber:
-
-					Track number
-
-				uint32 Duration:
-
-					Track duration in milliseconds
-
-		object Device [readonly]
-
-			Device object path.
-
-		string Name [readonly]
-
-			Player name
-
-		string Type [readonly]
-
-			Player type
-
-			Possible values:
-
-				"Audio"
-				"Video"
-				"Audio Broadcasting"
-				"Video Broadcasting"
-
-		string Subtype [readonly]
-
-			Player subtype
-
-			Possible values:
-
-				"Audio Book"
-				"Podcast"
-
-		boolean Browsable [readonly]
-
-			If present indicates the player can be browsed using
-			MediaFolder interface.
-
-			Possible values:
-
-				True: Supported and active
-				False: Supported but inactive
-
-			Note: If supported but inactive clients can enable it
-			by using MediaFolder interface but it might interfere
-			in the playback of other players.
-
-
-		boolean Searchable [readonly]
-
-			If present indicates the player can be searched using
-			MediaFolder interface.
-
-			Possible values:
-
-				True: Supported and active
-				False: Supported but inactive
-
-			Note: If supported but inactive clients can enable it
-			by using MediaFolder interface but it might interfere
-			in the playback of other players.
-
-		object Playlist
-
-			Playlist object path.
-
-MediaFolder1 hierarchy
-======================
-
-Service		unique name (Target role)
-		org.bluez (Controller role)
-Interface	org.bluez.MediaFolder1
-Object path	freely definable (Target role)
-		[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
-		(Controller role)
-
-Methods		object Search(string value, dict filter)
-
-			Return a folder object containing the search result.
-
-			To list the items found use the folder object returned
-			and pass to ChangeFolder.
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		array{objects, properties} ListItems(dict filter)
-
-			Return a list of items found
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void ChangeFolder(object folder)
-
-			Change current folder.
-
-			Note: By changing folder the items of previous folder
-			might be destroyed and have to be listed again, the
-			exception is NowPlaying folder which should be always
-			present while the player is active.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-Properties	uint32 NumberOfItems [readonly]
-
-			Number of items in the folder
-
-		string Name [readonly]
-
-			Folder name:
-
-			Possible values:
-				"/Filesystem/...": Filesystem scope
-				"/NowPlaying/...": NowPlaying scope
-
-			Note: /NowPlaying folder might not be listed if player
-			is stopped, folders created by Search are virtual so
-			once another Search is perform or the folder is
-			changed using ChangeFolder it will no longer be listed.
-
-Filters		uint32 Start:
-
-			Offset of the first item.
-
-			Default value: 0
-
-		uint32 End:
-
-			Offset of the last item.
-
-			Default value: NumbeOfItems
-
-		array{string} Attributes
-
-			Item properties that should be included in the list.
-
-			Possible Values:
-
-				"title", "artist", "album", "genre",
-				"number-of-tracks", "number", "duration"
-
-			Default Value: All
-
-MediaItem1 hierarchy
-====================
-
-Service		unique name (Target role)
-		org.bluez (Controller role)
-Interface	org.bluez.MediaItem1
-Object path	freely definable (Target role)
-		[variable
-		prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX/itemX
-		(Controller role)
-
-Methods		void Play()
-
-			Play item
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-		void AddtoNowPlaying()
-
-			Add item to now playing list
-
-			Possible Errors: org.bluez.Error.NotSupported
-					 org.bluez.Error.Failed
-
-Properties	object Player [readonly]
-
-			Player object path the item belongs to
-
-		string Name [readonly]
-
-			Item displayable name
-
-		string Type [readonly]
-
-			Item type
-
-			Possible values: "video", "audio", "folder"
-
-		string FolderType [readonly, optional]
-
-			Folder type.
-
-			Possible values: "mixed", "titles", "albums", "artists"
-
-			Available if property Type is "Folder"
-
-		boolean Playable [readonly, optional]
-
-			Indicates if the item can be played
-
-			Available if property Type is "folder"
-
-		dict Metadata [readonly]
-
-			Item metadata.
-
-			Possible values:
-
-				string Title
-
-					Item title name
-
-					Available if property Type is "audio"
-					or "video"
-
-				string Artist
-
-					Item artist name
-
-					Available if property Type is "audio"
-					or "video"
-
-				string Album
-
-					Item album name
-
-					Available if property Type is "audio"
-					or "video"
-
-				string Genre
-
-					Item genre name
-
-					Available if property Type is "audio"
-					or "video"
-
-				uint32 NumberOfTracks
-
-					Item album number of tracks in total
-
-					Available if property Type is "audio"
-					or "video"
-
-				uint32 Number
-
-					Item album number
-
-					Available if property Type is "audio"
-					or "video"
-
-				uint32 Duration
-
-					Item duration in milliseconds
-
-					Available if property Type is "audio"
-					or "video"
-
-MediaEndpoint1 hierarchy
-========================
-
-Service		unique name (Server role)
-		org.bluez (Client role)
-Interface	org.bluez.MediaEndpoint1
-Object path	freely definable (Server role)
-		[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/sepX
-		(Client role)
-
-Methods		void SetConfiguration(object transport, dict properties)
-
-			Set configuration for the transport.
-
-			For client role transport must be set with a server
-			endpoint oject which will be configured and the
-			properties must contain the following properties:
-
-				array{byte} Capabilities [Mandatory]
-				array{byte} Metadata [ISO only]
-				byte CIG [ISO only]
-				byte CIS [ISO only]
-				uint32 Interval [ISO only]
-				bool Framing [ISO only]
-				string PHY [ISO only]
-				uint16 SDU [ISO only]
-				byte Retransmissions [ISO only]
-				uint16 Latency [ISO only]
-				uint32 Delay [ISO only]
-				uint8 TargetLatency [ISO Latency]
-
-		array{byte} SelectConfiguration(array{byte} capabilities)
-
-			Select preferable configuration from the supported
-			capabilities.
-
-			Returns a configuration which can be used to setup
-			a transport.
-
-			Note: There is no need to cache the selected
-			configuration since on success the configuration is
-			send back as parameter of SetConfiguration.
-
-		dict SelectProperties(dict properties)
-
-			Select preferable properties from the supported
-			properties:
-				object Endpoint [ISO only]
-				Refer to SetConfiguration for the list of
-					other possible properties.
-
-			Returns propeties which can be used to setup
-			a transport.
-
-			Note: There is no need to cache the selected
-			properties since on success the configuration is
-			send back as parameter of SetConfiguration.
-
-		void ClearConfiguration(object transport)
-
-			Clear transport configuration.
-
-		void Release()
-
-			This method gets called when the service daemon
-			unregisters the endpoint. An endpoint can use it to do
-			cleanup tasks. There is no need to unregister the
-			endpoint, because when this method gets called it has
-			already been unregistered.
-
-Properties	string UUID [readonly, optional]:
-
-			UUID of the profile which the endpoint is for.
-
-		byte Codec [readonly, optional]:
-
-			Assigned number of codec that the endpoint implements.
-			The values should match the profile specification which
-			is indicated by the UUID.
-
-		array{byte} Capabilities [readonly, optional]:
-
-			Capabilities blob, it is used as it is so the size and
-			byte order must match.
-
-		object Device [readonly, optional]:
-
-			Device object which the endpoint is belongs to.
-
-		bool DelayReporting [readonly, optional]:
-
-			Indicates if endpoint supports Delay Reporting.
-
-		byte Framing [ISO only]
-
-			Indicates endpoint support framing.
-
-		byte PHY [ISO only]
-
-			Indicates endpoint supported PHY.
-
-		uint16_t MaximumLatency [ISO only]
-
-			Indicates endpoint maximum latency.
-
-		uint32_t MinimumDelay [ISO only]
-
-			Indicates endpoint minimum presentation delay.
-
-		uint32_t MaximumDelay [ISO only]
-
-			Indicates endpoint maximum presentation delay.
-
-		uint32_t PreferredMinimumDelay [ISO only]
-
-			Indicates endpoint preferred minimum presentation delay.
-
-		uint32_t PreferredMinimumDelay [ISO only]
-
-			Indicates endpoint preferred minimum presentation delay.
-
-		uint32 Location [ISO only]
-
-			Indicates endpoint supported locations.
-
-		uint16 SupportedContext [ISO only]
-
-			Indicates endpoint supported audio context.
-
-		uint16 Context [ISO only]
-
-			Indicates endpoint available audio context.
-
-MediaTransport1 hierarchy
-=========================
-
-Service		org.bluez
-Interface	org.bluez.MediaTransport1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/fdX
-
-Methods		fd, uint16, uint16 Acquire()
-
-			Acquire transport file descriptor and the MTU for read
-			and write respectively.
-
-			Possible Errors: org.bluez.Error.NotAuthorized
-					 org.bluez.Error.Failed
-
-		fd, uint16, uint16 TryAcquire()
-
-			Acquire transport file descriptor only if the transport
-			is in "pending" state at the time the message is
-			received by BlueZ. Otherwise no request will be sent
-			to the remote device and the function will just fail
-			with org.bluez.Error.NotAvailable.
-
-			Possible Errors: org.bluez.Error.NotAuthorized
-					 org.bluez.Error.Failed
-					 org.bluez.Error.NotAvailable
-
-		void Release()
-
-			Releases file descriptor.
-
-Properties	object Device [readonly]
-
-			Device object which the transport is connected to.
-
-		string UUID [readonly]
-
-			UUID of the profile which the transport is for.
-
-		byte Codec [readonly]
-
-			Assigned number of codec that the transport support.
-			The values should match the profile specification which
-			is indicated by the UUID.
-
-		array{byte} Configuration [readonly]
-
-			Configuration blob, it is used as it is so the size and
-			byte order must match.
-
-		string State [readonly]
-
-			Indicates the state of the transport. Possible
-			values are:
-				"idle": not streaming
-				"pending": streaming but not acquired
-				"active": streaming and acquired
-
-		uint16 Delay [readwrite]
-
-			Optional. Transport delay in 1/10 of millisecond, this
-			property is only writeable when the transport was
-			acquired by the sender.
-
-		uint16 Volume [readwrite]
-
-			Optional. Indicates volume level of the transport,
-			this property is only writeable when the transport was
-			acquired by the sender.
-
-			Possible Values: 0-127
-
-		object Endpoint [readonly, optional, experimental]
-
-			Endpoint object which the transport is associated
-			with.
-
-		uint32 Location [readonly, ISO only, experimental]
-
-			Indicates transport Audio Location.
-
-		array{byte} Metadata [ISO Only, experimental]
-
-			Indicates transport Metadata.
-
-		array{object} Links [readonly, optional, ISO only, experimental]
-
-			Linked transport objects which the transport is
-			associated with.
diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
deleted file mode 100644
index 85de670..0000000
--- a/doc/mesh-api.txt
+++ /dev/null
@@ -1,1247 +0,0 @@
-BlueZ D-Bus Mesh API description
-********************************
-
-Mesh Network Hierarchy
-======================
-Service		org.bluez.mesh
-Interface	org.bluez.mesh.Network1
-Object path	/org/bluez/mesh
-
-Methods:
-	void Join(object app_root, array{byte}[16] uuid)
-
-		This is the first method that an application has to call to
-		become a provisioned node on a mesh network. The call will
-		initiate broadcasting of Unprovisioned Device Beacon.
-
-		The app_root parameter is a D-Bus object root path of
-		the application that implements org.bluez.mesh.Application1
-		interface. The application represents a node where child mesh
-		elements have their own objects that implement
-		org.bluez.mesh.Element1 interface. The application hierarchy
-		also contains a provision agent object that implements
-		org.bluez.mesh.ProvisionAgent1 interface. The standard
-		DBus.ObjectManager interface must be available on the
-		app_root path.
-
-		The uuid parameter is a 16-byte array that contains Device UUID.
-		This UUID must be unique (at least from the daemon perspective),
-		therefore attempting to call this function using already
-		registered UUID results in an error. The composition of the UUID
-		octets must be in compliance with RFC 4122.
-
-		When provisioning finishes, the daemon will call either
-		JoinComplete or JoinFailed method on object implementing
-		org.bluez.mesh.Application1 interface.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists,
-
-	void Cancel(void)
-
-		Cancels an outstanding provisioning request initiated by Join()
-		method.
-
-	object node, array{byte, array{(uint16, dict)}} configuration
-			Attach(object app_root, uint64 token)
-
-		This is the first method that an application must call to get
-		access to mesh node functionalities.
-
-		The app_root parameter is a D-Bus object root path of
-		the application that implements org.bluez.mesh.Application1
-		interface. The application represents a node where child mesh
-		elements have their own objects that implement
-		org.bluez.mesh.Element1 interface. The standard
-		DBus.ObjectManager interface must be available on the
-		app_root path.
-
-		The token parameter is a 64-bit number that has been assigned to
-		the application when it first got provisioned/joined mesh
-		network, i.e. upon receiving JoinComplete() method. The daemon
-		uses the token to verify whether the application is authorized
-		to assume the mesh node identity.
-
-		In case of success, the method call returns mesh node object
-		(see Mesh Node Hierarchy section) and current configuration
-		settings. The return value of configuration parameter is an
-		array, where each entry is a structure that contains element
-		configuration. The element configuration structure is organized
-		as follows:
-
-		byte
-
-			Element index, identifies the element to which this
-			configuration entry pertains.
-
-		array{struct}
-
-			Models array where each entry is a structure with the
-			following members:
-
-			uint16
-
-				Either a SIG Model Identifier or, if Vendor key
-				is present in model configuration dictionary, a
-				16-bit vendor-assigned Model Identifier
-
-			dict
-
-				A dictionary that contains model configuration
-				with the following keys defined:
-
-				array{uint16} Bindings
-
-					Indices of application keys bound to the
-					model
-
-				uint32 PublicationPeriod
-
-					Model publication period in milliseconds
-
-				uint16 Vendor
-
-					A 16-bit Company ID as defined by the
-					Bluetooth SIG
-
-				array{variant} Subscriptions
-
-					Addresses the model is subscribed to.
-
-					Each address is provided either as
-					uint16 for group addresses, or
-					as array{byte} for virtual labels.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound,
-			org.bluez.mesh.Error.AlreadyExists,
-			org.bluez.mesh.Error.Busy,
-			org.bluez.mesh.Error.Failed
-
-	void Leave(uint64 token)
-
-		This removes the configuration information about the mesh node
-		identified by the 64-bit token parameter. The token parameter
-		has been obtained as a result of successful Join() method call.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound
-			org.bluez.mesh.Error.Busy
-
-	void CreateNetwork(object app_root, array{byte}[16] uuid)
-
-		This is the first method that an application calls to become
-		a Provisioner node, and a Configuration Client on a newly
-		created Mesh Network.
-
-		The app_root parameter is a D-Bus object root path of the
-		application that implements org.bluez.mesh.Application1
-		interface, and a org.bluez.mesh.Provisioner1 interface. The
-		application represents a node where child mesh elements have
-		their own objects that implement org.bluez.mesh.Element1
-		interface. The application hierarchy also contains a provision
-		agent object that implements org.bluez.mesh.ProvisionAgent1
-		interface. The standard DBus.ObjectManager interface must be
-		available on the app_root path.
-
-		The uuid parameter is a 16-byte array that contains Device UUID.
-		This UUID must be unique (at least from the daemon perspective),
-		therefore attempting to call this function using already
-		registered UUID results in an error. The composition of the UUID
-		octets must be in compliance with RFC 4122.
-
-		The other information the bluetooth-meshd daemon will preserve
-		about the initial node, is to give it the initial primary
-		unicast address (0x0001), and create and assign a net_key as the
-		primary network net_index (0x000).
-
-		Upon successful processing of Create() method, the daemon
-		will call JoinComplete method on object implementing
-		org.bluez.mesh.Application1.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists,
-
-	void Import(object app_root, array{byte}[16] uuid,
-				array{byte}[16] dev_key,
-				array{byte}[16] net_key, uint16 net_index,
-				dict flags, uint32 iv_index, uint16 unicast)
-
-		This method creates a local mesh node based on node
-		configuration that has been generated outside bluetooth-meshd.
-
-		The app_root parameter is a D-Bus object root path of the
-		application that implements org.bluez.mesh.Application1
-		interface.
-
-		The uuid parameter is a 16-byte array that contains Device UUID.
-		This UUID must be unique (at least from the daemon perspective),
-		therefore attempting to call this function using already
-		registered UUID results in an error. The composition of the UUID
-		octets must be in compliance with RFC 4122.
-
-		The dev_key parameter is the 16-byte value of the dev key of
-		the imported mesh node.
-
-		Remaining parameters correspond to provisioning data:
-
-		The net_key and net_index parameters describe the network (or a
-		subnet, if net_index is not 0) the imported mesh node belongs
-		to.
-
-		The flags parameter is a dictionary containing provisioning
-		flags. Supported values are:
-
-			boolean IvUpdate
-
-				When true, indicates that the network is in the
-				middle of IV Index Update procedure.
-
-			boolean KeyRefresh
-
-				When true, indicates that the specified net key
-				is in the middle of a key refresh procedure.
-
-		The iv_index parameter is the current IV Index value used by
-		the network. This value is known by the provisioner.
-
-		The unicast parameter is the primary unicast address of the
-		imported node.
-
-		Upon successful processing of Import() method, the daemon will
-		call JoinComplete method on object implementing
-		org.bluez.mesh.Application1 interface.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments,
-			org.bluez.mesh.Error.AlreadyExists,
-			org.bluez.mesh.Error.NotSupported,
-			org.bluez.mesh.Error.Failed
-
-Mesh Node Hierarchy
-===================
-Service		org.bluez.mesh
-Interface	org.bluez.mesh.Node1
-Object path	/org/bluez/mesh/node<uuid>
-		where <uuid> is the Device UUID passed to Join(),
-		CreateNetwork() or Import()
-
-Methods:
-	void Send(object element_path, uint16 destination, uint16 key_index,
-						dict options, array{byte} data)
-
-		This method is used to send a message originated by a local
-		model.
-
-		The element_path parameter is the object path of an element from
-		a collection of the application elements (see Mesh Application
-		Hierarchy section).
-
-		The destination parameter contains the destination address. This
-		destination must be a uint16 to a unicast address, or a well
-		known group address.
-
-		The key_index parameter determines which application key to use
-		for encrypting the message. The key_index must be valid for that
-		element, i.e., the application key must be bound to a model on
-		this element. Otherwise, org.bluez.mesh.Error.NotAuthorized will
-		be returned.
-
-		The options parameter is a dictionary with the following keys
-		defined:
-
-			bool ForceSegmented
-				Specifies whether to force sending of a short
-				message as one-segment payload. If not present,
-				the default setting is "false".
-
-		The data parameter is an outgoing message to be encypted by the
-		bluetooth-meshd daemon and sent on.
-
-		Possible errors:
-			org.bluez.mesh.Error.NotAuthorized
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound
-
-	void DevKeySend(object element_path, uint16 destination, boolean remote,
-			uint16 net_index, dict options, array{byte} data)
-
-		This method is used to send a message originated by a local
-		model encoded with the device key of the remote node.
-
-		The element_path parameter is the object path of an element from
-		a collection of the application elements (see Mesh Application
-		Hierarchy section).
-
-		The destination parameter contains the destination address. This
-		destination must be a uint16 to a unicast address, or a well
-		known group address.
-
-		The remote parameter, if true, looks up the device key by the
-		destination address in the key database to encrypt the message.
-		If remote is true, but requested key does not exist, a NotFound
-		error will be returned. If set to false, the local node's
-		device key is used.
-
-		The net_index parameter is the subnet index of the network on
-		which the message is to be sent.
-
-		The options parameter is a dictionary with the following keys
-		defined:
-
-			bool ForceSegmented
-				Specifies whether to force sending of a short
-				message as one-segment payload. If not present,
-				the default setting is "false".
-
-		The data parameter is an outgoing message to be encypted by the
-		meshd daemon and sent on.
-
-		Possible errors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound
-
-	void AddNetKey(object element_path, uint16 destination,
-			uint16 subnet_index, uint16 net_index, boolean update)
-
-		This method is used to send add or update network key originated
-		by the local configuration client to a remote configuration
-		server.
-
-		The element_path parameter is the object path of an element from
-		a collection of the application elements (see Mesh Application
-		Hierarchy section).
-
-		The destination parameter contains the destination address. This
-		destination must be a uint16 to a nodes primary unicast address.
-
-		The subnet_index parameter refers to the subnet index of the
-		network that is being added or updated. This key must exist in
-		the local key database.
-
-		The net_index parameter is the subnet index of the network on
-		which the message is to be sent.
-
-		The update parameter indicates if this is an addition or an
-		update. If true, the subnet key must be in the phase 1 state of
-		the key update procedure.
-
-		Possible errors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound
-
-	void AddAppKey(object element_path, uint16 destination,
-			uint16 app_index, uint16 net_index, boolean update)
-
-		This method is used to send add or update network key originated
-		by the local configuration client to a remote configuration
-		server.
-
-		The element_path parameter is the object path of an element from
-		a collection of the application elements (see Mesh Application
-		Hierarchy section).
-
-		The destination parameter contains the destination address. This
-		destination must be a uint16 to a nodes primary unicast address.
-
-		The app_index parameter refers to the application key which is
-		being added or updated. This key must exist in the local key
-		database.
-
-		The net_index parameter is the subnet index of the network on
-		which the message is to be sent.
-
-		The update parameter indicates if this is an addition or an
-		update. If true, the subnet key must be in the phase 1 state of
-		the key update procedure.
-
-		Possible errors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotFound
-
-	void Publish(object element_path, uint16 model, dict options,
-							array{byte} data)
-
-		This method is used to send a publication originated by a local
-		model. If the model does not exist, or it has no publication
-		record, the method returns org.bluez.mesh.Error.DoesNotExist
-		error.
-
-		The element_path parameter is the object path of an element from
-		a collection of the application elements (see Mesh Application
-		Hierarchy section).
-
-		The model parameter contains a model ID, as defined by the
-		Bluetooth SIG. If the options dictionary contains a "Vendor"
-		key, then this ID is defined by the specified vendor.
-
-		The options parameter is a dictionary with the following keys
-		defined:
-
-			bool ForceSegmented
-				Specifies whether to force sending of a short
-				message as one-segment payload. If not present,
-				the default setting is "false".
-
-			uint16 Vendor
-				A 16-bit Company ID as defined by the
-				Bluetooth SIG. This key should only exist when
-				publishing on a Vendor defined model.
-
-		The data parameter is an outgoing message to be encypted by the
-		meshd daemon and sent on.
-
-		Since only one Publish record may exist per element-model, the
-		destination and key_index are obtained from the Publication
-		record cached by the daemon.
-
-		Possible errors:
-			org.bluez.mesh.Error.DoesNotExist
-			org.bluez.mesh.Error.InvalidArguments
-
-
-Properties:
-	dict Features [read-only]
-
-		The dictionary that contains information about feature support.
-		The following keys are defined:
-
-		boolean Friend
-
-			Indicates the ability to establish a friendship with a
-			Low Power node
-
-		boolean LowPower
-
-			Indicates support for operating in Low Power node mode
-
-		boolean Proxy
-
-			Indicates support for GATT proxy
-
-		boolean Relay
-			Indicates support for relaying messages
-
-	If a key is absent from the dictionary, the feature is not supported.
-	Otherwise, true means that the feature is enabled and false means that
-	the feature is disabled.
-
-	boolean Beacon [read-only]
-
-		This property indicates whether the periodic beaconing is
-		enabled (true) or disabled (false).
-
-	boolean IvUpdate [read-only]
-
-		When true, indicates that the network is in the middle of IV
-		Index Update procedure. This information is only useful for
-		provisioning.
-
-	uint32 IvIndex [read-only]
-
-		This property may be read at any time to determine the IV_Index
-		that the current network is on. This information is only useful
-		for provisioning.
-
-	uint32 SecondsSinceLastHeard [read-only]
-
-		This property may be read at any time to determine the number of
-		seconds since mesh network layer traffic was last detected on
-		this node's network.
-
-	array{uint16} Addresses [read-only]
-
-		This property contains unicast addresses of node's elements.
-
-	uint32 SequenceNumber [read-only]
-
-		This property may be read at any time to determine the
-		sequence number.
-
-Mesh Provisioning Hierarchy
-============================
-Service		org.bluez.mesh
-Interface	org.bluez.mesh.Management1
-Object path	/org/bluez/mesh/node<uuid>
-		where <uuid> is the Device UUID passed to Join(),
-		CreateNetwork() or Import()
-
-Methods:
-	void UnprovisionedScan(dict options)
-
-		This method is used by the application that supports
-		org.bluez.mesh.Provisioner1 interface to start listening
-		(scanning) for unprovisioned devices in the area.
-
-		The options parameter is a dictionary with the following keys
-		defined:
-
-		uint16 Seconds
-			Specifies number of seconds for scanning to be active.
-			If set to 0 or if this key is not present, then the
-			scanning will continue until UnprovisionedScanCancel()
-			or AddNode() methods are called.
-
-		Each time a unique unprovisioned beacon is heard, the
-		ScanResult() method on the app will be called with the result.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotAuthorized
-			org.bluez.mesh.Error.Busy
-
-	void UnprovisionedScanCancel(void)
-
-		This method is used by the application that supports
-		org.bluez.mesh.Provisioner1 interface to stop listening
-		(scanning) for unprovisioned devices in the area.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotAuthorized
-
-	void AddNode(array{byte}[16] uuid, dict options)
-
-		This method is used by the application that supports
-		org.bluez.mesh.Provisioner1 interface to add the
-		unprovisioned device specified by uuid, to the Network.
-
-		The uuid parameter is a 16-byte array that contains Device UUID
-		of the unprovisioned device to be added to the network.
-
-		The options parameter is a dictionary that may contain
-		additional configuration info (currently an empty placeholder
-		for forward compatibility).
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.NotAuthorized
-
-	void CreateSubnet(uint16 net_index)
-
-		This method is used by the application to generate and add a new
-		network subnet key.
-
-		The net_index parameter is a 12-bit value (0x001-0xFFF)
-		specifying which net key to add.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists
-
-	void ImportSubnet(uint16 net_index, array{byte}[16] net_key)
-
-		This method is used by the application to add a network subnet
-		key, that was originally generated by a remote Config Client.
-
-		The net_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which net key to add.
-
-		The net_key parameter is the 16-byte value of the net key being
-		imported.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists
-
-	void UpdateSubnet(uint16 net_index)
-
-		This method is used by the application to generate a new network
-		subnet key, and set it's key refresh state to Phase 1.
-
-		The net_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which net key to update. Note that the subnet must
-		exist prior to updating.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.DoesNotExist
-			org.bluez.mesh.Error.Busy
-
-	void DeleteSubnet(uint16 net_index)
-
-		This method is used by the application that to delete a subnet.
-
-		The net_index parameter is a 12-bit value (0x001-0xFFF)
-		specifying which net key to delete. The primary net key (0x000)
-		may not be deleted.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-
-	void SetKeyPhase(uint16 net_index, uint8 phase)
-		This method is used to set the flooding key update phase of the
-		given subnet. When finalizing the procedure, it is important
-		to CompleteAppKeyUpdate() on all app keys that have been
-		updated during the procedure prior to setting phase 3.
-
-		The net_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which subnet phase to set.
-
-		The phase parameter is used to cycle the local key database
-		through the phases as defined by the Mesh Profile Specification.
-		Allowed values:
-			0 - Cancel Key Refresh (May only be called from Phase 1,
-				and should never be called once the new key has
-				started propagating)
-			1 - Invalid Argument (see NetKeyUpdate method)
-			2 - Go to Phase 2 (May only be called from Phase 1)
-			3 - Complete Key Refresh procedure (May only be called
-				from Phase 2)
-
-		This call affects the local bluetooth-meshd key database only.
-		It is the responsibility of the application to maintain the key
-		refresh phases per the Mesh Profile Specification.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.DoesNotExist
-
-	void CreateAppKey(uint16 net_index, uint16 app_index)
-
-		This method is used by the application to generate and add a new
-		application key.
-
-		The net_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which net key to bind the application key to.
-
-		The app_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which app key to add.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists
-			org.bluez.mesh.Error.DoesNotExist
-
-	void ImportAppKey(uint16 net_index, uint16 app_index,
-						array{byte}[16] app_key)
-
-		This method is used by the application to add an application
-		key, that was originally generated by a remote Config Client.
-
-		The net_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which net key to bind the application key to.
-
-		The app_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which app key to import.
-
-		The app_key parameter is the 16-byte value of the key being
-		imported.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.AlreadyExists
-			org.bluez.mesh.Error.DoesNotExist
-
-	void UpdateAppKey(uint16 app_index)
-
-		This method is used by the application to generate a new
-		application key.
-
-		The app_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which app key to update. Note that the subnet that
-		the key is bound to must exist and be in Phase 1.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-			org.bluez.mesh.Error.DoesNotExist
-			org.bluez.mesh.Error.InProgress
-
-	void DeleteAppKey(uint16 app_index)
-
-		This method is used by the application to delete an application
-		key.
-
-		The app_index parameter is a 12-bit value (0x000-0xFFF)
-		specifying which app key to delete.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-
-	void ImportRemoteNode(uint16 primary, uint8 count,
-					array{byte}[16] device_key)
-
-		This method is used by the application to import a remote node
-		that has been provisioned by an external process.
-
-		The primary parameter specifies the unicast address of the
-		the node being imported.
-
-		The count parameter specifies the number of elements that are
-		assigned to this remote node.
-
-		The device_key parameter is the access layer key that will be
-		will used to decrypt privledged messages from this remote node.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		It is an error to call this with address range overlapping
-		with local element addresses.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Failed
-			org.bluez.mesh.Error.InvalidArguments
-
-	void DeleteRemoteNode(uint16 primary, uint8 count)
-
-		This method is used by the application to delete a remote node
-		from the local device key database.
-
-		The primary parameter specifies the unicast address of the
-		the node being deleted.
-
-		The count parameter specifies the number of elements that were
-		assigned to the remote node.
-
-		This call affects the local bluetooth-meshd key database only.
-
-		It is an error to call this with address range overlapping
-		with local element addresses.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.InvalidArguments
-
-	dict ExportKeys(void)
-
-		This method is used by the application to export information
-		about network keys, application keys and device keys present
-		in the local key database.
-
-		dict
-			A dictionary that contains information for the keys
-			stored in the keyring with the following keys defined:
-
-			NetKeys:
-				array{struct} net_keys:
-
-				uint16 index
-					Subnet index
-
-				array{byte}[16] key
-
-				dict:
-					A dictionary that contains optional
-					key info with the following keys
-					defined:
-
-					uint8 Phase
-						Key Refresh phase of the subnet
-
-					array{byte}[16] OldKey
-
-					array{struct} AppKeys:
-
-						uint16 index
-
-							Application key index
-
-						array{byte}[16] key
-
-						dict:
-							A dictionary of optional
-							key info with the
-							following keys defined:
-
-							array{byte}[16] OldKey
-
-			DevKeys:
-				array{struct} dev_keys:
-
-				Device Key information for known remote
-				nodes in the configured Mesh network
-
-				uint16 unicast
-
-					Unicast address of the node's primary
-					element
-
-				array{byte}[16] key
-
-Mesh Application Hierarchy
-==========================
-Service		unique name
-Interface	org.bluez.mesh.Application1
-Object path	<app_root>
-
-An application is a collection of elements that host SIG defined and vendor
-specific models. It is expected that an application implements
-org.freedesktop.DBus.ObjectManager interface at app_root path.
-
-An example mesh application hierarchy may look like this:
-
--> /com/example
-  |   - org.freedesktop.DBus.ObjectManager
-  |
-  -> /com/example/application
-  |   - org.bluez.mesh.Application1
-  |   - org.bluez.mesh.Attention1 (optional)
-  |   - org.bluez.mesh.Provisioner1 (optional,Provisioner)
-  |
-  -> /com/example/agent
-  |   - org.bluez.mesh.ProvisionAgent1
-  |
-  -> /com/example/ele00
-  |   - org.bluez.mesh.Element1
-  |
-  -> /com/example/ele01
-  |   - org.bluez.mesh.Element1
-  |
-  ...
-  -> /com/example/elexx
-      - org.bluez.mesh.Element1
-
-Methods:
-	void JoinComplete(uint64 token)
-
-		This method is called when the node provisioning initiated
-		by a Join() method call successfully completed.
-
-		The token parameter serves as a unique identifier of the
-		particular node. The token must be preserved by the application
-		in order to authenticate itself to the mesh daemon and attach to
-		the network as a mesh node by calling Attach() method or
-		permanently remove the identity of the mesh node by calling
-		Leave() method.
-
-		If this method returns an error, the daemon will assume that the
-		application failed to preserve the token, and will remove the
-		freshly created node.
-
-	void JoinFailed(string reason)
-
-		This method is called when the node provisioning initiated by
-		Join() has failed.
-
-		The reason parameter identifies the reason for provisioning
-		failure. The defined values are: "timeout", "bad-pdu",
-		"confirmation-failed", "out-of-resources", "decryption-error",
-		"unexpected-error", "cannot-assign-addresses".
-
-Properties:
-	uint16 CompanyID [read-only]
-
-		A 16-bit Bluetooth-assigned Company Identifier of the vendor as
-		defined by Bluetooth SIG
-
-	uint16 ProductID [read-only]
-
-		A 16-bit vendor-assigned product identifier
-
-	uint16 VersionID [read-only]
-
-		A 16-bit vendor-assigned product version identifier
-
-	uint16 CRPL [read-only, optional]
-
-		A 16-bit minimum number of replay protection list entries
-
-
-Mesh Element Hierarchy
-======================
-Service		unique name
-Interface	org.bluez.mesh.Element1
-Object path	<app_defined_element_path>
-
-Methods:
-	void MessageReceived(uint16 source, uint16 key_index,
-					variant destination, array{byte} data)
-
-		This method is called by bluetooth-meshd daemon when a message
-		arrives addressed to the application.
-
-		The source parameter is unicast address of the remote
-		node-element that sent the message.
-
-		The key_index parameter indicates which application key has been
-		used to decode the incoming message. The same key_index should
-		be used by the application when sending a response to this
-		message (in case a response is expected).
-
-		The destination parameter contains the destination address of
-		received message. Underlying variant types are:
-
-		uint16
-
-			Destination is an unicast address, or a well known
-			group address
-
-		array{byte}
-
-			Destination is a virtual address label
-
-		The data parameter is the incoming message.
-
-	void DevKeyMessageReceived(uint16 source, boolean remote,
-					uint16 net_index, array{byte} data)
-
-		This method is called by meshd daemon when a message arrives
-		addressed to the application, which was sent with the remote
-		node's device key.
-
-		The source parameter is unicast address of the remote
-		node-element that sent the message.
-
-		The remote parameter if true indicates that the device key
-		used to decrypt the message was from the sender. False
-		indicates that the local nodes device key was used, and the
-		message has permissions to modify local states.
-
-		The net_index parameter indicates what subnet the message was
-		received on, and if a response is required, the same subnet
-		must be used to send the response.
-
-		The data parameter is the incoming message.
-
-	void UpdateModelConfiguration(uint16 model_id, dict config)
-
-		This method is called by bluetooth-meshd daemon when a model's
-		configuration is updated.
-
-		The model_id parameter contains BT SIG Model Identifier or, if
-		Vendor key is present in config dictionary, a 16-bit
-		vendor-assigned Model Identifier.
-
-		The config parameter is a dictionary with the following keys
-		defined:
-
-		array{uint16} Bindings
-
-			Indices of application keys bound to the model
-
-		uint32 PublicationPeriod
-
-			Model publication period in milliseconds
-
-		uint16 Vendor
-
-			A 16-bit Bluetooth-assigned Company Identifier of the
-			vendor as defined by Bluetooth SIG
-
-		array{variant} Subscriptions
-
-			Addresses the model is subscribed to.
-
-			Each address is provided either as uint16 for group
-			addresses, or as array{byte} for virtual labels.
-
-Properties:
-	uint8 Index [read-only]
-
-		Element index. It is required that the application follows
-		sequential numbering scheme for the elements, starting with 0.
-
-	array{(uint16 id, dict caps)} Models [read-only]
-
-		An array of SIG Models:
-
-			id - SIG Model Identifier
-
-			options - a dictionary that may contain additional model
-			info. The following keys are defined:
-
-				boolean Publish - indicates whether the model
-					supports publication mechanism. If not
-					present, publication is enabled.
-
-				boolean Subscribe - indicates whether the model
-					supports subscription mechanism. If not
-					present, subscriptons are enabled.
-
-		The array may be empty.
-
-
-	array{(uint16 vendor, uint16 id, dict options)} VendorModels [read-only]
-
-		An array of Vendor Models:
-
-			vendor - a 16-bit Bluetooth-assigned Company ID as
-			defined by Bluetooth SIG.
-
-			id - a 16-bit vendor-assigned Model Identifier
-
-			options - a dictionary that may contain additional model
-			info. The following keys are defined:
-
-				boolean Publish - indicates whether the model
-					supports publication mechanism
-
-				boolean Subscribe - indicates whether the model
-					supports subscription mechanism
-
-		The array may be empty.
-
-	uint16 Location [read-only, optional]
-
-		Location descriptor as defined in the GATT Bluetooth Namespace
-		Descriptors section of the Bluetooth SIG Assigned Numbers
-
-
-Mesh Attention Hierarchy
-========================
-Service		unique name
-Interface	org.bluez.mesh.Attention1
-Object path	freely definable
-
-This is an optional interface that implements health attention timer.
-
-Methods:
-	void SetTimer(uint8 element_index, uint16 time)
-
-		The element_index parameter is the element's index within the
-		node where the health server model is hosted.
-
-		The time parameter indicates how many seconds the attention
-		state shall be on.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.NotSupported
-
-	uint16 GetTimer(uint16 element)
-
-		The element parameter is the unicast address within the node
-		where the health server model is hosted.
-
-		Returns the number of seconds for how long the attention action
-		remains staying on.
-
-		PossibleErrors:
-			org.bluez.mesh.Error.NotSupported
-
-
-Mesh Provisioner Hierarchy
-============================
-Service		unique name
-Interface	org.bluez.mesh.Provisioner1
-Object path	freely definable
-
-	void ScanResult(int16 rssi, array{byte} data, dict options)
-
-		The method is called from the bluetooth-meshd daemon when a
-		unique UUID has been seen during UnprovisionedScan() for
-		unprovsioned devices.
-
-		The rssi parameter is a signed, normalized measurement of the
-		signal strength of the recieved unprovisioned beacon.
-
-		The data parameter is a variable length byte array, that may
-		have 1, 2 or 3 distinct fields contained in it including the 16
-		byte remote device UUID (always), a 16 bit mask of OOB
-		authentication flags (optional), and a 32 bit URI hash (if URI
-		bit set in OOB mask). Whether these fields exist or not is a
-		decision of the remote device.
-
-		The options parameter is a dictionary that may contain
-		additional scan result info (currently an empty placeholder for
-		forward compatibility).
-
-		If a beacon with a UUID that has already been reported is
-		recieved by the daemon, it will be silently discarded unless it
-		was recieved at a higher rssi power level.
-
-
-	uint16 net_index, uint16 unicast RequestProvData(uint8 count)
-
-		This method is implemented by a Provisioner capable application
-		and is called when the remote device has been fully
-		authenticated and confirmed.
-
-		The count parameter is the number of consecutive unicast
-		addresses the remote device is requesting.
-
-		Return Parameters are from the Mesh Profile Spec:
-		net_index - Subnet index of the net_key
-		unicast - Primary Unicast address of the new node
-
-		PossibleErrors:
-			org.bluez.mesh.Error.Abort
-
-	void AddNodeComplete(array{byte}[16] uuid, uint16 unicast, uint8 count)
-
-		This method is called when the node provisioning initiated
-		by an AddNode() method call successfully completed.
-
-		The unicast parameter is the primary address that has been
-		assigned to the new node, and the address of it's config server.
-
-		The count parameter is the number of unicast addresses assigned
-		to the new node.
-
-		The new node may now be sent messages using the credentials
-		supplied by the RequestProvData method.
-
-	void AddNodeFailed(array{byte}[16] uuid, string reason)
-
-		This method is called when the node provisioning initiated by
-		AddNode() has failed. Depending on how far Provisioning
-		proceeded before failing, some cleanup of cached data may be
-		required.
-
-		The reason parameter identifies the reason for provisioning
-		failure. The defined values are: "aborted", "timeout",
-		"bad-pdu", "confirmation-failed", "out-of-resources",
-		"decryption-error", "unexpected-error",
-		"cannot-assign-addresses".
-
-Provisioning Agent Hierarchy
-============================
-Service		unique name
-Interface	org.bluez.mesh.ProvisionAgent1
-Object path	freely definable
-
-Methods:
-	array{byte} PrivateKey()
-
-		This method is called during provisioning if the Provisioner
-		has requested Out-Of-Band ECC key exchange. The Private key is
-		returned to the Daemon, and the Public Key is delivered to the
-		remote Provisioner using a method that does not involve the
-		Bluetooth Mesh system. The Private Key returned must be 32
-		octets in size, or the Provisioning procedure will fail and be
-		canceled.
-
-		This function will only be called if the Provisioner has
-		requested pre-determined keys to be exchanged Out-of-Band, and
-		the local role is Unprovisioned device.
-
-	array{byte} PublicKey()
-
-		This method is called during provisioning if the local device is
-		the Provisioner, and is requestng Out-Of-Band ECC key exchange.
-		The Public key is returned to the Daemon that is the matched
-		pair of the Private key of the remote device. The Public Key
-		returned must be 64 octets in size, or the Provisioning
-		procedure will fail and be canceled.
-
-		This function will only be called if the Provisioner has
-		requested pre-determined keys to be exchanged Out-of-Band, and
-		the local role is Provisioner.
-
-	void DisplayString(string value)
-
-		This method is called when the Daemon has something important
-		for the Agent to Display, but does not require any additional
-		input locally. For instance: "Enter "ABCDE" on remote device".
-
-	void DisplayNumeric(string type, uint32 number)
-
-		This method is called when the Daemon has something important
-		for the Agent to Display, but does not require any additional
-		input locally. For instance: "Enter 14939264 on remote device".
-
-		The type parameter indicates the display method. Allowed values
-		are:
-			"blink" - Locally blink LED
-			"beep" - Locally make a noise
-			"vibrate" - Locally vibrate
-			"out-numeric" - Display value to enter remotely
-			"push" - Request pushes on remote button
-			"twist" - Request twists on remote knob
-
-		The number parameter is the specific value represented by the
-		Prompt.
-
-	uint32 PromptNumeric(string type)
-
-		This method is called when the Daemon requests the user to
-		enter a decimal value between 1-99999999.
-
-		The type parameter indicates the input method. Allowed values
-		are:
-			"blink" - Enter times remote LED blinked
-			"beep" - Enter times remote device beeped
-			"vibrate" - Enter times remote device vibrated
-			"in-numeric" - Enter remotely displayed value
-			"push" - Push local button remotely requested times
-			"twist" - Twist local knob remotely requested times
-
-
-		This agent should prompt the user for specific input. For
-		instance: "Enter value being displayed by remote device".
-
-	array{byte}[16] PromptStatic(string type)
-
-		This method is called when the Daemon requires a 16 octet byte
-		array, as an Out-of-Band authentication.
-
-		The type parameter indicates the input method. Allowed values
-		are:
-			"static-oob" - return 16 octet array
-			"in-alpha" - return 16 octet alpha array
-
-		The Static data returned must be 16 octets in size, or the
-		Provisioning procedure will fail and be canceled. If input type
-		is "in-alpha", the printable characters should be
-		left-justified, with trailing 0x00 octets filling the remaining
-		bytes.
-
-	void Cancel()
-
-		This method gets called by the daemon to cancel any existing
-		Agent Requests. When called, any pending user input should be
-		canceled, and any display requests removed.
-
-
-Properties:
-	array{string} Capabilities [read-only]
-
-		An array of strings with the following allowed values:
-			"blink"
-			"beep"
-			"vibrate"
-			"out-numeric"
-			"out-alpha"
-			"push"
-			"twist"
-			"in-numeric"
-			"in-alpha"
-			"static-oob"
-			"public-oob"
-
-	array{string} OutOfBandInfo [read-only, optional]
-
-		Indicates availability of OOB data. An array of strings with the
-		following allowed values:
-			"other"
-			"uri"
-			"machine-code-2d"
-			"bar-code"
-			"nfc"
-			"number"
-			"string"
-			"on-box"
-			"in-box"
-			"on-paper",
-			"in-manual"
-			"on-device"
-
-	string URI [read-only, optional]
-
-		Uniform Resource Identifier points to out-of-band (OOB)
-		information (e.g., a public key)
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 90d612e..59e61d3 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -332,7 +332,10 @@ Read Controller Information Command
 		15	Static Address
 		16	PHY Configuration
 		17	Wideband Speech
-		18	Quality Report
+		18	Connected Isochronous Stream - Central
+		19	Connected Isochronous Stream - Peripheral
+		20	Isochronous Broadcaster
+		21	Synchronized Receiver
 
 	This command generates a Command Complete event on success or
 	a Command Status event on failure.
@@ -2925,7 +2928,8 @@ Read Extended Controller Information Command
 		15	Static Address
 		16	PHY Configuration
 		17	Wideband Speech
-		18	Quality Report
+		18	Connected Isochronous Stream - Central
+		19	Connected Isochronous Stream - Peripheral
 
 	The EIR_Data field contains information about class of device,
 	local name and other values. Not all of them might be present. For
@@ -4395,6 +4399,7 @@ Device Found Event
 		2	Not Connectable
 		3	Reserved (not in use)
 		4	Name Request Failed
+		5	Scan Response
 
 	For the RSSI field a value of 127 indicates that the RSSI is
 	not available. That can happen with Bluetooth 1.1 and earlier
diff --git a/doc/network-api.txt b/doc/network-api.txt
deleted file mode 100644
index 109da28..0000000
--- a/doc/network-api.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-BlueZ D-Bus Network API description
-***********************************
-
-
-Network hierarchy
-=================
-
-Service		org.bluez
-Interface	org.bluez.Network1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Methods		string Connect(string uuid)
-
-			Connect to the network device and return the network
-			interface name. Examples of the interface name are
-			bnep0, bnep1 etc.
-
-			uuid can be either one of "gn", "panu" or "nap" (case
-			insensitive) or a traditional string representation of
-			UUID or a hexadecimal number.
-
-			The connection will be closed and network device
-			released either upon calling Disconnect() or when
-			the client disappears from the message bus.
-
-			Possible errors: org.bluez.Error.AlreadyConnected
-					 org.bluez.Error.ConnectionAttemptFailed
-
-		void Disconnect()
-
-			Disconnect from the network device.
-
-			To abort a connection attempt in case of errors or
-			timeouts in the client it is fine to call this method.
-
-			Possible errors: org.bluez.Error.Failed
-
-Properties	boolean Connected [readonly]
-
-			Indicates if the device is connected.
-
-		string Interface [readonly]
-
-			Indicates the network interface name when available.
-
-		string UUID [readonly]
-
-			Indicates the connection role when available.
-
-
-Network server hierarchy
-========================
-
-Service		org.bluez
-Interface	org.bluez.NetworkServer1
-Object path	/org/bluez/{hci0,hci1,...}
-
-Methods		void Register(string uuid, string bridge)
-
-			Register server for the provided UUID. Every new
-			connection to this server will be added the bridge
-			interface.
-
-			Valid UUIDs are "gn", "panu" or "nap".
-
-			Initially no network server SDP is provided. Only
-			after this method a SDP record will be available
-			and the BNEP server will be ready for incoming
-			connections.
-
-		void Unregister(string uuid)
-
-			Unregister the server for provided UUID.
-
-			All servers will be automatically unregistered when
-			the calling application terminates.
diff --git a/doc/obex-agent-api.txt b/doc/obex-agent-api.txt
deleted file mode 100644
index 3923da6..0000000
--- a/doc/obex-agent-api.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-OBEX D-Bus Agent API description
-********************************
-
-
-Agent Manager hierarchy
-=======================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.AgentManager1
-Object path	/org/bluez/obex
-
-Methods		void RegisterAgent(object agent)
-
-			Register an agent to request authorization of
-			the user to accept/reject objects. Object push
-			service needs to authorize each received object.
-
-			Possible errors: org.bluez.obex.Error.AlreadyExists
-
-		void UnregisterAgent(object agent)
-
-			This unregisters the agent that has been previously
-			registered. The object path parameter must match the
-			same value that has been used on registration.
-
-			Possible errors: org.bluez.obex.Error.DoesNotExist
-
-
-Agent hierarchy
-===============
-
-Service		unique name
-Interface	org.bluez.obex.Agent1
-Object path	freely definable
-
-Methods		void Release()
-
-			This method gets called when the service daemon
-			unregisters the agent. An agent can use it to do
-			cleanup tasks. There is no need to unregister the
-			agent, because when this method gets called it has
-			already been unregistered.
-
-		string AuthorizePush(object transfer)
-
-			This method gets called when the service daemon
-			needs to accept/reject a Bluetooth object push request.
-
-			Returns the full path (including the filename) where
-			the object shall be stored. The tranfer object will
-			contain a Filename property that contains the default
-			location and name that can be returned.
-
-			Possible errors: org.bluez.obex.Error.Rejected
-			                 org.bluez.obex.Error.Canceled
-
-		void Cancel()
-
-			This method gets called to indicate that the agent
-			request failed before a reply was returned. It cancels
-			the previous request.
diff --git a/doc/obex-api.txt b/doc/obex-api.txt
deleted file mode 100644
index f39355a..0000000
--- a/doc/obex-api.txt
+++ /dev/null
@@ -1,894 +0,0 @@
-OBEX D-Bus API description
-**************************
-
-
-Client hierarchy
-================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.Client1
-Object path	/org/bluez/obex
-
-Methods		object CreateSession(string destination, dict args)
-
-			Create a new OBEX session for the given remote address.
-
-			The last parameter is a dictionary to hold optional or
-			type-specific parameters. Typical parameters that can
-			be set in this dictionary include the following:
-
-				string "Target" : type of session to be created
-				string "Source" : local address to be used
-				byte "Channel"
-
-			The currently supported targets are the following:
-
-				"ftp"
-				"map"
-				"opp"
-				"pbap"
-				"sync"
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void RemoveSession(object session)
-
-			Unregister session and abort pending transfers.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.NotAuthorized
-
-Session hierarchy
-=================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.Session1
-Object path	/org/bluez/obex/server/session{0, 1, 2, ...} or
-		/org/bluez/obex/client/session{0, 1, 2, ...}
-
-Methods		string GetCapabilities()
-
-			Get remote device capabilities.
-
-			Possible errors: org.bluez.obex.Error.NotSupported
-					 org.bluez.obex.Error.Failed
-
-Properties	string Source [readonly]
-
-			Bluetooth adapter address
-
-		string Destination [readonly]
-
-			Bluetooth device address
-
-		byte Channel [readonly]
-
-			Bluetooth channel
-
-		string Target [readonly]
-
-			Target UUID
-
-		string Root [readonly]
-
-			Root path
-
-
-Transfer hierarchy
-==================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.Transfer1
-Object path	[Session object path]/transfer{0, 1, 2, ...}
-
-Methods		void Cancel()
-
-			Stops the current transference.
-
-			Possible errors: org.bluez.obex.Error.NotAuthorized
-					 org.bluez.obex.Error.InProgress
-					 org.bluez.obex.Error.Failed
-
-		void Suspend()
-
-			Suspend transference.
-
-			Possible errors: org.bluez.obex.Error.NotAuthorized
-					 org.bluez.obex.Error.NotInProgress
-
-			Note that it is not possible to suspend transfers
-			which are queued which is why NotInProgress is listed
-			as possible error.
-
-		void Resume()
-
-			Resume transference.
-
-			Possible errors: org.bluez.obex.Error.NotAuthorized
-					 org.bluez.obex.Error.NotInProgress
-
-			Note that it is not possible to resume transfers
-			which are queued which is why NotInProgress is listed
-			as possible error.
-
-Properties	string Status [readonly]
-
-			Inform the current status of the transfer.
-
-			Possible values: "queued", "active", "suspended",
-					"complete" or "error"
-
-		object Session [readonly]
-
-			The object path of the session the transfer belongs
-			to.
-
-		string Name [readonly]
-
-			Name of the transferred object. Either Name or Type
-			or both will be present.
-
-		string Type [readonly]
-
-			Type of the transferred object. Either Name or Type
-			or both will be present.
-
-		uint64 Time [readonly, optional]
-
-			Time of the transferred object if this is
-			provided by the remote party.
-
-		uint64 Size [readonly, optional]
-
-			Size of the transferred object. If the size is
-			unknown, then this property will not be present.
-
-		uint64 Transferred [readonly, optional]
-
-			Number of bytes transferred. For queued transfers, this
-			value will not be present.
-
-		string Filename [readonly, optional]
-
-			Complete name of the file being received or sent.
-
-			For incoming object push transaction, this will be
-			the proposed default location and name. It can be
-			overwritten by the AuthorizePush agent callback
-			and will be then updated accordingly.
-
-
-Object Push hierarchy
-=====================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.ObjectPush1
-Object path	[Session object path]
-
-Methods		object, dict SendFile(string sourcefile)
-
-			Send one local file to the remote device.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		object, dict PullBusinessCard(string targetfile)
-
-			Request the business card from a remote device and
-			store it in the local file.
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		object, dict ExchangeBusinessCards(string clientfile,
-							string targetfile)
-
-			Push the client's business card to the remote device
-			and then retrieve the remote business card and store
-			it in a local file.
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-
-File Transfer hierarchy
-=======================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.FileTransfer
-Object path	[Session object path]
-
-Methods		void ChangeFolder(string folder)
-
-			Change the current folder of the remote device.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void CreateFolder(string folder)
-
-			Create a new folder in the remote device.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		array{dict} ListFolder()
-
-			Returns a dictionary containing information about
-			the current folder content.
-
-			The following keys are defined:
-
-				string Name : Object name in UTF-8 format
-				string Type : Either "folder" or "file"
-				uint64 Size : Object size or number of items in
-						folder
-				string Permission : Group, owner and other
-							permission
-				uint64 Modified : Last change
-				uint64 Accessed : Last access
-				uint64 Created : Creation date
-
-			Possible errors: org.bluez.obex.Error.Failed
-
-		object, dict GetFile(string targetfile, string sourcefile)
-
-			Copy the source file (from remote device) to the
-			target file (on local filesystem).
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		object, dict PutFile(string sourcefile, string targetfile)
-
-			Copy the source file (from local filesystem) to the
-			target file (on remote device).
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void CopyFile(string sourcefile, string targetfile)
-
-			Copy a file within the remote device from source file
-			to target file.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void MoveFile(string sourcefile, string targetfile)
-
-			Move a file within the remote device from source file
-			to the target file.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void Delete(string file)
-
-			Deletes the specified file/folder.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-
-Phonebook Access hierarchy
-==========================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.PhonebookAccess1
-Object path	[Session object path]
-
-Methods		void Select(string location, string phonebook)
-
-			Select the phonebook object for other operations. Should
-			be call before all the other operations.
-
-			location : Where the phonebook is stored, possible
-			inputs :
-				"int" ( "internal" which is default )
-				"sim" ( "sim1" )
-				"sim2"
-				...
-
-			phonebook : Possible inputs :
-				"pb" :	phonebook for the saved contacts
-				"ich":	incoming call history
-				"och":	outgoing call history
-				"mch":	missing call history
-				"cch":	combination of ich och mch
-				"spd":	speed dials entry ( only for "internal" )
-				"fav":	favorites entry ( only for "internal" )
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		object, dict PullAll(string targetfile, dict filters)
-
-			Return the entire phonebook object from the PSE server
-			in plain string with vcard format, and store it in
-			a local file.
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible filters: Format, Order, Offset, MaxCount and
-			Fields
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					org.bluez.obex.Forbidden
-
-		array{string vcard, string name} List(dict filters)
-
-			Return an array of vcard-listing data where every entry
-			consists of a pair of strings containing the vcard
-			handle and the contact name. For example:
-				"1.vcf" : "John"
-
-			Possible filters: Order, Offset and MaxCount
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Forbidden
-
-		object, dict
-		Pull(string vcard, string targetfile, dict filters)
-
-			Given a vcard handle, retrieve the vcard in the current
-			phonebook object and store it in a local file.
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possbile filters: Format and Fields
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Forbidden
-					 org.bluez.obex.Error.Failed
-
-		array{string vcard, string name}
-		Search(string field, string value, dict filters)
-
-			Search for entries matching the given condition and
-			return an array of vcard-listing data where every entry
-			consists of a pair of strings containing the vcard
-			handle and the contact name.
-
-			vcard : name paired string match the search condition.
-
-			field : the field in the vcard to search with
-				{ "name" (default) | "number" | "sound" }
-			value : the string value to search for
-
-
-			Possible filters: Order, Offset and MaxCount
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Forbidden
-					 org.bluez.obex.Error.Failed
-
-		uint16 GetSize()
-
-			Return the number of entries in the selected phonebook
-			object that are actually used (i.e. indexes that
-			correspond to non-NULL entries).
-
-			Possible errors: org.bluez.obex.Error.Forbidden
-					 org.bluez.obex.Error.Failed
-
-		void UpdateVersion()
-
-			Attempt to update PrimaryCounter and SecondaryCounter.
-
-			Possible errors: org.bluez.obex.Error.NotSupported
-					 org.bluez.obex.Error.Forbidden
-					 org.bluez.obex.Error.Failed
-
-		array{string} ListFilterFields()
-
-			Return All Available fields that can be used in Fields
-			filter.
-
-			Possible errors: None
-
-Filter:		string Format:
-
-			Items vcard format
-
-			Possible values: "vcard21" (default) or "vcard30"
-
-		string Order:
-
-			Items order
-
-			Possible values: "indexed" (default), "alphanumeric" or
-			"phonetic"
-
-		uint16 Offset:
-
-			Offset of the first item, default is 0
-
-		uint16 MaxCount:
-
-			Maximum number of items, default is unlimited (65535)
-
-		array{string} Fields:
-
-			Item vcard fields, default is all values.
-
-			Possible values can be query with ListFilterFields.
-
-		array{string} FilterAll:
-
-			Filter items by fields using AND logic, cannot be used
-			together with FilterAny.
-
-			Possible values can be query with ListFilterFields.
-
-		array{string} FilterAny:
-
-			Filter items by fields using OR logic, cannot be used
-			together with FilterAll.
-
-			Possible values can be query with ListFilterFields.
-
-		bool ResetNewMissedCalls
-
-			Reset new the missed calls items, shall only be used
-			for folders mch and cch.
-
-Properties	string Folder [readonly]
-
-			Current folder.
-
-		string DatabaseIdentifier [readonly, optional]
-
-			128 bits persistent database identifier.
-
-			Possible values: 32-character hexadecimal such
-			as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
-
-		string PrimaryCounter [readonly, optional]
-
-			128 bits primary version counter.
-
-			Possible values: 32-character hexadecimal such
-			as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
-
-		string SecondaryCounter [readonly, optional]
-
-			128 bits secondary version counter.
-
-			Possible values: 32-character hexadecimal such
-			as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
-
-		bool FixedImageSize [readonly, optional]
-
-			Indicate support for fixed image size.
-
-			Possible values: True if image is JPEG 300x300 pixels
-			otherwise False.
-
-Synchronization hierarchy
-=========================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.Synchronization1
-Object path	[Session object path]
-
-Methods		void SetLocation(string location)
-
-			Set the phonebook object store location for other
-			operations. Should be called before all the other
-			operations.
-
-			location: Where the phonebook is stored, possible
-			values:
-				"int" ( "internal" which is default )
-				"sim1"
-				"sim2"
-				......
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-
-		object, dict GetPhonebook(string targetfile)
-
-			Retrieve an entire Phonebook Object store from remote
-			device, and stores it in a local file.
-
-			If an empty target file is given, a name will be
-			automatically calculated for the temporary file.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		object, dict PutPhonebook(string sourcefile)
-
-			Send an entire Phonebook Object store to remote device.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-
-Message Access hierarchy
-=========================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.MessageAccess1
-Object path	[Session object path]
-
-Methods		void SetFolder(string name)
-
-			Set working directory for current session, *name* may
-			be the directory name or '..[/dir]'.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		array{dict} ListFolders(dict filter)
-
-			Returns a dictionary containing information about
-			the current folder content.
-
-			The following keys are defined:
-
-				string Name : Folder name
-
-			Possible filters: Offset and MaxCount
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		array{string} ListFilterFields()
-
-			Return all available fields that can be used in Fields
-			filter.
-
-			Possible errors: None
-
-		array{object, dict} ListMessages(string folder, dict filter)
-
-			Returns an array containing the messages found in the
-			given subfolder of the current folder, or in the
-			current folder if folder is empty.
-
-			Possible Filters: Offset, MaxCount, SubjectLength, Fields,
-			Type, PeriodStart, PeriodEnd, Status, Recipient, Sender,
-			Priority
-
-			Each message is represented by an object path followed
-			by a dictionary of the properties.
-
-			Properties:
-
-				string Subject:
-
-					Message subject
-
-				string Timestamp:
-
-					Message timestamp
-
-				string Sender:
-
-					Message sender name
-
-				string SenderAddress:
-
-					Message sender address
-
-				string ReplyTo:
-
-					Message Reply-To address
-
-				string Recipient:
-
-					Message recipient name
-
-				string RecipientAddress:
-
-					Message recipient address
-
-				string Type:
-
-					Message type
-
-					Possible values: "email", "sms-gsm",
-					"sms-cdma" and "mms"
-
-				uint64 Size:
-
-					Message size in bytes
-
-				boolean Text:
-
-					Message text flag
-
-					Specifies whether message has textual
-					content or is binary only
-
-				string Status:
-
-					Message status
-
-					Possible values for received messages:
-					"complete", "fractioned", "notification"
-
-					Possible values for sent messages:
-					"delivery-success", "sending-success",
-					"delivery-failure", "sending-failure"
-
-				uint64 AttachmentSize:
-
-					Message overall attachment size in bytes
-
-				boolean Priority:
-
-					Message priority flag
-
-				boolean Read:
-
-					Message read flag
-
-				boolean Sent:
-
-					Message sent flag
-
-				boolean Protected:
-
-					Message protected flag
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-		void UpdateInbox(void)
-
-			Request remote to update its inbox.
-
-			Possible errors: org.bluez.obex.Error.Failed
-
-		object, dict
-		PushMessage(string sourcefile, string folder, dict args)
-
-			Transfer a message (in bMessage format) to the
-			remote device.
-
-			The message is transferred either to the given
-			subfolder of the current folder, or to the current
-			folder if folder is empty.
-
-			Possible args: Transparent, Retry, Charset
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetAll.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-
-Filter:		uint16 Offset:
-
-			Offset of the first item, default is 0
-
-		uint16 MaxCount:
-
-			Maximum number of items, default is 1024
-
-		byte SubjectLength:
-
-			Maximum length of the Subject property in the
-			message, default is 256
-
-		array{string} Fields:
-
-			Message fields, default is all values.
-
-			Possible values can be query with ListFilterFields.
-
-		array{string} Types:
-
-			Filter messages by type.
-
-			Possible values: "sms", "email", "mms".
-
-		string PeriodBegin:
-
-			Filter messages by starting period.
-
-			Possible values: Date in "YYYYMMDDTHHMMSS" format.
-
-		string PeriodEnd:
-
-			Filter messages by ending period.
-
-			Possible values: Date in "YYYYMMDDTHHMMSS" format.
-
-		boolean Read:
-
-			Filter messages by read flag.
-
-			Possible values: True for read or False for unread
-
-		string Recipient:
-
-			Filter messages by recipient address.
-
-		string Sender:
-
-			Filter messages by sender address.
-
-		boolean Priority:
-
-			Filter messages by priority flag.
-
-			Possible values: True for high priority or False for
-			non-high priority
-
-Message hierarchy
-=================
-
-Service		org.bluez.obex
-Interface	org.bluez.obex.Message1
-Object path	[Session object path]/{message0,...}
-
-Methods		object, dict Get(string targetfile, boolean attachment)
-
-			Download message and store it in the target file.
-
-			If an empty target file is given, a temporary file
-			will be automatically generated.
-
-			The returned path represents the newly created transfer,
-			which should be used to find out if the content has been
-			successfully transferred or if the operation fails.
-
-			The properties of this transfer are also returned along
-			with the object path, to avoid a call to GetProperties.
-
-			Possible errors: org.bluez.obex.Error.InvalidArguments
-					 org.bluez.obex.Error.Failed
-
-Properties	string Folder [readonly]
-
-			Folder which the message belongs to
-
-		string Subject [readonly]
-
-			Message subject
-
-		string Timestamp [readonly]
-
-			Message timestamp
-
-		string Sender [readonly]
-
-			Message sender name
-
-		string SenderAddress [readonly]
-
-			Message sender address
-
-		string ReplyTo [readonly]
-
-			Message Reply-To address
-
-		string Recipient [readonly]
-
-			Message recipient name
-
-		string RecipientAddress [readonly]
-
-			Message recipient address
-
-		string Type [readonly]
-
-			Message type
-
-			Possible values: "email", "sms-gsm",
-			"sms-cdma" and "mms"
-
-		uint64 Size [readonly]
-
-			Message size in bytes
-
-		string Status [readonly]
-
-			Message reception status
-
-			Possible values: "complete",
-			"fractioned" and "notification"
-
-		boolean Priority [readonly]
-
-			Message priority flag
-
-		boolean Read [read/write]
-
-			Message read flag
-
-		boolean Deleted [writeonly]
-
-			Message deleted flag
-
-		boolean Sent [readonly]
-
-			Message sent flag
-
-		boolean Protected [readonly]
-
-			Message protected flag
diff --git a/doc/org.bluez.Adapter.5 b/doc/org.bluez.Adapter.5
new file mode 100644
index 0000000..40cc405
--- /dev/null
+++ b/doc/org.bluez.Adapter.5
@@ -0,0 +1,486 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.ADAPTER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Adapter \- BlueZ D-Bus Adapter API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Adapter1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void StartDiscovery()
+.INDENT 0.0
+.INDENT 3.5
+Starts device discovery session which may include starting an inquiry
+and/or scanning procedures and remote device name resolving.
+.sp
+Use \fBStopDiscovery\fP to release the sessions acquired.
+.sp
+This process will start creating Device objects as new devices are
+discovered.
+.sp
+During discovery RSSI delta\-threshold is imposed.
+.sp
+Each client can request a single device discovery session per adapter.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void StopDiscovery()
+.INDENT 0.0
+.INDENT 3.5
+Stops device discovery session started by \fBStartDiscovery\fP\&.
+.sp
+Note that a discovery procedure is shared between all discovery sessions
+thus calling StopDiscovery will only release a single session and
+discovery will stop when all sessions from all clients have finished.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotAuthorized
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void RemoveDevice(object device)
+.INDENT 0.0
+.INDENT 3.5
+Removes the remote device object at the given path including cahed
+information such as bonding information.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void SetDiscoveryFilter(dict filter)
+.INDENT 0.0
+.INDENT 3.5
+Sets the device discovery filter for the caller. When this method is
+called with no filter parameter, filter is removed.
+.sp
+Possible filter values:
+.INDENT 0.0
+.TP
+.B array{string} UUIDs
+Filter by service UUIDs, empty means match \fIany\fP UUID.
+.sp
+When a remote device is found that advertises any UUID from
+UUIDs, it will be reported if:
+.INDENT 7.0
+.IP \(bu 2
+\fBPathloss\fP and \fBRSSI\fP are both empty.
+.IP \(bu 2
+only \fBPathloss\fP param is set, device advertise TX power, and
+computed pathloss is less than Pathloss param.
+.IP \(bu 2
+only \fBRSSI\fP param is set, and received RSSI is higher
+than RSSI param.
+.UNINDENT
+.TP
+.B int16 RSSI
+RSSI threshold value.
+.sp
+PropertiesChanged signals will be emitted for already existing
+Device objects, with updated RSSI value. If one or more
+discovery filters have been set, the RSSI delta\-threshold, that
+is imposed by StartDiscovery by default, will not be applied.
+.TP
+.B uint16 Pathloss
+Pathloss threshold value.
+.sp
+PropertiesChanged signals will be emitted for already existing
+Device objects, with updated Pathloss value.
+.TP
+.B string Transport (Default \(dqauto\(dq)
+Transport parameter determines the type of scan.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqauto\(dq
+Interleaved scan, use LE, BREDR, or both, depending on
+what\(aqs currently enabled.
+.TP
+.B \(dqbredr\(dq
+BR/EDR inquiry only.
+.TP
+.B \(dqle\(dq
+LE scan only.
+.UNINDENT
+.TP
+.B bool DuplicateData (Default true)
+Disables duplicate detection of advertisement data.
+.sp
+When enabled PropertiesChanged signals will be generated for
+either ManufacturerData and ServiceData everytime they are
+discovered.
+.TP
+.B bool Discoverable (Default false)
+Make adapter discoverable while discovering, if the adapter is
+already discoverable setting this filter won\(aqt do anything.
+.TP
+.B string Pattern (Default none)
+Discover devices where the pattern matches either the prefix of
+the address or device name which is convenient way to limited
+the number of device objects created during a discovery.
+.sp
+When set disregards device discoverable flags.
+.sp
+Note: The pattern matching is ignored if there are other client
+that don\(aqt set any pattern as it work as a logical OR, also
+setting empty string \(dq\(dq pattern will match any device found.
+.sp
+When discovery filter is set, Device objects will be created as
+new devices with matching criteria are discovered regardless of
+they are connectable or discoverable which enables listening to
+non\-connectable and non\-discoverable devices.
+.sp
+When multiple clients call SetDiscoveryFilter, their filters are
+internally merged, and notifications about new devices are sent
+to all clients. Therefore, each client must check that device
+updates actually match its filter.
+.sp
+When SetDiscoveryFilter is called multiple times by the same
+client, last filter passed will be active for given client.
+.sp
+SetDiscoveryFilter can be called before StartDiscovery.
+It is useful when client will create first discovery session,
+to ensure that proper scan will be started right after call to
+StartDiscovery.
+.sp
+Possible errors:
+.INDENT 7.0
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} GetDiscoveryFilters()
+.INDENT 0.0
+.INDENT 3.5
+Returns available filters that can be given to \fBSetDiscoveryFilter\fP\&.
+.sp
+Possible errors: None
+.UNINDENT
+.UNINDENT
+.SS object ConnectDevice(dict properties) [experimental]
+.INDENT 0.0
+.INDENT 3.5
+connects to device without need of performing General Discovery.
+Connection mechanism is similar to Connect method on
+\fBorg.bluez.Device1(5)\fP interface with exception that this method
+returns success when physical connection is established and you can
+specify bearer to connect with parameter. After this method returns,
+services discovery will continue and any supported profile will be
+connected. There is no need for calling Connect on Device1 after this
+call. If connection was successful this method returns object path to
+created device object or device that already exist.
+.sp
+Possible properties values:
+.INDENT 0.0
+.TP
+.B string Address (Mandatory)
+The Bluetooth device address of the remote device.
+.TP
+.B string AddressType (Default \(dqBR/EDR\(dq)
+The Bluetooth device Address Type. This is address type that
+should be used for initial connection.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqpublic\(dq
+Public address
+.TP
+.B \(dqrandom\(dq
+Random address
+.UNINDENT
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Address [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth device address.
+.UNINDENT
+.UNINDENT
+.SS string AddressType [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth Address Type. For dual\-mode and BR/EDR only adapter this
+defaults to \(dqpublic\(dq. Single mode LE adapters may have either value.
+With privacy enabled this contains type of Identity Address and not
+type of address used for connection.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqpublic\(dq
+Public address.
+.TP
+.B \(dqrandom
+Random address.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth system name (pretty hostname).
+.sp
+This property is either a static system default or controlled by an
+external daemon providing access to the pretty hostname configuration.
+.UNINDENT
+.UNINDENT
+.SS string Alias [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth friendly name. This value can be changed.
+.sp
+In case no alias is set, it will return the system provided name.
+Setting an empty string as alias will convert it back to the system
+provided name.
+.sp
+When resetting the alias with an empty string, the property will default
+back to system name.
+.sp
+On a well configured system, this property never needs to be changed
+since it defaults to the system name and provides the pretty hostname.
+Only if the local name needs to be different from the pretty hostname,
+this property should be used as last resort.
+.UNINDENT
+.UNINDENT
+.SS uint32 Class [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth class of device.
+.sp
+This property represents the value that is either automatically
+configured by DMI/ACPI information or provided as static configuration.
+.UNINDENT
+.UNINDENT
+.SS boolean Connectable [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Set an adapter to connectable or non\-connectable. This is a global
+setting and should only be used by the settings application.
+.sp
+Setting this property to false will set the Discoverable property
+of the adapter to false as well, which will not be reverted if
+if Connectable is set back to true. If required, the application
+will need to manually set Discoverable to true.
+.sp
+Note that this property only affects incoming connections.
+.UNINDENT
+.UNINDENT
+.SS boolean Powered [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Switch an adapter on or off. This will also set the appropriate
+connectable state of the controller.
+.sp
+The value of this property is not persistent. After restart or
+unplugging of the adapter it will reset back to false.
+.UNINDENT
+.UNINDENT
+.SS string PowerState [readonly, experimental]
+.INDENT 0.0
+.INDENT 3.5
+The power state of an adapter.
+.sp
+The power state will show whether the adapter is turning off, or turning
+on, as well as being on or off.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqon\(dq
+Powered on.
+.TP
+.B \(dqoff\(dq
+Powered off
+.TP
+.B \(dqoff\-enabling\(dq
+Transitioning from \(dqoff\(dq to \(dqon\(dq.
+.TP
+.B \(dqon\-disabling\(dq
+Transitioning from \(dqon\(dq to \(dqoff\(dq.
+.TP
+.B \(dqoff\-blocked\(dq
+Blocked by rfkill.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS boolean Discoverable [readwrite] (Default: false)
+.INDENT 0.0
+.INDENT 3.5
+Switch an adapter to discoverable or non\-discoverable to either make it
+visible or hide it. This is a global setting and should only be used by
+the settings application.
+.sp
+If the DiscoverableTimeout is set to a non\-zero value then the system
+will set this value back to false after the timer expired.
+.sp
+In case the adapter is switched off, setting this value will fail.
+.sp
+When changing the Powered property the new state of this property will
+be updated via a PropertiesChanged signal.
+.UNINDENT
+.UNINDENT
+.SS boolean Pairable [readwrite] (Default: true)
+.INDENT 0.0
+.INDENT 3.5
+Switch an adapter to pairable or non\-pairable. This is a global setting
+and should only be used by the settings application.
+.sp
+Note that this property only affects incoming pairing requests.
+.UNINDENT
+.UNINDENT
+.SS uint32 PairableTimeout [readwrite] (Default: 0)
+.INDENT 0.0
+.INDENT 3.5
+The pairable timeout in seconds. A value of zero means that the timeout
+is disabled and it will stay in pairable mode forever.
+.UNINDENT
+.UNINDENT
+.SS uint32 DiscoverableTimeout [readwrite] (Default: 180)
+.INDENT 0.0
+.INDENT 3.5
+The discoverable timeout in seconds. A value of zero means that the
+timeout is disabled and it will stay in discoverable/limited mode
+forever.
+.UNINDENT
+.UNINDENT
+.SS boolean Discovering [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates that a device discovery procedure is active.
+.UNINDENT
+.UNINDENT
+.SS array{string} UUIDs [readonly]
+.INDENT 0.0
+.INDENT 3.5
+List of 128\-bit UUIDs that represents the available local services.
+.UNINDENT
+.UNINDENT
+.SS string Modalias [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Local Device ID information in modalias format used by the kernel and
+udev.
+.UNINDENT
+.UNINDENT
+.SS array{string} Roles [readonly]
+.INDENT 0.0
+.INDENT 3.5
+List of supported roles.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqcentral\(dq
+Supports the central role.
+.TP
+.B \(dqperipheral\(dq
+Supports the peripheral role.
+.TP
+.B \(dqcentral\-peripheral\(dq
+Supports both roles concurrently.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} ExperimentalFeatures [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+List of 128\-bit UUIDs that represents the experimental features
+currently enabled.
+.UNINDENT
+.UNINDENT
+.SS uint16 Manufacturer [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The manufacturer of the device, as a uint16 company identifier defined
+by the Core Bluetooth Specification.
+.UNINDENT
+.UNINDENT
+.SS byte Version [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth version supported by the device, as a core version code
+defined by the Core Bluetooth Specification.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Adapter.rst b/doc/org.bluez.Adapter.rst
new file mode 100644
index 0000000..3f5fdc8
--- /dev/null
+++ b/doc/org.bluez.Adapter.rst
@@ -0,0 +1,425 @@
+=================
+org.bluez.Adapter
+=================
+
+-------------------------------------
+BlueZ D-Bus Adapter API documentation
+-------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.Adapter1
+:Object path:	[variable prefix]/{hci0,hci1,...}
+
+Methods
+-------
+
+void StartDiscovery()
+`````````````````````
+
+	Starts device discovery session which may include starting an inquiry
+	and/or scanning procedures and remote device name resolving.
+
+	Use **StopDiscovery** to release the sessions acquired.
+
+	This process will start creating Device objects as new devices are
+	discovered.
+
+	During discovery RSSI delta-threshold is imposed.
+
+	Each client can request a single device discovery session per adapter.
+
+	Possible errors:
+
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+
+void StopDiscovery()
+````````````````````
+
+	Stops device discovery session started by **StartDiscovery**.
+
+	Note that a discovery procedure is shared between all discovery sessions
+	thus calling StopDiscovery will only release a single session and
+	discovery will stop when all sessions from all clients have finished.
+
+	Possible errors:
+
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotAuthorized:
+
+void RemoveDevice(object device)
+````````````````````````````````
+
+	Removes the remote device object at the given path including cahed
+	information such as bonding information.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.Failed:
+
+void SetDiscoveryFilter(dict filter)
+````````````````````````````````````
+
+	Sets the device discovery filter for the caller. When this method is
+	called with no filter parameter, filter is removed.
+
+	Possible filter values:
+
+	:array{string} UUIDs:
+
+		Filter by service UUIDs, empty means match *any* UUID.
+
+		When a remote device is found that advertises any UUID from
+		UUIDs, it will be reported if:
+
+		- **Pathloss** and **RSSI** are both empty.
+		- only **Pathloss** param is set, device advertise TX power, and
+		  computed pathloss is less than Pathloss param.
+		- only **RSSI** param is set, and received RSSI is higher
+		  than RSSI param.
+
+	:int16 RSSI:
+
+		RSSI threshold value.
+
+		PropertiesChanged signals will be emitted for already existing
+		Device objects, with updated RSSI value. If one or more
+		discovery filters have been set, the RSSI delta-threshold, that
+		is imposed by StartDiscovery by default, will not be applied.
+
+	:uint16 Pathloss:
+
+		Pathloss threshold value.
+
+		PropertiesChanged signals will be emitted for already existing
+		Device objects, with updated Pathloss value.
+
+	:string Transport (Default "auto"):
+
+		Transport parameter determines the type of scan.
+
+		Possible values:
+
+		:"auto":
+
+			Interleaved scan, use LE, BREDR, or both, depending on
+			what's currently enabled.
+
+		:"bredr":
+
+			BR/EDR inquiry only.
+
+		:"le":
+
+			LE scan only.
+
+
+	:bool DuplicateData (Default true):
+
+		Disables duplicate detection of advertisement data.
+
+		When enabled PropertiesChanged signals will be generated for
+		either ManufacturerData and ServiceData everytime they are
+		discovered.
+
+	:bool Discoverable (Default false):
+
+		Make adapter discoverable while discovering, if the adapter is
+		already discoverable setting this filter won't do anything.
+
+	:string Pattern (Default none):
+
+		Discover devices where the pattern matches either the prefix of
+		the address or device name which is convenient way to limited
+		the number of device objects created during a discovery.
+
+		When set disregards device discoverable flags.
+
+		Note: The pattern matching is ignored if there are other client
+		that don't set any pattern as it work as a logical OR, also
+		setting empty string "" pattern will match any device found.
+
+		When discovery filter is set, Device objects will be created as
+		new devices with matching criteria are discovered regardless of
+		they are connectable or discoverable which enables listening to
+		non-connectable and non-discoverable devices.
+
+		When multiple clients call SetDiscoveryFilter, their filters are
+		internally merged, and notifications about new devices are sent
+		to all clients. Therefore, each client must check that device
+		updates actually match its filter.
+
+		When SetDiscoveryFilter is called multiple times by the same
+		client, last filter passed will be active for given client.
+
+		SetDiscoveryFilter can be called before StartDiscovery.
+		It is useful when client will create first discovery session,
+		to ensure that proper scan will be started right after call to
+		StartDiscovery.
+
+		Possible errors:
+
+		:org.bluez.Error.NotReady:
+		:org.bluez.Error.NotSupported:
+		:org.bluez.Error.Failed:
+
+array{string} GetDiscoveryFilters()
+```````````````````````````````````
+
+	Returns available filters that can be given to **SetDiscoveryFilter**.
+
+	Possible errors: None
+
+object ConnectDevice(dict properties) [experimental]
+````````````````````````````````````````````````````
+
+	connects to device without need of performing General Discovery.
+	Connection mechanism is similar to Connect method on
+	**org.bluez.Device1(5)** interface with exception that this method
+	returns success when physical connection is established and you can
+	specify bearer to connect with parameter. After this method returns,
+	services discovery will continue and any supported profile will be
+	connected. There is no need for calling Connect on Device1 after this
+	call. If connection was successful this method returns object path to
+	created device object or device that already exist.
+
+	Possible properties values:
+
+	:string Address (Mandatory):
+
+		The Bluetooth device address of the remote device.
+
+	:string AddressType (Default "BR/EDR"):
+
+		The Bluetooth device Address Type. This is address type that
+		should be used for initial connection.
+
+		Possible values:
+
+		:"public":
+
+			Public address
+
+		:"random":
+
+			Random address
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.Failed:
+
+Properties
+----------
+
+string Address [readonly]
+`````````````````````````
+
+	The Bluetooth device address.
+
+string AddressType [readonly]
+`````````````````````````````
+
+	The Bluetooth Address Type. For dual-mode and BR/EDR only adapter this
+	defaults to "public". Single mode LE adapters may have either value.
+	With privacy enabled this contains type of Identity Address and not
+	type of address used for connection.
+
+	Possible values:
+
+	:"public":
+
+		Public address.
+
+
+	:"random:
+
+		Random address.
+
+string Name [readonly]
+``````````````````````
+
+	The Bluetooth system name (pretty hostname).
+
+	This property is either a static system default or controlled by an
+	external daemon providing access to the pretty hostname configuration.
+
+string Alias [readwrite]
+````````````````````````
+
+	The Bluetooth friendly name. This value can be changed.
+
+	In case no alias is set, it will return the system provided name.
+	Setting an empty string as alias will convert it back to the system
+	provided name.
+
+	When resetting the alias with an empty string, the property will default
+	back to system name.
+
+	On a well configured system, this property never needs to be changed
+	since it defaults to the system name and provides the pretty hostname.
+	Only if the local name needs to be different from the pretty hostname,
+	this property should be used as last resort.
+
+uint32 Class [readonly]
+```````````````````````
+
+	The Bluetooth class of device.
+
+	This property represents the value that is either automatically
+	configured by DMI/ACPI information or provided as static configuration.
+
+boolean Connectable [readwrite]
+```````````````````````````````
+
+	Set an adapter to connectable or non-connectable. This is a global
+	setting and should only be used by the settings application.
+
+	Setting this property to false will set the Discoverable property
+	of the adapter to false as well, which will not be reverted if
+	if Connectable is set back to true. If required, the application
+	will need to manually set Discoverable to true.
+
+	Note that this property only affects incoming connections.
+
+boolean Powered [readwrite]
+```````````````````````````
+
+	Switch an adapter on or off. This will also set the appropriate
+	connectable state of the controller.
+
+	The value of this property is not persistent. After restart or
+	unplugging of the adapter it will reset back to false.
+
+string PowerState [readonly, experimental]
+``````````````````````````````````````````
+
+	The power state of an adapter.
+
+	The power state will show whether the adapter is turning off, or turning
+	on, as well as being on or off.
+
+	Possible values:
+
+	:"on":
+
+		Powered on.
+
+	:"off":
+
+		Powered off
+
+	:"off-enabling":
+
+		Transitioning from "off" to "on".
+
+	:"on-disabling":
+
+		Transitioning from "on" to "off".
+
+	:"off-blocked":
+
+		Blocked by rfkill.
+
+boolean Discoverable [readwrite] (Default: false)
+`````````````````````````````````````````````````
+
+	Switch an adapter to discoverable or non-discoverable to either make it
+	visible or hide it. This is a global setting and should only be used by
+	the settings application.
+
+	If the DiscoverableTimeout is set to a non-zero value then the system
+	will set this value back to false after the timer expired.
+
+	In case the adapter is switched off, setting this value will fail.
+
+	When changing the Powered property the new state of this property will
+	be updated via a PropertiesChanged signal.
+
+boolean Pairable [readwrite] (Default: true)
+````````````````````````````````````````````
+
+	Switch an adapter to pairable or non-pairable. This is a global setting
+	and should only be used by the settings application.
+
+	Note that this property only affects incoming pairing requests.
+
+uint32 PairableTimeout [readwrite] (Default: 0)
+```````````````````````````````````````````````
+
+	The pairable timeout in seconds. A value of zero means that the timeout
+	is disabled and it will stay in pairable mode forever.
+
+uint32 DiscoverableTimeout [readwrite] (Default: 180)
+`````````````````````````````````````````````````````
+
+	The discoverable timeout in seconds. A value of zero means that the
+	timeout is disabled and it will stay in discoverable/limited mode
+	forever.
+
+boolean Discovering [readonly]
+``````````````````````````````
+
+	Indicates that a device discovery procedure is active.
+
+array{string} UUIDs [readonly]
+``````````````````````````````
+
+	List of 128-bit UUIDs that represents the available local services.
+
+string Modalias [readonly, optional]
+````````````````````````````````````
+
+	Local Device ID information in modalias format used by the kernel and
+	udev.
+
+array{string} Roles [readonly]
+``````````````````````````````
+
+	List of supported roles.
+
+	Possible values:
+
+	:"central":
+
+		Supports the central role.
+
+	:"peripheral":
+
+		Supports the peripheral role.
+
+	:"central-peripheral":
+
+		Supports both roles concurrently.
+
+array{string} ExperimentalFeatures [readonly, optional]
+```````````````````````````````````````````````````````
+
+	List of 128-bit UUIDs that represents the experimental features
+	currently enabled.
+
+uint16 Manufacturer [readonly]
+``````````````````````````````
+
+	The manufacturer of the device, as a uint16 company identifier defined
+	by the Core Bluetooth Specification.
+
+byte Version [readonly]
+```````````````````````
+
+	The Bluetooth version supported by the device, as a core version code
+	defined by the Core Bluetooth Specification.
diff --git a/doc/org.bluez.AdminPolicySet.5 b/doc/org.bluez.AdminPolicySet.5
new file mode 100644
index 0000000..9367bf9
--- /dev/null
+++ b/doc/org.bluez.AdminPolicySet.5
@@ -0,0 +1,79 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.ADMINPOLICYSET" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.AdminPolicySet \- BlueZ D-Bus AdminPolicySet API documentation
+.SH DESCRIPTION
+.sp
+This API provides methods to control the behavior of \fBbluetoothd(8)\fP as an
+administrator.
+.sp
+Interface AdminPolicySet1 provides methods to set policies. Once the policy is
+set successfully, it will affect all clients and stay persistently even after
+restarting \fBbluetoothd(8)\fP\&. The only way to clear it is to overwrite the
+policy with the same method.
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.AdminPolicySet1 [experimental]
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void SetServiceAllowList(array{string} UUIDs)
+.INDENT 0.0
+.INDENT 3.5
+Sets the service allowlist by specifying service UUIDs.
+.sp
+When called, \fBbluetoothd(8)\fP will block incoming and outgoing
+connections to the service not in UUIDs for all of the clients.
+.sp
+Any subsequent calls to this method will supersede any previously set
+allowlist values.  Calling this method with an empty array will allow
+any service UUIDs to be used.
+.sp
+The default value is an empty array.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.AdminPolicySet.rst b/doc/org.bluez.AdminPolicySet.rst
new file mode 100644
index 0000000..7ce4efc
--- /dev/null
+++ b/doc/org.bluez.AdminPolicySet.rst
@@ -0,0 +1,52 @@
+========================
+org.bluez.AdminPolicySet
+========================
+
+--------------------------------------------
+BlueZ D-Bus AdminPolicySet API documentation
+--------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+============
+
+This API provides methods to control the behavior of **bluetoothd(8)** as an
+administrator.
+
+Interface AdminPolicySet1 provides methods to set policies. Once the policy is
+set successfully, it will affect all clients and stay persistently even after
+restarting **bluetoothd(8)**. The only way to clear it is to overwrite the
+policy with the same method.
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.AdminPolicySet1 [experimental]
+:Object path:	[variable prefix]/{hci0,hci1,...}
+
+Methods
+-------
+
+void SetServiceAllowList(array{string} UUIDs)
+`````````````````````````````````````````````
+
+	Sets the service allowlist by specifying service UUIDs.
+
+	When called, **bluetoothd(8)** will block incoming and outgoing
+	connections to the service not in UUIDs for all of the clients.
+
+	Any subsequent calls to this method will supersede any previously set
+	allowlist values.  Calling this method with an empty array will allow
+	any service UUIDs to be used.
+
+	The default value is an empty array.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.Failed:
diff --git a/doc/org.bluez.AdminPolicyStatus.5 b/doc/org.bluez.AdminPolicyStatus.5
new file mode 100644
index 0000000..e11d28e
--- /dev/null
+++ b/doc/org.bluez.AdminPolicyStatus.5
@@ -0,0 +1,77 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.ADMINPOLICYSTATUS" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.AdminPolicyStatus \- BlueZ D-Bus AdminPolicyStatus API documentation
+.SH DESCRIPTION
+.sp
+Interface AdminPolicyStatus1 provides readonly properties to indicate the
+current values of admin policy affecting the Adapter and Device objects.
+.SH INTERFACE
+.SS Adapter
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.AdminPolicyStatus1 [experimental]
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}
+.UNINDENT
+.SS Device
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.AdminPolicyStatus1 [experimental]
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Properties
+.SS array{string} ServiceAllowList [readonly, adapter\-only]
+.INDENT 0.0
+.INDENT 3.5
+Current value of service allow list.
+.UNINDENT
+.UNINDENT
+.SS bool IsAffectedByPolicy [readonly, device\-only]
+.INDENT 0.0
+.INDENT 3.5
+Indicate if there is any auto\-connect profile in this device is not
+allowed by admin policy.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.AdminPolicyStatus.rst b/doc/org.bluez.AdminPolicyStatus.rst
new file mode 100644
index 0000000..ad2dc58
--- /dev/null
+++ b/doc/org.bluez.AdminPolicyStatus.rst
@@ -0,0 +1,49 @@
+===========================
+org.bluez.AdminPolicyStatus
+===========================
+
+-----------------------------------------------
+BlueZ D-Bus AdminPolicyStatus API documentation
+-----------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+Interface AdminPolicyStatus1 provides readonly properties to indicate the
+current values of admin policy affecting the Adapter and Device objects.
+
+Interface
+=========
+
+Adapter
+-------
+
+:Service:	org.bluez
+:Interface:	org.bluez.AdminPolicyStatus1 [experimental]
+:Object path:	[variable prefix]/{hci0,hci1,...}
+
+Device
+------
+
+:Service:	org.bluez
+:Interface:	org.bluez.AdminPolicyStatus1 [experimental]
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Properties
+----------
+
+array{string} ServiceAllowList [readonly, adapter-only]
+```````````````````````````````````````````````````````
+
+	Current value of service allow list.
+
+bool IsAffectedByPolicy [readonly, device-only]
+```````````````````````````````````````````````
+
+	Indicate if there is any auto-connect profile in this device is not
+	allowed by admin policy.
diff --git a/doc/org.bluez.AdvertisementMonitor.5 b/doc/org.bluez.AdvertisementMonitor.5
new file mode 100644
index 0000000..b1058e0
--- /dev/null
+++ b/doc/org.bluez.AdvertisementMonitor.5
@@ -0,0 +1,189 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.ADVERTISEMENTMONITOR" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.AdvertisementMonitor \- BlueZ D-Bus AdvertisementMonitor API documentation
+.SH DESCRIPTION
+.sp
+This API allows an client to specify a job of monitoring advertisements by
+registering the root of hierarchy and then exposing advertisement monitors
+under the root with filtering conditions, thresholds of RSSI and timers
+of RSSI thresholds.
+.sp
+Once a monitoring job is activated by \fBbluetoothd(8)\fP, the client can expect
+to get notified on the targeted advertisements no matter if there is an ongoing
+discovery session (see \fBStartDiscovery()\fP in \fBorg.bluez.Adapter(5)\fP).
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.AdvertisementMonitor1 [experimental]
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS void Release() [noreply]
+.INDENT 0.0
+.INDENT 3.5
+This gets called as a signal for a client to perform clean\-up when:
+.INDENT 0.0
+.IP \(bu 2
+Monitor cannot be activated after it was exposed
+.IP \(bu 2
+Monitor has been deactivated.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Activate() [noreply]
+.INDENT 0.0
+.INDENT 3.5
+After a monitor was exposed, this gets called as a signal for client to
+get acknowledged when a monitor has been activated, so the client can
+expect to receive calls on \fBDeviceFound()\fP or \fBDeviceLost()\fP\&.
+.UNINDENT
+.UNINDENT
+.SS void DeviceFound(object device) [noreply]
+.INDENT 0.0
+.INDENT 3.5
+This gets called to notify the client of finding the targeted device.
+Once receiving the call, the client should start to monitor the
+corresponding device to retrieve the changes on RSSI and advertisement
+content.
+.UNINDENT
+.UNINDENT
+.SS void DeviceLost(object device) [noreply]
+.INDENT 0.0
+.INDENT 3.5
+This gets called to notify the client of losing the targeted device.
+Once receiving this call, the client should stop monitoring the
+corresponding device.
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Type [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+The type of the monitor. See \fBSupportedMonitorTypes\fP in
+\fBorg.bluez.AdvertisementMonitorManager(5)\fP for the available options.
+.UNINDENT
+.UNINDENT
+.SS int16 RSSILowThreshold [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+Used in conjunction with \fBRSSILowTimeout\fP to determine whether a
+device becomes out\-of\-range. Valid range is \-127 to 20 (dBm), while 127
+indicates unset.
+.UNINDENT
+.UNINDENT
+.SS int16 RSSIHighThreshold [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+Used in conjunction with RSSIHighTimeout to determine whether a device
+becomes in\-range. Valid range is \-127 to 20 (dBm), while 127 indicates
+unset.
+.UNINDENT
+.UNINDENT
+.SS uint16 RSSILowTimeout [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+The time it takes to consider a device as out\-of\-range. If this many
+seconds elapses without receiving any signal at least as strong as
+\fBRSSILowThreshold\fP, a currently in\-range device will be considered as
+out\-of\-range (lost). Valid range is 1 to 300 (seconds), while 0
+indicates unset.
+.UNINDENT
+.UNINDENT
+.SS uint16 RSSIHighTimeout [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+The time it takes to consider a device as in\-range. If this many
+seconds elapses while we continuouslyreceive signals at least as strong
+as \fBRSSIHighThreshold\fP, a currently out\-of\-range device will be
+considered as in\-range (found). Valid range is 1 to 300 (seconds),
+while 0 indicates unset.
+.UNINDENT
+.UNINDENT
+.SS uint16 RSSISamplingPeriod [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+Grouping rules on how to propagate the received advertisement packets
+to the client.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B 0
+All advertisement packets from in\-range devices would be
+propagated.
+.TP
+.B 255
+Only the first advertisement packet of in\-range devices would
+be propagated. If the device becomes lost, then the first
+packet when it is found again will also be propagated.
+.TP
+.B 1 to 254
+Advertisement packets would be grouped into 100ms * N time
+period. Packets in the same group will only be reported once,
+with the RSSI value being averaged out.
+.UNINDENT
+.sp
+Currently this is unimplemented in user space, so the value is only
+used to be forwarded to the kernel.
+.UNINDENT
+.UNINDENT
+.SS array{(uint8, uint8, array{byte})} Patterns [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+If the \fBType\fP property is set to \fB\(dqor_patterns\(dq\fP, then this
+property must exist and have at least one entry in the array.
+.sp
+The structure of a pattern contains the following:
+.INDENT 0.0
+.TP
+.B uint8 start_position
+The index in an AD data field where the search hould start. The
+beginning of an AD data field is index 0.
+.TP
+.B uint8 AD_data_type
+See  <https://www.bluetooth.com/specifications/assigned\-numbers/> 
+generic\-access\-profile/ for the possible allowed value.
+.TP
+.B array{byte} content_of_pattern
+This is the value of the pattern. The maximum length of the
+bytes is 31.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.AdvertisementMonitor.rst b/doc/org.bluez.AdvertisementMonitor.rst
new file mode 100644
index 0000000..98852ac
--- /dev/null
+++ b/doc/org.bluez.AdvertisementMonitor.rst
@@ -0,0 +1,153 @@
+==============================
+org.bluez.AdvertisementMonitor
+==============================
+
+--------------------------------------------------
+BlueZ D-Bus AdvertisementMonitor API documentation
+--------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+This API allows an client to specify a job of monitoring advertisements by
+registering the root of hierarchy and then exposing advertisement monitors
+under the root with filtering conditions, thresholds of RSSI and timers
+of RSSI thresholds.
+
+Once a monitoring job is activated by **bluetoothd(8)**, the client can expect
+to get notified on the targeted advertisements no matter if there is an ongoing
+discovery session (see **StartDiscovery()** in **org.bluez.Adapter(5)**).
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.AdvertisementMonitor1 [experimental]
+:Object path:	freely definable
+
+Methods
+-------
+
+void Release() [noreply]
+````````````````````````
+
+	This gets called as a signal for a client to perform clean-up when:
+
+	- Monitor cannot be activated after it was exposed
+	- Monitor has been deactivated.
+
+void Activate() [noreply]
+`````````````````````````
+
+	After a monitor was exposed, this gets called as a signal for client to
+	get acknowledged when a monitor has been activated, so the client can
+	expect to receive calls on **DeviceFound()** or **DeviceLost()**.
+
+void DeviceFound(object device) [noreply]
+`````````````````````````````````````````
+
+	This gets called to notify the client of finding the targeted device.
+	Once receiving the call, the client should start to monitor the
+	corresponding device to retrieve the changes on RSSI and advertisement
+	content.
+
+void DeviceLost(object device) [noreply]
+````````````````````````````````````````
+
+	This gets called to notify the client of losing the targeted device.
+	Once receiving this call, the client should stop monitoring the
+	corresponding device.
+
+Properties
+----------
+
+string Type [read-only]
+```````````````````````
+
+	The type of the monitor. See **SupportedMonitorTypes** in
+	**org.bluez.AdvertisementMonitorManager(5)** for the available options.
+
+int16 RSSILowThreshold [read-only, optional]
+````````````````````````````````````````````
+
+	Used in conjunction with **RSSILowTimeout** to determine whether a
+	device becomes out-of-range. Valid range is -127 to 20 (dBm), while 127
+	indicates unset.
+
+int16 RSSIHighThreshold [read-only, optional]
+`````````````````````````````````````````````
+
+	Used in conjunction with RSSIHighTimeout to determine whether a device
+	becomes in-range. Valid range is -127 to 20 (dBm), while 127 indicates
+	unset.
+
+uint16 RSSILowTimeout [read-only, optional]
+```````````````````````````````````````````
+
+	The time it takes to consider a device as out-of-range. If this many
+	seconds elapses without receiving any signal at least as strong as
+	**RSSILowThreshold**, a currently in-range device will be considered as
+	out-of-range (lost). Valid range is 1 to 300 (seconds), while 0
+	indicates unset.
+
+uint16 RSSIHighTimeout [read-only, optional]
+````````````````````````````````````````````
+
+	The time it takes to consider a device as in-range. If this many
+	seconds elapses while we continuouslyreceive signals at least as strong
+	as **RSSIHighThreshold**, a currently out-of-range device will be
+	considered as in-range (found). Valid range is 1 to 300 (seconds),
+	while 0 indicates unset.
+
+uint16 RSSISamplingPeriod [read-only, optional]
+```````````````````````````````````````````````
+
+	Grouping rules on how to propagate the received advertisement packets
+	to the client.
+
+	Possible values:
+
+	:0:
+		All advertisement packets from in-range devices would be
+		propagated.
+
+	:255:
+		Only the first advertisement packet of in-range devices would
+		be propagated. If the device becomes lost, then the first
+		packet when it is found again will also be propagated.
+
+	:1 to 254:
+		Advertisement packets would be grouped into 100ms * N time
+		period. Packets in the same group will only be reported once,
+		with the RSSI value being averaged out.
+
+	Currently this is unimplemented in user space, so the value is only
+	used to be forwarded to the kernel.
+
+array{(uint8, uint8, array{byte})} Patterns [read-only, optional]
+`````````````````````````````````````````````````````````````````
+
+	If the **Type** property is set to **"or_patterns"**, then this
+	property must exist and have at least one entry in the array.
+
+	The structure of a pattern contains the following:
+
+	:uint8 start_position:
+
+		The index in an AD data field where the search hould start. The
+		beginning of an AD data field is index 0.
+
+	:uint8 AD_data_type:
+
+		See https://www.bluetooth.com/specifications/assigned-numbers/
+		generic-access-profile/ for the possible allowed value.
+
+	:array{byte} content_of_pattern:
+
+		This is the value of the pattern. The maximum length of the
+		bytes is 31.
diff --git a/doc/org.bluez.AdvertisementMonitorManager.5 b/doc/org.bluez.AdvertisementMonitorManager.5
new file mode 100644
index 0000000..a35541f
--- /dev/null
+++ b/doc/org.bluez.AdvertisementMonitorManager.5
@@ -0,0 +1,119 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.ADVERTISEMENTMONITORMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.AdvertisementMonitorManager \- BlueZ D-Bus AdvertisementMonitorManager API documentation
+.SH INTERFACE
+.sp
+Service         org.bluez
+Interface       org.bluez.AdvertisementMonitorManager1 [experimental]
+Object path     /org/bluez/{hci0,hci1,...}
+.SS Methods
+.SS void RegisterMonitor(object application)
+.INDENT 0.0
+.INDENT 3.5
+Registers the root path of a hierarchy of advertisement monitors
+implementing \fBorg.bluez.AdvertisementMonitor(5)\fP\&.
+.sp
+The application object path together with the D\-Bus ystem bus
+connection ID define the identification of the application registering
+advertisement monitors.
+.sp
+Once a root path is registered by a client via this method, the client
+can freely expose/unexpose advertisement monitors without re\-registering
+the root path again. After use, the client should call
+\fBUnregisterMonitor()\fP method to invalidate the advertisement monitors.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterMonitor(object application)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters a hierarchy of advertisement monitors that has been
+previously registered with \fBRegisterMonitor()\fP\&. The object path
+parameter must match the same value that has been used on registration.
+.sp
+Upon unregistration, the advertisement monitor(s) should expect to
+receive \fBRelease()\fP method as the signal that the advertisement
+monitor(s) has been deactivated.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS array{string} SupportedMonitorTypes [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+This lists the supported types of advertisement monitors. An application
+should check this before instantiate and expose an object of
+\fBorg.bluez.AdvertisementMonitor(5)\fP\&.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqor_patterns\(dq
+Patterns with logic OR applied. With this type, property
+\fBPatterns\fP must exist and has at least one pattern.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} SupportedFeatures [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+This lists the features of advertisement monitoring supported by
+\fBbluetoothd(8)\fP\&.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqcontroller\-patterns\(dq
+If the controller is capable of performing advertisement
+monitoring by patterns, \fBbluetoothd(8)\fP would offload the
+patterns to the controller to reduce power consumption.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.AdvertisementMonitorManager.rst b/doc/org.bluez.AdvertisementMonitorManager.rst
new file mode 100644
index 0000000..3775a48
--- /dev/null
+++ b/doc/org.bluez.AdvertisementMonitorManager.rst
@@ -0,0 +1,90 @@
+=====================================
+org.bluez.AdvertisementMonitorManager
+=====================================
+
+---------------------------------------------------------
+BlueZ D-Bus AdvertisementMonitorManager API documentation
+---------------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+Service		org.bluez
+Interface	org.bluez.AdvertisementMonitorManager1 [experimental]
+Object path	/org/bluez/{hci0,hci1,...}
+
+Methods
+-------
+
+void RegisterMonitor(object application)
+````````````````````````````````````````
+
+	Registers the root path of a hierarchy of advertisement monitors
+	implementing **org.bluez.AdvertisementMonitor(5)**.
+
+	The application object path together with the D-Bus ystem bus
+	connection ID define the identification of the application registering
+	advertisement monitors.
+
+	Once a root path is registered by a client via this method, the client
+	can freely expose/unexpose advertisement monitors without re-registering
+	the root path again. After use, the client should call
+	**UnregisterMonitor()** method to invalidate the advertisement monitors.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+	:org.bluez.Error.Failed:
+
+void UnregisterMonitor(object application)
+``````````````````````````````````````````
+
+	Unregisters a hierarchy of advertisement monitors that has been
+	previously registered with **RegisterMonitor()**. The object path
+	parameter must match the same value that has been used on registration.
+
+	Upon unregistration, the advertisement monitor(s) should expect to
+	receive **Release()** method as the signal that the advertisement
+	monitor(s) has been deactivated.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.DoesNotExist:
+
+Properties
+----------
+
+array{string} SupportedMonitorTypes [read-only]
+```````````````````````````````````````````````
+
+	This lists the supported types of advertisement monitors. An application
+	should check this before instantiate and expose an object of
+	**org.bluez.AdvertisementMonitor(5)**.
+
+	Possible values:
+
+	:"or_patterns":
+
+		Patterns with logic OR applied. With this type, property
+		**Patterns** must exist and has at least one pattern.
+
+array{string} SupportedFeatures [read-only]
+```````````````````````````````````````````
+
+	This lists the features of advertisement monitoring supported by
+	**bluetoothd(8)**.
+
+	Possible values:
+
+	:"controller-patterns":
+
+		If the controller is capable of performing advertisement
+		monitoring by patterns, **bluetoothd(8)** would offload the
+		patterns to the controller to reduce power consumption.
diff --git a/doc/org.bluez.Agent.5 b/doc/org.bluez.Agent.5
new file mode 100644
index 0000000..d187bc5
--- /dev/null
+++ b/doc/org.bluez.Agent.5
@@ -0,0 +1,201 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.AGENT" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Agent \- BlueZ D-Bus Agent API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+unique name
+.TP
+.B Interface
+org.bluez.Agent1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon unregisters the agent.
+An agent can use it to do cleanup tasks. There is no need to unregister
+the agent, because when this method gets called it has already been
+unregistered.
+.UNINDENT
+.UNINDENT
+.SS string RequestPinCode(object device)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to get the passkey
+for an authentication.
+.sp
+The return value should be a string of 1\-16 characters length. The
+string can be alphanumeric.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void DisplayPinCode(object device, string pincode)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to display a
+pincode for an authentication.
+.sp
+An empty reply should be returned. When the pincode needs no longer to
+be displayed, the Cancel method of the agent will be called.
+.sp
+This is used during the pairing process of keyboards that don\(aqt support
+Bluetooth 2.1 Secure Simple Pairing, in contrast to DisplayPasskey which
+is used for those that do.
+.sp
+This method will only ever be called once since older keyboards do not
+support typing notification.
+.sp
+Note that the PIN will always be a 6\-digit number, zero\-padded to 6
+digits. This is for harmony with the later specification.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint32 RequestPasskey(object device)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to get the passkey
+for an authentication.
+.sp
+The return value should be a numeric value between 0\-999999.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void DisplayPasskey(object device, uint32 passkey, uint16 entered)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to display a
+passkey for an authentication.
+.sp
+The entered parameter indicates the number of already typed keys on the
+remote side.
+.sp
+An empty reply should be returned. When the passkey needs no longer to
+be displayed, the Cancel method of the agent will be called.
+.sp
+During the pairing process this method might be called multiple times to
+update the entered value.
+.sp
+Note that the passkey will always be a 6\-digit number, so the display
+should be zero\-padded at the start if the value contains less than 6
+digits.
+.UNINDENT
+.UNINDENT
+.SS void RequestConfirmation(object device, uint32 passkey)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to confirm a
+passkey for an authentication.
+.sp
+To confirm the value it should return an empty reply or an error in case
+the passkey is invalid.
+.sp
+Note that the passkey will always be a 6\-digit number, so the display
+should be zero\-padded at the start if the value contains less than 6
+digits.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void RequestAuthorization(object device)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called to request the user to authorize an incoming
+pairing attempt which would in other circumstances trigger the
+just\-works model, or when the user plugged in a device that implements
+cable pairing. In the latter case, the device would not be connected to
+the adapter via Bluetooth yet.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void AuthorizeService(object device, string uuid)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon needs to authorize a
+connection/service request.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Cancel()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called to indicate that the agent request failed before
+a reply was returned.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Agent.rst b/doc/org.bluez.Agent.rst
new file mode 100644
index 0000000..11d09b9
--- /dev/null
+++ b/doc/org.bluez.Agent.rst
@@ -0,0 +1,149 @@
+===============
+org.bluez.Agent
+===============
+
+-----------------------------------
+BlueZ D-Bus Agent API documentation
+-----------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	unique name
+:Interface:	org.bluez.Agent1
+:Object path:	freely definable
+
+Methods
+-------
+
+void Release()
+``````````````
+
+	This method gets called when the service daemon unregisters the agent.
+	An agent can use it to do cleanup tasks. There is no need to unregister
+	the agent, because when this method gets called it has already been
+	unregistered.
+
+string RequestPinCode(object device)
+````````````````````````````````````
+
+	This method gets called when the service daemon needs to get the passkey
+	for an authentication.
+
+	The return value should be a string of 1-16 characters length. The
+	string can be alphanumeric.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+void DisplayPinCode(object device, string pincode)
+``````````````````````````````````````````````````
+
+	This method gets called when the service daemon needs to display a
+	pincode for an authentication.
+
+	An empty reply should be returned. When the pincode needs no longer to
+	be displayed, the Cancel method of the agent will be called.
+
+	This is used during the pairing process of keyboards that don't support
+	Bluetooth 2.1 Secure Simple Pairing, in contrast to DisplayPasskey which
+	is used for those that do.
+
+	This method will only ever be called once since older keyboards do not
+	support typing notification.
+
+	Note that the PIN will always be a 6-digit number, zero-padded to 6
+	digits. This is for harmony with the later specification.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+uint32 RequestPasskey(object device)
+````````````````````````````````````
+
+	This method gets called when the service daemon needs to get the passkey
+	for an authentication.
+
+	The return value should be a numeric value between 0-999999.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+void DisplayPasskey(object device, uint32 passkey, uint16 entered)
+``````````````````````````````````````````````````````````````````
+
+	This method gets called when the service daemon needs to display a
+	passkey for an authentication.
+
+	The entered parameter indicates the number of already typed keys on the
+	remote side.
+
+	An empty reply should be returned. When the passkey needs no longer to
+	be displayed, the Cancel method of the agent will be called.
+
+	During the pairing process this method might be called multiple times to
+	update the entered value.
+
+	Note that the passkey will always be a 6-digit number, so the display
+	should be zero-padded at the start if the value contains less than 6
+	digits.
+
+void RequestConfirmation(object device, uint32 passkey)
+```````````````````````````````````````````````````````
+
+	This method gets called when the service daemon needs to confirm a
+	passkey for an authentication.
+
+	To confirm the value it should return an empty reply or an error in case
+	the passkey is invalid.
+
+	Note that the passkey will always be a 6-digit number, so the display
+	should be zero-padded at the start if the value contains less than 6
+	digits.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+void RequestAuthorization(object device)
+````````````````````````````````````````
+
+	This method gets called to request the user to authorize an incoming
+	pairing attempt which would in other circumstances trigger the
+	just-works model, or when the user plugged in a device that implements
+	cable pairing. In the latter case, the device would not be connected to
+	the adapter via Bluetooth yet.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+void AuthorizeService(object device, string uuid)
+`````````````````````````````````````````````````
+
+	This method gets called when the service daemon needs to authorize a
+	connection/service request.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
+
+void Cancel()
+`````````````
+
+	This method gets called to indicate that the agent request failed before
+	a reply was returned.
diff --git a/doc/org.bluez.AgentManager.5 b/doc/org.bluez.AgentManager.5
new file mode 100644
index 0000000..fb0f2f4
--- /dev/null
+++ b/doc/org.bluez.AgentManager.5
@@ -0,0 +1,122 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.AGENTMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.AgentManager \- BlueZ D-Bus AgentManager API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.AgentManager1
+.TP
+.B Object path
+/org/bluez
+.UNINDENT
+.SS Methods
+.SS void RegisterAgent(object agent, string capability)
+.INDENT 0.0
+.INDENT 3.5
+Registers pairing agent.
+.sp
+The object path defines the path of the agent that will be called when
+user input is needed and must implement \fBorg.bluez.Agent(5)\fP
+interface.
+.sp
+Every application can register its own agent and for all actions
+triggered by that application its agent is used.
+.sp
+It is not required by an application to register an agent. If an
+application does chooses to not register an agent, the default agent is
+used. This is on most cases a good idea. Only application like a pairing
+wizard should register their own agent.
+.sp
+An application can only register one agent. Multiple agents per
+application is not supported.
+.sp
+Possible capability values:
+.INDENT 0.0
+.TP
+.B \(dq\(dq
+Fallback to \(dqKeyboardDisplay\(dq.
+.TP
+.B \(dqDisplayOnly\(dq
+.TP
+.B \(dqDisplayYesNo\(dq
+.TP
+.B \(dqKeyboardOnly\(dq
+.TP
+.B \(dqNoInputNoOutput\(dq
+.TP
+.B \(dqKeyboardDisplay\(dq
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterAgent(object agent)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters an agent that has been previously registered using
+\fBRegisterAgent\fP\&. The object path parameter must match the same value
+that has been used on registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void RequestDefaultAgent(object agent)
+.INDENT 0.0
+.INDENT 3.5
+Requests to make the application agent the default agent. The
+application is required to register an agent.
+.sp
+Special permission might be required to become the default agent.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.AgentManager.rst b/doc/org.bluez.AgentManager.rst
new file mode 100644
index 0000000..dfc0297
--- /dev/null
+++ b/doc/org.bluez.AgentManager.rst
@@ -0,0 +1,83 @@
+======================
+org.bluez.AgentManager
+======================
+
+------------------------------------------
+BlueZ D-Bus AgentManager API documentation
+------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.AgentManager1
+:Object path:	/org/bluez
+
+Methods
+-------
+
+void RegisterAgent(object agent, string capability)
+```````````````````````````````````````````````````
+
+	Registers pairing agent.
+
+	The object path defines the path of the agent that will be called when
+	user input is needed and must implement **org.bluez.Agent(5)**
+	interface.
+
+	Every application can register its own agent and for all actions
+	triggered by that application its agent is used.
+
+	It is not required by an application to register an agent. If an
+	application does chooses to not register an agent, the default agent is
+	used. This is on most cases a good idea. Only application like a pairing
+	wizard should register their own agent.
+
+	An application can only register one agent. Multiple agents per
+	application is not supported.
+
+	Possible capability values:
+
+	:"":
+
+		Fallback to "KeyboardDisplay".
+
+	:"DisplayOnly":
+	:"DisplayYesNo":
+	:"KeyboardOnly":
+	:"NoInputNoOutput":
+	:"KeyboardDisplay":
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+
+void UnregisterAgent(object agent)
+``````````````````````````````````
+
+	Unregisters an agent that has been previously registered using
+	**RegisterAgent**. The object path parameter must match the same value
+	that has been used on registration.
+
+	Possible errors:
+
+	:org.bluez.Error.DoesNotExist:
+
+void RequestDefaultAgent(object agent)
+``````````````````````````````````````
+
+	Requests to make the application agent the default agent. The
+	application is required to register an agent.
+
+	Special permission might be required to become the default agent.
+
+	Possible errors:
+
+	:org.bluez.Error.DoesNotExist:
+
diff --git a/doc/org.bluez.Battery.5 b/doc/org.bluez.Battery.5
new file mode 100644
index 0000000..6dff392
--- /dev/null
+++ b/doc/org.bluez.Battery.5
@@ -0,0 +1,66 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.BATTERY" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Battery \- BlueZ D-Bus Battery API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Battery1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Properties
+.SS byte Percentage [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The percentage of battery left as an unsigned 8\-bit integer.
+.UNINDENT
+.UNINDENT
+.SS string Source [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Describes where the battery information comes from.
+.sp
+This property is informational only and may be useful for debugging
+purposes.
+.sp
+Providers from \fBorg.bluez.BatteryProvider(5)\fP may make use
+of this property to indicate where the battery report comes from
+(e.g. \(dqHFP 1.7\(dq, \(dqHID\(dq, or the profile UUID).
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Battery.rst b/doc/org.bluez.Battery.rst
new file mode 100644
index 0000000..d7e903c
--- /dev/null
+++ b/doc/org.bluez.Battery.rst
@@ -0,0 +1,39 @@
+=================
+org.bluez.Battery
+=================
+
+-------------------------------------
+BlueZ D-Bus Battery API documentation
+-------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.Battery1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Properties
+----------
+
+byte Percentage [readonly]
+``````````````````````````
+
+	The percentage of battery left as an unsigned 8-bit integer.
+
+string Source [readonly, optional]
+``````````````````````````````````
+
+	Describes where the battery information comes from.
+
+	This property is informational only and may be useful for debugging
+	purposes.
+
+	Providers from **org.bluez.BatteryProvider(5)** may make use
+	of this property to indicate where the battery report comes from
+	(e.g. "HFP 1.7", "HID", or the profile UUID).
diff --git a/doc/org.bluez.BatteryProvider.5 b/doc/org.bluez.BatteryProvider.5
new file mode 100644
index 0000000..c079ebd
--- /dev/null
+++ b/doc/org.bluez.BatteryProvider.5
@@ -0,0 +1,58 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.BATTERYPROVIDER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.BatteryProvider \- BlueZ D-Bus BatteryProvider API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+<client D\-Bus address>
+.TP
+.B Interface
+org.bluez.BatteryProvider1
+.TP
+.B Object path
+{provider_root}/{unique battery object path}
+.UNINDENT
+.SS Properties
+.sp
+Objects provided on this interface contain the same properties as
+\fBorg.bluez.Battery(5)\fP interface. Additionally, this interface needs to have
+the Device property indicating the object path of the device this battery
+provides.
+.SS object Device [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The object path of the device that has this battery.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.BatteryProvider.rst b/doc/org.bluez.BatteryProvider.rst
new file mode 100644
index 0000000..b8d8b1c
--- /dev/null
+++ b/doc/org.bluez.BatteryProvider.rst
@@ -0,0 +1,32 @@
+=========================
+org.bluez.BatteryProvider
+=========================
+
+---------------------------------------------
+BlueZ D-Bus BatteryProvider API documentation
+---------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	<client D-Bus address>
+:Interface:	org.bluez.BatteryProvider1
+:Object path:	{provider_root}/{unique battery object path}
+
+Properties
+----------
+
+Objects provided on this interface contain the same properties as
+**org.bluez.Battery(5)** interface. Additionally, this interface needs to have
+the Device property indicating the object path of the device this battery
+provides.
+
+object Device [readonly]
+````````````````````````
+
+	The object path of the device that has this battery.
diff --git a/doc/org.bluez.BatteryProviderManager.5 b/doc/org.bluez.BatteryProviderManager.5
new file mode 100644
index 0000000..0d5db98
--- /dev/null
+++ b/doc/org.bluez.BatteryProviderManager.5
@@ -0,0 +1,75 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.BATTERYPROVIDERMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.BatteryProviderManager \- BlueZ D-Bus BatteryProviderManager API documentation
+.SH DESCRIPTION
+.sp
+A battery provider starts by registering itself as a battery provider with the
+\fBRegisterBatteryProvider()\fP method passing an object path as the provider ID.
+Then, it can start exposing \fBorg.bluez.BatteryProvider(5)\fP objects having the
+path starting with the given provider ID. It can also remove objects at any
+time.
+The objects and their properties exposed by battery providers will be reflected
+on \fBorg.bluez.Battery(5)\fP interface.
+.sp
+\fBbluetoothd(8)\fP will stop monitoring these exposed and removed objects after
+UnregisterBatteryProvider is called for that provider ID.
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.BatteryProviderManager1
+.TP
+.B Object path
+/org/bluez/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void RegisterBatteryProvider(object provider)
+.INDENT 0.0
+.INDENT 3.5
+Registers a battery provider. A registered battery provider can then
+expose objects with \fBorg.bluez.BatteryProvider(5)\fP interface.
+.UNINDENT
+.UNINDENT
+.SS void UnregisterBatteryProvider(object provider)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters a battery provider previously registered with
+\fBRegisterBatteryProvider()\fP\&. After unregistration, the
+\fBorg.bluez.BatteryProvider(5)\fP objects provided by this client are
+ignored by \fBbluetoothd(8)\fP\&.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.BatteryProviderManager.rst b/doc/org.bluez.BatteryProviderManager.rst
new file mode 100644
index 0000000..ab5cf2d
--- /dev/null
+++ b/doc/org.bluez.BatteryProviderManager.rst
@@ -0,0 +1,50 @@
+================================
+org.bluez.BatteryProviderManager
+================================
+
+----------------------------------------------------
+BlueZ D-Bus BatteryProviderManager API documentation
+----------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+============
+
+A battery provider starts by registering itself as a battery provider with the
+**RegisterBatteryProvider()** method passing an object path as the provider ID.
+Then, it can start exposing **org.bluez.BatteryProvider(5)** objects having the
+path starting with the given provider ID. It can also remove objects at any
+time.
+The objects and their properties exposed by battery providers will be reflected
+on **org.bluez.Battery(5)** interface.
+
+**bluetoothd(8)** will stop monitoring these exposed and removed objects after
+UnregisterBatteryProvider is called for that provider ID.
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.BatteryProviderManager1
+:Object path:	/org/bluez/{hci0,hci1,...}
+
+Methods
+-------
+
+void RegisterBatteryProvider(object provider)
+`````````````````````````````````````````````
+
+	Registers a battery provider. A registered battery provider can then
+	expose objects with **org.bluez.BatteryProvider(5)** interface.
+
+void UnregisterBatteryProvider(object provider)
+```````````````````````````````````````````````
+
+	Unregisters a battery provider previously registered with
+	**RegisterBatteryProvider()**. After unregistration, the
+	**org.bluez.BatteryProvider(5)** objects provided by this client are
+	ignored by **bluetoothd(8)**.
diff --git a/doc/org.bluez.Device.5 b/doc/org.bluez.Device.5
new file mode 100644
index 0000000..a1f2a7f
--- /dev/null
+++ b/doc/org.bluez.Device.5
@@ -0,0 +1,445 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.DEVICE" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Device \- BlueZ D-Bus Device API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Device1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Methods
+.SS void Connect()
+.INDENT 0.0
+.INDENT 3.5
+Connects all profiles the remote device supports that can be connected
+to and have been flagged as auto\-connectable. If only subset of profiles
+is already connected it will try to connect currently disconnected ones.
+.sp
+If at least one profile was connected successfully this method will
+indicate success.
+.sp
+For dual\-mode devices only one bearer is connected at time, the
+conditions are in the following order:
+.INDENT 0.0
+.IP 1. 3
+Connect the disconnected bearer if already connected.
+.UNINDENT
+.sp
+2. Connect first the bonded bearer. If no bearers are bonded or both
+are skip and check latest seen bearer.
+.sp
+3. Connect last seen bearer, in case the timestamps are the same BR/EDR
+takes precedence.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.AlreadyConnected
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Disconnect()
+.INDENT 0.0
+.INDENT 3.5
+Disconnects all connected profiles and then terminates low\-level ACL
+connection.
+.sp
+ACL connection will be terminated even if some profiles were not
+disconnected properly e.g. due to misbehaving device.
+.sp
+This method can be also used to cancel a preceding Connect call before
+a reply to it has been received.
+.sp
+For non\-trusted devices connected over LE bearer calling this method
+will disable incoming connections until Connect method is called again.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotConnected
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void ConnectProfile(string uuid)
+.INDENT 0.0
+.INDENT 3.5
+Connects a specific profile of this device. The UUID provided is the
+remote service UUID for the profile.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotAvailable
+.TP
+.B org.bluez.Error.NotReady
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void DisconnectProfile(string uuid)
+.INDENT 0.0
+.INDENT 3.5
+Disconnects a specific profile of this device. The profile needs to be
+registered client profile.
+.sp
+There is no connection tracking for a profile, so as long as the
+profile is registered this will always succeed.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Pair()
+.INDENT 0.0
+.INDENT 3.5
+Connects to the remote device and initiate pairing procedure then
+proceed with service discovery.
+.sp
+If the application has registered its own agent, then that specific
+agent will be used. Otherwise it will use the default agent.
+.sp
+Only for applications like a pairing wizard it would make sense to have
+its own agent. In almost all other cases the default agent will handle
+this just fine.
+.sp
+In case there is no application agent and also no default agent present,
+this method will fail.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.AlreadyExists
+.TP
+.B org.bluez.Error.AuthenticationCanceled
+.TP
+.B org.bluez.Error.AuthenticationFailed
+.TP
+.B org.bluez.Error.AuthenticationRejected
+.TP
+.B org.bluez.Error.AuthenticationTimeout
+.TP
+.B org.bluez.Error.ConnectionAttemptFailed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void CancelPairing()
+.INDENT 0.0
+.INDENT 3.5
+Cancels a pairing operation initiated by the \fBPair\fP method.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.DoesNotExist
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{array{byte}} GetServiceRecords() [experimental]
+.INDENT 0.0
+.INDENT 3.5
+Returns all currently known BR/EDR service records for the device. Each
+individual byte array represents a raw SDP record, as defined by the
+Bluetooth Service Discovery Protocol specification.
+.sp
+This method is intended to be only used by compatibility layers like
+Wine, that need to provide access to raw SDP records to support foreign
+Bluetooth APIs. General applications should instead use the Profile API
+for services\-related functionality.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.NotConnected
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Address [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth device address of the remote device.
+.UNINDENT
+.UNINDENT
+.SS string AddressType [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth device Address Type. For dual\-mode and BR/EDR only devices
+this defaults to \(dqpublic\(dq. Single mode LE devices may have either value.
+If remote device uses privacy than before pairing this represents
+address type used for connection and Identity Address after pairing.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqpublic\(dq
+Public address
+.TP
+.B \(dqrandom\(dq
+Random address
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth remote name.
+.sp
+This value is only present for completeness. It is better to always use
+the \fBAlias\fP property when displaying the devices name.
+.sp
+If the \fBAlias\fP property is unset, it will reflect this value which
+makes it more convenient.
+.UNINDENT
+.UNINDENT
+.SS string Icon [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Proposed icon name according to the freedesktop.org icon naming
+specification.
+.UNINDENT
+.UNINDENT
+.SS uint32 Class [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+The Bluetooth class of device of the remote device.
+.UNINDENT
+.UNINDENT
+.SS uint16 Appearance [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+External appearance of device, as found on GAP service.
+.UNINDENT
+.UNINDENT
+.SS array{string} UUIDs [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+List of 128\-bit UUIDs that represents the available remote services.
+.UNINDENT
+.UNINDENT
+.SS boolean Paired [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the remote device is paired. Paired means the pairing
+process where devices exchange the information to establish an
+encrypted connection has been completed.
+.UNINDENT
+.UNINDENT
+.SS boolean Bonded [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the remote device is bonded. Bonded means the information
+exchanged on pairing process has been stored and will be persisted.
+.UNINDENT
+.UNINDENT
+.SS boolean Connected [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the remote device is currently connected.
+A PropertiesChanged signal indicate changes to this status.
+.UNINDENT
+.UNINDENT
+.SS boolean Trusted [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the remote is seen as trusted. This setting can be changed
+by the application.
+.UNINDENT
+.UNINDENT
+.SS boolean Blocked [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+If set to true any incoming connections from the device will be
+immediately rejected. Any device drivers will also be removed and
+no new ones will be probed as long as the device is blocked.
+.UNINDENT
+.UNINDENT
+.SS boolean WakeAllowed [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+If set to true this device will be allowed to wake the host from
+system suspend.
+.UNINDENT
+.UNINDENT
+.SS string Alias [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+The name alias for the remote device. The alias can be used to have a
+different friendly name for the remote device.
+.sp
+In case no alias is set, it will return the remote device name. Setting
+an empty string as alias will convert it back to the remote device name.
+.sp
+When resetting the alias with an empty string, the property will default
+back to the remote name.
+.UNINDENT
+.UNINDENT
+.SS object Adapter [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The object path of the adapter the device belongs to.
+.UNINDENT
+.UNINDENT
+.SS boolean LegacyPairing [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Set to true if the device only supports the pre\-2.1 pairing mechanism.
+This property is useful during device discovery to anticipate whether
+legacy or simple pairing will occur if pairing is initiated.
+.sp
+Note that this property can exhibit false\-positives in the case of
+Bluetooth 2.1 (or newer) devices that have disabled Extended Inquiry
+Response support.
+.UNINDENT
+.UNINDENT
+.SS string Modalias [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Remote Device ID information in modalias format used by the kernel and
+udev.
+.UNINDENT
+.UNINDENT
+.SS int16 RSSI [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Received Signal Strength Indicator of the remote device (inquiry or
+advertising).
+.UNINDENT
+.UNINDENT
+.SS int16 TxPower [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Advertised transmitted power level (inquiry or advertising).
+.UNINDENT
+.UNINDENT
+.SS dict ManufacturerData [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Manufacturer specific advertisement data. Keys are 16 bits Manufacturer
+ID followed by its byte array value.
+.UNINDENT
+.UNINDENT
+.SS dict ServiceData [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Service advertisement data. Keys are the UUIDs in string format followed
+by its byte array value.
+.UNINDENT
+.UNINDENT
+.SS bool ServicesResolved [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicate whether or not service discovery has been resolved.
+.UNINDENT
+.UNINDENT
+.SS array{byte} AdvertisingFlags [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Advertising Data Flags of the remote device.
+.UNINDENT
+.UNINDENT
+.SS dict AdvertisingData [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The Advertising Data of the remote device. Keys are 1 byte AD Type
+followed by data as byte array.
+.sp
+Note: Only types considered safe to be handled by application are
+exposed.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B <type>
+<byte array>
+.UNINDENT
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+<Transport Discovery> <Organization Flags...>
+0x26                   0x01         0x01...
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{object, dict} Sets [readonly, experimental]
+.INDENT 0.0
+.INDENT 3.5
+The object paths of the sets the device belongs to followed by a
+dictionary which can contain the following:
+.INDENT 0.0
+.TP
+.B byte Rank
+Rank of the device in the Set.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Device.rst b/doc/org.bluez.Device.rst
new file mode 100644
index 0000000..f8d4a68
--- /dev/null
+++ b/doc/org.bluez.Device.rst
@@ -0,0 +1,348 @@
+================
+org.bluez.Device
+================
+
+------------------------------------
+BlueZ D-Bus Device API documentation
+------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.Device1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods
+-------
+
+void Connect()
+``````````````
+
+	Connects all profiles the remote device supports that can be connected
+	to and have been flagged as auto-connectable. If only subset of profiles
+	is already connected it will try to connect currently disconnected ones.
+
+	If at least one profile was connected successfully this method will
+	indicate success.
+
+	For dual-mode devices only one bearer is connected at time, the
+	conditions are in the following order:
+
+	1. Connect the disconnected bearer if already connected.
+
+	2. Connect first the bonded bearer. If no bearers are bonded or both
+	are skip and check latest seen bearer.
+
+	3. Connect last seen bearer, in case the timestamps are the same BR/EDR
+	takes precedence.
+
+	Possible errors:
+
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.AlreadyConnected:
+
+void Disconnect()
+`````````````````
+
+	Disconnects all connected profiles and then terminates low-level ACL
+	connection.
+
+	ACL connection will be terminated even if some profiles were not
+	disconnected properly e.g. due to misbehaving device.
+
+	This method can be also used to cancel a preceding Connect call before
+	a reply to it has been received.
+
+	For non-trusted devices connected over LE bearer calling this method
+	will disable incoming connections until Connect method is called again.
+
+	Possible errors:
+
+	:org.bluez.Error.NotConnected:
+
+void ConnectProfile(string uuid)
+````````````````````````````````
+
+	Connects a specific profile of this device. The UUID provided is the
+	remote service UUID for the profile.
+
+	Possible errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotAvailable:
+	:org.bluez.Error.NotReady:
+
+void DisconnectProfile(string uuid)
+```````````````````````````````````
+
+	Disconnects a specific profile of this device. The profile needs to be
+	registered client profile.
+
+	There is no connection tracking for a profile, so as long as the
+	profile is registered this will always succeed.
+
+	Possible errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+
+void Pair()
+```````````
+
+	Connects to the remote device and initiate pairing procedure then
+	proceed with service discovery.
+
+	If the application has registered its own agent, then that specific
+	agent will be used. Otherwise it will use the default agent.
+
+	Only for applications like a pairing wizard it would make sense to have
+	its own agent. In almost all other cases the default agent will handle
+	this just fine.
+
+	In case there is no application agent and also no default agent present,
+	this method will fail.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.AlreadyExists:
+	:org.bluez.Error.AuthenticationCanceled:
+	:org.bluez.Error.AuthenticationFailed:
+	:org.bluez.Error.AuthenticationRejected:
+	:org.bluez.Error.AuthenticationTimeout:
+	:org.bluez.Error.ConnectionAttemptFailed:
+
+void CancelPairing()
+````````````````````
+
+	Cancels a pairing operation initiated by the **Pair** method.
+
+	Possible errors:
+
+	:org.bluez.Error.DoesNotExist:
+	:org.bluez.Error.Failed:
+
+array{array{byte}} GetServiceRecords() [experimental]
+`````````````````````````````````````````````````````
+
+	Returns all currently known BR/EDR service records for the device. Each
+	individual byte array represents a raw SDP record, as defined by the
+	Bluetooth Service Discovery Protocol specification.
+
+	This method is intended to be only used by compatibility layers like
+	Wine, that need to provide access to raw SDP records to support foreign
+	Bluetooth APIs. General applications should instead use the Profile API
+	for services-related functionality.
+
+	Possible errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.NotConnected:
+	:org.bluez.Error.DoesNotExist:
+
+Properties
+----------
+
+string Address [readonly]
+`````````````````````````
+
+	The Bluetooth device address of the remote device.
+
+string AddressType [readonly]
+`````````````````````````````
+
+	The Bluetooth device Address Type. For dual-mode and BR/EDR only devices
+	this defaults to "public". Single mode LE devices may have either value.
+	If remote device uses privacy than before pairing this represents
+	address type used for connection and Identity Address after pairing.
+
+	Possible values:
+
+	:"public":
+
+		Public address
+
+	:"random":
+
+		Random address
+
+string Name [readonly, optional]
+````````````````````````````````
+
+	The Bluetooth remote name.
+
+	This value is only present for completeness. It is better to always use
+	the **Alias** property when displaying the devices name.
+
+	If the **Alias** property is unset, it will reflect this value which
+	makes it more convenient.
+
+string Icon [readonly, optional]
+````````````````````````````````
+
+	Proposed icon name according to the freedesktop.org icon naming
+	specification.
+
+uint32 Class [readonly, optional]
+`````````````````````````````````
+
+	The Bluetooth class of device of the remote device.
+
+uint16 Appearance [readonly, optional]
+``````````````````````````````````````
+
+	External appearance of device, as found on GAP service.
+
+array{string} UUIDs [readonly, optional]
+````````````````````````````````````````
+
+	List of 128-bit UUIDs that represents the available remote services.
+
+boolean Paired [readonly]
+`````````````````````````
+
+	Indicates if the remote device is paired. Paired means the pairing
+	process where devices exchange the information to establish an
+	encrypted connection has been completed.
+
+boolean Bonded [readonly]
+`````````````````````````
+
+	Indicates if the remote device is bonded. Bonded means the information
+	exchanged on pairing process has been stored and will be persisted.
+
+boolean Connected [readonly]
+````````````````````````````
+
+	Indicates if the remote device is currently connected.
+	A PropertiesChanged signal indicate changes to this status.
+
+boolean Trusted [readwrite]
+```````````````````````````
+
+	Indicates if the remote is seen as trusted. This setting can be changed
+	by the application.
+
+boolean Blocked [readwrite]
+```````````````````````````
+
+	If set to true any incoming connections from the device will be
+	immediately rejected. Any device drivers will also be removed and
+	no new ones will be probed as long as the device is blocked.
+
+boolean WakeAllowed [readwrite]
+```````````````````````````````
+
+	If set to true this device will be allowed to wake the host from
+	system suspend.
+
+string Alias [readwrite]
+````````````````````````
+
+	The name alias for the remote device. The alias can be used to have a
+	different friendly name for the remote device.
+
+	In case no alias is set, it will return the remote device name. Setting
+	an empty string as alias will convert it back to the remote device name.
+
+	When resetting the alias with an empty string, the property will default
+	back to the remote name.
+
+object Adapter [readonly]
+`````````````````````````
+
+	The object path of the adapter the device belongs to.
+
+boolean LegacyPairing [readonly]
+````````````````````````````````
+
+	Set to true if the device only supports the pre-2.1 pairing mechanism.
+	This property is useful during device discovery to anticipate whether
+	legacy or simple pairing will occur if pairing is initiated.
+
+	Note that this property can exhibit false-positives in the case of
+	Bluetooth 2.1 (or newer) devices that have disabled Extended Inquiry
+	Response support.
+
+string Modalias [readonly, optional]
+````````````````````````````````````
+
+	Remote Device ID information in modalias format used by the kernel and
+	udev.
+
+int16 RSSI [readonly, optional]
+```````````````````````````````
+
+	Received Signal Strength Indicator of the remote device (inquiry or
+	advertising).
+
+int16 TxPower [readonly, optional]
+``````````````````````````````````
+
+	Advertised transmitted power level (inquiry or advertising).
+
+dict ManufacturerData [readonly, optional]
+``````````````````````````````````````````
+
+	Manufacturer specific advertisement data. Keys are 16 bits Manufacturer
+	ID followed by its byte array value.
+
+dict ServiceData [readonly, optional]
+`````````````````````````````````````
+
+	Service advertisement data. Keys are the UUIDs in string format followed
+	by its byte array value.
+
+bool ServicesResolved [readonly]
+````````````````````````````````
+
+	Indicate whether or not service discovery has been resolved.
+
+array{byte} AdvertisingFlags [readonly]
+```````````````````````````````````````
+
+	The Advertising Data Flags of the remote device.
+
+dict AdvertisingData [readonly]
+```````````````````````````````
+
+	The Advertising Data of the remote device. Keys are 1 byte AD Type
+	followed by data as byte array.
+
+	Note: Only types considered safe to be handled by application are
+	exposed.
+
+	Possible values:
+
+	:<type>:
+
+		<byte array>
+
+	Example:
+
+		<Transport Discovery> <Organization Flags...>
+		0x26                   0x01         0x01...
+
+array{object, dict} Sets [readonly, experimental]
+`````````````````````````````````````````````````
+
+	The object paths of the sets the device belongs to followed by a
+	dictionary which can contain the following:
+
+	:byte Rank:
+
+		Rank of the device in the Set.
diff --git a/doc/org.bluez.DeviceSet.5 b/doc/org.bluez.DeviceSet.5
new file mode 100644
index 0000000..4386152
--- /dev/null
+++ b/doc/org.bluez.DeviceSet.5
@@ -0,0 +1,107 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.DEVICESET" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.DeviceSet \- BlueZ D-Bus DeviceSet API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.DeviceSet1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/set_{sirk}
+.UNINDENT
+.SS Methods
+.SS void Connect() [experimental]
+.INDENT 0.0
+.INDENT 3.5
+Connects all \fBdevices\fP members of the set, each member is
+connected in sequence as they were added/loaded following the
+same proceedure as described in \fBDevice1.Connect\fP\&.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotReady
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.AlreadyConnected
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Disconnect() [experimental]
+.INDENT 0.0
+.INDENT 3.5
+Disconnects all \fBdevices\fP members of the set, each member is
+disconnected in sequence as they were connected following the
+same proceedure as described in \fBDevice1.Disconnect\fP\&.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotConnected
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS object Adapter [readonly, experimental]
+.INDENT 0.0
+.INDENT 3.5
+The object path of the adapter the set belongs to.
+.UNINDENT
+.UNINDENT
+.SS bool AutoConnect [read\-write, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the \fBdevices\fP members of the set shall be automatically
+connected once any of its members is connected.
+.UNINDENT
+.UNINDENT
+.SS array(object) Devices [ready\-only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+List of devices objects that are members of the set.
+.UNINDENT
+.UNINDENT
+.SS byte Size [read\-only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Set members size.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.DeviceSet.rst b/doc/org.bluez.DeviceSet.rst
new file mode 100644
index 0000000..c6dc8b0
--- /dev/null
+++ b/doc/org.bluez.DeviceSet.rst
@@ -0,0 +1,71 @@
+===================
+org.bluez.DeviceSet
+===================
+
+---------------------------------------
+BlueZ D-Bus DeviceSet API documentation
+---------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.DeviceSet1
+:Object path:	[variable prefix]/{hci0,hci1,...}/set_{sirk}
+
+Methods
+-------
+
+void Connect() [experimental]
+`````````````````````````````
+
+	Connects all **devices** members of the set, each member is
+	connected in sequence as they were added/loaded following the
+	same proceedure as described in **Device1.Connect**.
+
+	Possible errors:
+
+	:org.bluez.Error.NotReady:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.AlreadyConnected:
+
+void Disconnect() [experimental]
+````````````````````````````````
+
+	Disconnects all **devices** members of the set, each member is
+	disconnected in sequence as they were connected following the
+	same proceedure as described in **Device1.Disconnect**.
+
+	Possible errors:
+
+	:org.bluez.Error.NotConnected:
+
+Properties
+----------
+
+object Adapter [readonly, experimental]
+```````````````````````````````````````
+
+	The object path of the adapter the set belongs to.
+
+bool AutoConnect [read-write, experimental]
+```````````````````````````````````````````
+
+	Indicates if the **devices** members of the set shall be automatically
+	connected once any of its members is connected.
+
+array(object) Devices [ready-only, experimental]
+````````````````````````````````````````````````
+
+	List of devices objects that are members of the set.
+
+byte Size [read-only, experimental]
+```````````````````````````````````
+
+	Set members size.
diff --git a/doc/org.bluez.GattCharacteristic.5 b/doc/org.bluez.GattCharacteristic.5
new file mode 100644
index 0000000..3ff54b6
--- /dev/null
+++ b/doc/org.bluez.GattCharacteristic.5
@@ -0,0 +1,478 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.GATTCHARACTERISTIC" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.GattCharacteristic \- BlueZ D-Bus GattCharacteristic API documentation
+.SH DESCRIPTION
+.sp
+GATT local/server and remote/client characteristic attribute representation
+share the same high\-level D\-Bus API.
+.sp
+Local/Server refers to GATT based characteristics exported by a plugin or an
+external application.
+.sp
+Remote/Client refers to GATT characteristics exported by the peer.
+.SH INTERFACE
+.SS Client
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.GattCharacteristic1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+.UNINDENT
+.SS Server
+.INDENT 0.0
+.TP
+.B Service
+unique name
+.TP
+.B Interface
+org.bluez.GattCharacteristic1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS array{byte} ReadValue(dict options)
+.INDENT 0.0
+.INDENT 3.5
+Issues a request to read the value of the characteristic and returns the
+value if the operation was successful.
+.sp
+Possible options:
+.INDENT 0.0
+.TP
+.B uint16_t offset
+Read start offset in bytes.
+.TP
+.B uint16_t mtu (server only)
+Exchange MTU in bytes.
+.TP
+.B object device (server only)
+Device object.
+.TP
+.B string link (server only)
+Link type.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+Possible values: string 0x80 \- 0x9f
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.NotPermitted
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.InvalidOffset
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void WriteValue(array{byte} value, dict options)
+.INDENT 0.0
+.INDENT 3.5
+Issues a request to write the value of the characteristic.
+.sp
+Possible options:
+.INDENT 0.0
+.TP
+.B uint16 offset
+Write start offset in bytes.
+.TP
+.B string type
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqcommand\(dq
+Use Write without response procedure.
+.TP
+.B \(dqrequest\(dq
+Use Write with response procedure.
+.TP
+.B \(dqreliable\(dq
+Use Reliable Write procedure.
+.UNINDENT
+.TP
+.B uint16 mtu
+Exchanged MTU (Server only).
+.TP
+.B object device
+Device path (Server only).
+.TP
+.B string link
+Link type (Server only).
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.TP
+.B boolean prepare\-authorize
+True if prepare authorization request.
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+Possible values: string 0x80 \- 0x9f
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.NotPermitted
+.TP
+.B org.bluez.Error.InvalidValueLength
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.ImproperlyConfigured
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS fd, uint16 AcquireWrite(dict options) [optional]
+.INDENT 0.0
+.INDENT 3.5
+Acquire file descriptor and MTU for writing. Only sockets are supported.
+Usage of WriteValue will be locked causing it to return NotPermitted
+error.
+.sp
+For server the MTU returned shall be equal or smaller than the
+negotiated MTU.
+.sp
+For client it only works with characteristic that has \fBWriteAcquired\fP
+property which relies on write\-without\-response \fBFlag\fP\&.
+.sp
+To release the lock the client shall close the file descriptor, a HUP
+is generated in case the device is disconnected.
+.sp
+Note: the MTU can only be negotiated once and is symmetric therefore
+this method may be delayed in order to have the exchange MTU completed,
+because of that the file descriptor is closed during reconnections as
+the MTU has to be renegotiated.
+.sp
+Possible options:
+.INDENT 0.0
+.TP
+.B object device
+Object Device (Server only).
+.TP
+.B uint16 mtu
+Exchanged MTU (Server only).
+.TP
+.B string link
+Link type (Server only).
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS fd, uint16 AcquireNotify(dict options) [optional]
+.INDENT 0.0
+.INDENT 3.5
+Acquire file descriptor and MTU for notify. Only sockets are support.
+.sp
+Usage of StartNotify will be locked causing it to return
+\fBorg.bluez.Error.NotPermitted\fP\&.
+.sp
+For server the MTU returned shall be equal or smaller than the
+negotiated MTU.
+.sp
+Only works with characteristic that has \fBNotifyAcquired\fP property
+which relies on \fB\(dqnotify\(dq\fP \fBFlag\fP and no other client have called
+\fBStartNotify()\fP\&.
+.sp
+Notification are enabled during this procedure so \fBStartNotify()\fP
+shall not be called, any notification will be dispatched via file
+descriptor therefore the Value property is not affected during the time
+where notify has been acquired.
+.sp
+To release the lock the client shall close the file descriptor, a HUP is
+generated in case the device is disconnected.
+.sp
+Note: the MTU can only be negotiated once and is symmetric therefore
+this method may be delayed in order to have the exchange MTU completed,
+because of that the file descriptor is closed during reconnections as
+the MTU has to be renegotiated.
+.sp
+Possible options:
+.INDENT 0.0
+.TP
+.B object device
+Object Device (Server only).
+.TP
+.B uint16 mtu
+Exchanged MTU (Server only).
+.TP
+.B string link
+Link type (Server only).
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.NotPermitted
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void StartNotify()
+.INDENT 0.0
+.INDENT 3.5
+Starts a notification session from this characteristic if it supports
+value notifications or indications.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotPermitted
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.NotConnected
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void StopNotify()
+.INDENT 0.0
+.INDENT 3.5
+Stops or cancel session previously created by \fBStartNotify()\fP\&.
+.sp
+Note that notifications from a characteristic are shared between
+sessions thus calling StopNotify will release a single session.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Confirm() [noreply, optional] (Server only)
+.INDENT 0.0
+.INDENT 3.5
+Confirms value was received.
+.sp
+Possible Errors:
+.sp
+org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string UUID [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+128\-bit characteristic UUID.
+.UNINDENT
+.UNINDENT
+.SS object Service [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Object path of the GATT service the characteristic belongs to.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Value [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+The cached value of the characteristic. This property gets updated only
+after a successful read request and when a notification or indication
+is received, upon which a PropertiesChanged signal will be emitted.
+.UNINDENT
+.UNINDENT
+.SS boolean WriteAcquired [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+True, if this characteristic has been acquired by any client using
+AcquireWrite.
+.sp
+For client properties is ommited in case \(aqwrite\-without\-response\(aq flag
+is not set.
+.sp
+For server the presence of this property indicates that AcquireWrite is
+supported.
+.UNINDENT
+.UNINDENT
+.SS boolean NotifyAcquired [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+True, if this characteristic has been acquired by any client using
+AcquireNotify.
+.sp
+For client this properties is ommited in case \(aqnotify\(aq flag is not set.
+.sp
+For server the presence of this property indicates that AcquireNotify
+is supported.
+.UNINDENT
+.UNINDENT
+.SS boolean Notifying [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+True, if notifications or indications on this characteristic are
+currently enabled.
+.UNINDENT
+.UNINDENT
+.SS array{string} Flags [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Defines how the characteristic value can be used. See Core spec
+\(dqTable 3.5: Characteristic Properties bit field\(dq, and
+\(dqTable 3.8: Characteristic Extended Properties bit field\(dq.
+.sp
+The \(dqx\-notify\(dq and \(dqx\-indicate\(dq flags restrict access to notifications
+and indications by imposing write restrictions on a characteristic\(aqs
+client characteristic configuration descriptor.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqbroadcast\(dq
+.TP
+.B \(dqread\(dq
+.TP
+.B \(dqwrite\-without\-response\(dq
+.TP
+.B \(dqwrite\(dq
+.TP
+.B \(dqnotify\(dq
+.TP
+.B \(dqindicate\(dq
+.TP
+.B \(dqauthenticated\-signed\-writes\(dq
+.TP
+.B \(dqextended\-properties\(dq
+.TP
+.B \(dqreliable\-write\(dq
+.TP
+.B \(dqwritable\-auxiliaries\(dq
+.TP
+.B \(dqencrypt\-read\(dq
+.TP
+.B \(dqencrypt\-write\(dq
+.TP
+.B \(dqencrypt\-notify\(dq (Server only)
+.TP
+.B \(dqencrypt\-indicate\(dq (Server only)
+.TP
+.B \(dqencrypt\-authenticated\-read\(dq
+.TP
+.B \(dqencrypt\-authenticated\-write\(dq
+.TP
+.B \(dqencrypt\-authenticated\-notify\(dq (Server only)
+.TP
+.B \(dqencrypt\-authenticated\-indicate\(dq (Server only)
+.TP
+.B \(dqsecure\-read\(dq (Server only)
+.TP
+.B \(dqsecure\-write\(dq (Server only)
+.TP
+.B \(dqsecure\-notify\(dq (Server only)
+.TP
+.B \(dqsecure\-indicate\(dq (Server only)
+.TP
+.B \(dqauthorize\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-only] (Client Only)
+.INDENT 0.0
+.INDENT 3.5
+Characteristic handle.
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-write, optional] (Server Only)
+.INDENT 0.0
+.INDENT 3.5
+Characteristic handle. When available in the server it would attempt to
+use to allocate into the database which may fail, to auto allocate the
+value 0x0000 shall be used which will cause the allocated handle to be
+set once registered.
+.UNINDENT
+.UNINDENT
+.SS uint16 MTU [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Characteristic MTU, this is valid both for \fBReadValue()\fP and
+\fBWriteValue()\fP but either method can use long procedures when
+supported.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.GattCharacteristic.rst b/doc/org.bluez.GattCharacteristic.rst
new file mode 100644
index 0000000..a43476d
--- /dev/null
+++ b/doc/org.bluez.GattCharacteristic.rst
@@ -0,0 +1,385 @@
+============================
+org.bluez.GattCharacteristic
+============================
+
+------------------------------------------------
+BlueZ D-Bus GattCharacteristic API documentation
+------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+GATT local/server and remote/client characteristic attribute representation
+share the same high-level D-Bus API.
+
+Local/Server refers to GATT based characteristics exported by a plugin or an
+external application.
+
+Remote/Client refers to GATT characteristics exported by the peer.
+
+Interface
+=========
+
+Client
+------
+
+:Service:	org.bluez
+:Interface:	org.bluez.GattCharacteristic1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Server
+------
+
+:Service:	unique name
+:Interface:	org.bluez.GattCharacteristic1
+:Object path:	freely definable
+
+Methods
+-------
+
+array{byte} ReadValue(dict options)
+```````````````````````````````````
+
+	Issues a request to read the value of the characteristic and returns the
+	value if the operation was successful.
+
+	Possible options:
+
+	:uint16_t offset:
+
+		Read start offset in bytes.
+
+	:uint16_t mtu (server only):
+
+		Exchange MTU in bytes.
+
+	:object device (server only):
+
+		Device object.
+
+	:string link (server only):
+
+		Link type.
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+
+		Possible values: string 0x80 - 0x9f
+
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.NotPermitted:
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.InvalidOffset:
+	:org.bluez.Error.NotSupported:
+
+void WriteValue(array{byte} value, dict options)
+````````````````````````````````````````````````
+
+	Issues a request to write the value of the characteristic.
+
+	Possible options:
+
+	:uint16 offset:
+
+		Write start offset in bytes.
+
+	:string type:
+
+		Possible values:
+
+		:"command":
+
+			Use Write without response procedure.
+
+		:"request":
+
+			Use Write with response procedure.
+
+		:"reliable":
+
+			Use Reliable Write procedure.
+
+	:uint16 mtu:
+
+		Exchanged MTU (Server only).
+
+	:object device:
+
+		Device path (Server only).
+
+	:string link:
+
+		Link type (Server only).
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	:boolean prepare-authorize:
+
+		True if prepare authorization request.
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+
+		Possible values: string 0x80 - 0x9f
+
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.NotPermitted:
+	:org.bluez.Error.InvalidValueLength:
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.ImproperlyConfigured:
+
+fd, uint16 AcquireWrite(dict options) [optional]
+````````````````````````````````````````````````
+
+	Acquire file descriptor and MTU for writing. Only sockets are supported.
+	Usage of WriteValue will be locked causing it to return NotPermitted
+	error.
+
+	For server the MTU returned shall be equal or smaller than the
+	negotiated MTU.
+
+	For client it only works with characteristic that has **WriteAcquired**
+	property which relies on write-without-response **Flag**.
+
+	To release the lock the client shall close the file descriptor, a HUP
+	is generated in case the device is disconnected.
+
+	Note: the MTU can only be negotiated once and is symmetric therefore
+	this method may be delayed in order to have the exchange MTU completed,
+	because of that the file descriptor is closed during reconnections as
+	the MTU has to be renegotiated.
+
+	Possible options:
+
+	:object device:
+
+		Object Device (Server only).
+
+	:uint16 mtu:
+
+		Exchanged MTU (Server only).
+
+	:string link:
+
+		Link type (Server only).
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotSupported:
+
+fd, uint16 AcquireNotify(dict options) [optional]
+`````````````````````````````````````````````````
+
+	Acquire file descriptor and MTU for notify. Only sockets are support.
+
+	Usage of StartNotify will be locked causing it to return
+	**org.bluez.Error.NotPermitted**.
+
+	For server the MTU returned shall be equal or smaller than the
+	negotiated MTU.
+
+	Only works with characteristic that has **NotifyAcquired** property
+	which relies on **"notify"** **Flag** and no other client have called
+	**StartNotify()**.
+
+	Notification are enabled during this procedure so **StartNotify()**
+	shall not be called, any notification will be dispatched via file
+	descriptor therefore the Value property is not affected during the time
+	where notify has been acquired.
+
+	To release the lock the client shall close the file descriptor, a HUP is
+	generated in case the device is disconnected.
+
+	Note: the MTU can only be negotiated once and is symmetric therefore
+	this method may be delayed in order to have the exchange MTU completed,
+	because of that the file descriptor is closed during reconnections as
+	the MTU has to be renegotiated.
+
+	Possible options:
+
+	:object device:
+
+		Object Device (Server only).
+
+	:uint16 mtu:
+
+		Exchanged MTU (Server only).
+
+	:string link:
+
+		Link type (Server only).
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.NotPermitted:
+
+void StartNotify()
+``````````````````
+
+	Starts a notification session from this characteristic if it supports
+	value notifications or indications.
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotPermitted:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.NotConnected:
+	:org.bluez.Error.NotSupported:
+
+void StopNotify()
+`````````````````
+
+	Stops or cancel session previously created by **StartNotify()**.
+
+	Note that notifications from a characteristic are shared between
+	sessions thus calling StopNotify will release a single session.
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+
+void Confirm() [noreply, optional] (Server only)
+````````````````````````````````````````````````
+
+
+	Confirms value was received.
+
+	Possible Errors:
+
+	org.bluez.Error.Failed
+
+Properties
+----------
+
+string UUID [read-only]
+```````````````````````
+
+	128-bit characteristic UUID.
+
+object Service [read-only]
+``````````````````````````
+
+	Object path of the GATT service the characteristic belongs to.
+
+array{byte} Value [read-only, optional]
+```````````````````````````````````````
+
+	The cached value of the characteristic. This property gets updated only
+	after a successful read request and when a notification or indication
+	is received, upon which a PropertiesChanged signal will be emitted.
+
+boolean WriteAcquired [read-only, optional]
+```````````````````````````````````````````
+
+	True, if this characteristic has been acquired by any client using
+	AcquireWrite.
+
+	For client properties is ommited in case 'write-without-response' flag
+	is not set.
+
+	For server the presence of this property indicates that AcquireWrite is
+	supported.
+
+boolean NotifyAcquired [read-only, optional]
+````````````````````````````````````````````
+
+	True, if this characteristic has been acquired by any client using
+	AcquireNotify.
+
+	For client this properties is ommited in case 'notify' flag is not set.
+
+	For server the presence of this property indicates that AcquireNotify
+	is supported.
+
+boolean Notifying [read-only, optional]
+```````````````````````````````````````
+
+	True, if notifications or indications on this characteristic are
+	currently enabled.
+
+array{string} Flags [read-only]
+```````````````````````````````
+
+	Defines how the characteristic value can be used. See Core spec
+	"Table 3.5: Characteristic Properties bit field", and
+	"Table 3.8: Characteristic Extended Properties bit field".
+
+	The "x-notify" and "x-indicate" flags restrict access to notifications
+	and indications by imposing write restrictions on a characteristic's
+	client characteristic configuration descriptor.
+
+	Possible values:
+
+	:"broadcast":
+	:"read":
+	:"write-without-response":
+	:"write":
+	:"notify":
+	:"indicate":
+	:"authenticated-signed-writes":
+	:"extended-properties":
+	:"reliable-write":
+	:"writable-auxiliaries":
+	:"encrypt-read":
+	:"encrypt-write":
+	:"encrypt-notify" (Server only):
+	:"encrypt-indicate" (Server only):
+	:"encrypt-authenticated-read":
+	:"encrypt-authenticated-write":
+	:"encrypt-authenticated-notify" (Server only):
+	:"encrypt-authenticated-indicate" (Server only):
+	:"secure-read" (Server only):
+	:"secure-write" (Server only):
+	:"secure-notify" (Server only):
+	:"secure-indicate" (Server only):
+	:"authorize":
+
+uint16 Handle [read-only] (Client Only)
+```````````````````````````````````````
+
+	Characteristic handle.
+
+uint16 Handle [read-write, optional] (Server Only)
+``````````````````````````````````````````````````
+
+	Characteristic handle. When available in the server it would attempt to
+	use to allocate into the database which may fail, to auto allocate the
+	value 0x0000 shall be used which will cause the allocated handle to be
+	set once registered.
+
+uint16 MTU [read-only]
+``````````````````````
+
+	Characteristic MTU, this is valid both for **ReadValue()** and
+	**WriteValue()** but either method can use long procedures when
+	supported.
diff --git a/doc/org.bluez.GattDescriptor.5 b/doc/org.bluez.GattDescriptor.5
new file mode 100644
index 0000000..40b36fa
--- /dev/null
+++ b/doc/org.bluez.GattDescriptor.5
@@ -0,0 +1,226 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.GATTDESCRIPTOR" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.GattDescriptor \- BlueZ D-Bus GattDescriptor API documentation
+.SH DESCRIPTION
+.sp
+GATT local/server and remote/client descriptor attribute representation
+share the same high\-level D\-Bus API.
+.sp
+Local/Server refers to GATT based descriptors exported by a plugin or an
+external application.
+.sp
+Remote/Client refers to GATT descriptors exported by the peer.
+.SH INTERFACE
+.SS Client
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.GattDescriptor1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+.UNINDENT
+.SS Server
+.INDENT 0.0
+.TP
+.B Service
+unique name
+.TP
+.B Interface
+org.bluez.GattDescriptor1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS array{byte} ReadValue(dict flags)
+.INDENT 0.0
+.INDENT 3.5
+Issues a request to read the value of the descriptor and returns the
+value if the operation was successful.
+.sp
+Possible options:
+.INDENT 0.0
+.TP
+.B uint16_t offset
+Read start offset in bytes.
+.TP
+.B object device (server only)
+Device object.
+.TP
+.B string link
+Link type (Server only).
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.NotPermitted
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void WriteValue(array{byte} value, dict flags)
+.INDENT 0.0
+.INDENT 3.5
+Issues a request to write the value of the descriptor.
+.sp
+Possible flags:
+.INDENT 0.0
+.TP
+.B uint16 offset
+Write start offset in bytes.
+.TP
+.B uint16 mtu
+Exchanged MTU (Server only).
+.TP
+.B object device
+Device path (Server only).
+.TP
+.B string link
+Link type (Server only).
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBR/EDR\(dq
+.TP
+.B \(dqLE\(dq
+.UNINDENT
+.TP
+.B boolean prepare\-authorize
+True if prepare authorization request.
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.NotPermitted
+.TP
+.B org.bluez.Error.InvalidValueLength
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.ImproperlyConfigured
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string UUID [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+128\-bit descriptor UUID.
+.UNINDENT
+.UNINDENT
+.SS object Characteristic [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Object path of the GATT characteristic the descriptor belongs to.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Value [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+The cached value of the descriptor. This property gets updated only
+after a successful read request, upon which a PropertiesChanged signal
+will be emitted.
+.UNINDENT
+.UNINDENT
+.SS array{string} Flags [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Defines how the descriptor value can be used.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqread\(dq
+.TP
+.B \(dqwrite\(dq
+.TP
+.B \(dqencrypt\-read\(dq
+.TP
+.B \(dqencrypt\-write\(dq
+.TP
+.B \(dqencrypt\-authenticated\-read\(dq
+.TP
+.B \(dqencrypt\-authenticated\-write\(dq
+.TP
+.B \(dqsecure\-read\(dq (Server Only)
+.TP
+.B \(dqsecure\-write\(dq (Server Only)
+.TP
+.B \(dqauthorize\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-only] (Client Only)
+.INDENT 0.0
+.INDENT 3.5
+Descriptor handle.
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-write, optional] (Server Only)
+.INDENT 0.0
+.INDENT 3.5
+Descriptor handle. When available in the server it would attempt to
+use to allocate into the database which may fail, to auto allocate the
+value 0x0000 shall be used which will cause the allocated handle to be
+set once registered.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.GattDescriptor.rst b/doc/org.bluez.GattDescriptor.rst
new file mode 100644
index 0000000..f4497c6
--- /dev/null
+++ b/doc/org.bluez.GattDescriptor.rst
@@ -0,0 +1,168 @@
+========================
+org.bluez.GattDescriptor
+========================
+
+--------------------------------------------
+BlueZ D-Bus GattDescriptor API documentation
+--------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+GATT local/server and remote/client descriptor attribute representation
+share the same high-level D-Bus API.
+
+Local/Server refers to GATT based descriptors exported by a plugin or an
+external application.
+
+Remote/Client refers to GATT descriptors exported by the peer.
+
+Interface
+=========
+
+Client
+------
+
+:Service:	org.bluez
+:Interface:	org.bluez.GattDescriptor1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Server
+------
+
+:Service:	unique name
+:Interface:	org.bluez.GattDescriptor1
+:Object path:	freely definable
+
+Methods
+-------
+
+array{byte} ReadValue(dict flags)
+`````````````````````````````````
+
+	Issues a request to read the value of the descriptor and returns the
+	value if the operation was successful.
+
+	Possible options:
+
+	:uint16_t offset:
+
+		Read start offset in bytes.
+
+	:object device (server only):
+
+		Device object.
+
+	:string link:
+
+		Link type (Server only).
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.NotPermitted:
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.NotSupported:
+
+void WriteValue(array{byte} value, dict flags)
+``````````````````````````````````````````````
+
+	Issues a request to write the value of the descriptor.
+
+	Possible flags:
+
+	:uint16 offset:
+
+		Write start offset in bytes.
+
+	:uint16 mtu:
+
+		Exchanged MTU (Server only).
+
+	:object device:
+
+		Device path (Server only).
+
+	:string link:
+
+		Link type (Server only).
+
+		Possible values:
+
+		:"BR/EDR":
+		:"LE":
+
+	:boolean prepare-authorize:
+
+		True if prepare authorization request.
+
+	Possible Errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.NotPermitted:
+	:org.bluez.Error.InvalidValueLength:
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.ImproperlyConfigured:
+
+Properties
+----------
+
+string UUID [read-only]
+```````````````````````
+
+	128-bit descriptor UUID.
+
+object Characteristic [read-only]
+`````````````````````````````````
+
+	Object path of the GATT characteristic the descriptor belongs to.
+
+array{byte} Value [read-only, optional]
+```````````````````````````````````````
+
+	The cached value of the descriptor. This property gets updated only
+	after a successful read request, upon which a PropertiesChanged signal
+	will be emitted.
+
+array{string} Flags [read-only]
+```````````````````````````````
+
+	Defines how the descriptor value can be used.
+
+	Possible values:
+
+	:"read":
+	:"write":
+	:"encrypt-read":
+	:"encrypt-write":
+	:"encrypt-authenticated-read":
+	:"encrypt-authenticated-write":
+	:"secure-read" (Server Only):
+	:"secure-write" (Server Only):
+	:"authorize":
+
+uint16 Handle [read-only] (Client Only)
+```````````````````````````````````````
+
+	Descriptor handle.
+
+uint16 Handle [read-write, optional] (Server Only)
+``````````````````````````````````````````````````
+
+	Descriptor handle. When available in the server it would attempt to
+	use to allocate into the database which may fail, to auto allocate the
+	value 0x0000 shall be used which will cause the allocated handle to be
+	set once registered.
diff --git a/doc/org.bluez.GattManager.5 b/doc/org.bluez.GattManager.5
new file mode 100644
index 0000000..7285048
--- /dev/null
+++ b/doc/org.bluez.GattManager.5
@@ -0,0 +1,149 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.GATTMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.GattManager \- BlueZ D-Bus GattManager API documentation
+.SH DESCRIPTION
+.sp
+GATT Manager allows external applications to register GATT services and
+profiles.
+.sp
+Registering a profile allows applications to subscribe to \fIremote/client\fP
+services.
+.sp
+Registering a service allows applications to publish a \fIlocal/server\fP GATT
+service, which then becomes available to remote devices. A GATT service is
+represented by a D\-Bus object hierarchy where the root node corresponds to a
+service and the child nodes represent characteristics and descriptors that
+belong to that service. Each node must implement one of
+\fBorg.bluez.GattService(5)\fP, \fBorg.bluez.GattCharacteristic(5)\fP or
+\fBorg.bluez.GattDescriptor(5)\fP interfaces, based on the attribute it
+represents. Each node must also implement the standard D\-Bus Properties
+interface to expose their properties. These objects collectively represent a
+GATT service definition.
+.sp
+To make service registration simple, \fBbluetoothd(8)\fP requires that all objects
+that belong to a GATT service be grouped under a D\-Bus Object Manager that
+solely manages the objects of that service. Hence, the standard
+DBus.ObjectManager interface must be available on the root service path. An
+example application hierarchy containing two separate GATT services may look
+like this:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+\-> /com/example
+  |   \- org.freedesktop.DBus.ObjectManager
+  |
+  \-> /com/example/service0
+  | |   \- org.freedesktop.DBus.Properties
+  | |   \- org.bluez.GattService1
+  | |
+  | \-> /com/example/service0/char0
+  | |     \- org.freedesktop.DBus.Properties
+  | |     \- org.bluez.GattCharacteristic1
+  | |
+  | \-> /com/example/service0/char1
+  |   |   \- org.freedesktop.DBus.Properties
+  |   |   \- org.bluez.GattCharacteristic1
+  |   |
+  |   \-> /com/example/service0/char1/desc0
+  |       \- org.freedesktop.DBus.Properties
+  |       \- org.bluez.GattDescriptor1
+  |
+  \-> /com/example/service1
+    |   \- org.freedesktop.DBus.Properties
+    |   \- org.bluez.GattService1
+    |
+   \-> /com/example/service1/char0
+        \- org.freedesktop.DBus.Properties
+        \- org.bluez.GattCharacteristic1
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+When a service is registered, \fBbluetoothd(8)\fP will automatically obtain
+information about all objects using the service\(aqs Object Manager. Once a service
+has been registered, the objects of a service should not be removed. If
+\fBbluetoothd(8)\fP receives an InterfacesRemoved signal from a service\(aqs Object
+Manager, it will immediately unregister the service. Similarly, if the
+application disconnects from the bus, all of its registered services will be
+automatically unregistered. InterfacesAdded signals will be ignored.
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.GattManager1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void RegisterApplication(object application, dict options)
+.INDENT 0.0
+.INDENT 3.5
+Registers a local GATT services hierarchy as described above
+(GATT Server) and/or GATT profiles (GATT Client).
+.sp
+The application object path together with the D\-Bus system bus
+connection ID define the identification of the application registering
+a GATT based service (\fBorg.bluez.GattService(5)\fP) and/or profile
+(\fBorg.bluez.GattProfile(5)\fP).
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterApplication(object application)
+.INDENT 0.0
+.INDENT 3.5
+This unregisters the services and/or profiles that has been previously
+registered using \fBRegisterApplication()\fP\&. The object path parameter
+must match the same value that has been used on registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.GattManager.rst b/doc/org.bluez.GattManager.rst
new file mode 100644
index 0000000..f98296b
--- /dev/null
+++ b/doc/org.bluez.GattManager.rst
@@ -0,0 +1,114 @@
+=====================
+org.bluez.GattManager
+=====================
+
+-----------------------------------------
+BlueZ D-Bus GattManager API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+GATT Manager allows external applications to register GATT services and
+profiles.
+
+Registering a profile allows applications to subscribe to *remote/client*
+services.
+
+Registering a service allows applications to publish a *local/server* GATT
+service, which then becomes available to remote devices. A GATT service is
+represented by a D-Bus object hierarchy where the root node corresponds to a
+service and the child nodes represent characteristics and descriptors that
+belong to that service. Each node must implement one of
+**org.bluez.GattService(5)**, **org.bluez.GattCharacteristic(5)** or
+**org.bluez.GattDescriptor(5)** interfaces, based on the attribute it
+represents. Each node must also implement the standard D-Bus Properties
+interface to expose their properties. These objects collectively represent a
+GATT service definition.
+
+To make service registration simple, **bluetoothd(8)** requires that all objects
+that belong to a GATT service be grouped under a D-Bus Object Manager that
+solely manages the objects of that service. Hence, the standard
+DBus.ObjectManager interface must be available on the root service path. An
+example application hierarchy containing two separate GATT services may look
+like this:
+
+.. code-block::
+
+    -> /com/example
+      |   - org.freedesktop.DBus.ObjectManager
+      |
+      -> /com/example/service0
+      | |   - org.freedesktop.DBus.Properties
+      | |   - org.bluez.GattService1
+      | |
+      | -> /com/example/service0/char0
+      | |     - org.freedesktop.DBus.Properties
+      | |     - org.bluez.GattCharacteristic1
+      | |
+      | -> /com/example/service0/char1
+      |   |   - org.freedesktop.DBus.Properties
+      |   |   - org.bluez.GattCharacteristic1
+      |   |
+      |   -> /com/example/service0/char1/desc0
+      |       - org.freedesktop.DBus.Properties
+      |       - org.bluez.GattDescriptor1
+      |
+      -> /com/example/service1
+        |   - org.freedesktop.DBus.Properties
+        |   - org.bluez.GattService1
+        |
+       -> /com/example/service1/char0
+            - org.freedesktop.DBus.Properties
+            - org.bluez.GattCharacteristic1
+
+When a service is registered, **bluetoothd(8)** will automatically obtain
+information about all objects using the service's Object Manager. Once a service
+has been registered, the objects of a service should not be removed. If
+**bluetoothd(8)** receives an InterfacesRemoved signal from a service's Object
+Manager, it will immediately unregister the service. Similarly, if the
+application disconnects from the bus, all of its registered services will be
+automatically unregistered. InterfacesAdded signals will be ignored.
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.GattManager1
+:Object path:	[variable prefix]/{hci0,hci1,...}
+
+Methods
+-------
+
+void RegisterApplication(object application, dict options)
+``````````````````````````````````````````````````````````
+
+	Registers a local GATT services hierarchy as described above
+	(GATT Server) and/or GATT profiles (GATT Client).
+
+	The application object path together with the D-Bus system bus
+	connection ID define the identification of the application registering
+	a GATT based service (**org.bluez.GattService(5)**) and/or profile
+	(**org.bluez.GattProfile(5)**).
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+
+void UnregisterApplication(object application)
+``````````````````````````````````````````````
+
+	This unregisters the services and/or profiles that has been previously
+	registered using **RegisterApplication()**. The object path parameter
+	must match the same value that has been used on registration.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.DoesNotExist:
diff --git a/doc/org.bluez.GattProfile.5 b/doc/org.bluez.GattProfile.5
new file mode 100644
index 0000000..0af4335
--- /dev/null
+++ b/doc/org.bluez.GattProfile.5
@@ -0,0 +1,69 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.GATTPROFILE" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.GattProfile \- BlueZ D-Bus GattProfile API documentation
+.SH DESCRIPTION
+.sp
+Local profile (GATT client) instance. By registering this type of object
+an application effectively indicates support for a specific GATT profile
+and requests automatic connections to be established to devices
+supporting it.
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+<application dependent>
+.TP
+.B Interface
+org.bluez.GattProfile1
+.TP
+.B Object path
+<application dependent>
+.UNINDENT
+.SS Methods
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon
+unregisters the profile. The profile can use it to do cleanup tasks.
+There is no need to unregister the profile, because when this method
+gets called it has already been unregistered.
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS array{string} UUIDs [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+128\-bit GATT service UUIDs to auto connect.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.GattProfile.rst b/doc/org.bluez.GattProfile.rst
new file mode 100644
index 0000000..904301a
--- /dev/null
+++ b/doc/org.bluez.GattProfile.rst
@@ -0,0 +1,46 @@
+=====================
+org.bluez.GattProfile
+=====================
+
+-----------------------------------------
+BlueZ D-Bus GattProfile API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+Local profile (GATT client) instance. By registering this type of object
+an application effectively indicates support for a specific GATT profile
+and requests automatic connections to be established to devices
+supporting it.
+
+Interface
+=========
+
+:Service:	<application dependent>
+:Interface:	org.bluez.GattProfile1
+:Object path:	<application dependent>
+
+Methods
+-------
+
+void Release()
+``````````````
+
+	This method gets called when the service daemon
+	unregisters the profile. The profile can use it to do cleanup tasks.
+	There is no need to unregister the profile, because when this method
+	gets called it has already been unregistered.
+
+Properties
+----------
+
+array{string} UUIDs [read-only]
+```````````````````````````````
+
+	128-bit GATT service UUIDs to auto connect.
diff --git a/doc/org.bluez.GattService.5 b/doc/org.bluez.GattService.5
new file mode 100644
index 0000000..2d44b79
--- /dev/null
+++ b/doc/org.bluez.GattService.5
@@ -0,0 +1,111 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.GATTSERVICE" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.GattService \- BlueZ D-Bus GattService API documentation
+.SH DESCRIPTION
+.sp
+GATT local/server and remote/client services share the same high\-level D\-Bus
+API.
+.sp
+Local/Server refers to GATT based service exported by a plugin or an external
+application.
+.sp
+Remote/Client refers to GATT services exported by the peer.
+.SH INTERFACE
+.SS Client
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.GattService1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+.UNINDENT
+.SS Server
+.INDENT 0.0
+.TP
+.B Service
+unique name
+.TP
+.B Interface
+org.bluez.GattService1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Properties
+.SS string UUID [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+128\-bit service UUID.
+.UNINDENT
+.UNINDENT
+.SS boolean Primary [read\-only]
+.INDENT 0.0
+.INDENT 3.5
+Indicates whether or not this GATT service is a primary service. If
+false, the service is secondary.
+.UNINDENT
+.UNINDENT
+.SS object Device [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+Object path of the Bluetooth device the service belongs to. Only
+present on services from remote devices.
+.UNINDENT
+.UNINDENT
+.SS array{object} Includes [read\-only, optional]
+.INDENT 0.0
+.INDENT 3.5
+Array of object paths representing the included services of this
+service.
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-only] (client only)
+.INDENT 0.0
+.INDENT 3.5
+Service handle.
+.UNINDENT
+.UNINDENT
+.SS uint16 Handle [read\-write, optional] (Server Only)
+.INDENT 0.0
+.INDENT 3.5
+Service handle. When available in the server it would attempt to use to
+allocate into the database which may fail, to auto allocate the value
+0x0000 shall be used which will cause the allocated handle to be set
+once registered.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.GattService.rst b/doc/org.bluez.GattService.rst
new file mode 100644
index 0000000..4a1e81f
--- /dev/null
+++ b/doc/org.bluez.GattService.rst
@@ -0,0 +1,79 @@
+=====================
+org.bluez.GattService
+=====================
+
+-------------------------------------------------
+BlueZ D-Bus GattService API documentation
+-------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+GATT local/server and remote/client services share the same high-level D-Bus
+API.
+
+Local/Server refers to GATT based service exported by a plugin or an external
+application.
+
+Remote/Client refers to GATT services exported by the peer.
+
+Interface
+=========
+
+Client
+------
+
+:Service:	org.bluez
+:Interface:	org.bluez.GattService1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Server
+------
+
+:Service:	unique name
+:Interface:	org.bluez.GattService1
+:Object path:	freely definable
+
+Properties
+----------
+
+string UUID [read-only]
+```````````````````````
+
+	128-bit service UUID.
+
+boolean Primary [read-only]
+```````````````````````````
+
+	Indicates whether or not this GATT service is a primary service. If
+	false, the service is secondary.
+
+object Device [read-only, optional]
+```````````````````````````````````
+
+	Object path of the Bluetooth device the service belongs to. Only
+	present on services from remote devices.
+
+array{object} Includes [read-only, optional]
+````````````````````````````````````````````
+
+	Array of object paths representing the included services of this
+	service.
+
+uint16 Handle [read-only] (client only)
+```````````````````````````````````````
+
+	Service handle.
+
+uint16 Handle [read-write, optional] (Server Only)
+``````````````````````````````````````````````````
+
+	Service handle. When available in the server it would attempt to use to
+	allocate into the database which may fail, to auto allocate the value
+	0x0000 shall be used which will cause the allocated handle to be set
+	once registered.
diff --git a/doc/org.bluez.Input.5 b/doc/org.bluez.Input.5
new file mode 100644
index 0000000..c987027
--- /dev/null
+++ b/doc/org.bluez.Input.5
@@ -0,0 +1,75 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.INPUT" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Input \- BlueZ D-Bus Input API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Input1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Properties
+.SS string ReconnectMode [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the Connectability mode of the HID device as defined by the
+HID Profile specification, Section 5.4.2.
+.sp
+This mode is based in the two properties HIDReconnectInitiate (see
+Section 5.3.4.6) and HIDNormallyConnectable (see Section 5.3.4.14) which
+define the following four possible values:
+.INDENT 0.0
+.TP
+.B \(dqnone\(dq
+Device and host are not required to automatically restore the
+connection.
+.TP
+.B \(dqhost\(dq
+Bluetooth HID host restores connection.
+.TP
+.B \(dqdevice\(dq
+Bluetooth HID device restores connection.
+.TP
+.B \(dqany\(dq
+Bluetooth HID device shall attempt to restore the lost
+connection, but Bluetooth HID Host may also restore the
+connection.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Input.rst b/doc/org.bluez.Input.rst
new file mode 100644
index 0000000..c3c223c
--- /dev/null
+++ b/doc/org.bluez.Input.rst
@@ -0,0 +1,51 @@
+===============
+org.bluez.Input
+===============
+
+-----------------------------------
+BlueZ D-Bus Input API documentation
+-----------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.Input1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Properties
+----------
+
+string ReconnectMode [readonly]
+```````````````````````````````
+
+	Indicates the Connectability mode of the HID device as defined by the
+	HID Profile specification, Section 5.4.2.
+
+	This mode is based in the two properties HIDReconnectInitiate (see
+	Section 5.3.4.6) and HIDNormallyConnectable (see Section 5.3.4.14) which
+	define the following four possible values:
+
+	:"none":
+
+		Device and host are not required to automatically restore the
+		connection.
+
+	:"host":
+
+		Bluetooth HID host restores connection.
+
+	:"device":
+
+		Bluetooth HID device restores connection.
+
+	:"any":
+
+		Bluetooth HID device shall attempt to restore the lost
+		connection, but Bluetooth HID Host may also restore the
+		connection.
diff --git a/doc/org.bluez.LEAdvertisement.5 b/doc/org.bluez.LEAdvertisement.5
new file mode 100644
index 0000000..6bbb1ff
--- /dev/null
+++ b/doc/org.bluez.LEAdvertisement.5
@@ -0,0 +1,244 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.LEADVERTISEMENT" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.LEAdvertisement \- BlueZ D-Bus LEAdvertisement API documentation
+.SH DESCRIPTION
+.sp
+Advertising packets are structured data which is broadcast on the LE Advertising
+channels and available for all devices in range.  Because of the limited space
+available in LE Advertising packets, each packet\(aqs contents must be carefully
+controlled.
+.sp
+The service daemon acts as a store for the Advertisement Data which is meant to
+be sent. It constructs the correct Advertisement Data from the structured
+data and configured the kernel to send the correct advertisement.
+.SH INTERFACE
+.sp
+Specifies the Advertisement Data to be broadcast and some advertising
+parameters.  Properties which are not present will not be included in the
+data.  Required advertisement data types will always be included.
+All UUIDs are 128\-bit versions in the API, and 16 or 32\-bit
+versions of the same UUID will be used in the advertising data as appropriate.
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.LEAdvertisement1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS void Release() [noreply]
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon removes the
+Advertisement. A client can use it to do cleanup tasks. There is no
+need to call \fBUnregisterAdvertisement()\fP because when this method
+gets called it has already been unregistered.
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Type [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Determines the type of advertising packet requested.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqbroadcast\(dq
+.TP
+.B \(dqperipheral\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} ServiceUUIDs
+.INDENT 0.0
+.INDENT 3.5
+List of UUIDs to include in the \(dqService UUID\(dq field of the Advertising
+Data.
+.UNINDENT
+.UNINDENT
+.SS dict ManufacturerData
+.INDENT 0.0
+.INDENT 3.5
+Manufacturer Data fields to include in the Advertising Data.  Keys are
+the Manufacturer ID to associate with the data.
+.UNINDENT
+.UNINDENT
+.SS array{string} SolicitUUIDs
+.INDENT 0.0
+.INDENT 3.5
+Array of UUIDs to include in \(dqService Solicitation\(dq Advertisement Data.
+.UNINDENT
+.UNINDENT
+.SS dict ServiceData
+.INDENT 0.0
+.INDENT 3.5
+Service Data elements to include. The keys are the UUID to associate
+with the data.
+.UNINDENT
+.UNINDENT
+.SS dict Data
+.INDENT 0.0
+.INDENT 3.5
+Advertising Data to include. Key is the advertising type and value is
+the data as byte array.
+.sp
+Note: Types already handled by other properties shall not be used.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B <type>
+<byte array>
+.UNINDENT
+.INDENT 0.0
+.TP
+.B Example:
+<Transport Discovery> <Organization Flags...>
+0x26                   0x01         0x01...
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS bool Discoverable
+.INDENT 0.0
+.INDENT 3.5
+Advertise as general discoverable. When present this will override
+adapter Discoverable property.
+.sp
+Note: This property shall not be set when \fBType\fP is set to
+\(dqbroadcast\(dq.
+.UNINDENT
+.UNINDENT
+.SS uint16 DiscoverableTimeout
+.INDENT 0.0
+.INDENT 3.5
+The discoverable timeout in seconds. A value of zero means that the
+timeout is disabled and it will stay in discoverable/limited mode
+forever.
+.sp
+Note: This property shall not be set when \fBType\fP is set to
+\(dqbroadcast\(dq.
+.UNINDENT
+.UNINDENT
+.SS array{string} Includes
+.INDENT 0.0
+.INDENT 3.5
+List of features to be included in the advertising packet.
+.sp
+Possible values:
+.sp
+See \fBorg.bluez.LEAdvertisingManager(5)\fP \fBSupportedIncludes\fP
+property.
+.UNINDENT
+.UNINDENT
+.SS string LocalName
+.INDENT 0.0
+.INDENT 3.5
+Local name to be used in the advertising report. If the string is too
+big to fit into the packet it will be truncated.
+.sp
+If this property is available \(aqlocal\-name\(aq cannot be present in the
+\fBIncludes\fP\&.
+.UNINDENT
+.UNINDENT
+.SS uint16 Appearance
+.INDENT 0.0
+.INDENT 3.5
+Appearance to be used in the advertising report.
+.sp
+Possible values: as found on GAP Service.
+.UNINDENT
+.UNINDENT
+.SS uint16_t Duration
+.INDENT 0.0
+.INDENT 3.5
+Rotation duration of the advertisement in seconds. If there are other
+applications advertising no duration is set the default is 2 seconds.
+.UNINDENT
+.UNINDENT
+.SS uint16_t Timeout
+.INDENT 0.0
+.INDENT 3.5
+Timeout of the advertisement in seconds. This defines the lifetime of
+the advertisement.
+.UNINDENT
+.UNINDENT
+.SS string SecondaryChannel
+.INDENT 0.0
+.INDENT 3.5
+Secondary channel to be used. Primary channel is always set to \(dq1M\(dq
+except when \(dqCoded\(dq is set.
+.sp
+Possible value:
+.INDENT 0.0
+.TP
+.B \(dq1M\(dq (default)
+.TP
+.B \(dq2M\(dq
+.TP
+.B \(dqCoded\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint32 MinInterval
+.INDENT 0.0
+.INDENT 3.5
+Minimum advertising interval to be used by the advertising set, in
+milliseconds. Acceptable values are in the range [20ms, 10,485s].
+If the provided MinInterval is larger than the provided MaxInterval,
+the registration will return failure.
+.UNINDENT
+.UNINDENT
+.SS uint32 MaxInterval
+.INDENT 0.0
+.INDENT 3.5
+Maximum advertising interval to be used by the advertising set, in
+milliseconds. Acceptable values are in the range [20ms, 10,485s]. If the
+provided MinInterval is larger than the provided MaxInterval, the
+registration will return failure.
+.UNINDENT
+.UNINDENT
+.SS int16 TxPower
+.INDENT 0.0
+.INDENT 3.5
+Requested transmission power of this advertising set. The provided value
+is used only if the \(dqCanSetTxPower\(dq feature is enabled on the
+\fBorg.bluez.LEAdvertisingManager(5)\fP\&. The provided value must be in
+range [\-127 to +20], where units are in dBm.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.LEAdvertisement.rst b/doc/org.bluez.LEAdvertisement.rst
new file mode 100644
index 0000000..d3f9cc4
--- /dev/null
+++ b/doc/org.bluez.LEAdvertisement.rst
@@ -0,0 +1,195 @@
+=========================
+org.bluez.LEAdvertisement
+=========================
+
+---------------------------------------------
+BlueZ D-Bus LEAdvertisement API documentation
+---------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Description
+===========
+
+Advertising packets are structured data which is broadcast on the LE Advertising
+channels and available for all devices in range.  Because of the limited space
+available in LE Advertising packets, each packet's contents must be carefully
+controlled.
+
+The service daemon acts as a store for the Advertisement Data which is meant to
+be sent. It constructs the correct Advertisement Data from the structured
+data and configured the kernel to send the correct advertisement.
+
+Interface
+=========
+
+Specifies the Advertisement Data to be broadcast and some advertising
+parameters.  Properties which are not present will not be included in the
+data.  Required advertisement data types will always be included.
+All UUIDs are 128-bit versions in the API, and 16 or 32-bit
+versions of the same UUID will be used in the advertising data as appropriate.
+
+:Service:	org.bluez
+:Interface:	org.bluez.LEAdvertisement1
+:Object path:	freely definable
+
+Methods
+-------
+
+void Release() [noreply]
+````````````````````````
+
+	This method gets called when the service daemon removes the
+	Advertisement. A client can use it to do cleanup tasks. There is no
+	need to call **UnregisterAdvertisement()** because when this method
+	gets called it has already been unregistered.
+
+Properties
+----------
+
+string Type [readonly]
+``````````````````````
+
+	Determines the type of advertising packet requested.
+
+	Possible values:
+
+	:"broadcast":
+	:"peripheral":
+
+array{string} ServiceUUIDs
+``````````````````````````
+
+	List of UUIDs to include in the "Service UUID" field of the Advertising
+	Data.
+
+dict ManufacturerData
+`````````````````````
+
+	Manufacturer Data fields to include in the Advertising Data.  Keys are
+	the Manufacturer ID to associate with the data.
+
+array{string} SolicitUUIDs
+``````````````````````````
+
+	Array of UUIDs to include in "Service Solicitation" Advertisement Data.
+
+dict ServiceData
+````````````````
+
+	Service Data elements to include. The keys are the UUID to associate
+	with the data.
+
+dict Data
+`````````
+
+	Advertising Data to include. Key is the advertising type and value is
+	the data as byte array.
+
+	Note: Types already handled by other properties shall not be used.
+
+	Possible values:
+
+	:<type>:
+
+		<byte array>
+
+	Example:
+		<Transport Discovery> <Organization Flags...>
+		0x26                   0x01         0x01...
+
+bool Discoverable
+`````````````````
+
+	Advertise as general discoverable. When present this will override
+	adapter Discoverable property.
+
+	Note: This property shall not be set when **Type** is set to
+	"broadcast".
+
+uint16 DiscoverableTimeout
+``````````````````````````
+
+	The discoverable timeout in seconds. A value of zero means that the
+	timeout is disabled and it will stay in discoverable/limited mode
+	forever.
+
+	Note: This property shall not be set when **Type** is set to
+	"broadcast".
+
+array{string} Includes
+``````````````````````
+
+	List of features to be included in the advertising packet.
+
+	Possible values:
+
+	See **org.bluez.LEAdvertisingManager(5)** **SupportedIncludes**
+	property.
+
+string LocalName
+````````````````
+
+	Local name to be used in the advertising report. If the string is too
+	big to fit into the packet it will be truncated.
+
+	If this property is available 'local-name' cannot be present in the
+	**Includes**.
+
+uint16 Appearance
+`````````````````
+
+	Appearance to be used in the advertising report.
+
+	Possible values: as found on GAP Service.
+
+uint16_t Duration
+`````````````````
+
+	Rotation duration of the advertisement in seconds. If there are other
+	applications advertising no duration is set the default is 2 seconds.
+
+uint16_t Timeout
+````````````````
+
+	Timeout of the advertisement in seconds. This defines the lifetime of
+	the advertisement.
+
+string SecondaryChannel
+```````````````````````
+
+	Secondary channel to be used. Primary channel is always set to "1M"
+	except when "Coded" is set.
+
+	Possible value:
+
+	:"1M" (default):
+	:"2M":
+	:"Coded":
+
+uint32 MinInterval
+``````````````````
+
+	Minimum advertising interval to be used by the advertising set, in
+	milliseconds. Acceptable values are in the range [20ms, 10,485s].
+	If the provided MinInterval is larger than the provided MaxInterval,
+	the registration will return failure.
+
+uint32 MaxInterval
+``````````````````
+
+	Maximum advertising interval to be used by the advertising set, in
+	milliseconds. Acceptable values are in the range [20ms, 10,485s]. If the
+	provided MinInterval is larger than the provided MaxInterval, the
+	registration will return failure.
+
+int16 TxPower
+`````````````
+
+	Requested transmission power of this advertising set. The provided value
+	is used only if the "CanSetTxPower" feature is enabled on the
+	**org.bluez.LEAdvertisingManager(5)**. The provided value must be in
+	range [-127 to +20], where units are in dBm.
diff --git a/doc/org.bluez.LEAdvertisingManager.5 b/doc/org.bluez.LEAdvertisingManager.5
new file mode 100644
index 0000000..fc0fb56
--- /dev/null
+++ b/doc/org.bluez.LEAdvertisingManager.5
@@ -0,0 +1,189 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.LEADVERTISINGMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.LEAdvertisingManager \- BlueZ D-Bus LEAvertisingManager API documentation
+.SH INTERFACE
+.sp
+The Advertising Manager allows external applications to register Advertisement
+Data which should be broadcast to devices.  Advertisement Data elements must
+follow the API for LE Advertisement Data described above.
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.LEAdvertisingManager1
+.TP
+.B Object path
+/org/bluez/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void RegisterAdvertisement(object advertisement, dict options)
+.INDENT 0.0
+.INDENT 3.5
+Registers an advertisement object to be sent over the LE Advertising
+channel.  The service must implement \fBorg.bluez.LEAdvertisement(5)\fP
+interface.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+Indicates that the object has invalid or conflicting properties.
+.TP
+.B org.bluez.Error.AlreadyExists
+Indicates the object is already registered.
+.TP
+.B org.bluez.Error.InvalidLength
+Indicates that the data provided generates a data packet which
+is too long
+.TP
+.B org.bluez.Error.NotPermitted
+Indicates the maximum number of advertisement instances has
+been reached.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterAdvertisement(object advertisement)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters an advertisement that has been previously registered using
+\fBRegisterAdvertisement()\fP\&.  The object path parameter must match the
+same value that has been used on registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS byte ActiveInstances [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Number of active advertising instances.
+.UNINDENT
+.UNINDENT
+.SS byte SupportedInstances [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Number of available advertising instances.
+.UNINDENT
+.UNINDENT
+.SS array{string} SupportedIncludes [readonly]
+.INDENT 0.0
+.INDENT 3.5
+List of supported system includes.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqtx\-power\(dq
+.TP
+.B \(dqappearance\(dq
+.TP
+.B \(dqlocal\-name\(dq
+.TP
+.B \(dqrsi\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} SupportedSecondaryChannels [readonly]
+.INDENT 0.0
+.INDENT 3.5
+List of supported Secondary channels. Secondary channels can be used to
+advertise with the corresponding PHY.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dq1M\(dq
+.TP
+.B \(dq2M\(dq
+.TP
+.B \(dqCoded\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS dict SupportedCapabilities [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Enumerates Advertising\-related controller capabilities useful to the
+client.
+.sp
+Possible Values:
+.INDENT 0.0
+.TP
+.B byte MaxAdvLen
+Max advertising data length
+.TP
+.B byte MaxScnRspLen
+Max advertising scan response length
+.UNINDENT
+.sp
+;int16 MinTxPower:
+.INDENT 0.0
+.INDENT 3.5
+Min advertising tx power (dBm)
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int16 MaxTxPower
+Max advertising tx power (dBm)
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} SupportedFeatures [readonly,optional]
+.INDENT 0.0
+.INDENT 3.5
+List of supported platform features. If no features are available on
+the platform, the SupportedFeatures array will be empty.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqCanSetTxPower\(dq
+Indicates whether platform can specify tx power on each
+advertising instance.
+.TP
+.B \(dqHardwareOffload\(dq
+Indicates whether multiple advertising will be offloaded to the
+controller.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.LEAdvertisingManager.rst b/doc/org.bluez.LEAdvertisingManager.rst
new file mode 100644
index 0000000..7f6359d
--- /dev/null
+++ b/doc/org.bluez.LEAdvertisingManager.rst
@@ -0,0 +1,144 @@
+==============================
+org.bluez.LEAdvertisingManager
+==============================
+
+-------------------------------------------------
+BlueZ D-Bus LEAvertisingManager API documentation
+-------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+The Advertising Manager allows external applications to register Advertisement
+Data which should be broadcast to devices.  Advertisement Data elements must
+follow the API for LE Advertisement Data described above.
+
+:Service:	org.bluez
+:Interface:	org.bluez.LEAdvertisingManager1
+:Object path:	/org/bluez/{hci0,hci1,...}
+
+Methods
+-------
+
+void RegisterAdvertisement(object advertisement, dict options)
+``````````````````````````````````````````````````````````````
+
+	Registers an advertisement object to be sent over the LE Advertising
+	channel.  The service must implement **org.bluez.LEAdvertisement(5)**
+	interface.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+
+		Indicates that the object has invalid or conflicting properties.
+
+	:org.bluez.Error.AlreadyExists:
+
+		Indicates the object is already registered.
+
+	:org.bluez.Error.InvalidLength:
+
+		Indicates that the data provided generates a data packet which
+		is too long
+
+	:org.bluez.Error.NotPermitted:
+
+		Indicates the maximum number of advertisement instances has
+		been reached.
+
+void UnregisterAdvertisement(object advertisement)
+``````````````````````````````````````````````````
+
+	Unregisters an advertisement that has been previously registered using
+	**RegisterAdvertisement()**.  The object path parameter must match the
+	same value that has been used on registration.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.DoesNotExist:
+
+Properties
+----------
+
+byte ActiveInstances [readonly]
+```````````````````````````````
+
+	Number of active advertising instances.
+
+byte SupportedInstances [readonly]
+``````````````````````````````````
+
+	Number of available advertising instances.
+
+array{string} SupportedIncludes [readonly]
+``````````````````````````````````````````
+
+	List of supported system includes.
+
+	Possible values:
+
+	:"tx-power":
+	:"appearance":
+	:"local-name":
+	:"rsi":
+
+array{string} SupportedSecondaryChannels [readonly]
+```````````````````````````````````````````````````
+
+	List of supported Secondary channels. Secondary channels can be used to
+	advertise with the corresponding PHY.
+
+	Possible values:
+
+	:"1M":
+	:"2M":
+	:"Coded":
+
+dict SupportedCapabilities [readonly]
+`````````````````````````````````````
+
+	Enumerates Advertising-related controller capabilities useful to the
+	client.
+
+	Possible Values:
+
+	:byte MaxAdvLen:
+
+		Max advertising data length
+
+	:byte MaxScnRspLen:
+
+		Max advertising scan response length
+
+	;int16 MinTxPower:
+
+		Min advertising tx power (dBm)
+
+	:int16 MaxTxPower:
+
+		Max advertising tx power (dBm)
+
+array{string} SupportedFeatures [readonly,optional]
+```````````````````````````````````````````````````
+
+	List of supported platform features. If no features are available on
+	the platform, the SupportedFeatures array will be empty.
+
+	Possible values:
+
+	:"CanSetTxPower":
+
+		Indicates whether platform can specify tx power on each
+		advertising instance.
+
+	:"HardwareOffload":
+
+		Indicates whether multiple advertising will be offloaded to the
+		controller.
diff --git a/doc/org.bluez.Media.5 b/doc/org.bluez.Media.5
new file mode 100644
index 0000000..cd2c16a
--- /dev/null
+++ b/doc/org.bluez.Media.5
@@ -0,0 +1,175 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIA" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Media \- BlueZ D-Bus Media API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Media1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void RegisterEndpoint(object endpoint, dict properties)
+.INDENT 0.0
+.INDENT 3.5
+Register a local end point to sender, the sender can register as many
+end points as it likes.
+.sp
+Note: If the sender disconnects the end points are automatically
+unregistered.
+.sp
+possible properties:
+.INDENT 0.0
+.TP
+.B string UUID
+UUID of the profile which the endpoint is for.
+.sp
+UUID must be in the list of SupportedUUIDS.
+.TP
+.B byte Codec
+Assigned number of codec that the endpoint implements. The
+values should match the profile specification which is
+indicated by the UUID.
+.TP
+.B uint32_t Vendor [Optional]
+Vendor\-specific Company ID, Codec ID tuple that the endpoint
+implements.
+.sp
+It shall be set to appropriate value when Vendor Specific Codec
+(0xff) is used.
+.TP
+.B array{byte} Capabilities
+Capabilities blob, it is used as it is so the size and byte
+order must match.
+.TP
+.B array{byte} Metadata [Optional]
+Metadata blob, it is used as it is so the size and byte order
+must match.
+.UNINDENT
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+emitted when interface for the end\-point is disabled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterEndpoint(object endpoint)
+.INDENT 0.0
+.INDENT 3.5
+Unregister sender end point.
+.UNINDENT
+.UNINDENT
+.SS void RegisterPlayer(object player, dict properties)
+.INDENT 0.0
+.INDENT 3.5
+Register a media player object to sender, the sender can register as
+many objects as it likes.
+.sp
+Object must implement at least org.mpris.MediaPlayer2.Player as defined
+in MPRIS 2.2 spec:
+.INDENT 0.0
+.INDENT 3.5
+ <http://specifications.freedesktop.org/mpris\-spec/latest/> 
+.UNINDENT
+.UNINDENT
+.sp
+Note: If the sender disconnects its objects are automatically
+unregistered.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterPlayer(object player)
+.INDENT 0.0
+.INDENT 3.5
+Unregister sender media player.
+.UNINDENT
+.UNINDENT
+.SS void RegisterApplication(object root, dict options)
+.INDENT 0.0
+.INDENT 3.5
+Register endpoints an player objects within root object which must
+implement ObjectManager.
+.sp
+The application object path together with the D\-Bus system bus
+connection ID define the identification of the application.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterApplication(object application)
+.INDENT 0.0
+.INDENT 3.5
+This unregisters the services that has been previously registered. The
+object path parameter must match the same value that has been used on
+registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS array{string} SupportedUUIDs [readonly]
+.INDENT 0.0
+.INDENT 3.5
+List of 128\-bit UUIDs that represents the supported Endpoint
+registration.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Media.rst b/doc/org.bluez.Media.rst
new file mode 100644
index 0000000..678e609
--- /dev/null
+++ b/doc/org.bluez.Media.rst
@@ -0,0 +1,133 @@
+===============
+org.bluez.Media
+===============
+
+-----------------------------------
+BlueZ D-Bus Media API documentation
+-----------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service: org.bluez
+:Interface: org.bluez.Media1
+:Object path: [variable prefix]/{hci0,hci1,...}
+
+Methods
+-------
+
+void RegisterEndpoint(object endpoint, dict properties)
+```````````````````````````````````````````````````````
+
+	Register a local end point to sender, the sender can register as many
+	end points as it likes.
+
+	Note: If the sender disconnects the end points are automatically
+	unregistered.
+
+	possible properties:
+
+	:string UUID:
+
+		UUID of the profile which the endpoint is for.
+
+		UUID must be in the list of SupportedUUIDS.
+
+	:byte Codec:
+
+		Assigned number of codec that the endpoint implements. The
+		values should match the profile specification which is
+		indicated by the UUID.
+
+	:uint32_t Vendor [Optional]:
+
+		Vendor-specific Company ID, Codec ID tuple that the endpoint
+		implements.
+
+		It shall be set to appropriate value when Vendor Specific Codec
+		(0xff) is used.
+
+	:array{byte} Capabilities:
+
+		Capabilities blob, it is used as it is so the size and byte
+		order must match.
+
+	:array{byte} Metadata [Optional]:
+
+		Metadata blob, it is used as it is so the size and byte order
+		must match.
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+
+		emitted when interface for the end-point is disabled
+
+void UnregisterEndpoint(object endpoint)
+````````````````````````````````````````
+	Unregister sender end point.
+
+void RegisterPlayer(object player, dict properties)
+```````````````````````````````````````````````````
+
+	Register a media player object to sender, the sender can register as
+	many objects as it likes.
+
+	Object must implement at least org.mpris.MediaPlayer2.Player as defined
+	in MPRIS 2.2 spec:
+
+		http://specifications.freedesktop.org/mpris-spec/latest/
+
+	Note: If the sender disconnects its objects are automatically
+	unregistered.
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+
+void UnregisterPlayer(object player)
+````````````````````````````````````
+
+	Unregister sender media player.
+
+void RegisterApplication(object root, dict options)
+```````````````````````````````````````````````````
+
+	Register endpoints an player objects within root object which must
+	implement ObjectManager.
+
+	The application object path together with the D-Bus system bus
+	connection ID define the identification of the application.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+
+void UnregisterApplication(object application)
+``````````````````````````````````````````````
+
+	This unregisters the services that has been previously registered. The
+	object path parameter must match the same value that has been used on
+	registration.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.DoesNotExist:
+
+Properties
+----------
+
+array{string} SupportedUUIDs [readonly]
+```````````````````````````````````````
+
+	List of 128-bit UUIDs that represents the supported Endpoint
+	registration.
diff --git a/doc/org.bluez.MediaAssistant.5 b/doc/org.bluez.MediaAssistant.5
new file mode 100644
index 0000000..2c09cc3
--- /dev/null
+++ b/doc/org.bluez.MediaAssistant.5
@@ -0,0 +1,120 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIAASSISTANT" "5" "June 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaAssistant \- BlueZ D-Bus MediaAssistant API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.MediaAssistant1
+.TP
+.B Object path
+/org/bluez/{hci0,hci1,...}/src_XX_XX_XX_XX_XX_XX/dev_YY_YY_YY_YY_YY_YY/bisZ
+.UNINDENT
+.SS Methods
+.SS void Push(dict properties)
+.INDENT 0.0
+.INDENT 3.5
+Send stream information to the remote device.
+.INDENT 0.0
+.TP
+.B dict properties
+.UNINDENT
+.sp
+Indicate stream properties that will be sent to the peer.
+.sp
+Values:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.B array{byte} Metadata [ISO only]
+See Metadata property.
+.TP
+.B dict QoS [ISO only]
+See QoS property.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string State [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the state of the assistant object. Possible values are:
+.INDENT 0.0
+.TP
+.B \(dqidle\(dq
+assistant object was created for the stream
+.TP
+.B \(dqpending\(dq
+assistant object was pushed (stream information was sent to the peer)
+.TP
+.B \(dqrequesting\(dq
+remote device requires Broadcast_Code
+.TP
+.B \(dqactive\(dq
+remote device started receiving stream
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{byte} Metadata [readwrite, ISO Only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates stream Metadata.
+.UNINDENT
+.UNINDENT
+.SS dict QoS [readwrite, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates stream QoS capabilities.
+.sp
+Values:
+.INDENT 0.0
+.TP
+.B byte Encryption
+Indicates whether the stream is encrypted.
+.UNINDENT
+.sp
+:array{byte} BCode
+.INDENT 0.0
+.INDENT 3.5
+Indicates Broadcast_Code to decrypt stream.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaAssistant.rst b/doc/org.bluez.MediaAssistant.rst
new file mode 100644
index 0000000..4aac895
--- /dev/null
+++ b/doc/org.bluez.MediaAssistant.rst
@@ -0,0 +1,74 @@
+========================
+org.bluez.MediaAssistant
+========================
+
+--------------------------------------------
+BlueZ D-Bus MediaAssistant API documentation
+--------------------------------------------
+
+:Version: BlueZ
+:Date: June 2024
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.MediaAssistant1
+:Object path:	/org/bluez/{hci0,hci1,...}/src_XX_XX_XX_XX_XX_XX/dev_YY_YY_YY_YY_YY_YY/bisZ
+
+Methods
+-------
+
+void Push(dict properties)
+````````````````````````````````````````````````````````
+
+	Send stream information to the remote device.
+
+	:dict properties:
+
+	Indicate stream properties that will be sent to the peer.
+
+	Values:
+
+		:array{byte} Metadata [ISO only]:
+
+			See Metadata property.
+
+		:dict QoS [ISO only]:
+
+			See QoS property.
+
+Properties
+----------
+
+string State [readonly]
+```````````````````````
+
+	Indicates the state of the assistant object. Possible values are:
+
+	:"idle": assistant object was created for the stream
+	:"pending": assistant object was pushed (stream information was sent to the peer)
+	:"requesting": remote device requires Broadcast_Code
+	:"active": remote device started receiving stream
+
+array{byte} Metadata [readwrite, ISO Only, experimental]
+````````````````````````````````````````````````````````
+
+	Indicates stream Metadata.
+
+dict QoS [readwrite, ISO only, experimental]
+`````````````````````````````````````````````````````
+
+	Indicates stream QoS capabilities.
+
+	Values:
+
+	:byte Encryption:
+
+		Indicates whether the stream is encrypted.
+
+	:array{byte} BCode
+
+		Indicates Broadcast_Code to decrypt stream.
diff --git a/doc/org.bluez.MediaControl.5 b/doc/org.bluez.MediaControl.5
new file mode 100644
index 0000000..43ec2d4
--- /dev/null
+++ b/doc/org.bluez.MediaControl.5
@@ -0,0 +1,111 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIACONTROL" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaControl \- BlueZ D-Bus MediaControl API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.MediaControl1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Methods
+.SS void Play() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Resume playback.
+.UNINDENT
+.UNINDENT
+.SS void Pause() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Pause playback.
+.UNINDENT
+.UNINDENT
+.SS void Stop() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Stop playback.
+.UNINDENT
+.UNINDENT
+.SS void Next() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Next item.
+.UNINDENT
+.UNINDENT
+.SS void Previous() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Previous item.
+.UNINDENT
+.UNINDENT
+.SS void VolumeUp() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Adjust remote volume one step up
+.UNINDENT
+.UNINDENT
+.SS void VolumeDown() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Adjust remote volume one step down
+.UNINDENT
+.UNINDENT
+.SS void FastForward() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Fast forward playback, this action is only stopped when another method
+in this interface is called.
+.UNINDENT
+.UNINDENT
+.SS void Rewind() [Deprecated]
+.INDENT 0.0
+.INDENT 3.5
+Rewind playback, this action is only stopped when another method in
+this interface is called.
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS boolean Connected [readonly]
+.SS object Player [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Addressed Player object path.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaControl.rst b/doc/org.bluez.MediaControl.rst
new file mode 100644
index 0000000..54e84e8
--- /dev/null
+++ b/doc/org.bluez.MediaControl.rst
@@ -0,0 +1,80 @@
+======================
+org.bluez.MediaControl
+======================
+
+------------------------------------------
+BlueZ D-Bus MediaControl API documentation
+------------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.MediaControl1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods
+-------
+
+void Play() [Deprecated]
+````````````````````````
+
+	Resume playback.
+
+void Pause() [Deprecated]
+`````````````````````````
+
+	Pause playback.
+
+void Stop() [Deprecated]
+````````````````````````
+
+	Stop playback.
+
+void Next() [Deprecated]
+````````````````````````
+
+	Next item.
+
+void Previous() [Deprecated]
+````````````````````````````
+
+	Previous item.
+
+void VolumeUp() [Deprecated]
+````````````````````````````
+
+	Adjust remote volume one step up
+
+void VolumeDown() [Deprecated]
+``````````````````````````````
+
+	Adjust remote volume one step down
+
+void FastForward() [Deprecated]
+```````````````````````````````
+
+	Fast forward playback, this action is only stopped when another method
+	in this interface is called.
+
+void Rewind() [Deprecated]
+``````````````````````````
+
+	Rewind playback, this action is only stopped when another method in
+	this interface is called.
+
+Properties
+----------
+
+boolean Connected [readonly]
+````````````````````````````
+
+object Player [readonly, optional]
+``````````````````````````````````
+
+	Addressed Player object path.
diff --git a/doc/org.bluez.MediaEndpoint.5 b/doc/org.bluez.MediaEndpoint.5
new file mode 100644
index 0000000..434ac74
--- /dev/null
+++ b/doc/org.bluez.MediaEndpoint.5
@@ -0,0 +1,282 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIAENDPOINT" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaEndpoint \- BlueZ D-Bus MediaEndpoint API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+unique name (Server role)
+org.bluez (Client role)
+.TP
+.B Interface
+org.bluez.MediaEndpoint1
+.TP
+.B Object path
+freely definable (Server role)
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/sepX
+(Client role)
+.UNINDENT
+.SS Methods
+.SS void SetConfiguration(object transport, dict properties)
+.INDENT 0.0
+.INDENT 3.5
+Set configuration for the transport.
+.INDENT 0.0
+.TP
+.B object transport
+Configured transport object.
+.TP
+.B dict properties
+Configured \fBorg.bluez.MediaTransport(5)\fP properties.
+.UNINDENT
+.sp
+For client role transport must be set with a server endpoint
+object which will be configured and the properties must
+contain the following properties:
+.INDENT 0.0
+.TP
+.B array{byte} Capabilities [Mandatory]
+See Capabilities property.
+.TP
+.B array{byte} Metadata [ISO only]
+See Metadata property.
+.TP
+.B dict QoS [ISO only]
+See \fBorg.bluez.MediaTransport(5)\fP QoS property.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{byte} SelectConfiguration(array{byte} capabilities)
+.INDENT 0.0
+.INDENT 3.5
+Select preferable configuration from the supported capabilities.
+.sp
+Returns a configuration which can be used to setup a transport, see
+\fBorg.bluez.MediaTransport(5)\fP for possible values.
+.sp
+Note: There is no need to cache the selected configuration since on
+success the configuration is send back as parameter of SetConfiguration.
+.UNINDENT
+.UNINDENT
+.SS dict SelectProperties(dict capabilities)
+.INDENT 0.0
+.INDENT 3.5
+Select BAP unicast configuration from the supported capabilities:
+.INDENT 0.0
+.TP
+.B object Endpoint
+.TP
+.B array{byte} Capabilities
+.TP
+.B array{byte} Metadata
+.TP
+.B uint32 Locations
+.TP
+.B uint32_t ChannelAllocation
+.TP
+.B dict QoS
+.INDENT 7.0
+.TP
+.B byte Framing
+.TP
+.B byte PHY
+.TP
+.B uint16 MaximumLatency
+.TP
+.B uint32 MinimumDelay
+.TP
+.B uint32 MaximumDelay
+.TP
+.B uint32 PreferredMinimumDelay
+.TP
+.B uint32 PreferredMaximumDelay
+.UNINDENT
+.UNINDENT
+.sp
+See MediaEndpoint Properties for their possible values.
+.sp
+Returns a configuration which can be used to setup a transport:
+.INDENT 0.0
+.TP
+.B array{byte} Capabilities
+.TP
+.B array{byte} Metadata [optional]
+.TP
+.B dict QoS
+.UNINDENT
+.sp
+See SetConfiguration for their possible values.
+.sp
+Note: There is no need to cache the selected properties since on
+success the configuration is send back as parameter of SetConfiguration.
+.UNINDENT
+.UNINDENT
+.SS void ClearConfiguration(object transport)
+.INDENT 0.0
+.INDENT 3.5
+Clear transport configuration.
+.UNINDENT
+.UNINDENT
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon unregisters the
+endpoint. An endpoint can use it to do cleanup tasks. There is no need
+to unregister the endpoint, because when this method gets called it has
+already been unregistered.
+.UNINDENT
+.UNINDENT
+.SS MediaEndpoint Properties
+.SS string UUID [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+UUID of the profile which the endpoint is for.
+.UNINDENT
+.UNINDENT
+.SS byte Codec [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Assigned number of codec that the endpoint implements.
+The values should match the profile specification which is indicated by
+the UUID.
+.UNINDENT
+.UNINDENT
+.SS uint32_t Vendor [readonly, Optional]
+.INDENT 0.0
+.INDENT 3.5
+Vendor\-specific Company ID, Codec ID tuple that the endpoint implements.
+.sp
+It shall be set to appropriate value when Vendor Specific Codec (0xff)
+is used.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Capabilities [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Capabilities blob, it is used as it is so the size and byte order must
+match.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Metadata [readonly, Optional]
+.INDENT 0.0
+.INDENT 3.5
+Metadata blob, it is used as it is so the size and byte order must
+match.
+.UNINDENT
+.UNINDENT
+.SS object Device [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Device object which the endpoint is belongs to.
+.UNINDENT
+.UNINDENT
+.SS bool DelayReporting [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if endpoint supports Delay Reporting.
+.UNINDENT
+.UNINDENT
+.SS uint32 Locations [readonly, optional, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates endpoint supported locations.
+.UNINDENT
+.UNINDENT
+.SS uint16 SupportedContext [readonly, optional, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates endpoint supported audio context.
+.UNINDENT
+.UNINDENT
+.SS uint16 Context [readonly, optional, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates endpoint available audio context.
+.UNINDENT
+.UNINDENT
+.SS dict QoS [readonly, optional, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates QoS capabilities.
+.INDENT 0.0
+.TP
+.B byte Framing
+Indicates endpoint support framing.
+.sp
+Possible Values:
+.INDENT 7.0
+.TP
+.B 0x00
+Unframed PDUs supported.
+.TP
+.B 0x01
+Unframed PDUs not supported.
+.UNINDENT
+.TP
+.B byte PHY
+Indicates endpoint preferred PHY.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B bit 0
+LE 1M preferred.
+.TP
+.B bit 1
+LE 2M preferred.
+.TP
+.B bit 2
+LE Coded preferred.
+.UNINDENT
+.TP
+.B byte Retransmissions
+Indicates endpoint preferred number of retransmissions.
+.TP
+.B uint16 MaximumLatency
+Indicates endpoint maximum latency.
+.TP
+.B uint32 MinimumDelay
+Indicates endpoint minimum presentation delay.
+.TP
+.B uint32 MaximumDelay
+Indicates endpoint maximum presentation delay.
+.TP
+.B uint32 PreferredMinimumDelay
+Indicates endpoint preferred minimum presentation delay.
+.TP
+.B uint32 PreferredMaximumDelay
+Indicates endpoint preferred maximum presentation delay.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaEndpoint.rst b/doc/org.bluez.MediaEndpoint.rst
new file mode 100644
index 0000000..f2b830a
--- /dev/null
+++ b/doc/org.bluez.MediaEndpoint.rst
@@ -0,0 +1,240 @@
+=======================
+org.bluez.MediaEndpoint
+=======================
+
+-------------------------------------------
+BlueZ D-Bus MediaEndpoint API documentation
+-------------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	unique name (Server role)
+		org.bluez (Client role)
+:Interface:	org.bluez.MediaEndpoint1
+:Object path:	freely definable (Server role)
+		[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/sepX
+		(Client role)
+
+Methods
+-------
+
+.. _SetConfiguration:
+
+void SetConfiguration(object transport, dict properties)
+````````````````````````````````````````````````````````
+
+	Set configuration for the transport.
+
+	:object transport:
+
+		Configured transport object.
+
+	:dict properties:
+
+		Configured **org.bluez.MediaTransport(5)** properties.
+
+	For client role transport must be set with a server endpoint
+	object which will be configured and the properties must
+	contain the following properties:
+
+	:array{byte} Capabilities [Mandatory]:
+
+		See Capabilities property.
+
+	:array{byte} Metadata [ISO only]:
+
+		See Metadata property.
+
+	:dict QoS [ISO only]:
+
+		See **org.bluez.MediaTransport(5)** QoS property.
+
+array{byte} SelectConfiguration(array{byte} capabilities)
+`````````````````````````````````````````````````````````
+
+	Select preferable configuration from the supported capabilities.
+
+	Returns a configuration which can be used to setup a transport, see
+	**org.bluez.MediaTransport(5)** for possible values.
+
+	Note: There is no need to cache the selected configuration since on
+	success the configuration is send back as parameter of SetConfiguration.
+
+dict SelectProperties(dict capabilities)
+````````````````````````````````````````
+
+	Select BAP unicast configuration from the supported capabilities:
+
+	:object Endpoint:
+
+	:array{byte} Capabilities:
+
+	:array{byte} Metadata:
+
+	:uint32 Locations:
+
+	:uint32_t ChannelAllocation:
+
+	:dict QoS:
+
+		:byte Framing:
+		:byte PHY:
+		:uint16 MaximumLatency:
+		:uint32 MinimumDelay:
+		:uint32 MaximumDelay:
+		:uint32 PreferredMinimumDelay:
+		:uint32 PreferredMaximumDelay:
+
+	See `MediaEndpoint Properties`_ for their possible values.
+
+	Returns a configuration which can be used to setup a transport:
+
+	:array{byte} Capabilities:
+	:array{byte} Metadata [optional]:
+	:dict QoS:
+
+	See `SetConfiguration`_ for their possible values.
+
+	Note: There is no need to cache the selected properties since on
+	success the configuration is send back as parameter of SetConfiguration.
+
+void ClearConfiguration(object transport)
+`````````````````````````````````````````
+
+	Clear transport configuration.
+
+void Release()
+``````````````
+
+	This method gets called when the service daemon unregisters the
+	endpoint. An endpoint can use it to do cleanup tasks. There is no need
+	to unregister the endpoint, because when this method gets called it has
+	already been unregistered.
+
+MediaEndpoint Properties
+------------------------
+
+string UUID [readonly, optional]
+````````````````````````````````
+
+	UUID of the profile which the endpoint is for.
+
+byte Codec [readonly, optional]
+```````````````````````````````
+
+	Assigned number of codec that the endpoint implements.
+	The values should match the profile specification which is indicated by
+	the UUID.
+
+uint32_t Vendor [readonly, Optional]
+````````````````````````````````````
+
+	Vendor-specific Company ID, Codec ID tuple that the endpoint implements.
+
+	It shall be set to appropriate value when Vendor Specific Codec (0xff)
+	is used.
+
+array{byte} Capabilities [readonly, optional]
+`````````````````````````````````````````````
+
+	Capabilities blob, it is used as it is so the size and byte order must
+	match.
+
+array{byte} Metadata [readonly, Optional]
+`````````````````````````````````````````
+
+	Metadata blob, it is used as it is so the size and byte order must
+	match.
+
+object Device [readonly, optional]
+``````````````````````````````````
+
+	Device object which the endpoint is belongs to.
+
+bool DelayReporting [readonly, optional]
+````````````````````````````````````````
+
+	Indicates if endpoint supports Delay Reporting.
+
+uint32 Locations [readonly, optional, ISO only, experimental]
+`````````````````````````````````````````````````````````````
+
+	Indicates endpoint supported locations.
+
+uint16 SupportedContext [readonly, optional, ISO only, experimental]
+````````````````````````````````````````````````````````````````````
+
+	Indicates endpoint supported audio context.
+
+uint16 Context [readonly, optional, ISO only, experimental]
+```````````````````````````````````````````````````````````
+
+	Indicates endpoint available audio context.
+
+dict QoS [readonly, optional, ISO only, experimental]
+`````````````````````````````````````````````````````
+
+	Indicates QoS capabilities.
+
+	:byte Framing:
+
+		Indicates endpoint support framing.
+
+
+		Possible Values:
+
+		:0x00:
+
+			Unframed PDUs supported.
+
+		:0x01:
+
+			Unframed PDUs not supported.
+
+	:byte PHY:
+
+		Indicates endpoint preferred PHY.
+
+		Possible values:
+
+		:bit 0:
+
+			LE 1M preferred.
+
+		:bit 1:
+
+			LE 2M preferred.
+
+		:bit 2:
+
+			LE Coded preferred.
+
+	:byte Retransmissions:
+
+		Indicates endpoint preferred number of retransmissions.
+
+	:uint16 MaximumLatency:
+
+		Indicates endpoint maximum latency.
+
+	:uint32 MinimumDelay:
+
+		Indicates endpoint minimum presentation delay.
+
+	:uint32 MaximumDelay:
+
+		Indicates endpoint maximum presentation delay.
+
+	:uint32 PreferredMinimumDelay:
+
+		Indicates endpoint preferred minimum presentation delay.
+
+	:uint32 PreferredMaximumDelay:
+
+		Indicates endpoint preferred maximum presentation delay.
diff --git a/doc/org.bluez.MediaFolder.5 b/doc/org.bluez.MediaFolder.5
new file mode 100644
index 0000000..3531a1a
--- /dev/null
+++ b/doc/org.bluez.MediaFolder.5
@@ -0,0 +1,156 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIAFOLDER" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaFolder \- BlueZ D-Bus MediaFolder API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+unique name (Target role)
+org.bluez (Controller role)
+.TP
+.B Interface
+org.bluez.MediaFolder1
+.TP
+.B Object path
+freely definable (Target role)
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
+(Controller role)
+.UNINDENT
+.SS Methods
+.SS object Search(string value, dict filter)
+.INDENT 0.0
+.INDENT 3.5
+Return a folder object containing the search result.
+.sp
+To list the items found use the folder object returned and pass to
+ChangeFolder.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{objects, properties} ListItems(dict filter)
+.INDENT 0.0
+.INDENT 3.5
+Return a list of items found
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void ChangeFolder(object folder)
+.INDENT 0.0
+.INDENT 3.5
+Change current folder.
+.sp
+Note: By changing folder the items of previous folder might be destroyed
+and have to be listed again, the exception is NowPlaying folder which
+should be always present while the player is active.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS uint32 NumberOfItems [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Number of items in the folder
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Folder name:
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dq/Filesystem/...\(dq
+Filesystem scope
+.TP
+.B \(dq/NowPlaying/...\(dq
+NowPlaying scope
+.UNINDENT
+.sp
+Note: /NowPlaying folder might not be listed if player is stopped,
+folders created by Search are virtual so once another Search is perform
+or the folder is changed using ChangeFolder it will no longer be listed.
+.UNINDENT
+.UNINDENT
+.SS Filters
+.INDENT 0.0
+.TP
+.B uint32 Start
+Offset of the first item.
+.sp
+Default value: 0
+.TP
+.B uint32 End
+Offset of the last item.
+.sp
+Default value: NumbeOfItems
+.TP
+.B array{string} Attributes
+Item properties that should be included in the list.
+.sp
+Possible Values:
+.INDENT 7.0
+.INDENT 3.5
+\(dqtitle\(dq, \(dqartist\(dq, \(dqalbum\(dq, \(dqgenre\(dq, \(dqnumber\-of\-tracks\(dq,
+\(dqnumber\(dq, \(dqduration\(dq
+.sp
+Default Value: All
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaFolder.rst b/doc/org.bluez.MediaFolder.rst
new file mode 100644
index 0000000..dd56f06
--- /dev/null
+++ b/doc/org.bluez.MediaFolder.rst
@@ -0,0 +1,117 @@
+=====================
+org.bluez.MediaFolder
+=====================
+
+-----------------------------------------
+BlueZ D-Bus MediaFolder API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	unique name (Target role)
+		org.bluez (Controller role)
+:Interface:	org.bluez.MediaFolder1
+:Object path:	freely definable (Target role)
+		[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
+		(Controller role)
+
+Methods
+-------
+
+object Search(string value, dict filter)
+````````````````````````````````````````
+
+	Return a folder object containing the search result.
+
+	To list the items found use the folder object returned and pass to
+	ChangeFolder.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+array{objects, properties} ListItems(dict filter)
+`````````````````````````````````````````````````
+
+	Return a list of items found
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void ChangeFolder(object folder)
+````````````````````````````````
+
+	Change current folder.
+
+	Note: By changing folder the items of previous folder might be destroyed
+	and have to be listed again, the exception is NowPlaying folder which
+	should be always present while the player is active.
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+Properties
+----------
+
+uint32 NumberOfItems [readonly]
+```````````````````````````````
+
+	Number of items in the folder
+
+string Name [readonly]
+``````````````````````
+
+	Folder name:
+
+	Possible values:
+
+	:"/Filesystem/...":
+
+		Filesystem scope
+
+	:"/NowPlaying/...":
+
+		NowPlaying scope
+
+	Note: /NowPlaying folder might not be listed if player is stopped,
+	folders created by Search are virtual so once another Search is perform
+	or the folder is changed using ChangeFolder it will no longer be listed.
+
+Filters
+-------
+
+:uint32 Start:
+
+	Offset of the first item.
+
+	Default value: 0
+
+:uint32 End:
+
+	Offset of the last item.
+
+	Default value: NumbeOfItems
+
+:array{string} Attributes:
+
+	Item properties that should be included in the list.
+
+	Possible Values:
+
+		"title", "artist", "album", "genre", "number-of-tracks",
+		"number", "duration"
+
+		Default Value: All
diff --git a/doc/org.bluez.MediaItem.5 b/doc/org.bluez.MediaItem.5
new file mode 100644
index 0000000..e6d2780
--- /dev/null
+++ b/doc/org.bluez.MediaItem.5
@@ -0,0 +1,163 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIAITEM" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaItem \- BlueZ D-Bus MediaItem API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+unique name (Target role)
+org.bluez (Controller role)
+.TP
+.B Interface
+org.bluez.MediaItem1
+.TP
+.B Object path
+freely definable (Target role)
+[variable
+prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX/itemX
+(Controller role)
+.UNINDENT
+.SS Methods
+.SS void Play()
+.INDENT 0.0
+.INDENT 3.5
+Play item
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void AddtoNowPlaying()
+.INDENT 0.0
+.INDENT 3.5
+Add item to now playing list
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS object Player [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Player object path the item belongs to
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Item displayable name
+.UNINDENT
+.UNINDENT
+.SS string Type [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Item type
+.sp
+Possible values: \(dqvideo\(dq, \(dqaudio\(dq, \(dqfolder\(dq
+.UNINDENT
+.UNINDENT
+.SS string FolderType [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Folder type.
+.sp
+Possible values: \(dqmixed\(dq, \(dqtitles\(dq, \(dqalbums\(dq, \(dqartists\(dq
+.sp
+Available if property Type is \(dqFolder\(dq
+.UNINDENT
+.UNINDENT
+.SS boolean Playable [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the item can be played
+.sp
+Available if property Type is \(dqfolder\(dq
+.UNINDENT
+.UNINDENT
+.SS dict Metadata [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Item metadata.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B string Title
+Item title name
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B string Artist
+Item artist name
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B string Album
+Item album name
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B string Genre
+Item genre name
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B uint32 NumberOfTracks
+Item album number of tracks in total
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B uint32 Number
+Item album number
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.TP
+.B uint32 Duration
+Item duration in milliseconds
+.sp
+Available if property Type is \(dqaudio\(dq or \(dqvideo\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaItem.rst b/doc/org.bluez.MediaItem.rst
new file mode 100644
index 0000000..855e8a6
--- /dev/null
+++ b/doc/org.bluez.MediaItem.rst
@@ -0,0 +1,131 @@
+===================
+org.bluez.MediaItem
+===================
+
+---------------------------------------
+BlueZ D-Bus MediaItem API documentation
+---------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	unique name (Target role)
+		org.bluez (Controller role)
+:Interface:	org.bluez.MediaItem1
+:Object path:	freely definable (Target role)
+		[variable
+		prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX/itemX
+		(Controller role)
+
+Methods
+-------
+
+void Play()
+```````````
+
+	Play item
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void AddtoNowPlaying()
+``````````````````````
+
+	Add item to now playing list
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+Properties
+----------
+
+object Player [readonly]
+````````````````````````
+
+	Player object path the item belongs to
+
+string Name [readonly]
+``````````````````````
+
+	Item displayable name
+
+string Type [readonly]
+``````````````````````
+
+	Item type
+
+	Possible values: "video", "audio", "folder"
+
+string FolderType [readonly, optional]
+``````````````````````````````````````
+
+	Folder type.
+
+	Possible values: "mixed", "titles", "albums", "artists"
+
+	Available if property Type is "Folder"
+
+boolean Playable [readonly, optional]
+`````````````````````````````````````
+
+	Indicates if the item can be played
+
+	Available if property Type is "folder"
+
+dict Metadata [readonly]
+````````````````````````
+
+	Item metadata.
+
+	Possible values:
+
+	:string Title:
+
+		Item title name
+
+		Available if property Type is "audio" or "video"
+
+	:string Artist:
+
+		Item artist name
+
+		Available if property Type is "audio" or "video"
+
+	:string Album:
+
+		Item album name
+
+		Available if property Type is "audio" or "video"
+
+	:string Genre:
+
+		Item genre name
+
+		Available if property Type is "audio" or "video"
+
+	:uint32 NumberOfTracks:
+
+		Item album number of tracks in total
+
+		Available if property Type is "audio" or "video"
+
+	:uint32 Number:
+
+		Item album number
+
+		Available if property Type is "audio" or "video"
+
+	:uint32 Duration:
+
+		Item duration in milliseconds
+
+		Available if property Type is "audio" or "video"
diff --git a/doc/org.bluez.MediaPlayer.5 b/doc/org.bluez.MediaPlayer.5
new file mode 100644
index 0000000..6ee5ecc
--- /dev/null
+++ b/doc/org.bluez.MediaPlayer.5
@@ -0,0 +1,431 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIAPLAYER" "5" "September 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaPlayer \- BlueZ D-Bus MediaPlayer API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez (Controller role)
+.TP
+.B Interface
+org.bluez.MediaPlayer1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
+.UNINDENT
+.SS Methods
+.SS void Play()
+.INDENT 0.0
+.INDENT 3.5
+Resume playback.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Pause()
+.INDENT 0.0
+.INDENT 3.5
+Pause playback.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Stop()
+.INDENT 0.0
+.INDENT 3.5
+Stop playback.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Next()
+.INDENT 0.0
+.INDENT 3.5
+Next item.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Previous()
+.INDENT 0.0
+.INDENT 3.5
+Previous item.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void FastForward()
+.INDENT 0.0
+.INDENT 3.5
+Fast forward playback, this action is only stopped when another method
+in this interface is called.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Rewind()
+.INDENT 0.0
+.INDENT 3.5
+Rewind playback, this action is only stopped when another method in
+this interface is called.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Press(byte avc_key)
+.INDENT 0.0
+.INDENT 3.5
+Press a specific key to send as passthrough command. The key will be
+released automatically. Use Hold() instead if the intention is to hold
+down the key.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Hold(byte avc_key)
+.INDENT 0.0
+.INDENT 3.5
+Press and hold a specific key to send as passthrough command. It is
+your responsibility to make sure that Release() is called after calling
+this method. The held key will also be released when any other method
+in this interface is called.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+Release the previously held key invoked using Hold().
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Equalizer [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Indicates Player Equalizer setting.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqoff\(dq
+.TP
+.B \(dqon\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Repeat [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Indicates Player Repeat setting.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqoff\(dq
+.TP
+.B \(dqsingletrack\(dq
+.TP
+.B \(dqalltracks\(dq
+.TP
+.B \(dqgroup\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Shuffle [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Indicates Player Suffle setting.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqoff\(dq
+.TP
+.B \(dqalltracks\(dq
+.TP
+.B \(dqgroup\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Scan [readwrite]
+.INDENT 0.0
+.INDENT 3.5
+Indicates Player Scan setting.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqoff\(dq
+.TP
+.B \(dqalltracks\(dq
+.TP
+.B \(dqgroup\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Status [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates Player Status setting.
+.sp
+Possible status:
+.INDENT 0.0
+.TP
+.B \(dqplaying\(dq
+.TP
+.B \(dqstopped\(dq
+.TP
+.B \(dqpaused\(dq
+.TP
+.B \(dqforward\-seek\(dq
+.TP
+.B \(dqreverse\-seek\(dq
+.TP
+.B \(dqerror\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint32 Position [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Playback position in milliseconds. Changing the position may generate
+additional events that will be sent to the remote device. When position
+is 0 it means the track is starting and when it\(aqs greater than or equal
+to track\(aqs duration the track has ended.
+.sp
+Note that even if duration is not available in metadata it\(aqs possible
+to signal its end by setting position to the maximum uint32 value.
+.UNINDENT
+.UNINDENT
+.SS dict Track [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Track metadata.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B string Title
+Track title name
+.TP
+.B string Artist
+Track artist name
+.TP
+.B string Album
+Track album name
+.TP
+.B string Genre
+Track genre name
+.TP
+.B uint32 NumberOfTracks
+Number of tracks in total
+.TP
+.B uint32 TrackNumber
+Track number
+.TP
+.B uint32 Duration
+Track duration in milliseconds
+.TP
+.B string ImgHandle
+[experimental]
+.sp
+Track image handle, available and valid only during the lifetime of an
+OBEX BIP connection to the ObexPort.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object Device [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Device object path.
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Player name
+.UNINDENT
+.UNINDENT
+.SS string Type [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Player type
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+\(dqAudio\(dq
+\(dqVideo\(dq
+\(dqAudio Broadcasting\(dq
+\(dqVideo Broadcasting\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string Subtype [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Player subtype
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+\(dqAudio Book\(dq
+\(dqPodcast\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS boolean Browsable [readonly]
+.INDENT 0.0
+.INDENT 3.5
+If present indicates the player can be browsed using MediaFolder
+interface.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B True
+Supported and active
+.TP
+.B False
+Supported but inactive
+.UNINDENT
+.sp
+Note: If supported but inactive clients can enable it by using
+MediaFolder interface but it might interfere in the playback of other
+players.
+.UNINDENT
+.UNINDENT
+.SS boolean Searchable [readonly]
+.INDENT 0.0
+.INDENT 3.5
+If present indicates the player can be searched using MediaFolder
+interface.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B True
+Supported and active
+.TP
+.B False
+Supported but inactive
+.UNINDENT
+.sp
+Note: If supported but inactive clients can enable it by using
+MediaFolder interface but it might interfere in the playback of other
+players.
+.UNINDENT
+.UNINDENT
+.SS object Playlist
+.INDENT 0.0
+.INDENT 3.5
+Playlist object path.
+.UNINDENT
+.UNINDENT
+.SS uint16 ObexPort [readonly, experimental]
+.INDENT 0.0
+.INDENT 3.5
+If present indicates the player can get cover art using BIP over OBEX
+on this PSM port.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaPlayer.rst b/doc/org.bluez.MediaPlayer.rst
new file mode 100644
index 0000000..94f5b84
--- /dev/null
+++ b/doc/org.bluez.MediaPlayer.rst
@@ -0,0 +1,326 @@
+=====================
+org.bluez.MediaPlayer
+=====================
+
+-----------------------------------------
+BlueZ D-Bus MediaPlayer API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: September 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez (Controller role)
+:Interface:	org.bluez.MediaPlayer1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
+
+Methods
+-------
+
+void Play()
+```````````
+
+	Resume playback.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Pause()
+````````````
+
+	Pause playback.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Stop()
+```````````
+
+	Stop playback.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Next()
+```````````
+
+	Next item.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Previous()
+```````````````
+
+	Previous item.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void FastForward()
+``````````````````
+
+	Fast forward playback, this action is only stopped when another method
+	in this interface is called.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Rewind()
+`````````````
+
+	Rewind playback, this action is only stopped when another method in
+	this interface is called.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Press(byte avc_key)
+````````````````````````
+
+	Press a specific key to send as passthrough command. The key will be
+	released automatically. Use Hold() instead if the intention is to hold
+	down the key.
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Hold(byte avc_key)
+```````````````````````
+
+	Press and hold a specific key to send as passthrough command. It is
+	your responsibility to make sure that Release() is called after calling
+	this method. The held key will also be released when any other method
+	in this interface is called.
+
+	Possible Errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+void Release()
+``````````````
+
+	Release the previously held key invoked using Hold().
+
+	Possible Errors:
+
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.Failed:
+
+Properties
+----------
+
+string Equalizer [readwrite]
+````````````````````````````
+
+	Indicates Player Equalizer setting.
+
+	Possible values:
+
+	:"off":
+	:"on":
+
+string Repeat [readwrite]
+`````````````````````````
+
+	Indicates Player Repeat setting.
+
+	Possible values:
+
+	:"off":
+	:"singletrack":
+	:"alltracks":
+	:"group":
+
+string Shuffle [readwrite]
+``````````````````````````
+
+	Indicates Player Suffle setting.
+
+	Possible values:
+
+	:"off":
+	:"alltracks":
+	:"group":
+
+string Scan [readwrite]
+```````````````````````
+
+	Indicates Player Scan setting.
+
+	Possible values:
+
+	:"off":
+	:"alltracks":
+	:"group":
+
+string Status [readonly]
+````````````````````````
+
+	Indicates Player Status setting.
+
+	Possible status:
+
+	:"playing":
+	:"stopped":
+	:"paused":
+	:"forward-seek":
+	:"reverse-seek":
+	:"error":
+
+uint32 Position [readonly]
+``````````````````````````
+
+	Playback position in milliseconds. Changing the position may generate
+	additional events that will be sent to the remote device. When position
+	is 0 it means the track is starting and when it's greater than or equal
+	to track's duration the track has ended.
+
+	Note that even if duration is not available in metadata it's possible
+	to signal its end by setting position to the maximum uint32 value.
+
+dict Track [readonly]
+`````````````````````
+
+	Track metadata.
+
+	Possible values:
+
+	:string Title:
+
+		Track title name
+
+	:string Artist:
+
+		Track artist name
+
+	:string Album:
+
+		Track album name
+
+	:string Genre:
+
+		Track genre name
+
+	:uint32 NumberOfTracks:
+
+		Number of tracks in total
+
+	:uint32 TrackNumber:
+
+		Track number
+
+	:uint32 Duration:
+
+		Track duration in milliseconds
+
+	:string ImgHandle: [experimental]
+
+		Track image handle, available and valid only during the lifetime of an
+		OBEX BIP connection to the ObexPort.
+
+object Device [readonly]
+````````````````````````
+
+	Device object path.
+
+string Name [readonly]
+``````````````````````
+
+	Player name
+
+string Type [readonly]
+``````````````````````
+
+	Player type
+
+	Possible values:
+
+		"Audio"
+		"Video"
+		"Audio Broadcasting"
+		"Video Broadcasting"
+
+string Subtype [readonly]
+`````````````````````````
+
+	Player subtype
+
+	Possible values:
+
+		"Audio Book"
+		"Podcast"
+
+boolean Browsable [readonly]
+````````````````````````````
+
+	If present indicates the player can be browsed using MediaFolder
+	interface.
+
+	Possible values:
+
+	:True:
+
+		Supported and active
+
+	:False:
+
+		Supported but inactive
+
+	Note: If supported but inactive clients can enable it by using
+	MediaFolder interface but it might interfere in the playback of other
+	players.
+
+boolean Searchable [readonly]
+`````````````````````````````
+
+	If present indicates the player can be searched using MediaFolder
+	interface.
+
+	Possible values:
+
+	:True:
+
+		Supported and active
+
+	:False:
+
+		Supported but inactive
+
+	Note: If supported but inactive clients can enable it by using
+	MediaFolder interface but it might interfere in the playback of other
+	players.
+
+object Playlist
+```````````````
+
+	Playlist object path.
+
+uint16 ObexPort [readonly, experimental]
+````````````````````````````````````````
+
+	If present indicates the player can get cover art using BIP over OBEX
+	on this PSM port.
diff --git a/doc/org.bluez.MediaTransport.5 b/doc/org.bluez.MediaTransport.5
new file mode 100644
index 0000000..ed26c62
--- /dev/null
+++ b/doc/org.bluez.MediaTransport.5
@@ -0,0 +1,369 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.MEDIATRANSPORT" "5" "July 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.MediaTransport \- BlueZ D-Bus MediaTransport API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.MediaTransport1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/fdX
+.UNINDENT
+.SS Methods
+.SS fd, uint16, uint16 Acquire()
+.INDENT 0.0
+.INDENT 3.5
+Acquire transport file descriptor and the MTU for read and write
+respectively.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS fd, uint16, uint16 TryAcquire()
+.INDENT 0.0
+.INDENT 3.5
+Acquire transport file descriptor only if the transport is in \(dqpending\(dq
+state at the time the message is received by BlueZ. Otherwise no request
+will be sent to the remote device and the function will just fail with
+org.bluez.Error.NotAvailable.
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotAuthorized
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotAvailable
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+Releases file descriptor.
+.UNINDENT
+.UNINDENT
+.SS void Select()
+.INDENT 0.0
+.INDENT 3.5
+Applicable only for transports created by a broadcast sink. This moves
+the transport from \(aqidle\(aq to \(aqbroadcasting\(aq. This allows the user to
+select which BISes he wishes to sync to via a 2 step process:
+1) the user calls the method, changing the transport\(aqs state to broadcasting
+2) the audio server detects that the transport is in the \(aqbroadcasting\(aq
+state and automatically acquires it
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotAuthorized
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Unselect()
+.INDENT 0.0
+.INDENT 3.5
+Applicable only for transports created by a broadcast sink. This moves
+the transport from \(aqbroadcasting\(aq or \(aqactive\(aq to \(aqidle\(aq. This allows the
+user to terminate the sync to a BIS to via a 2 step process:
+1) the user calls this method, changing the transport\(aqs state to idle
+2) the audio server detects this event and releases the transport
+.sp
+Possible Errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.NotAuthorized
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS object Device [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Device object which the transport is connected to.
+.UNINDENT
+.UNINDENT
+.SS string UUID [readonly]
+.INDENT 0.0
+.INDENT 3.5
+UUID of the profile which the transport is for.
+.UNINDENT
+.UNINDENT
+.SS byte Codec [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Assigned number of codec that the transport support.
+The values should match the profile specification which is indicated by
+the UUID.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Configuration [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Configuration blob, it is used as it is so the size and byte order must
+match.
+.UNINDENT
+.UNINDENT
+.SS string State [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the state of the transport. Possible values are:
+.INDENT 0.0
+.TP
+.B \(dqidle\(dq
+not streaming
+.TP
+.B \(dqpending\(dq
+streaming but not acquired
+.TP
+.B \(dqbroadcasting\(dq
+streaming but not acquired, applicable only for transports
+created by a broadcast sink
+.TP
+.B \(dqactive\(dq
+streaming and acquired
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint16 Delay [readwrite, optional]
+.INDENT 0.0
+.INDENT 3.5
+Transport delay in 1/10 of millisecond, this property is only writeable
+when the transport corresponds to a sink endpoint and it was acquired by
+the sender.
+.UNINDENT
+.UNINDENT
+.SS uint16 Volume [readwrite, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicates volume level of the transport, this property is only writeable
+when the transport was acquired by the sender.
+.sp
+Possible Values: 0\-127
+.UNINDENT
+.UNINDENT
+.SS object Endpoint [readonly, optional, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Endpoint object which the transport is associated with.
+.UNINDENT
+.UNINDENT
+.SS uint32 Location [readonly, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates transport Audio Location.
+.UNINDENT
+.UNINDENT
+.SS array{byte} Metadata [readwrite, ISO Only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Indicates transport Metadata.
+.UNINDENT
+.UNINDENT
+.SS array{object} Links [readonly, optional, CIS only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Linked transport objects which the transport is associated with.
+.UNINDENT
+.UNINDENT
+.SS array{object} Links [readwrite, BIS only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+For a Broadcast Sink, the BIG sync procedure requires all
+desired streams to be enumerated from the start and it cannot
+be later reconfigured by adding or removing BISes. To avoid
+terminating and recreating the BIG sync everytime a new
+transport is selected for acquire, all transports selected via
+Transport.Select need to be linked together. When the first
+transport is acquired via Transport.Acquire, all links are
+included in the BIG sync command. An acquired transport will
+create and set fds for all its links. Then, each link needs
+to be acquired separately, to get the fd and start receiving
+audio.
+.UNINDENT
+.UNINDENT
+.SS dict QoS [readwrite, optional, ISO only, experimental]
+.INDENT 0.0
+.INDENT 3.5
+Only present when QoS is configured.
+.sp
+Possible values for Unicast:
+.INDENT 0.0
+.TP
+.B byte CIG
+Indicates configured CIG.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B 0x00 \- 0xef
+Valid ID range.
+.TP
+.B 0xff
+Auto allocate.
+.UNINDENT
+.TP
+.B byte CIS
+Indicates configured CIS.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B 0x00 \- 0xef
+Valid ID range.
+.TP
+.B 0xff
+Auto allocate.
+.UNINDENT
+.TP
+.B byte Framing
+Indicates configured framing.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B 0x00
+Unframed.
+.TP
+.B 0x01
+Framed.
+.UNINDENT
+.TP
+.B uint32 PresentationDelay
+Indicates configured transport presentation delay (us).
+.TP
+.B byte TargetLatency
+Indicates the requested target latency.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B 0x01
+Low Latency.
+.TP
+.B 0x02
+Balanced Latency/Reliability.
+.TP
+.B 0x03
+High Reliability.
+.UNINDENT
+.UNINDENT
+.sp
+Possible values for Broadcast:
+.INDENT 0.0
+.TP
+.B byte BIG
+Indicates configured QoS BIG.
+.TP
+.B byte BIS
+Indicates configured BIS.
+.TP
+.B byte SyncFactor
+Indicates configured broadcast sync factor.
+.TP
+.B byte Packing
+Indicates configured packing.
+.TP
+.B byte Framing
+Indicates configured framing.
+.TP
+.B array{byte} BCode
+Indicates the string used for encryption/decryption.
+.TP
+.B byte encryption
+Indicates if the stream is encrypted.
+.TP
+.B byte Options
+Indicates configured broadcast options.
+.TP
+.B uint16 Skip
+Indicates configured broadcast skip.
+.TP
+.B byte SyncTimeout
+Indicates configured broadcast sync timeout.
+.TP
+.B byte SyncType
+Indicates configured broadcast sync CTE type.
+.TP
+.B byte MSE
+Indicates configured broadcast MSE.
+.TP
+.B uint16 Timeout
+Indicates configured broadcast timeout.
+.UNINDENT
+.sp
+Possible values for both Unicast and Broadcast:
+.INDENT 0.0
+.TP
+.B uint32 Interval
+Indicates configured ISO interval (us).
+.TP
+.B uint16 Latency
+Indicates configured transport latency (ms).
+.TP
+.B uint16 SDU
+Indicates configured maximum SDU.
+.TP
+.B byte PHY
+Indicates configured PHY.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B bit 0
+LE 1M
+.TP
+.B bit 1
+LE 2M
+.TP
+.B bit 2
+LE Coded
+.UNINDENT
+.TP
+.B byte Retransmissions
+Indicates configured retransmissions.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.MediaTransport.rst b/doc/org.bluez.MediaTransport.rst
new file mode 100644
index 0000000..78789bc
--- /dev/null
+++ b/doc/org.bluez.MediaTransport.rst
@@ -0,0 +1,327 @@
+========================
+org.bluez.MediaTransport
+========================
+
+--------------------------------------------
+BlueZ D-Bus MediaTransport API documentation
+--------------------------------------------
+
+:Version: BlueZ
+:Date: July 2024
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.MediaTransport1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/fdX
+
+Methods
+-------
+
+fd, uint16, uint16 Acquire()
+````````````````````````````
+
+	Acquire transport file descriptor and the MTU for read and write
+	respectively.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.Failed:
+
+fd, uint16, uint16 TryAcquire()
+```````````````````````````````
+
+	Acquire transport file descriptor only if the transport is in "pending"
+	state at the time the message is received by BlueZ. Otherwise no request
+	will be sent to the remote device and the function will just fail with
+	org.bluez.Error.NotAvailable.
+
+	Possible Errors:
+
+	:org.bluez.Error.NotAuthorized:
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotAvailable:
+
+void Release()
+``````````````
+
+	Releases file descriptor.
+
+void Select()
+`````````````
+
+	Applicable only for transports created by a broadcast sink. This moves
+	the transport from 'idle' to 'broadcasting'. This allows the user to
+	select which BISes he wishes to sync to via a 2 step process:
+	1) the user calls the method, changing the transport's state to broadcasting
+	2) the audio server detects that the transport is in the 'broadcasting'
+	state and automatically acquires it
+
+	Possible Errors:
+
+	:org.bluez.Error.NotAuthorized:
+
+void Unselect()
+```````````````
+
+	Applicable only for transports created by a broadcast sink. This moves
+	the transport from 'broadcasting' or 'active' to 'idle'. This allows the
+	user to terminate the sync to a BIS to via a 2 step process:
+	1) the user calls this method, changing the transport's state to idle
+	2) the audio server detects this event and releases the transport
+
+	Possible Errors:
+
+	:org.bluez.Error.NotAuthorized:
+
+Properties
+----------
+
+object Device [readonly]
+````````````````````````
+
+	Device object which the transport is connected to.
+
+string UUID [readonly]
+``````````````````````
+
+	UUID of the profile which the transport is for.
+
+byte Codec [readonly]
+`````````````````````
+
+	Assigned number of codec that the transport support.
+	The values should match the profile specification which is indicated by
+	the UUID.
+
+array{byte} Configuration [readonly]
+````````````````````````````````````
+
+	Configuration blob, it is used as it is so the size and byte order must
+	match.
+
+string State [readonly]
+```````````````````````
+
+	Indicates the state of the transport. Possible values are:
+
+	:"idle": not streaming
+	:"pending": streaming but not acquired
+	:"broadcasting": streaming but not acquired, applicable only for transports
+		created by a broadcast sink
+	:"active": streaming and acquired
+
+uint16 Delay [readwrite, optional]
+``````````````````````````````````
+
+	Transport delay in 1/10 of millisecond, this property is only writeable
+	when the transport corresponds to a sink endpoint and it was acquired by
+	the sender.
+
+uint16 Volume [readwrite, optional]
+```````````````````````````````````
+
+	Indicates volume level of the transport, this property is only writeable
+	when the transport was acquired by the sender.
+
+	Possible Values: 0-127
+
+object Endpoint [readonly, optional, experimental]
+``````````````````````````````````````````````````
+
+	Endpoint object which the transport is associated with.
+
+uint32 Location [readonly, ISO only, experimental]
+``````````````````````````````````````````````````
+
+	Indicates transport Audio Location.
+
+array{byte} Metadata [readwrite, ISO Only, experimental]
+````````````````````````````````````````````````````````
+
+	Indicates transport Metadata.
+
+array{object} Links [readonly, optional, CIS only, experimental]
+````````````````````````````````````````````````````````````````
+
+	Linked transport objects which the transport is associated with.
+
+array{object} Links [readwrite, BIS only, experimental]
+```````````````````````````````````````````````````````
+
+	For a Broadcast Sink, the BIG sync procedure requires all
+	desired streams to be enumerated from the start and it cannot
+	be later reconfigured by adding or removing BISes. To avoid
+	terminating and recreating the BIG sync everytime a new
+	transport is selected for acquire, all transports selected via
+	Transport.Select need to be linked together. When the first
+	transport is acquired via Transport.Acquire, all links are
+	included in the BIG sync command. An acquired transport will
+	create and set fds for all its links. Then, each link needs
+	to be acquired separately, to get the fd and start receiving
+	audio.
+
+dict QoS [readwrite, optional, ISO only, experimental]
+``````````````````````````````````````````````````````
+
+	Only present when QoS is configured.
+
+	Possible values for Unicast:
+
+	:byte CIG:
+
+		Indicates configured CIG.
+
+		Possible values:
+
+		:0x00 - 0xef:
+
+			Valid ID range.
+
+		:0xff:
+
+			Auto allocate.
+
+	:byte CIS:
+
+		Indicates configured CIS.
+
+		Possible values:
+
+		:0x00 - 0xef:
+
+			Valid ID range.
+
+		:0xff:
+
+			Auto allocate.
+
+	:byte Framing:
+
+		Indicates configured framing.
+
+		Possible values:
+
+		:0x00:
+
+			Unframed.
+
+		:0x01:
+
+			Framed.
+
+	:uint32 PresentationDelay:
+
+		Indicates configured transport presentation delay (us).
+
+	:byte TargetLatency:
+
+		Indicates the requested target latency.
+
+		Possible values:
+
+		:0x01:
+
+			Low Latency.
+
+		:0x02:
+
+			Balanced Latency/Reliability.
+
+		:0x03:
+
+			High Reliability.
+
+	Possible values for Broadcast:
+
+	:byte BIG:
+
+		Indicates configured QoS BIG.
+
+	:byte BIS:
+
+		Indicates configured BIS.
+
+	:byte SyncFactor:
+
+		Indicates configured broadcast sync factor.
+
+	:byte Packing:
+
+		Indicates configured packing.
+
+	:byte Framing:
+
+		Indicates configured framing.
+
+	:array{byte} BCode:
+
+		Indicates the string used for encryption/decryption.
+
+	:byte encryption:
+
+		Indicates if the stream is encrypted.
+
+	:byte Options:
+
+		Indicates configured broadcast options.
+
+	:uint16 Skip:
+
+		Indicates configured broadcast skip.
+
+	:byte SyncTimeout:
+
+		Indicates configured broadcast sync timeout.
+
+	:byte SyncType:
+
+		Indicates configured broadcast sync CTE type.
+
+	:byte MSE:
+
+		Indicates configured broadcast MSE.
+
+	:uint16 Timeout:
+
+		Indicates configured broadcast timeout.
+
+	Possible values for both Unicast and Broadcast:
+
+	:uint32 Interval:
+
+		Indicates configured ISO interval (us).
+
+	:uint16 Latency:
+
+		Indicates configured transport latency (ms).
+
+	:uint16 SDU:
+
+		Indicates configured maximum SDU.
+
+	:byte PHY:
+
+		Indicates configured PHY.
+
+		Possible values:
+
+		:bit 0:
+
+			LE 1M
+
+		:bit 1:
+
+			LE 2M
+
+		:bit 2:
+
+			LE Coded
+
+	:byte Retransmissions:
+
+		Indicates configured retransmissions.
diff --git a/doc/org.bluez.Network.5 b/doc/org.bluez.Network.5
new file mode 100644
index 0000000..6d10927
--- /dev/null
+++ b/doc/org.bluez.Network.5
@@ -0,0 +1,118 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.NETWORK" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Network \- BlueZ D-Bus Network API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.Network1
+.TP
+.B Object path
+[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+.UNINDENT
+.SS Methods
+.SS string Connect(string uuid)
+.INDENT 0.0
+.INDENT 3.5
+Connects to the network device and return the network interface name.
+.sp
+Possible uuid values:
+.INDENT 0.0
+.TP
+.B \(dqpanu\(dq, \(dq00001115\-0000\-1000\-8000\-00805f9b34fb\(dq
+Personal Network User role.
+.TP
+.B \(dqnap\(dq, \(dq00001116\-0000\-1000\-8000\-00805f9b34fb\(dq
+Network Access Point role.
+.TP
+.B \(dqgn\(dq, \(dq00001117\-0000\-1000\-8000\-00805f9b34fb\(dq
+Group Network role.
+.UNINDENT
+.sp
+The connection will be closed and network device released either upon
+calling \fBDisconnect()\fP or when the client disappears from the
+message bus.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.NotSupported
+.TP
+.B org.bluez.Error.InProgress
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Disconnect()
+.INDENT 0.0
+.INDENT 3.5
+Disconnects from the network device.
+.sp
+To abort a connection attempt in case of errors or timeouts in the
+client it is fine to call this method.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Failed
+.TP
+.B org.bluez.Error.NotConnected
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS boolean Connected [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates if the device is connected.
+.UNINDENT
+.UNINDENT
+.SS string Interface [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the network interface name when available.
+.UNINDENT
+.UNINDENT
+.SS string UUID [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the connection role when available.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Network.rst b/doc/org.bluez.Network.rst
new file mode 100644
index 0000000..d81a69d
--- /dev/null
+++ b/doc/org.bluez.Network.rst
@@ -0,0 +1,83 @@
+=================
+org.bluez.Network
+=================
+
+-------------------------------------
+BlueZ D-Bus Network API documentation
+-------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.Network1
+:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods
+-------
+
+string Connect(string uuid)
+```````````````````````````
+
+	Connects to the network device and return the network interface name.
+
+	Possible uuid values:
+
+	:"panu", "00001115-0000-1000-8000-00805f9b34fb":
+
+		Personal Network User role.
+
+	:"nap", "00001116-0000-1000-8000-00805f9b34fb":
+
+		Network Access Point role.
+
+	:"gn", "00001117-0000-1000-8000-00805f9b34fb":
+
+		Group Network role.
+
+	The connection will be closed and network device released either upon
+	calling **Disconnect()** or when the client disappears from the
+	message bus.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.NotSupported:
+	:org.bluez.Error.InProgress:
+	:org.bluez.Error.Failed:
+
+void Disconnect()
+`````````````````
+
+	Disconnects from the network device.
+
+	To abort a connection attempt in case of errors or timeouts in the
+	client it is fine to call this method.
+
+	Possible errors:
+
+	:org.bluez.Error.Failed:
+	:org.bluez.Error.NotConnected:
+
+Properties
+----------
+
+boolean Connected [readonly]
+````````````````````````````
+
+	Indicates if the device is connected.
+
+string Interface [readonly, optional]
+`````````````````````````````````````
+
+	Indicates the network interface name when available.
+
+string UUID [readonly, optional]
+````````````````````````````````
+
+	Indicates the connection role when available.
diff --git a/doc/org.bluez.NetworkServer.5 b/doc/org.bluez.NetworkServer.5
new file mode 100644
index 0000000..3f47596
--- /dev/null
+++ b/doc/org.bluez.NetworkServer.5
@@ -0,0 +1,100 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.NETWORKSERVER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.NetworkServer \- BlueZ D-Bus NetworkServer API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.NetworkServer1
+.TP
+.B Object path
+/org/bluez/{hci0,hci1,...}
+.UNINDENT
+.SS Methods
+.SS void Register(string uuid, string bridge)
+.INDENT 0.0
+.INDENT 3.5
+Registers server for the provided UUID.
+.sp
+Every new connection to this server will be added the bridge interface.
+.sp
+Possible uuid values:
+.INDENT 0.0
+.TP
+.B \(dqpanu\(dq, \(dq00001115\-0000\-1000\-8000\-00805f9b34fb\(dq
+Personal Network User role.
+.TP
+.B \(dqnap\(dq, \(dq00001116\-0000\-1000\-8000\-00805f9b34fb\(dq
+Network Access Point role.
+.TP
+.B \(dqgn\(dq, \(dq00001117\-0000\-1000\-8000\-00805f9b34fb\(dq
+Group Network role.
+.UNINDENT
+.sp
+Initially no network server SDP is provided. Only after this method a
+SDP record will be available and the BNEP server will be ready for
+incoming connections.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Unregister(string uuid)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters the server for provided UUID which was previously
+registered with \fBRegister()\fP method.
+.sp
+All servers will be automatically unregistered when the calling
+application terminates.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.NetworkServer.rst b/doc/org.bluez.NetworkServer.rst
new file mode 100644
index 0000000..d15d223
--- /dev/null
+++ b/doc/org.bluez.NetworkServer.rst
@@ -0,0 +1,68 @@
+=======================
+org.bluez.NetworkServer
+=======================
+
+-------------------------------------------
+BlueZ D-Bus NetworkServer API documentation
+-------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.NetworkServer1
+:Object path:	/org/bluez/{hci0,hci1,...}
+
+
+Methods
+-------
+
+void Register(string uuid, string bridge)
+`````````````````````````````````````````
+
+	Registers server for the provided UUID.
+
+	Every new connection to this server will be added the bridge interface.
+
+	Possible uuid values:
+
+	:"panu", "00001115-0000-1000-8000-00805f9b34fb":
+
+		Personal Network User role.
+
+	:"nap", "00001116-0000-1000-8000-00805f9b34fb":
+
+		Network Access Point role.
+
+	:"gn", "00001117-0000-1000-8000-00805f9b34fb":
+
+		Group Network role.
+
+	Initially no network server SDP is provided. Only after this method a
+	SDP record will be available and the BNEP server will be ready for
+	incoming connections.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+	:org.bluez.Error.Failed:
+
+void Unregister(string uuid)
+````````````````````````````
+
+	Unregisters the server for provided UUID which was previously
+	registered with **Register()** method.
+
+	All servers will be automatically unregistered when the calling
+	application terminates.
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.Failed:
diff --git a/doc/org.bluez.Profile.5 b/doc/org.bluez.Profile.5
new file mode 100644
index 0000000..3cbb5f2
--- /dev/null
+++ b/doc/org.bluez.Profile.5
@@ -0,0 +1,81 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.PROFILE" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.Profile \- BlueZ D-Bus Profile API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+unique name
+.TP
+.B Interface
+org.bluez.Profile1
+.TP
+.B Object path
+freely definable
+.UNINDENT
+.SS Methods
+.SS void Release() [noreply]
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the service daemon unregisters the profile.
+A profile can use it to do cleanup tasks. There is no need to unregister
+the profile, because when this method gets called it has already been
+unregistered.
+.UNINDENT
+.UNINDENT
+.SS void NewConnection(object device, fd, dict fd_properties)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when a new service level connection has been
+made and authorized.
+.sp
+Possible fd_properties values:
+.INDENT 0.0
+.TP
+.B uint16 Version [optional]
+Profile version.
+.TP
+.B uint16 Features [optional]
+Profile features.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.Rejected
+.TP
+.B org.bluez.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.Profile.rst b/doc/org.bluez.Profile.rst
new file mode 100644
index 0000000..d8ae669
--- /dev/null
+++ b/doc/org.bluez.Profile.rst
@@ -0,0 +1,51 @@
+=================
+org.bluez.Profile
+=================
+
+-------------------------------------
+BlueZ D-Bus Profile API documentation
+-------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	unique name
+:Interface:	org.bluez.Profile1
+:Object path:	freely definable
+
+Methods
+-------
+
+void Release() [noreply]
+````````````````````````
+
+	This method gets called when the service daemon unregisters the profile.
+	A profile can use it to do cleanup tasks. There is no need to unregister
+	the profile, because when this method gets called it has already been
+	unregistered.
+
+void NewConnection(object device, fd, dict fd_properties)
+`````````````````````````````````````````````````````````
+
+	This method gets called when a new service level connection has been
+	made and authorized.
+
+	Possible fd_properties values:
+
+	:uint16 Version [optional]:
+
+		Profile version.
+
+	:uint16 Features [optional]:
+
+		Profile features.
+
+	Possible errors:
+
+	:org.bluez.Error.Rejected:
+	:org.bluez.Error.Canceled:
diff --git a/doc/org.bluez.ProfileManager.5 b/doc/org.bluez.ProfileManager.5
new file mode 100644
index 0000000..61f9a33
--- /dev/null
+++ b/doc/org.bluez.ProfileManager.5
@@ -0,0 +1,164 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.PROFILEMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.ProfileManager \- BlueZ D-Bus ProfileManager API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez
+.TP
+.B Interface
+org.bluez.ProfileManager1
+.TP
+.B Object path
+/org/bluez
+.UNINDENT
+.SS Methods
+.SS void RegisterProfile(object profile, string uuid, dict options)
+.INDENT 0.0
+.INDENT 3.5
+Registers profile agent.
+.sp
+The object path defines the path of the profile that will be called
+when there is a connection and must implement \fBorg.bluez.Profile(5)\fP
+interface.
+.sp
+If an application disconnects from the bus all its registered profiles
+will be removed.
+.sp
+Possible uuid values:
+.INDENT 0.0
+.TP
+.B \(dq0000111f\-0000\-1000\-8000\-00805f9b34fb\(dq
+HFP AG, default profile Version is 1.7, profile Features is
+0b001001 and RFCOMM channel is 13. Authentication is required.
+.TP
+.B \(dq0000111e\-0000\-1000\-8000\-00805f9b34fb\(dq
+HFP HS, default profile Version is 1.7, profile Features is
+0b000000 and RFCOMM channel is 7. Authentication is required.
+.TP
+.B \(dq00001112\-0000\-1000\-8000\-00805f9b34fb\(dq
+HSP AG, default profile Version is 1.2, RFCOMM channel is 12 and
+Authentication is required. Does not support any Features,
+option is ignored.
+.TP
+.B \(dq00001108\-0000\-1000\-8000\-00805f9b34fb\(dq
+HSP HS, default profile Version is 1.2, profile Features is 0b0
+and RFCOMM channel is 6. Authentication is required.
+Features is one bit value, specify capability of Remote Audio
+Volume Control (by default turned off).
+.TP
+.B \(dq<vendor UUID>\(dq
+Vendor defined UUID, no defaults, must set options.
+.UNINDENT
+.sp
+Possible options values:
+.INDENT 0.0
+.TP
+.B string Name
+Human readable name for the profile
+.TP
+.B string Service
+The primary service class UUID (if different from the actual
+profile UUID).
+.TP
+.B string Role
+For asymmetric profiles that do not have UUIDs available to
+uniquely identify each side this parameter allows specifying the
+precise local role.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqclient\(dq
+.TP
+.B \(dqserver\(dq
+.UNINDENT
+.TP
+.B uint16 Channel
+RFCOMM channel number that is used for client and server UUIDs.
+.sp
+If applicable it will be used in the SDP record as well.
+.TP
+.B uint16 PSM
+PSM number that is used for client and server UUIDs.
+.sp
+If applicable it will be used in the SDP record as well.
+.TP
+.B boolean RequireAuthentication
+Pairing is required before connections will be established.
+No devices will be connected if not paired.
+.TP
+.B boolean RequireAuthorization
+Request authorization before any connection will be established.
+.TP
+.B boolean AutoConnect
+In case of a client UUID this will force connection of the
+RFCOMM or L2CAP channels when a remote device is connected.
+.TP
+.B string ServiceRecord
+Provide a manual SDP record.
+.TP
+.B uint16 Version
+Profile version (for SDP record)
+.TP
+.B uint16 Features
+Profile features (for SDP record)
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.InvalidArguments
+.TP
+.B org.bluez.Error.AlreadyExists
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterProfile(object profile)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters profile object that has been previously registered using
+\fBRegisterProfile\fP\&.
+.sp
+The object path parameter must match the same value that has been used
+on registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.ProfileManager.rst b/doc/org.bluez.ProfileManager.rst
new file mode 100644
index 0000000..ccd7a26
--- /dev/null
+++ b/doc/org.bluez.ProfileManager.rst
@@ -0,0 +1,141 @@
+========================
+org.bluez.ProfileManager
+========================
+
+--------------------------------------------
+BlueZ D-Bus ProfileManager API documentation
+--------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez
+:Interface:	org.bluez.ProfileManager1
+:Object path:	/org/bluez
+
+Methods
+-------
+
+void RegisterProfile(object profile, string uuid, dict options)
+```````````````````````````````````````````````````````````````
+
+	Registers profile agent.
+
+	The object path defines the path of the profile that will be called
+	when there is a connection and must implement **org.bluez.Profile(5)**
+	interface.
+
+	If an application disconnects from the bus all its registered profiles
+	will be removed.
+
+	Possible uuid values:
+
+	:"0000111f-0000-1000-8000-00805f9b34fb":
+
+		HFP AG, default profile Version is 1.7, profile Features is
+		0b001001 and RFCOMM channel is 13. Authentication is required.
+
+	:"0000111e-0000-1000-8000-00805f9b34fb":
+
+		HFP HS, default profile Version is 1.7, profile Features is
+		0b000000 and RFCOMM channel is 7. Authentication is required.
+
+	:"00001112-0000-1000-8000-00805f9b34fb":
+
+		HSP AG, default profile Version is 1.2, RFCOMM channel is 12 and
+		Authentication is required. Does not support any Features,
+		option is ignored.
+
+	:"00001108-0000-1000-8000-00805f9b34fb":
+
+		HSP HS, default profile Version is 1.2, profile Features is 0b0
+		and RFCOMM channel is 6. Authentication is required.
+		Features is one bit value, specify capability of Remote Audio
+		Volume Control (by default turned off).
+
+	:"<vendor UUID>":
+
+		Vendor defined UUID, no defaults, must set options.
+
+	Possible options values:
+
+	:string Name:
+
+		Human readable name for the profile
+
+	:string Service:
+
+		The primary service class UUID (if different from the actual
+		profile UUID).
+
+	:string Role:
+
+		For asymmetric profiles that do not have UUIDs available to
+		uniquely identify each side this parameter allows specifying the
+		precise local role.
+
+		Possible values:
+
+		:"client":
+		:"server":
+
+	:uint16 Channel:
+
+		RFCOMM channel number that is used for client and server UUIDs.
+
+		If applicable it will be used in the SDP record as well.
+
+	:uint16 PSM:
+
+		PSM number that is used for client and server UUIDs.
+
+		If applicable it will be used in the SDP record as well.
+
+	:boolean RequireAuthentication:
+
+		Pairing is required before connections will be established.
+		No devices will be connected if not paired.
+
+	:boolean RequireAuthorization:
+
+		Request authorization before any connection will be established.
+
+	:boolean AutoConnect:
+
+		In case of a client UUID this will force connection of the
+		RFCOMM or L2CAP channels when a remote device is connected.
+
+	:string ServiceRecord:
+
+		Provide a manual SDP record.
+
+	:uint16 Version:
+
+		Profile version (for SDP record)
+
+	:uint16 Features:
+
+		Profile features (for SDP record)
+
+	Possible errors:
+
+	:org.bluez.Error.InvalidArguments:
+	:org.bluez.Error.AlreadyExists:
+
+void UnregisterProfile(object profile)
+``````````````````````````````````````
+
+	Unregisters profile object that has been previously registered using
+	**RegisterProfile**.
+
+	The object path parameter must match the same value that has been used
+	on registration.
+
+	Possible errors:
+
+	:org.bluez.Error.DoesNotExist:
diff --git a/doc/org.bluez.obex.Agent.5 b/doc/org.bluez.obex.Agent.5
new file mode 100644
index 0000000..b65e047
--- /dev/null
+++ b/doc/org.bluez.obex.Agent.5
@@ -0,0 +1,78 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.AGENT" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Agent \- BlueZ D-Bus OBEX Agent API documentation
+.SH INTERFACE
+.sp
+;Service:       unique name
+:Interface:     org.bluez.obex.Agent1
+:Object path:   freely definable
+.SS Methods
+.SS void Release()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when \fBobexd(8)\fP daemon unregisters the agent.
+An agent can use it to do cleanup tasks. There is no need to unregister
+the agent, because when this method gets called it has already been
+unregistered.
+.UNINDENT
+.UNINDENT
+.SS string AuthorizePush(object transfer)
+.INDENT 0.0
+.INDENT 3.5
+This method gets called when the \fBobexd(8)\fP needs to accept/reject a
+Bluetooth object push request.
+.sp
+Returns the full path (including the filename) or the folder name
+suffixed with \(aq/\(aq where the object shall be stored.
+.sp
+The transfer object, see \fBorg.bluez.obex.Transfer(5)\fP will contain a
+Filename property that contains the default location and name that can
+be returned.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.Rejected
+.TP
+.B org.bluez.obex.Error.Canceled
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Cancel()
+.INDENT 0.0
+.INDENT 3.5
+This method gets called to indicate that the agent request failed before
+a reply was returned. It cancels the previous request.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Agent.rst b/doc/org.bluez.obex.Agent.rst
new file mode 100644
index 0000000..b832e27
--- /dev/null
+++ b/doc/org.bluez.obex.Agent.rst
@@ -0,0 +1,54 @@
+====================
+org.bluez.obex.Agent
+====================
+
+----------------------------------------
+BlueZ D-Bus OBEX Agent API documentation
+----------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+;Service:	unique name
+:Interface:	org.bluez.obex.Agent1
+:Object path:	freely definable
+
+Methods
+-------
+
+void Release()
+``````````````
+
+	This method gets called when **obexd(8)** daemon unregisters the agent.
+	An agent can use it to do cleanup tasks. There is no need to unregister
+	the agent, because when this method gets called it has already been
+	unregistered.
+
+string AuthorizePush(object transfer)
+`````````````````````````````````````
+
+	This method gets called when the **obexd(8)** needs to accept/reject a
+	Bluetooth object push request.
+
+	Returns the full path (including the filename) or the folder name
+	suffixed with '/' where the object shall be stored.
+
+	The transfer object, see **org.bluez.obex.Transfer(5)** will contain a
+	Filename property that contains the default location and name that can
+	be returned.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.Rejected:
+	:org.bluez.obex.Error.Canceled:
+
+void Cancel()
+`````````````
+
+	This method gets called to indicate that the agent request failed before
+	a reply was returned. It cancels the previous request.
diff --git a/doc/org.bluez.obex.AgentManager.5 b/doc/org.bluez.obex.AgentManager.5
new file mode 100644
index 0000000..a8f6b76
--- /dev/null
+++ b/doc/org.bluez.obex.AgentManager.5
@@ -0,0 +1,76 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.AGENTMANAGER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.AgentManager \- BlueZ D-Bus OBEX AgentManager API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.AgentManager1
+.TP
+.B Object path
+/org/bluez/obex
+.UNINDENT
+.SS Methods
+.SS void RegisterAgent(object agent)
+.INDENT 0.0
+.INDENT 3.5
+Registers an agent, which must implement \fBorg.bluez.obex.Agent(5)\fP, to
+request authorization of the user to accept/reject objects.
+.sp
+Object push service needs to authorize each received object.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.AlreadyExists
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UnregisterAgent(object agent)
+.INDENT 0.0
+.INDENT 3.5
+Unregisters the agent that has been previously registered using
+\fBRegisterAgent()\fP\&. The object path parameter must match the same value
+that has been used on registration.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.DoesNotExist
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.AgentManager.rst b/doc/org.bluez.obex.AgentManager.rst
new file mode 100644
index 0000000..f18f227
--- /dev/null
+++ b/doc/org.bluez.obex.AgentManager.rst
@@ -0,0 +1,45 @@
+===========================
+org.bluez.obex.AgentManager
+===========================
+
+-----------------------------------------------
+BlueZ D-Bus OBEX AgentManager API documentation
+-----------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.AgentManager1
+:Object path:	/org/bluez/obex
+
+Methods
+```````
+
+void RegisterAgent(object agent)
+````````````````````````````````
+
+	Registers an agent, which must implement **org.bluez.obex.Agent(5)**, to
+	request authorization of the user to accept/reject objects.
+
+	Object push service needs to authorize each received object.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.AlreadyExists:
+
+void UnregisterAgent(object agent)
+``````````````````````````````````
+
+	Unregisters the agent that has been previously registered using
+	**RegisterAgent()**. The object path parameter must match the same value
+	that has been used on registration.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.DoesNotExist:
diff --git a/doc/org.bluez.obex.Client.5 b/doc/org.bluez.obex.Client.5
new file mode 100644
index 0000000..2b50583
--- /dev/null
+++ b/doc/org.bluez.obex.Client.5
@@ -0,0 +1,112 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.CLIENT" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Client \- BlueZ D-Bus OBEX Client API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Client1
+.TP
+.B Object path
+/org/bluez/obex
+.UNINDENT
+.SS Methods
+.SS object CreateSession(string destination, dict args)
+.INDENT 0.0
+.INDENT 3.5
+Connects to the destination address and then proceed to create an OBEX
+session object which implements \fBorg.bluez.obex.Session(5)\fP interface.
+.sp
+The last parameter is a dictionary to hold optional or type\-specific
+parameters.
+.sp
+Possible args values:
+.INDENT 0.0
+.TP
+.B string Target
+Type of session to be created.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqftp\(dq
+.TP
+.B \(dqmap\(dq
+.TP
+.B \(dqopp\(dq
+.TP
+.B \(dqpbap\(dq
+.TP
+.B \(dqsync\(dq
+.TP
+.B \(dqbip\-avrcp\(dq
+.UNINDENT
+.TP
+.B string Source
+Local address to be used.
+.TP
+.B byte Channel
+Channel to be used.
+.TP
+.B uint16 PSM
+L2CAP PSM to be used.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void RemoveSession(object session)
+.INDENT 0.0
+.INDENT 3.5
+Disconnects and removes session previously created by
+\fBCreateSession()\fP aborting any pending transfers.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.NotAuthorized
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Client.rst b/doc/org.bluez.obex.Client.rst
new file mode 100644
index 0000000..f20dd5b
--- /dev/null
+++ b/doc/org.bluez.obex.Client.rst
@@ -0,0 +1,74 @@
+=====================
+org.bluez.obex.Client
+=====================
+
+-----------------------------------------
+BlueZ D-Bus OBEX Client API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Client1
+:Object path:	/org/bluez/obex
+
+Methods
+-------
+
+object CreateSession(string destination, dict args)
+```````````````````````````````````````````````````
+
+	Connects to the destination address and then proceed to create an OBEX
+	session object which implements **org.bluez.obex.Session(5)** interface.
+
+	The last parameter is a dictionary to hold optional or type-specific
+	parameters.
+
+	Possible args values:
+
+	:string Target:
+
+		Type of session to be created.
+
+		Possible values:
+
+		:"ftp":
+		:"map":
+		:"opp":
+		:"pbap":
+		:"sync":
+		:"bip-avrcp":
+
+	:string Source:
+
+		Local address to be used.
+
+	:byte Channel:
+
+		Channel to be used.
+
+	:uint16 PSM:
+
+		L2CAP PSM to be used.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+void RemoveSession(object session)
+``````````````````````````````````
+
+	Disconnects and removes session previously created by
+	**CreateSession()** aborting any pending transfers.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.NotAuthorized:
diff --git a/doc/org.bluez.obex.FileTransfer.5 b/doc/org.bluez.obex.FileTransfer.5
new file mode 100644
index 0000000..76432d5
--- /dev/null
+++ b/doc/org.bluez.obex.FileTransfer.5
@@ -0,0 +1,203 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.FILETRANSFER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.FileTransfer \- BlueZ D-Bus OBEX FileTransfer API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.FileTransfer1
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS void ChangeFolder(string folder)
+.INDENT 0.0
+.INDENT 3.5
+Changes the current folder of the remote device.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void CreateFolder(string folder)
+.INDENT 0.0
+.INDENT 3.5
+Creates a new folder in the remote device.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{dict} ListFolder()
+.INDENT 0.0
+.INDENT 3.5
+Returns a dictionary containing information about the current folder
+content.
+.sp
+Possible return values:
+.INDENT 0.0
+.TP
+.B string Name
+Object name in UTF\-8 format.
+.TP
+.B string Type
+Either \(dqfolder\(dq or \(dqfile\(dq.
+.TP
+.B uint64 Size
+Object size or number of items in folder.
+.TP
+.B string Permission
+Group, owner and other permission.
+.TP
+.B uint64 Modified
+Last change.
+.TP
+.B uint64 Accessed
+Last access.
+.TP
+.B uint64 Created
+Creation date.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict GetFile(string targetfile, string sourcefile)
+.INDENT 0.0
+.INDENT 3.5
+Copies the contents of the source file (from remote device) to the
+target file (on local filesystem).
+.sp
+If an empty target file is given, a name will be automatically generated
+for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or
+if the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict PutFile(string sourcefile, string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Copies the contents of the source file (from local filesystem) to the
+target file (on remote device).
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void CopyFile(string sourcefile, string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Copies the contents from source file to target file on the remote
+device.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void MoveFile(string sourcefile, string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Moves a file within the remote device from source file to the target
+file.
+.sp
+Possible errors:
+.sp
+;org.bluez.obex.Error.InvalidArguments:
+:org.bluez.obex.Error.Failed:
+.UNINDENT
+.UNINDENT
+.SS void Delete(string file)
+.INDENT 0.0
+.INDENT 3.5
+Deletes the specified file/folder.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.FileTransfer.rst b/doc/org.bluez.obex.FileTransfer.rst
new file mode 100644
index 0000000..6dce7e5
--- /dev/null
+++ b/doc/org.bluez.obex.FileTransfer.rst
@@ -0,0 +1,155 @@
+===========================
+org.bluez.obex.FileTransfer
+===========================
+
+-----------------------------------------------
+BlueZ D-Bus OBEX FileTransfer API documentation
+-----------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.FileTransfer1
+:Object path:	[Session object path]
+
+Methods
+-------
+
+void ChangeFolder(string folder)
+````````````````````````````````
+
+	Changes the current folder of the remote device.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+void CreateFolder(string folder)
+````````````````````````````````
+
+	Creates a new folder in the remote device.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+array{dict} ListFolder()
+````````````````````````
+
+	Returns a dictionary containing information about the current folder
+	content.
+
+	Possible return values:
+
+	:string Name:
+
+		Object name in UTF-8 format.
+
+	:string Type:
+
+		Either "folder" or "file".
+
+	:uint64 Size:
+
+		Object size or number of items in folder.
+
+	:string Permission:
+
+		Group, owner and other permission.
+
+	:uint64 Modified:
+
+		Last change.
+
+	:uint64 Accessed:
+
+		Last access.
+
+	:uint64 Created:
+
+		Creation date.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.Failed:
+
+object, dict GetFile(string targetfile, string sourcefile)
+``````````````````````````````````````````````````````````
+
+	Copies the contents of the source file (from remote device) to the
+	target file (on local filesystem).
+
+	If an empty target file is given, a name will be automatically generated
+	for the temporary file.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or
+	if the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict PutFile(string sourcefile, string targetfile)
+``````````````````````````````````````````````````````````
+
+	Copies the contents of the source file (from local filesystem) to the
+	target file (on remote device).
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+void CopyFile(string sourcefile, string targetfile)
+```````````````````````````````````````````````````
+
+	Copies the contents from source file to target file on the remote
+	device.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+void MoveFile(string sourcefile, string targetfile)
+```````````````````````````````````````````````````
+
+	Moves a file within the remote device from source file to the target
+	file.
+
+	Possible errors:
+
+	;org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+void Delete(string file)
+````````````````````````
+
+	Deletes the specified file/folder.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
diff --git a/doc/org.bluez.obex.Image.5 b/doc/org.bluez.obex.Image.5
new file mode 100644
index 0000000..4e24e37
--- /dev/null
+++ b/doc/org.bluez.obex.Image.5
@@ -0,0 +1,165 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.IMAGE" "5" "August 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Image \- BlueZ D-Bus OBEX Image API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Image1 [experimental]
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS object, dict Get(string targetfile, string handle, dict description)
+.INDENT 0.0
+.INDENT 3.5
+Retrieves the image corresponding to the handle and the description, as
+one of the descriptions retrieved by GetImageProperties, and store it in
+a local file.
+.sp
+If the \(dqtransform\(dq property description exists it should be set to one
+of the value listed by GetImageProperties for this description.
+.sp
+If description is an empty dict, the native image will be retrieved.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{dict} Properties(string handle)
+.INDENT 0.0
+.INDENT 3.5
+Retrieves the image properties corresponding to the handle.
+.sp
+The first dict entry is mandatory and correspond to \(aqhandle\(aq and \(aqname\(aq
+of the image.
+.sp
+The second dict entry is mandatory and correspond to the native
+description (\(aqtype\(aq:\(aqnative\(aq) of the image.
+.sp
+The following dict entries are optional and correspond to variant
+descriptions of the image. If the \(aqtransform\(aq entry exists in the
+description, it lists the available possible image transformations and
+should be set to one of them before using the description as parameter
+to GetImage.
+.sp
+Possible property values:
+.INDENT 0.0
+.TP
+.B string type
+Type of dict properties. Mandatory for each dict.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqnative\(dq
+.TP
+.B \(dqvariant\(dq
+.UNINDENT
+.TP
+.B string encoding
+File encoding format.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqBMP\(dq
+.TP
+.B \(dqGIF\(dq
+.TP
+.B \(dqJPEG\(dq
+.TP
+.B \(dqJPEG2000\(dq
+.TP
+.B \(dqPNG\(dq
+.TP
+.B \(dqWBMP\(dq
+.UNINDENT
+.TP
+.B string pixel
+File encoding format size of form \(dq<width>*<height>\(dq.
+.TP
+.B uint64 size
+File size.
+.TP
+.B uint64 maxsize
+File maximum size.
+.TP
+.B string transformation
+List of available transformations separated by space.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqcrop\(dq
+.TP
+.B \(dqfill\(dq
+.TP
+.B \(dqstretch\(dq
+.UNINDENT
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict GetThumbnail(string targetfile, string handle)
+.INDENT 0.0
+.INDENT 3.5
+Retrieves the image thumbnail corresponding to the handle and store it
+in a local file.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Image.rst b/doc/org.bluez.obex.Image.rst
new file mode 100644
index 0000000..c40d3f4
--- /dev/null
+++ b/doc/org.bluez.obex.Image.rst
@@ -0,0 +1,118 @@
+====================
+org.bluez.obex.Image
+====================
+
+--------------------------------------------------
+BlueZ D-Bus OBEX Image API documentation
+--------------------------------------------------
+
+:Version: BlueZ
+:Date: August 2024
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Image1 [experimental]
+:Object path:	[Session object path]
+
+Methods
+-------
+
+object, dict Get(string targetfile, string handle, dict description)
+````````````````````````````````````````````````````````````````````
+
+	Retrieves the image corresponding to the handle and the description, as
+	one of the descriptions retrieved by GetImageProperties, and store it in
+	a local file.
+
+	If the "transform" property description exists it should be set to one
+	of the value listed by GetImageProperties for this description.
+
+	If description is an empty dict, the native image will be retrieved.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+array{dict} Properties(string handle)
+`````````````````````````````````````
+
+	Retrieves the image properties corresponding to the handle.
+
+	The first dict entry is mandatory and correspond to 'handle' and 'name'
+	of the image.
+
+	The second dict entry is mandatory and correspond to the native
+	description ('type':'native') of the image.
+
+	The following dict entries are optional and correspond to variant
+	descriptions of the image. If the 'transform' entry exists in the
+	description, it lists the available possible image transformations and
+	should be set to one of them before using the description as parameter
+	to GetImage.
+
+	Possible property values:
+
+	:string type:
+
+		Type of dict properties. Mandatory for each dict.
+
+		Possible values:
+
+		:"native":
+		:"variant":
+
+	:string encoding:
+
+		File encoding format.
+
+		Possible values:
+
+		:"BMP":
+		:"GIF":
+		:"JPEG":
+		:"JPEG2000":
+		:"PNG":
+		:"WBMP":
+
+	:string pixel:
+
+		File encoding format size of form "<width>*<height>".
+
+	:uint64 size:
+
+		File size.
+
+	:uint64 maxsize:
+
+		File maximum size.
+
+	:string transformation:
+
+		List of available transformations separated by space.
+
+		Possible values:
+
+		:"crop":
+		:"fill":
+		:"stretch":
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict GetThumbnail(string targetfile, string handle)
+```````````````````````````````````````````````````````````
+
+	Retrieves the image thumbnail corresponding to the handle and store it
+	in a local file.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
diff --git a/doc/org.bluez.obex.Message.5 b/doc/org.bluez.obex.Message.5
new file mode 100644
index 0000000..3354331
--- /dev/null
+++ b/doc/org.bluez.obex.Message.5
@@ -0,0 +1,191 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.MESSAGE" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Message \- BlueZ D-Bus OBEX Message API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Message1
+.TP
+.B Object path
+[Session object path]/message{#}
+.UNINDENT
+.SS Methods
+.SS object, dict Get(string targetfile, boolean attachment)
+.INDENT 0.0
+.INDENT 3.5
+Download message and store it in the target file.
+.sp
+If an empty target file is given, a temporary file will be automatically
+generated.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Folder [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Folder which the message belongs to
+.UNINDENT
+.UNINDENT
+.SS string Subject [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message subject
+.UNINDENT
+.UNINDENT
+.SS string Timestamp [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message timestamp
+.UNINDENT
+.UNINDENT
+.SS string Sender [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message sender name
+.UNINDENT
+.UNINDENT
+.SS string SenderAddress [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message sender address
+.UNINDENT
+.UNINDENT
+.SS string ReplyTo [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message Reply\-To address
+.UNINDENT
+.UNINDENT
+.SS string Recipient [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message recipient name
+.UNINDENT
+.UNINDENT
+.SS string RecipientAddress [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message recipient address
+.UNINDENT
+.UNINDENT
+.SS string Type [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message type
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqemail\(dq
+.TP
+.B \(dqsms\-gsm\(dq
+.TP
+.B \(dqsms\-cdma\(dq
+.TP
+.B \(dqmms\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint64 Size [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message size in bytes
+.UNINDENT
+.UNINDENT
+.SS string Status [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message reception status
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqcomplete\(dq
+.TP
+.B \(dqfractioned\(dq
+.TP
+.B \(dqnotification\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS boolean Priority [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message priority flag
+.UNINDENT
+.UNINDENT
+.SS boolean Read [read/write]
+.INDENT 0.0
+.INDENT 3.5
+Message read flag
+.UNINDENT
+.UNINDENT
+.SS boolean Deleted [writeonly]
+.INDENT 0.0
+.INDENT 3.5
+Message deleted flag
+.UNINDENT
+.UNINDENT
+.SS boolean Sent [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message sent flag
+.UNINDENT
+.UNINDENT
+.SS boolean Protected [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Message protected flag
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Message.rst b/doc/org.bluez.obex.Message.rst
new file mode 100644
index 0000000..082f872
--- /dev/null
+++ b/doc/org.bluez.obex.Message.rst
@@ -0,0 +1,139 @@
+======================
+org.bluez.obex.Message
+======================
+
+------------------------------------------
+BlueZ D-Bus OBEX Message API documentation
+------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Message1
+:Object path:	[Session object path]/message{#}
+
+Methods
+-------
+
+object, dict Get(string targetfile, boolean attachment)
+```````````````````````````````````````````````````````
+
+	Download message and store it in the target file.
+
+	If an empty target file is given, a temporary file will be automatically
+	generated.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+Properties
+----------
+
+string Folder [readonly]
+````````````````````````
+
+	Folder which the message belongs to
+
+string Subject [readonly]
+`````````````````````````
+
+	Message subject
+
+string Timestamp [readonly]
+```````````````````````````
+
+	Message timestamp
+
+string Sender [readonly]
+````````````````````````
+
+	Message sender name
+
+string SenderAddress [readonly]
+```````````````````````````````
+
+	Message sender address
+
+string ReplyTo [readonly]
+`````````````````````````
+
+	Message Reply-To address
+
+string Recipient [readonly]
+```````````````````````````
+
+	Message recipient name
+
+string RecipientAddress [readonly]
+``````````````````````````````````
+
+	Message recipient address
+
+string Type [readonly]
+``````````````````````
+
+	Message type
+
+	Possible values:
+
+	:"email":
+	:"sms-gsm":
+	:"sms-cdma":
+	:"mms":
+
+uint64 Size [readonly]
+``````````````````````
+
+	Message size in bytes
+
+string Status [readonly]
+````````````````````````
+
+	Message reception status
+
+	Possible values:
+
+	:"complete":
+	:"fractioned":
+	:"notification":
+
+boolean Priority [readonly]
+```````````````````````````
+
+	Message priority flag
+
+boolean Read [read/write]
+`````````````````````````
+
+	Message read flag
+
+boolean Deleted [writeonly]
+```````````````````````````
+
+	Message deleted flag
+
+boolean Sent [readonly]
+```````````````````````
+
+	Message sent flag
+
+boolean Protected [readonly]
+````````````````````````````
+
+	Message protected flag
diff --git a/doc/org.bluez.obex.MessageAccess.5 b/doc/org.bluez.obex.MessageAccess.5
new file mode 100644
index 0000000..8f16e5d
--- /dev/null
+++ b/doc/org.bluez.obex.MessageAccess.5
@@ -0,0 +1,279 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.MESSAGEACCESS" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.MessageAccess \- BlueZ D-Bus OBEX MessageAccess API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.MessageAccess1
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS void SetFolder(string name)
+.INDENT 0.0
+.INDENT 3.5
+Set working directory for current session.
+.sp
+Possible name:
+.INDENT 0.0
+.INDENT 3.5
+Directory name or \(aq..[/dir]\(aq.
+.UNINDENT
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{dict} ListFolders(dict filter)
+.INDENT 0.0
+.INDENT 3.5
+Returns a dictionary containing information about the current folder
+content.
+.sp
+Possible filter:
+.INDENT 0.0
+.TP
+.B uint16 Offset (default 0)
+Offset of the first item.
+.TP
+.B uint16 MaxCount (default 1024)
+Maximum number of items.
+.UNINDENT
+.sp
+Possible return:
+.INDENT 0.0
+.TP
+.B string Name
+Folder name
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} ListFilterFields()
+.INDENT 0.0
+.INDENT 3.5
+Return all available fields that can be used in \fBFields\fP filter.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqsubject\(dq
+.TP
+.B \(dqtimestamp\(dq
+.TP
+.B \(dqsender\(dq
+.TP
+.B \(dqsender\-address\(dq
+.TP
+.B \(dqrecipient\(dq
+.TP
+.B \(dqrecipient\-address\(dq
+.TP
+.B \(dqtype\(dq
+.TP
+.B \(dqsize\(dq
+.TP
+.B \(dqstatus\(dq
+.TP
+.B \(dqtext\(dq
+.TP
+.B \(dqattachment\(dq
+.TP
+.B \(dqpriority\(dq
+.TP
+.B \(dqread\(dq
+.TP
+.B \(dqsent\(dq
+.TP
+.B \(dqprotected\(dq
+.TP
+.B \(dqreplyto\(dq
+.UNINDENT
+.sp
+Possible errors: None
+.UNINDENT
+.UNINDENT
+.SS array{object, dict} ListMessages(string folder, dict filter)
+.INDENT 0.0
+.INDENT 3.5
+Returns an array containing the messages objects found in the given
+subfolder of the current folder, or in the current folder if folder is
+empty.
+.sp
+Possible Filters:
+.INDENT 0.0
+.TP
+.B uint16 Offset (default 0)
+Offset of the first item.
+.UNINDENT
+.sp
+uint16 MaxCount (default 1024):
+.INDENT 0.0
+.INDENT 3.5
+Maximum number of items.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B byte SubjectLength (default 256)
+Maximum length of the Subject property in the message.
+.TP
+.B array{string} Fields
+Message fields, default is all values.
+.sp
+See \fBListFilterFields()\fP for possible values.
+.TP
+.B array{string} Types
+Filter messages by type.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqsms\(dq
+.TP
+.B \(dqemail\(dq
+.TP
+.B \(dqmms\(dq
+.UNINDENT
+.TP
+.B string PeriodBegin
+Filter messages by starting period.
+.sp
+Possible values:
+.INDENT 7.0
+.INDENT 3.5
+Date in \(dqYYYYMMDDTHHMMSS\(dq format.
+.UNINDENT
+.UNINDENT
+.TP
+.B string PeriodEnd
+Filter messages by ending period.
+.sp
+Possible values:
+.INDENT 7.0
+.INDENT 3.5
+Date in \(dqYYYYMMDDTHHMMSS\(dq format.
+.UNINDENT
+.UNINDENT
+.TP
+.B boolean Read
+Filter messages by read flag.
+.sp
+Possible values:
+.INDENT 7.0
+.INDENT 3.5
+True for read or False for unread
+.UNINDENT
+.UNINDENT
+.TP
+.B string Recipient
+Filter messages by recipient address.
+.TP
+.B string Sender
+Filter messages by sender address.
+.TP
+.B boolean Priority
+Filter messages by priority flag.
+.sp
+Possible values:
+.INDENT 7.0
+.INDENT 3.5
+True for high priority or False for non\-high priority.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+Each message is represented by an object path, which implements
+\fBorg.bluez.obex.Message(5)\fP interface, followed by a dictionary
+of its properties.
+.UNINDENT
+.UNINDENT
+.sp
+void UpdateInbox(void)
+.INDENT 0.0
+.INDENT 3.5
+Requests remote to update its inbox.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict PushMessage(string sourcefile, string folder, dict args)
+.INDENT 0.0
+.INDENT 3.5
+Transfers a message (in bMessage format) to the remote device.
+.sp
+The message is transferred either to the given subfolder of the current
+folder, or to the current folder if folder is empty.
+.sp
+Possible args: Transparent, Retry, Charset
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.MessageAccess.rst b/doc/org.bluez.obex.MessageAccess.rst
new file mode 100644
index 0000000..4f7f07d
--- /dev/null
+++ b/doc/org.bluez.obex.MessageAccess.rst
@@ -0,0 +1,201 @@
+============================
+org.bluez.obex.MessageAccess
+============================
+
+------------------------------------------------
+BlueZ D-Bus OBEX MessageAccess API documentation
+------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.MessageAccess1
+:Object path:	[Session object path]
+
+Methods
+-------
+
+void SetFolder(string name)
+```````````````````````````
+
+	Set working directory for current session.
+
+	Possible name:
+
+		Directory name or '..[/dir]'.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+array{dict} ListFolders(dict filter)
+````````````````````````````````````
+
+	Returns a dictionary containing information about the current folder
+	content.
+
+	Possible filter:
+
+	:uint16 Offset (default 0):
+
+		Offset of the first item.
+
+	:uint16 MaxCount (default 1024):
+
+		Maximum number of items.
+
+	Possible return:
+
+	:string Name:
+
+		Folder name
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+array{string} ListFilterFields()
+````````````````````````````````
+
+	Return all available fields that can be used in **Fields** filter.
+
+	Possible values:
+
+	:"subject":
+	:"timestamp":
+	:"sender":
+	:"sender-address":
+	:"recipient":
+	:"recipient-address":
+	:"type":
+	:"size":
+	:"status":
+	:"text":
+	:"attachment":
+	:"priority":
+	:"read":
+	:"sent":
+	:"protected":
+	:"replyto":
+
+	Possible errors: None
+
+array{object, dict} ListMessages(string folder, dict filter)
+````````````````````````````````````````````````````````````
+
+	Returns an array containing the messages objects found in the given
+	subfolder of the current folder, or in the current folder if folder is
+	empty.
+
+	Possible Filters:
+
+	:uint16 Offset (default 0):
+
+		Offset of the first item.
+
+	uint16 MaxCount (default 1024):
+
+		Maximum number of items.
+
+	:byte SubjectLength (default 256):
+
+		Maximum length of the Subject property in the message.
+
+	:array{string} Fields:
+
+		Message fields, default is all values.
+
+		See **ListFilterFields()** for possible values.
+
+	:array{string} Types:
+
+		Filter messages by type.
+
+		Possible values:
+
+		:"sms":
+		:"email":
+		:"mms":
+
+	:string PeriodBegin:
+
+		Filter messages by starting period.
+
+		Possible values:
+
+			Date in "YYYYMMDDTHHMMSS" format.
+
+	:string PeriodEnd:
+
+		Filter messages by ending period.
+
+		Possible values:
+
+			Date in "YYYYMMDDTHHMMSS" format.
+
+	:boolean Read:
+
+		Filter messages by read flag.
+
+		Possible values:
+
+			True for read or False for unread
+
+	:string Recipient:
+
+		Filter messages by recipient address.
+
+	:string Sender:
+
+		Filter messages by sender address.
+
+	:boolean Priority:
+
+		Filter messages by priority flag.
+
+		Possible values:
+
+			True for high priority or False for non-high priority.
+
+	Each message is represented by an object path, which implements
+	**org.bluez.obex.Message(5)** interface, followed by a dictionary
+	of its properties.
+
+void UpdateInbox(void)
+
+	Requests remote to update its inbox.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.Failed:
+
+object, dict PushMessage(string sourcefile, string folder, dict args)
+`````````````````````````````````````````````````````````````````````
+
+	Transfers a message (in bMessage format) to the remote device.
+
+	The message is transferred either to the given subfolder of the current
+	folder, or to the current folder if folder is empty.
+
+	Possible args: Transparent, Retry, Charset
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
diff --git a/doc/org.bluez.obex.ObjectPush.5 b/doc/org.bluez.obex.ObjectPush.5
new file mode 100644
index 0000000..1c9510d
--- /dev/null
+++ b/doc/org.bluez.obex.ObjectPush.5
@@ -0,0 +1,121 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.OBJECTPUSH" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.ObjectPush \- BlueZ D-Bus OBEX ObjectPush API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.ObjectPush1
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS object, dict SendFile(string sourcefile)
+.INDENT 0.0
+.INDENT 3.5
+Sends local file to the remote device.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict PullBusinessCard(string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Request the business card from a remote device and store it in the local
+file.
+.sp
+If an empty target file is given, a name will be automatically
+generated for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict ExchangeBusinessCards(string clientfile, string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Push the client\(aqs business card to the remote device and then retrieve
+the remote business card and store it in a local file.
+.sp
+If an empty target file is given, a name will be automatically
+generated for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should
+be used to find out if the content has been successfully transferred or
+if the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.ObjectPush.rst b/doc/org.bluez.obex.ObjectPush.rst
new file mode 100644
index 0000000..aba2282
--- /dev/null
+++ b/doc/org.bluez.obex.ObjectPush.rst
@@ -0,0 +1,84 @@
+=========================
+org.bluez.obex.ObjectPush
+=========================
+
+---------------------------------------------
+BlueZ D-Bus OBEX ObjectPush API documentation
+---------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.ObjectPush1
+:Object path:	[Session object path]
+
+Methods
+-------
+
+object, dict SendFile(string sourcefile)
+````````````````````````````````````````
+
+	Sends local file to the remote device.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict PullBusinessCard(string targetfile)
+````````````````````````````````````````````````
+
+	Request the business card from a remote device and store it in the local
+	file.
+
+	If an empty target file is given, a name will be automatically
+	generated for the temporary file.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict ExchangeBusinessCards(string clientfile, string targetfile)
+````````````````````````````````````````````````````````````````````````
+
+	Push the client's business card to the remote device and then retrieve
+	the remote business card and store it in a local file.
+
+	If an empty target file is given, a name will be automatically
+	generated for the temporary file.
+
+	The returned path represents the newly created transfer, which should
+	be used to find out if the content has been successfully transferred or
+	if the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
diff --git a/doc/org.bluez.obex.PhonebookAccess.5 b/doc/org.bluez.obex.PhonebookAccess.5
new file mode 100644
index 0000000..361d24b
--- /dev/null
+++ b/doc/org.bluez.obex.PhonebookAccess.5
@@ -0,0 +1,515 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.PHONEBOOKACCESS" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.PhonebookAccess \- BlueZ D-Bus OBEX PhonebookAccess API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.PhonebookAccess1
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS void Select(string location, string phonebook)
+.INDENT 0.0
+.INDENT 3.5
+Selects the phonebook object for other operations. Should be call before
+all the other operations.
+.sp
+Possible location values:
+.INDENT 0.0
+.TP
+.B \(dqint\(dq, \(dqinternal\(dq (default)
+Store in the Internal memory.
+.TP
+.B \(dqsim{#}\(dq
+Store in the sim number.
+.UNINDENT
+.sp
+Possible phonebook values:
+.INDENT 0.0
+.TP
+.B \(dqpb\(dq
+Store as contact.
+.TP
+.B \(dqich\(dq
+Store as incoming call.
+.TP
+.B \(dqoch\(dq
+Store as outgoing call.
+.TP
+.B \(dqmch\(dq
+Store as missing call.
+.TP
+.B \(dqcch\(dq
+Store as a combination of incoming, outgoing and missing call.
+.UNINDENT
+.sp
+\(dqspd\(dq:
+.INDENT 0.0
+.INDENT 3.5
+Store as speed dials entry ( only for \(dqinternal\(dq )
+.UNINDENT
+.UNINDENT
+.sp
+\(dqfav\(dq:
+.INDENT 0.0
+.INDENT 3.5
+Store as favorites entry ( only for \(dqinternal\(dq )
+.UNINDENT
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict PullAll(string targetfile, dict filters)
+.INDENT 0.0
+.INDENT 3.5
+Returns the entire phonebook object from the PSE server in plain string
+with vcard format, and store it in a local file.
+.sp
+If an empty target file is given, a name will be automatically generated
+for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should
+be used to find out if the content has been successfully transferred or
+if the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible filters:
+.INDENT 0.0
+.TP
+.B string Format
+Items vcard format.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dqvcard21\(dq (default)
+.TP
+.B \(dqvcard30\(dq
+.UNINDENT
+.TP
+.B string Order
+Items order.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dq\(dq
+.TP
+.B \(dqindexed\(dq
+.TP
+.B \(dqalphanumeric\(dq
+.TP
+.B \(dqphonetic\(dq
+.UNINDENT
+.TP
+.B uint16 Offset (default 0)
+Offset of the first item.
+.TP
+.B uint16 MaxCount (default 65535)
+Maximum number of items.
+.TP
+.B array{string} Fields (default all fields)
+Item vcard fields.
+.sp
+See \fBListFilterFields()\fP for possible values.
+.TP
+.B array{string} FilterAll
+Filter items by fields using AND logic, cannot be used
+together with \fBFilterAny\fP\&.
+.sp
+See \fBListFilterFields()\fP for possible values.
+.TP
+.B array{string} FilterAny
+Filter items by fields using OR logic, cannot be used together
+with \fBFilterAll\fP\&.
+.sp
+See \fBListFilterFields()\fP for possible values.
+.TP
+.B bool ResetNewMissedCalls
+Reset new the missed calls items, shall only be used for folders
+mch and cch.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Forbidden
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string vcard, string name} List(dict filters)
+.INDENT 0.0
+.INDENT 3.5
+Returns array of vcard\-listing data where every entry consists of a
+pair of strings containing the vcard handle and the contact name.
+For example:
+.INDENT 0.0
+.TP
+.B \(dq1.vcf\(dq
+\(dqJohn\(dq
+.UNINDENT
+.sp
+Possible filters:
+.INDENT 0.0
+.TP
+.B string Order
+Contact order.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dq\(dq
+.TP
+.B \(dqindexed\(dq
+.TP
+.B \(dqalphanumeric\(dq
+.TP
+.B \(dqphonetic\(dq
+.UNINDENT
+.TP
+.B uint16 Offset
+Start offset.
+.TP
+.B uint16 MaxCount
+Maximum number of contacts.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Forbidden
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict Pull(string vcard, string targetfile, dict filters)
+.INDENT 0.0
+.INDENT 3.5
+Retrieves the vcard in the current phonebook object and store it in a
+local file.
+.sp
+If an empty target file is given, a name will be automatically generated
+for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible filters:
+.INDENT 0.0
+.TP
+.B string Format
+Contact data format.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dq\(dq
+.TP
+.B \(dqvcard21\(dq
+.TP
+.B \(dqvcard30\(dq
+.UNINDENT
+.TP
+.B array{string} Fields
+See \fBListFilterFields()\fP for possible values.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Forbidden
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string vcard, string name} Search(string field, string value, dict filters)
+.INDENT 0.0
+.INDENT 3.5
+Searches for entries matching the given condition and return an array of
+vcard\-listing data where every entry consists of a pair of strings
+containing the vcard handle and the contact name.
+.sp
+Possible field values:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.B \(dqname\(dq (default)
+Search by name.
+.TP
+.B \(dqnumber\(dq
+Search by number.
+.TP
+.B \(dqsound\(dq
+Search by sound.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+value: the string value to search for
+.sp
+Possible filters:
+.INDENT 0.0
+.TP
+.B string Order
+Contact order.
+.sp
+Possible values:
+.INDENT 7.0
+.TP
+.B \(dq\(dq
+.TP
+.B \(dqindexed\(dq
+.TP
+.B \(dqalphanumeric\(dq
+.TP
+.B \(dqphonetic\(dq
+.UNINDENT
+.TP
+.B uint16 Offset
+Start offset.
+.TP
+.B uint16 MaxCount
+Maximum number of contacts.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Forbidden
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS uint16 GetSize()
+.INDENT 0.0
+.INDENT 3.5
+Returns the number of entries in the selected phonebook object that are
+actually used (i.e. indexes that correspond to non\-NULL entries).
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.Forbidden
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void UpdateVersion()
+.INDENT 0.0
+.INDENT 3.5
+Attempts to update PrimaryCounter and SecondaryCounter.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.NotSupported
+.TP
+.B org.bluez.obex.Error.Forbidden
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS array{string} ListFilterFields()
+.INDENT 0.0
+.INDENT 3.5
+Returns all Available fields that can be used in Fields filter.
+.sp
+Possible return:
+.INDENT 0.0
+.TP
+.B \(dqVERSION\(dq
+.TP
+.B \(dqFN\(dq
+.TP
+.B \(dqN\(dq
+.TP
+.B \(dqPHOTO\(dq
+.TP
+.B \(dqBDAY\(dq
+.TP
+.B \(dqADR\(dq
+.TP
+.B \(dqLABEL\(dq
+.TP
+.B \(dqTEL\(dq
+.TP
+.B \(dqEMAIL\(dq
+.TP
+.B \(dqMAILER\(dq
+.TP
+.B \(dqTZ\(dq
+.TP
+.B \(dqGEO\(dq
+.TP
+.B \(dqTITLE\(dq
+.TP
+.B \(dqROLE\(dq
+.TP
+.B \(dqLOGO\(dq
+.TP
+.B \(dqAGENT\(dq
+.TP
+.B \(dqORG\(dq
+.TP
+.B \(dqNOTE\(dq
+.TP
+.B \(dqREV\(dq
+.TP
+.B \(dqSOUND\(dq
+.TP
+.B \(dqURL\(dq
+.TP
+.B \(dqUID\(dq
+.TP
+.B \(dqKEY\(dq
+.TP
+.B \(dqNICKNAME\(dq
+.TP
+.B \(dqCATEGORIES\(dq
+.TP
+.B \(dqPROID\(dq
+.TP
+.B \(dqCLASS\(dq
+.TP
+.B \(dqSORT\-STRING\(dq
+.TP
+.B \(dqX\-IRMC\-CALL\-DATETIME\(dq
+.TP
+.B \(dqX\-BT\-SPEEDDIALKEY\(dq
+.TP
+.B \(dqX\-BT\-UCI\(dq
+.TP
+.B \(dqX\-BT\-UID\(dq
+.TP
+.B \(dqBIT\-{#}\(dq
+.UNINDENT
+.sp
+Possible errors: None
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Folder [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Current folder.
+.UNINDENT
+.UNINDENT
+.SS string DatabaseIdentifier [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+128 bits persistent database identifier.
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+32\-character hexadecimal such as
+A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string PrimaryCounter [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+128 bits primary version counter.
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+32\-character hexadecimal such as
+A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS string SecondaryCounter [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+128 bits secondary version counter.
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+32\-character hexadecimal such as
+A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS bool FixedImageSize [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Indicate support for fixed image size.
+.sp
+Possible values:
+.INDENT 0.0
+.INDENT 3.5
+True if image is JPEG 300x300 pixels otherwise False.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.PhonebookAccess.rst b/doc/org.bluez.obex.PhonebookAccess.rst
new file mode 100644
index 0000000..0e126b1
--- /dev/null
+++ b/doc/org.bluez.obex.PhonebookAccess.rst
@@ -0,0 +1,386 @@
+==============================
+org.bluez.obex.PhonebookAccess
+==============================
+
+--------------------------------------------------
+BlueZ D-Bus OBEX PhonebookAccess API documentation
+--------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.PhonebookAccess1
+:Object path:	[Session object path]
+
+Methods
+-------
+
+void Select(string location, string phonebook)
+``````````````````````````````````````````````
+
+	Selects the phonebook object for other operations. Should be call before
+	all the other operations.
+
+	Possible location values:
+
+	:"int", "internal" (default):
+
+		Store in the Internal memory.
+
+	:"sim{#}":
+
+		Store in the sim number.
+
+	Possible phonebook values:
+
+	:"pb":
+
+		Store as contact.
+
+	:"ich":
+
+		Store as incoming call.
+
+	:"och":
+
+		Store as outgoing call.
+
+	:"mch":
+
+		Store as missing call.
+
+	:"cch":
+
+		Store as a combination of incoming, outgoing and missing call.
+
+	"spd":
+
+		Store as speed dials entry ( only for "internal" )
+
+	"fav":
+
+		Store as favorites entry ( only for "internal" )
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict PullAll(string targetfile, dict filters)
+`````````````````````````````````````````````````````
+
+	Returns the entire phonebook object from the PSE server in plain string
+	with vcard format, and store it in a local file.
+
+	If an empty target file is given, a name will be automatically generated
+	for the temporary file.
+
+	The returned path represents the newly created transfer, which should
+	be used to find out if the content has been successfully transferred or
+	if the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible filters:
+
+	:string Format:
+
+		Items vcard format.
+
+		Possible values:
+
+		:"vcard21" (default):
+		:"vcard30":
+
+	:string Order:
+
+		Items order.
+
+		Possible values:
+
+		:"":
+		:"indexed":
+		:"alphanumeric":
+		:"phonetic":
+
+	:uint16 Offset (default 0):
+
+		Offset of the first item.
+
+	:uint16 MaxCount (default 65535):
+
+		Maximum number of items.
+
+	:array{string} Fields (default all fields):
+
+		Item vcard fields.
+
+		See **ListFilterFields()** for possible values.
+
+	:array{string} FilterAll:
+
+		Filter items by fields using AND logic, cannot be used
+		together with **FilterAny**.
+
+		See **ListFilterFields()** for possible values.
+
+	:array{string} FilterAny:
+
+		Filter items by fields using OR logic, cannot be used together
+		with **FilterAll**.
+
+		See **ListFilterFields()** for possible values.
+
+	:bool ResetNewMissedCalls:
+
+		Reset new the missed calls items, shall only be used for folders
+		mch and cch.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Forbidden:
+
+array{string vcard, string name} List(dict filters)
+```````````````````````````````````````````````````
+
+	Returns array of vcard-listing data where every entry consists of a
+	pair of strings containing the vcard handle and the contact name.
+	For example:
+
+	:"1.vcf": "John"
+
+	Possible filters:
+
+	:string Order:
+
+		Contact order.
+
+		Possible values:
+
+		:"":
+		:"indexed":
+		:"alphanumeric":
+		:"phonetic":
+
+	:uint16 Offset:
+
+		Start offset.
+
+	:uint16 MaxCount:
+
+		Maximum number of contacts.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Forbidden:
+
+object, dict Pull(string vcard, string targetfile, dict filters)
+````````````````````````````````````````````````````````````````
+
+	Retrieves the vcard in the current phonebook object and store it in a
+	local file.
+
+	If an empty target file is given, a name will be automatically generated
+	for the temporary file.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible filters:
+
+	:string Format:
+
+		Contact data format.
+
+		Possible values:
+
+		:"":
+		:"vcard21":
+		:"vcard30":
+
+	:array{string} Fields:
+
+		See **ListFilterFields()** for possible values.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Forbidden:
+	:org.bluez.obex.Error.Failed:
+
+array{string vcard, string name} Search(string field, string value, dict filters)
+`````````````````````````````````````````````````````````````````````````````````
+
+	Searches for entries matching the given condition and return an array of
+	vcard-listing data where every entry consists of a pair of strings
+	containing the vcard handle and the contact name.
+
+	Possible field values:
+
+		:"name" (default):
+
+			Search by name.
+
+		:"number":
+
+			Search by number.
+
+		:"sound":
+
+			Search by sound.
+
+	value: the string value to search for
+
+	Possible filters:
+
+	:string Order:
+
+		Contact order.
+
+		Possible values:
+
+		:"":
+		:"indexed":
+		:"alphanumeric":
+		:"phonetic":
+
+	:uint16 Offset:
+
+		Start offset.
+
+	:uint16 MaxCount:
+
+		Maximum number of contacts.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Forbidden:
+	:org.bluez.obex.Error.Failed:
+
+uint16 GetSize()
+````````````````
+
+	Returns the number of entries in the selected phonebook object that are
+	actually used (i.e. indexes that correspond to non-NULL entries).
+
+	Possible errors:
+
+	:org.bluez.obex.Error.Forbidden:
+	:org.bluez.obex.Error.Failed:
+
+void UpdateVersion()
+````````````````````
+
+	Attempts to update PrimaryCounter and SecondaryCounter.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.NotSupported:
+	:org.bluez.obex.Error.Forbidden:
+	:org.bluez.obex.Error.Failed:
+
+array{string} ListFilterFields()
+````````````````````````````````
+
+	Returns all Available fields that can be used in Fields filter.
+
+	Possible return:
+
+	:"VERSION":
+	:"FN":
+	:"N":
+	:"PHOTO":
+	:"BDAY":
+	:"ADR":
+	:"LABEL":
+	:"TEL":
+	:"EMAIL":
+	:"MAILER":
+	:"TZ":
+	:"GEO":
+	:"TITLE":
+	:"ROLE":
+	:"LOGO":
+	:"AGENT":
+	:"ORG":
+	:"NOTE":
+	:"REV":
+	:"SOUND":
+	:"URL":
+	:"UID":
+	:"KEY":
+	:"NICKNAME":
+	:"CATEGORIES":
+	:"PROID":
+	:"CLASS":
+	:"SORT-STRING":
+	:"X-IRMC-CALL-DATETIME":
+	:"X-BT-SPEEDDIALKEY":
+	:"X-BT-UCI":
+	:"X-BT-UID":
+	:"BIT-{#}":
+
+	Possible errors: None
+
+Properties
+----------
+
+string Folder [readonly]
+````````````````````````
+
+	Current folder.
+
+string DatabaseIdentifier [readonly, optional]
+``````````````````````````````````````````````
+
+	128 bits persistent database identifier.
+
+	Possible values:
+
+		32-character hexadecimal such as
+		A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+
+string PrimaryCounter [readonly, optional]
+``````````````````````````````````````````
+
+	128 bits primary version counter.
+
+	Possible values:
+
+		32-character hexadecimal such as
+		A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+
+string SecondaryCounter [readonly, optional]
+````````````````````````````````````````````
+
+	128 bits secondary version counter.
+
+	Possible values:
+
+		32-character hexadecimal such as
+		A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
+
+bool FixedImageSize [readonly, optional]
+````````````````````````````````````````
+
+	Indicate support for fixed image size.
+
+	Possible values:
+
+		True if image is JPEG 300x300 pixels otherwise False.
diff --git a/doc/org.bluez.obex.Session.5 b/doc/org.bluez.obex.Session.5
new file mode 100644
index 0000000..8deb628
--- /dev/null
+++ b/doc/org.bluez.obex.Session.5
@@ -0,0 +1,99 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.SESSION" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Session \- BlueZ D-Bus OBEX Client API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Session1
+.TP
+.B Object path
+/org/bluez/obex/server/session{#} or
+/org/bluez/obex/client/session{#}
+.UNINDENT
+.SS Methods
+.SS string GetCapabilities()
+.INDENT 0.0
+.INDENT 3.5
+Get remote device capabilities.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.NotSupported
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Source [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Bluetooth adapter address
+.UNINDENT
+.UNINDENT
+.SS string Destination [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Bluetooth device address
+.UNINDENT
+.UNINDENT
+.SS byte Channel [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Bluetooth channel
+.UNINDENT
+.UNINDENT
+.SS uint16 PSM [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Bluetooth L2CAP PSM
+.UNINDENT
+.UNINDENT
+.SS string Target [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Target UUID
+.UNINDENT
+.UNINDENT
+.SS string Root [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Root path
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Session.rst b/doc/org.bluez.obex.Session.rst
new file mode 100644
index 0000000..fc5f14e
--- /dev/null
+++ b/doc/org.bluez.obex.Session.rst
@@ -0,0 +1,66 @@
+======================
+org.bluez.obex.Session
+======================
+
+-----------------------------------------
+BlueZ D-Bus OBEX Client API documentation
+-----------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Session1
+:Object path:	/org/bluez/obex/server/session{#} or
+		/org/bluez/obex/client/session{#}
+
+Methods
+-------
+
+string GetCapabilities()
+````````````````````````
+
+	Get remote device capabilities.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.NotSupported:
+	:org.bluez.obex.Error.Failed:
+
+Properties
+----------
+
+string Source [readonly]
+````````````````````````
+
+	Bluetooth adapter address
+
+string Destination [readonly]
+`````````````````````````````
+
+	Bluetooth device address
+
+byte Channel [readonly]
+```````````````````````
+
+	Bluetooth channel
+
+uint16 PSM [readonly]
+```````````````````````
+
+	Bluetooth L2CAP PSM
+
+string Target [readonly]
+````````````````````````
+
+	Target UUID
+
+string Root [readonly]
+``````````````````````
+
+	Root path
diff --git a/doc/org.bluez.obex.Synchronization.5 b/doc/org.bluez.obex.Synchronization.5
new file mode 100644
index 0000000..3edf393
--- /dev/null
+++ b/doc/org.bluez.obex.Synchronization.5
@@ -0,0 +1,118 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.SYNCHRONIZATION" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Synchronization \- BlueZ D-Bus OBEX Synchronization API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Synchronization1
+.TP
+.B Object path
+[Session object path]
+.UNINDENT
+.SS Methods
+.SS void SetLocation(string location)
+.INDENT 0.0
+.INDENT 3.5
+Sets the phonebook object store location for other operations. Should be
+called before all the other operations.
+.sp
+Possible location:
+.INDENT 0.0
+.TP
+.B \(dqint\(dq ( \(dqinternal\(dq which is default )
+Store in the interval memory.
+.TP
+.B \(dqsim{#}\(dq
+Store in sim card number #.
+.UNINDENT
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict GetPhonebook(string targetfile)
+.INDENT 0.0
+.INDENT 3.5
+Retrieves an entire Phonebook Object store from remote device, and
+stores it in a local file.
+.sp
+If an empty target file is given, a name will be automatically
+calculated for the temporary file.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object, dict PutPhonebook(string sourcefile)
+.INDENT 0.0
+.INDENT 3.5
+Sends an entire Phonebook Object store to remote device.
+.sp
+The returned path represents the newly created transfer, which should be
+used to find out if the content has been successfully transferred or if
+the operation fails.
+.sp
+The properties of this transfer are also returned along with the object
+path, to avoid a call to GetProperties, see
+\fBorg.bluez.obex.Transfer(5)\fP for the possible list of properties.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.InvalidArguments
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Synchronization.rst b/doc/org.bluez.obex.Synchronization.rst
new file mode 100644
index 0000000..a41197d
--- /dev/null
+++ b/doc/org.bluez.obex.Synchronization.rst
@@ -0,0 +1,82 @@
+==============================
+org.bluez.obex.Synchronization
+==============================
+
+--------------------------------------------------
+BlueZ D-Bus OBEX Synchronization API documentation
+--------------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Synchronization1
+:Object path:	[Session object path]
+
+Methods
+-------
+
+void SetLocation(string location)
+`````````````````````````````````
+
+	Sets the phonebook object store location for other operations. Should be
+	called before all the other operations.
+
+	Possible location:
+
+	:"int" ( "internal" which is default ):
+
+		Store in the interval memory.
+
+	:"sim{#}":
+
+		Store in sim card number #.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+
+object, dict GetPhonebook(string targetfile)
+````````````````````````````````````````````
+
+	Retrieves an entire Phonebook Object store from remote device, and
+	stores it in a local file.
+
+	If an empty target file is given, a name will be automatically
+	calculated for the temporary file.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
+
+object, dict PutPhonebook(string sourcefile)
+````````````````````````````````````````````
+
+	Sends an entire Phonebook Object store to remote device.
+
+	The returned path represents the newly created transfer, which should be
+	used to find out if the content has been successfully transferred or if
+	the operation fails.
+
+	The properties of this transfer are also returned along with the object
+	path, to avoid a call to GetProperties, see
+	**org.bluez.obex.Transfer(5)** for the possible list of properties.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.InvalidArguments:
+	:org.bluez.obex.Error.Failed:
diff --git a/doc/org.bluez.obex.Transfer.5 b/doc/org.bluez.obex.Transfer.5
new file mode 100644
index 0000000..40ce404
--- /dev/null
+++ b/doc/org.bluez.obex.Transfer.5
@@ -0,0 +1,171 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ORG.BLUEZ.OBEX.TRANSFER" "5" "October 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+org.bluez.obex.Transfer \- BlueZ D-Bus OBEX Transfer API documentation
+.SH INTERFACE
+.INDENT 0.0
+.TP
+.B Service
+org.bluez.obex
+.TP
+.B Interface
+org.bluez.obex.Transfer1
+.TP
+.B Object path
+[Session object path]/transfer{#}
+.UNINDENT
+.SS Methods
+.SS void Cancel()
+.INDENT 0.0
+.INDENT 3.5
+Cancels the current transference.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.NotAuthorized
+.TP
+.B org.bluez.obex.Error.InProgress
+.TP
+.B org.bluez.obex.Error.Failed
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Suspend()
+.INDENT 0.0
+.INDENT 3.5
+Suspends transference.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.NotAuthorized
+.TP
+.B org.bluez.obex.Error.NotInProgress
+If transfer is still in with \fBStatus\fP \fB\(dqqueued\(dq\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS void Resume()
+.INDENT 0.0
+.INDENT 3.5
+Resumes transference previously suspended with use of \fBSuspend()\fP
+method.
+.sp
+Possible errors:
+.INDENT 0.0
+.TP
+.B org.bluez.obex.Error.NotAuthorized
+.TP
+.B org.bluez.obex.Error.NotInProgress
+If transfer is still in with \fBStatus\fP \fB\(dqqueued\(dq\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Properties
+.SS string Status [readonly]
+.INDENT 0.0
+.INDENT 3.5
+Indicates the current status of the transfer.
+.sp
+Possible values:
+.INDENT 0.0
+.TP
+.B \(dqqueued\(dq
+.TP
+.B \(dqactive\(dq
+.TP
+.B \(dqsuspended\(dq
+.TP
+.B \(dqcomplete\(dq
+.TP
+.B \(dqerror\(dq
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS object Session [readonly]
+.INDENT 0.0
+.INDENT 3.5
+The object path of the session the transfer belongs to.
+.UNINDENT
+.UNINDENT
+.SS string Name [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Name of the object being transferred.
+.sp
+Either Name or Type or both will be present.
+.UNINDENT
+.UNINDENT
+.SS string Type [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Type of the object transferred being transferred.
+.sp
+Either Name or Type or both will be present.
+.UNINDENT
+.UNINDENT
+.SS uint64 Time [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Time of the object being transferred if this is provided by the remote
+party.
+.UNINDENT
+.UNINDENT
+.SS uint64 Size [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Size of the object being transferred.
+.sp
+If the size is unknown, then this property will not be present.
+.UNINDENT
+.UNINDENT
+.SS uint64 Transferred [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Number of bytes transferred.
+.sp
+For transfers with \fBStatus\fP set to \fB\(dqqueued\(dq\fP, this value will not
+be present.
+.UNINDENT
+.UNINDENT
+.SS string Filename [readonly, optional]
+.INDENT 0.0
+.INDENT 3.5
+Complete name of the file being received or sent.
+.sp
+For incoming object push transaction, this will be the proposed default
+location and name. It can be overwritten by the \fBAuthorizePush()\fP in
+\fBorg.bluez.obex.Agent(5)\fP and will be then updated accordingly.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/org.bluez.obex.Transfer.rst b/doc/org.bluez.obex.Transfer.rst
new file mode 100644
index 0000000..733d828
--- /dev/null
+++ b/doc/org.bluez.obex.Transfer.rst
@@ -0,0 +1,123 @@
+=======================
+org.bluez.obex.Transfer
+=======================
+
+-------------------------------------------
+BlueZ D-Bus OBEX Transfer API documentation
+-------------------------------------------
+
+:Version: BlueZ
+:Date: October 2023
+:Manual section: 5
+:Manual group: Linux System Administration
+
+Interface
+=========
+
+:Service:	org.bluez.obex
+:Interface:	org.bluez.obex.Transfer1
+:Object path:	[Session object path]/transfer{#}
+
+Methods
+-------
+
+void Cancel()
+`````````````
+
+	Cancels the current transference.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.NotAuthorized:
+	:org.bluez.obex.Error.InProgress:
+	:org.bluez.obex.Error.Failed:
+
+void Suspend()
+``````````````
+
+	Suspends transference.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.NotAuthorized:
+	:org.bluez.obex.Error.NotInProgress:
+
+		If transfer is still in with **Status** **"queued"**.
+
+void Resume()
+`````````````
+
+	Resumes transference previously suspended with use of **Suspend()**
+	method.
+
+	Possible errors:
+
+	:org.bluez.obex.Error.NotAuthorized:
+	:org.bluez.obex.Error.NotInProgress:
+
+		If transfer is still in with **Status** **"queued"**.
+
+Properties
+----------
+
+string Status [readonly]
+````````````````````````
+
+	Indicates the current status of the transfer.
+
+	Possible values:
+
+	:"queued":
+	:"active":
+	:"suspended":
+	:"complete":
+	:"error":
+
+object Session [readonly]
+`````````````````````````
+
+	The object path of the session the transfer belongs to.
+
+string Name [readonly, optional]
+````````````````````````````````
+
+	Name of the object being transferred.
+
+	Either Name or Type or both will be present.
+
+string Type [readonly, optional]
+````````````````````````````````
+
+	Type of the object transferred being transferred.
+
+	Either Name or Type or both will be present.
+
+uint64 Time [readonly, optional]
+````````````````````````````````
+
+	Time of the object being transferred if this is provided by the remote
+	party.
+
+uint64 Size [readonly, optional]
+````````````````````````````````
+
+	Size of the object being transferred.
+
+	If the size is unknown, then this property will not be present.
+
+uint64 Transferred [readonly, optional]
+```````````````````````````````````````
+
+	Number of bytes transferred.
+
+	For transfers with **Status** set to **"queued"**, this value will not
+	be present.
+
+string Filename [readonly, optional]
+````````````````````````````````````
+
+	Complete name of the file being received or sent.
+
+	For incoming object push transaction, this will be the proposed default
+	location and name. It can be overwritten by the **AuthorizePush()** in
+	**org.bluez.obex.Agent(5)** and will be then updated accordingly.
diff --git a/doc/profile-api.txt b/doc/profile-api.txt
deleted file mode 100644
index 183c6c1..0000000
--- a/doc/profile-api.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-BlueZ D-Bus Profile API description
-***********************************
-
-
-Profile Manager hierarchy
-=========================
-
-Service		org.bluez
-Interface	org.bluez.ProfileManager1
-Object path	/org/bluez
-
-		void RegisterProfile(object profile, string uuid, dict options)
-
-			This registers a profile implementation.
-
-			If an application disconnects from the bus all
-			its registered profiles will be removed.
-
-			Some predefined services:
-
-			HFP AG UUID: 0000111f-0000-1000-8000-00805f9b34fb
-
-				Default profile Version is 1.7, profile Features
-				is 0b001001 and RFCOMM channel is 13.
-				Authentication is required.
-
-			HFP HS UUID: 0000111e-0000-1000-8000-00805f9b34fb
-
-				Default profile Version is 1.7, profile Features
-				is 0b000000 and RFCOMM channel is 7.
-				Authentication is required.
-
-			HSP AG UUID: 00001112-0000-1000-8000-00805f9b34fb
-
-				Default profile Version is 1.2, RFCOMM channel
-				is 12 and Authentication is required. Does not
-				support any Features, option is ignored.
-
-			HSP HS UUID: 00001108-0000-1000-8000-00805f9b34fb
-
-				Default profile Version is 1.2, profile Features
-				is 0b0 and RFCOMM channel is 6. Authentication
-				is required. Features is one bit value, specify
-				capability of Remote Audio Volume Control
-				(by default turned off).
-
-			Available options:
-
-				string Name
-
-					Human readable name for the profile
-
-				string Service
-
-					The primary service class UUID
-					(if different from the actual
-					 profile UUID)
-
-				string Role
-
-					For asymmetric profiles that do not
-					have UUIDs available to uniquely
-					identify each side this
-					parameter allows specifying the
-					precise local role.
-
-					Possible values: "client", "server"
-
-				uint16 Channel
-
-					RFCOMM channel number that is used
-					for client and server UUIDs.
-
-					If applicable it will be used in the
-					SDP record as well.
-
-				uint16 PSM
-
-					PSM number that is used for client
-					and server UUIDs.
-
-					If applicable it will be used in the
-					SDP record as well.
-
-				boolean RequireAuthentication
-
-					Pairing is required before connections
-					will be established. No devices will
-					be connected if not paired.
-
-				boolean RequireAuthorization
-
-					Request authorization before any
-					connection will be established.
-
-				boolean AutoConnect
-
-					In case of a client UUID this will
-					force connection of the RFCOMM or
-					L2CAP channels when a remote device
-					is connected.
-
-				string ServiceRecord
-
-					Provide a manual SDP record.
-
-				uint16 Version
-
-					Profile version (for SDP record)
-
-				uint16 Features
-
-					Profile features (for SDP record)
-
-			Possible errors: org.bluez.Error.InvalidArguments
-			                 org.bluez.Error.AlreadyExists
-
-		void UnregisterProfile(object profile)
-
-			This unregisters the profile that has been previously
-			registered. The object path parameter must match the
-			same value that has been used on registration.
-
-			Possible errors: org.bluez.Error.DoesNotExist
-
-
-Profile hierarchy
-=================
-
-Service		unique name
-Interface	org.bluez.Profile1
-Object path	freely definable
-
-Methods		void Release() [noreply]
-
-			This method gets called when the service daemon
-			unregisters the profile. A profile can use it to do
-			cleanup tasks. There is no need to unregister the
-			profile, because when this method gets called it has
-			already been unregistered.
-
-		void NewConnection(object device, fd, dict fd_properties)
-
-			This method gets called when a new service level
-			connection has been made and authorized.
-
-			Common fd_properties:
-
-			uint16 Version		Profile version (optional)
-			uint16 Features		Profile features (optional)
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
-
-		void RequestDisconnection(object device)
-
-			This method gets called when a profile gets
-			disconnected.
-
-			The file descriptor is no longer owned by the service
-			daemon and the profile implementation needs to take
-			care of cleaning up all connections.
-
-			If multiple file descriptors are indicated via
-			NewConnection, it is expected that all of them
-			are disconnected before returning from this
-			method call.
-
-			Possible errors: org.bluez.Error.Rejected
-			                 org.bluez.Error.Canceled
diff --git a/doc/rfcomm.7 b/doc/rfcomm.7
new file mode 100644
index 0000000..d69519d
--- /dev/null
+++ b/doc/rfcomm.7
@@ -0,0 +1,452 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "RFCOMM" "7" "May 2024" "BlueZ" "Linux System Administration"
+.SH NAME
+rfcomm \- RFCOMM protocol
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+
+rfcomm_socket = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+.EE
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+The RFCOMM protocol provides emulation of serial ports over the L2CAP(7)
+protocol. The protocol is based on the ETSI standard TS 07.10.
+.sp
+RFCOMM is a simple transport protocol, with additional provisions for emulating
+the 9 circuits of RS\-232 (EIATIA\-232\-E) serial ports.
+.SH SOCKET ADDRESS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct sockaddr_rc {
+    sa_family_t rc_family;
+    unsigned short rc_bdaddr;
+    unsigned char rc_channel;
+};
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+struct sockaddr_rc addr;
+
+memset(&addr, 0, sizeof(addr));
+addr.rc_family = AF_BLUETOOTH;
+bacpy(&addr.rc_bdaddr, bdaddr);
+addr.rc_channel = channel;
+.EE
+.UNINDENT
+.UNINDENT
+.SH SOCKET OPTIONS
+.sp
+The socket options listed below can be set by using \fBsetsockopt(2)\fP and read
+with \fBgetsockopt(2)\fP with the socket level set to SOL_BLUETOOTH.
+.SS BT_SECURITY (since Linux 2.6.30)
+.sp
+Channel security level, possible values:
+.TS
+box center;
+l|l|l|l.
+T{
+Value
+T}	T{
+Security Level
+T}	T{
+Link Key Type
+T}	T{
+Encryption
+T}
+_
+T{
+\fBBT_SECURITY_SDP\fP
+T}	T{
+0 (SDP Only)
+T}	T{
+None
+T}	T{
+Not required
+T}
+_
+T{
+\fBBT_SECURITY_LOW\fP
+T}	T{
+1 (Low)
+T}	T{
+Unauthenticated
+T}	T{
+Not required
+T}
+_
+T{
+\fBBT_SECURITY_MEDIUM\fP
+T}	T{
+2 (Medium \- default)
+T}	T{
+Unauthenticated
+T}	T{
+Desired
+T}
+_
+T{
+\fBBT_SECURITY_HIGH\fP
+T}	T{
+3 (High)
+T}	T{
+Authenticated
+T}	T{
+Required
+T}
+_
+T{
+\fBBT_SECURITY_FIPS\fP (since Linux 3.15)
+T}	T{
+4 (Secure Only)
+T}	T{
+Authenticated (P\-256 based Secure Simple Pairing and Secure Authentication)
+T}	T{
+Required
+T}
+.TE
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+int level = BT_SECURITY_HIGH;
+int err = setsockopt(rfcomm_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
+                     sizeof(level));
+if (err == \-1) {
+    perror(\(dqsetsockopt\(dq);
+    return 1;
+}
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_DEFER_SETUP (since Linux 2.6.30)
+.sp
+Channel defer connection setup, this control if the connection procedure
+needs to be authorized by userspace before responding which allows
+authorization at profile level, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Value
+T}	T{
+Description
+T}	T{
+Authorization
+T}
+_
+T{
+\fB0\fP
+T}	T{
+Disable (default)
+T}	T{
+Not required
+T}
+_
+T{
+\fB1\fP
+T}	T{
+Enable
+T}	T{
+Required
+T}
+.TE
+.sp
+Example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+int defer_setup = 1;
+int err = setsockopt(rfcomm_socket, SOL_BLUETOOTH, BT_DEFER_SETUP,
+                     &defer_setup, sizeof(defer_setup));
+if (err == \-1) {
+    perror(\(dqsetsockopt\(dq);
+    return err;
+}
+
+err = listen(rfcomm_socket, 5);
+if (err) {
+    perror(\(dqlisten\(dq);
+    return err;
+}
+
+struct sockaddr_rc remote_addr = {0};
+socklen_t addr_len = sizeof(remote_addr);
+int new_socket = accept(rfcomm_socket, (struct sockaddr*)&remote_addr,
+                        &addr_len);
+if (new_socket < 0) {
+    perror(\(dqaccept\(dq);
+    return new_socket;
+}
+
+/* To complete the connection setup of new_socket read 1 byte */
+char c;
+struct pollfd pfd;
+
+memset(&pfd, 0, sizeof(pfd));
+pfd.fd = new_socket;
+pfd.events = POLLOUT;
+
+err = poll(&pfd, 1, 0);
+if (err) {
+    perror(\(dqpoll\(dq);
+    return err;
+}
+
+if (!(pfd.revents & POLLOUT)) {
+    err = read(sk, &c, 1);
+    if (err < 0) {
+        perror(\(dqread\(dq);
+        return err;
+    }
+}
+.EE
+.UNINDENT
+.UNINDENT
+.SS BT_FLUSHABLE (since Linux 2.6.39)
+.sp
+Channel flushable flag, this control if the channel data can be flushed or
+not, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_FLUSHABLE_OFF\fP
+T}	T{
+0x00 (default)
+T}	T{
+Do not flush data
+T}
+_
+T{
+\fBBT_FLUSHABLE_ON\fP
+T}	T{
+0x01
+T}	T{
+Flush data
+T}
+.TE
+.SS BT_POWER (since Linux 3.1)
+.sp
+Channel power policy, this control if the channel shall force exit of sniff
+mode or not, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_POWER_FORCE_ACTIVE_OFF\fP
+T}	T{
+0x00 (default)
+T}	T{
+Don\(aqt force exit of sniff mode
+T}
+_
+T{
+\fBBT_POWER_FORCE_ACTIVE_ON\fP
+T}	T{
+0x01
+T}	T{
+Force exit of sniff mode
+T}
+.TE
+.SS BT_CHANNEL_POLICY (since Linux 3.10)
+.sp
+High\-speed (AMP) channel policy, possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_ONLY\fP
+T}	T{
+0 (default)
+T}	T{
+BR/EDR only
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_PREFERRED\fP
+T}	T{
+1
+T}	T{
+BR/EDR Preferred
+T}
+_
+T{
+\fBBT_CHANNEL_POLICY_BREDR_PREFERRED\fP
+T}	T{
+2
+T}	T{
+AMP Preferred
+T}
+.TE
+.SS BT_PHY (since Linux 5.10)
+.sp
+Channel supported PHY(s), possible values:
+.TS
+box center;
+l|l|l.
+T{
+Define
+T}	T{
+Value
+T}	T{
+Description
+T}
+_
+T{
+\fBBT_PHY_BR_1M_1SLOT\fP
+T}	T{
+BIT 0
+T}	T{
+BR 1Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_1M_3SLOT\fP
+T}	T{
+BIT 1
+T}	T{
+BR 1Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_1M_5SLOT\fP
+T}	T{
+BIT 2
+T}	T{
+BR 1Mbps 5SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_1SLOT\fP
+T}	T{
+BIT 3
+T}	T{
+EDR 2Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_3SLOT\fP
+T}	T{
+BIT 4
+T}	T{
+EDR 2Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_2M_5SLOT\fP
+T}	T{
+BIT 5
+T}	T{
+EDR 2Mbps 5SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_1SLOT\fP
+T}	T{
+BIT 6
+T}	T{
+EDR 3Mbps 1SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_3SLOT\fP
+T}	T{
+BIT 7
+T}	T{
+EDR 3Mbps 3SLOT
+T}
+_
+T{
+\fBBT_PHY_BR_3M_5SLOT\fP
+T}	T{
+BIT 8
+T}	T{
+EDR 3Mbps 5SLOT
+T}
+.TE
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH SEE ALSO
+.sp
+socket(7), rctest(1)
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/rfcomm.rst b/doc/rfcomm.rst
new file mode 100644
index 0000000..b20c754
--- /dev/null
+++ b/doc/rfcomm.rst
@@ -0,0 +1,225 @@
+======
+rfcomm
+======
+
+---------------
+RFCOMM protocol
+---------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: May 2024
+:Manual section: 7
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+.. code-block::
+
+    #include <sys/socket.h>
+    #include <bluetooth/bluetooth.h>
+    #include <bluetooth/rfcomm.h>
+
+    rfcomm_socket = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+
+DESCRIPTION
+===========
+
+The RFCOMM protocol provides emulation of serial ports over the L2CAP(7)
+protocol. The protocol is based on the ETSI standard TS 07.10.
+
+RFCOMM is a simple transport protocol, with additional provisions for emulating
+the 9 circuits of RS-232 (EIATIA-232-E) serial ports.
+
+SOCKET ADDRESS
+==============
+
+.. code-block::
+
+    struct sockaddr_rc {
+        sa_family_t rc_family;
+        unsigned short rc_bdaddr;
+        unsigned char rc_channel;
+    };
+
+Example:
+
+.. code-block::
+
+    struct sockaddr_rc addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.rc_family = AF_BLUETOOTH;
+    bacpy(&addr.rc_bdaddr, bdaddr);
+    addr.rc_channel = channel;
+
+SOCKET OPTIONS
+==============
+
+The socket options listed below can be set by using **setsockopt(2)** and read
+with **getsockopt(2)** with the socket level set to SOL_BLUETOOTH.
+
+BT_SECURITY (since Linux 2.6.30)
+--------------------------------
+
+Channel security level, possible values:
+
+.. csv-table::
+    :header: "Value", "Security Level", "Link Key Type", "Encryption"
+    :widths: auto
+
+    **BT_SECURITY_SDP**, 0 (SDP Only), None, Not required
+    **BT_SECURITY_LOW**, 1 (Low), Unauthenticated, Not required
+    **BT_SECURITY_MEDIUM**, 2 (Medium - default), Unauthenticated, Desired
+    **BT_SECURITY_HIGH**, 3 (High), Authenticated, Required
+    **BT_SECURITY_FIPS** (since Linux 3.15), 4 (Secure Only), Authenticated (P-256 based Secure Simple Pairing and Secure Authentication), Required
+
+Example:
+
+.. code-block::
+
+    int level = BT_SECURITY_HIGH;
+    int err = setsockopt(rfcomm_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
+                         sizeof(level));
+    if (err == -1) {
+        perror("setsockopt");
+        return 1;
+    }
+
+BT_DEFER_SETUP (since Linux 2.6.30)
+-----------------------------------
+
+Channel defer connection setup, this control if the connection procedure
+needs to be authorized by userspace before responding which allows
+authorization at profile level, possible values:
+
+.. csv-table::
+    :header: "Value", "Description", "Authorization"
+    :widths: auto
+
+    **0**, Disable (default), Not required
+    **1**, Enable, Required
+
+Example:
+
+.. code-block::
+
+    int defer_setup = 1;
+    int err = setsockopt(rfcomm_socket, SOL_BLUETOOTH, BT_DEFER_SETUP,
+                         &defer_setup, sizeof(defer_setup));
+    if (err == -1) {
+        perror("setsockopt");
+        return err;
+    }
+
+    err = listen(rfcomm_socket, 5);
+    if (err) {
+        perror("listen");
+        return err;
+    }
+
+    struct sockaddr_rc remote_addr = {0};
+    socklen_t addr_len = sizeof(remote_addr);
+    int new_socket = accept(rfcomm_socket, (struct sockaddr*)&remote_addr,
+                            &addr_len);
+    if (new_socket < 0) {
+        perror("accept");
+        return new_socket;
+    }
+
+    /* To complete the connection setup of new_socket read 1 byte */
+    char c;
+    struct pollfd pfd;
+
+    memset(&pfd, 0, sizeof(pfd));
+    pfd.fd = new_socket;
+    pfd.events = POLLOUT;
+
+    err = poll(&pfd, 1, 0);
+    if (err) {
+        perror("poll");
+        return err;
+    }
+
+    if (!(pfd.revents & POLLOUT)) {
+        err = read(sk, &c, 1);
+        if (err < 0) {
+            perror("read");
+            return err;
+        }
+    }
+
+BT_FLUSHABLE (since Linux 2.6.39)
+---------------------------------
+
+Channel flushable flag, this control if the channel data can be flushed or
+not, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_FLUSHABLE_OFF**, 0x00 (default), Do not flush data
+    **BT_FLUSHABLE_ON**, 0x01, Flush data
+
+BT_POWER (since Linux 3.1)
+--------------------------
+
+Channel power policy, this control if the channel shall force exit of sniff
+mode or not, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_POWER_FORCE_ACTIVE_OFF**, 0x00 (default), Don't force exit of sniff mode
+    **BT_POWER_FORCE_ACTIVE_ON**, 0x01, Force exit of sniff mode
+
+BT_CHANNEL_POLICY (since Linux 3.10)
+------------------------------------
+
+High-speed (AMP) channel policy, possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_CHANNEL_POLICY_BREDR_ONLY**, 0 (default), BR/EDR only
+    **BT_CHANNEL_POLICY_BREDR_PREFERRED**, 1, BR/EDR Preferred
+    **BT_CHANNEL_POLICY_BREDR_PREFERRED**, 2, AMP Preferred
+
+BT_PHY (since Linux 5.10)
+-------------------------
+
+Channel supported PHY(s), possible values:
+
+.. csv-table::
+    :header: "Define", "Value", "Description"
+    :widths: auto
+
+    **BT_PHY_BR_1M_1SLOT**, BIT 0, BR 1Mbps 1SLOT
+    **BT_PHY_BR_1M_3SLOT**, BIT 1, BR 1Mbps 3SLOT
+    **BT_PHY_BR_1M_5SLOT**, BIT 2, BR 1Mbps 5SLOT
+    **BT_PHY_BR_2M_1SLOT**, BIT 3, EDR 2Mbps 1SLOT
+    **BT_PHY_BR_2M_3SLOT**, BIT 4, EDR 2Mbps 3SLOT
+    **BT_PHY_BR_2M_5SLOT**, BIT 5, EDR 2Mbps 5SLOT
+    **BT_PHY_BR_3M_1SLOT**, BIT 6, EDR 3Mbps 1SLOT
+    **BT_PHY_BR_3M_3SLOT**, BIT 7, EDR 3Mbps 3SLOT
+    **BT_PHY_BR_3M_5SLOT**, BIT 8, EDR 3Mbps 5SLOT
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
+
+SEE ALSO
+========
+
+socket(7), rctest(1)
diff --git a/doc/security-bugs.txt b/doc/security-bugs.txt
deleted file mode 100644
index bd4b0d6..0000000
--- a/doc/security-bugs.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-Security bugs
-=============
-
-BlueZ developers take security very seriously.  As such, we'd like to know
-when a security bug is found so that it can be fixed and disclosed as quickly
-as possible.  Please report security bugs to the BlueZ security team.
-
-
-Contact
--------
-
-The BlueZ security team can be contacted by email at <security@bluez.org>.
-This is a private list of security officers who will help verify the bug
-report and develop and release a fix.  If you already have a fix, please
-include it with your report, as that can speed up the process considerably.
-
-As it is with any bug, the more information provided the easier it will
-be to diagnose and fix.  Any exploit code is very helpful and will not
-be released without consent from the reporter unless it has already been
-made public.
-
-Please send plain text emails without attachments where possible.
-
-
-Disclosure and embargoed information
-------------------------------------
-
-The security list is not a disclosure channel.  For that, see Coordination
-below.
-
-Once a robust fix has been developed, the release process starts.  Fixes
-for publicly known bugs are released immediately.
-
-Although our preference is to release fixes for publicly undisclosed bugs
-as soon as they become available, this may be postponed at the request of
-the reporter or an affected party for up to 7 calendar days from the start
-of the release process, with an exceptional extension to 14 calendar days
-if it is agreed that the criticality of the bug requires more time.  The
-only valid reason for deferring the publication of a fix is to accommodate
-the logistics of QA and large scale rollouts which require release
-coordination.
-
-While embargoed information may be shared with trusted individuals in
-order to develop a fix, such information will not be published alongside
-the fix or on any other disclosure channel without the permission of the
-reporter.  This includes but is not limited to the original bug report
-and followup discussions (if any), exploits, CVE information or the
-identity of the reporter.
-
-In other words our only interest is in getting bugs fixed.  All other
-information submitted to the security list and any followup discussions
-of the report are treated confidentially even after the embargo has been
-lifted, in perpetuity.
-
-
-Coordination
-------------
-
-Fixes for sensitive bugs, such as those that might lead to privilege
-escalations, may need to be coordinated with the private
-<linux-distros@vs.openwall.org> mailing list so that distribution vendors
-are well prepared to issue a fixed package upon public disclosure of the
-upstream fix.  Distros will need some time to test the proposed patch and
-will generally request at least a few days of embargo, and vendor update
-publication prefers to happen Tuesday through Thursday. When appropriate,
-the security team can assist with this coordination, or the reporter can
-include linux-distros from the start.  In this case, remember to prefix
-the email Subject line with "[vs]" as described in the linux-distros wiki:
-<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
-
-
-CVE assignment
---------------
-
-The security team does not normally assign CVEs, nor do we require them
-for reports or fixes, as this can needlessly complicate the process and
-may delay the bug handling. If a reporter wishes to have a CVE identifier
-assigned ahead of public disclosure, they will need to contact the private
-linux-distros list, described above. When such a CVE identifier is known
-before a patch is provided, it is desirable to mention it in the commit
-message if the reporter agrees.
-
-
-Non-disclosure agreements
--------------------------
-
-The BlueZ security team is not a formal body and therefore unable to enter
-any non-disclosure agreements.
diff --git a/doc/test-runner.rst b/doc/test-runner.rst
new file mode 100644
index 0000000..423a937
--- /dev/null
+++ b/doc/test-runner.rst
@@ -0,0 +1,178 @@
+===========
+test-runner
+===========
+
+**test-runner** [*OPTIONS*] -- <test-name>
+
+DESCRIPTION
+===========
+
+**test-runner(1)** is used to test Kernel changes to the Bluetooth subsystem,
+it lunches a virtual machine using qemu(1) and mounts the local filesystem
+using virtio (9p).
+
+OPTIONS
+=======
+
+:-a:--auto: Find tests and run them
+:-b/--dbus: Start D-Bus system daemon
+:-s/--dbus-session: Start D-Bus session daemon
+:-d/--daemon: Start bluetoothd
+:-m/--monitor: Start btmon
+:-l/--emulator: Start btvirt
+:-A/-audio[=path]: Start audio server
+:-u/--unix[=path]: Provide serial device
+:-q/--qemu=<path>: QEMU binary
+:-k/--kernel=<image>: Kernel image (bzImage)
+:-h/--help: Show help options
+
+Kernel
+======
+
+The test-runner tool requires a kernel that is at least build with these
+minimal options for a successful boot. These options should be installed as
+.config in the kernel source directory followed by:
+
+.. code-block::
+
+	make olddefconfig
+
+After that a default kernel with the required options can be built. More
+option (like the Bluetooth subsystem) can be enabled on top of this.
+
+.. code-block::
+
+	CONFIG_VIRTIO=y
+	CONFIG_VIRTIO_PCI=y
+
+	CONFIG_NET=y
+	CONFIG_INET=y
+
+	CONFIG_NET_9P=y
+	CONFIG_NET_9P_VIRTIO=y
+
+	CONFIG_9P_FS=y
+	CONFIG_9P_FS_POSIX_ACL=y
+
+	CONFIG_SERIAL_8250=y
+	CONFIG_SERIAL_8250_CONSOLE=y
+	CONFIG_SERIAL_8250_PCI=yCONFIG_DEBUG_KERNEL=y
+	CONFIG_SERIAL_8250_NR_UARTS=4
+
+	CONFIG_TMPFS=y
+	CONFIG_TMPFS_POSIX_ACL=y
+	CONFIG_TMPFS_XATTR=y
+
+	CONFIG_DEVTMPFS=y
+	CONFIG_DEBUG_FS=y
+
+Bluetooth
+---------
+
+.. code-block::
+
+	CONFIG_BT=y
+	CONFIG_BT_BREDR=y
+	CONFIG_BT_RFCOMM=y
+	CONFIG_BT_BNEP=y
+	CONFIG_BT_HIDP=y
+	CONFIG_BT_LE=y
+
+	CONFIG_BT_HCIUART=y
+	CONFIG_BT_HCIUART_H4=y
+	CONFIG_BT_HCIVHCI=y
+
+	CONFIG_CRYPTO_CMAC=y
+	CONFIG_CRYPTO_USER_API=y
+	CONFIG_CRYPTO_USER_API_HASH=y
+	CONFIG_CRYPTO_USER_API_SKCIPHER=y
+
+	CONFIG_UNIX=y
+
+	CONFIG_UHID=y
+
+Lock debuging
+-------------
+
+To catch locking related issues the following set of kernel config
+options may be useful:
+
+.. code-block::
+
+	CONFIG_DEBUG_KERNEL=y
+	CONFIG_LOCKDEP_SUPPORT=y
+	CONFIG_DEBUG_SPINLOCK=y
+	CONFIG_DEBUG_LOCK_ALLOC=y
+	CONFIG_DEBUG_ATOMIC_SLEEP=y
+	CONFIG_PROVE_LOCKING=y
+	CONFIG_PROVE_RCU=y
+	CONFIG_LOCKDEP=y
+	CONFIG_DEBUG_MUTEXES=y
+	CONFIG_KASAN=y
+
+EXAMPLES
+========
+
+Running mgmt-tester
+-------------------
+
+.. code-block::
+
+	$ tools/test-runner -k /pathto/bzImage -- tools/mgmt-tester
+
+Running a specific test of mgmt-tester
+--------------------------------------
+
+.. code-block::
+
+	$ tools/test-runner -k /pathto/bzImage -- tools/mgmt-tester -s "<name>"
+
+Running bluetoothctl with emulated controller
+---------------------------------------------
+
+.. code-block::
+
+	$ tools/test-runner -l -d -k /pathto/bzImage -- client/bluetoothctl
+	[CHG] Controller 00:AA:01:00:00:00 Pairable: yes
+	[bluetooth]#
+
+Running bluetoothctl with emulated controller and audio support
+---------------------------------------------------------------
+
+.. code-block::
+
+	$ tools/test-runner -l -d -A -k /pathto/bzImage -- client/bluetoothctl
+	[CHG] Controller 00:AA:01:00:00:00 Pairable: yes
+	[bluetooth]#
+	[CHG] Controller 00:AA:01:00:00:00 Pairable: yes
+	[CHG] Controller 00:AA:01:00:00:00 Class: 0x00600000 (6291456)
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000111f-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001200-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110a-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001800-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001801-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000180a-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 Class: 0x006c0000 (7077888)
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000111f-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001200-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110a-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001800-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 00001801-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000180a-0000-1000-8000-00805f9b34fb
+	[CHG] Controller 00:AA:01:00:00:00 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
+
+Running shell with host controller using btproxy
+------------------------------------------------
+
+.. code-block::
+
+	$ tools/btproxy -u [1]
+	$ tools/test-runner -u -d -k /pathto/bzImage -- /bin/bash [2]
+
diff --git a/doc/test-runner.txt b/doc/test-runner.txt
deleted file mode 100644
index 019c231..0000000
--- a/doc/test-runner.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-Notes for test-runner usage
-***************************
-
-
-Kernel configuration
-====================
-
-The test-runner tool requires a kernel that is at least build with these
-minimal options for a successful boot.
-
-	CONFIG_VIRTIO=y
-	CONFIG_VIRTIO_PCI=y
-
-	CONFIG_NET=y
-	CONFIG_INET=y
-
-	CONFIG_NET_9P=y
-	CONFIG_NET_9P_VIRTIO=y
-
-	CONFIG_9P_FS=y
-	CONFIG_9P_FS_POSIX_ACL=y
-
-	CONFIG_SERIAL_8250=y
-	CONFIG_SERIAL_8250_CONSOLE=y
-	CONFIG_SERIAL_8250_PCI=y
-	CONFIG_SERIAL_8250_NR_UARTS=4
-
-	CONFIG_TMPFS=y
-	CONFIG_TMPFS_POSIX_ACL=y
-	CONFIG_TMPFS_XATTR=y
-
-	CONFIG_DEVTMPFS=y
-	CONFIG_DEBUG_FS=y
-
-For Bluetooth functionality:
-
-	CONFIG_BT=y
-	CONFIG_BT_BREDR=y
-	CONFIG_BT_RFCOMM=y
-	CONFIG_BT_BNEP=y
-	CONFIG_BT_HIDP=y
-	CONFIG_BT_LE=y
-
-	CONFIG_BT_HCIUART=y
-	CONFIG_BT_HCIUART_H4=y
-	CONFIG_BT_HCIVHCI=y
-
-	CONFIG_CRYPTO_CMAC=y
-	CONFIG_CRYPTO_USER_API=y
-	CONFIG_CRYPTO_USER_API_HASH=y
-	CONFIG_CRYPTO_USER_API_SKCIPHER=y
-
-	CONFIG_UNIX=y
-
-	CONFIG_UHID=y
-
-For Audio functionality:
-	CONFIG_SYSVIPC=y
-	CONFIG_SOUND=y
-	CONFIG_SND=y
-	CONFIG_SND_INTEL8X0=y
-
-These options should be installed as .config in the kernel source directory
-followed by this command.
-
-	make olddefconfig
-
-After that a default kernel with the required options can be built. More
-option (like the Bluetooth subsystem) can be enabled on top of this.
-
-Lock debuging
--------------
-
-To catch locking related issues the following set of kernel config
-options may be useful:
-
-	CONFIG_LOCKDEP_SUPPORT=y
-	CONFIG_DEBUG_SPINLOCK=y
-	CONFIG_DEBUG_LOCK_ALLOC=y
-	CONFIG_PROVE_LOCKING=y
-	CONFIG_LOCKDEP=y
-	CONFIG_DEBUG_MUTEXES=y
diff --git a/doc/tester.config b/doc/tester.config
deleted file mode 100644
index 4429a72..0000000
--- a/doc/tester.config
+++ /dev/null
@@ -1,56 +0,0 @@
-CONFIG_PCI=y
-CONFIG_VIRTIO=y
-CONFIG_VIRTIO_PCI=y
-
-CONFIG_NET=y
-CONFIG_INET=y
-
-CONFIG_NET_9P=y
-CONFIG_NET_9P_VIRTIO=y
-
-CONFIG_9P_FS=y
-CONFIG_9P_FS_POSIX_ACL=y
-
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_TMPFS_XATTR=y
-
-CONFIG_DEVTMPFS=y
-CONFIG_DEBUG_FS=y
-
-CONFIG_BT=y
-CONFIG_BT_BREDR=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_LE=y
-CONFIG_BT_HS=y
-CONFIG_BT_MSFTEXT=y
-CONFIG_BT_AOSPEXT=y
-CONFIG_BT_FEATURE_DEBUG=y
-
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIVHCI=y
-
-CONFIG_CRYPTO_CMAC=y
-CONFIG_CRYPTO_USER_API=y
-CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_USER_API_SKCIPHER=y
-
-CONFIG_UNIX=y
-
-CONFIG_UHID=y
-
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_LOCKDEP=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_KASAN=y
diff --git a/doc/thermometer-api.txt b/doc/thermometer-api.txt
deleted file mode 100644
index c7c8a5d..0000000
--- a/doc/thermometer-api.txt
+++ /dev/null
@@ -1,134 +0,0 @@
-BlueZ D-Bus Thermometer API description
-***************************************
-
-	Santiago Carot-Nemesio <sancane@gmail.com>
-
-Health Thermometer Manager hierarchy
-====================================
-
-Service		org.bluez
-Interface	org.bluez.ThermometerManager1
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		RegisterWatcher(object agent)
-
-			Registers a watcher to monitor scanned measurements.
-			This agent will be notified about final temperature
-			measurements.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-
-		UnregisterWatcher(object agent)
-
-			Unregisters a watcher.
-
-		EnableIntermediateMeasurement(object agent)
-
-			Enables intermediate measurement notifications
-			for this agent. Intermediate measurements will
-			be enabled only for thermometers which support it.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-
-		DisableIntermediateMeasurement(object agent)
-
-			Disables intermediate measurement notifications
-			for this agent. It will disable notifications in
-			thermometers when the last agent removes the
-			watcher for intermediate measurements.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					org.bluez.Error.NotFound
-
-Health Thermometer Profile hierarchy
-====================================
-
-Service		org.bluez
-Interface	org.bluez.Thermometer1
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-
-Properties	boolean Intermediate [readonly]
-
-			True if the thermometer supports intermediate
-			measurement notifications.
-
-		uint16 Interval (optional) [readwrite]
-
-			The Measurement Interval defines the time (in
-			seconds) between measurements. This interval is
-			not related to the intermediate measurements and
-			must be defined into a valid range. Setting it
-			to zero means that no periodic measurements will
-			be taken.
-
-		uint16 Maximum (optional) [readonly]
-
-			Defines the maximum value allowed for the interval
-			between periodic measurements.
-
-		uint16 Minimum (optional) [readonly]
-
-			Defines the minimum value allowed for the interval
-			between periodic measurements.
-
-
-Health Thermometer Watcher hierarchy
-====================================
-
-Service		unique name
-Interface	org.bluez.ThermometerWatcher1
-Object path	freely definable
-
-Methods		void MeasurementReceived(dict measurement)
-
-			This callback gets called when a measurement has been
-			scanned in the thermometer.
-
-			Measurement:
-
-				int16 Exponent:
-				int32 Mantissa:
-
-					Exponent and Mantissa values as
-					extracted from float value defined by
-					IEEE-11073-20601.
-
-					Measurement value is calculated as
-					(Mantissa) * (10^Exponent)
-
-					For special cases Exponent is
-					set to 0 and Mantissa is set to
-					one of following values:
-
-					+(2^23 - 1)	NaN (invalid or
-							missing data)
-					-(2^23)		NRes
-					+(2^23 - 2)	+Infinity
-					-(2^23 - 2)	-Infinity
-
-				string Unit:
-
-					Possible values: "celsius" or
-							"fahrenheit"
-
-				uint64 Time (optional):
-
-					Time of measurement, if
-					supported by device.
-					Expressed in seconds since epoch.
-
-				string Type (optional):
-
-					Only present if measurement type
-					is known.
-
-					Possible values: "armpit", "body",
-						"ear", "finger", "intestines",
-						"mouth", "rectum", "toe",
-						"tympanum"
-
-				string Measurement:
-
-					Possible values: "final" or
-							"intermediate"
diff --git a/ell/asn1-private.h b/ell/asn1-private.h
new file mode 100644
index 0000000..08f04ba
--- /dev/null
+++ b/ell/asn1-private.h
@@ -0,0 +1,193 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2017  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
+
+#define ASN1_CLASS_UNIVERSAL	0
+#define ASN1_CLASS_CONTEXT	2
+
+#define ASN1_ID_SEQUENCE	ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
+#define ASN1_ID_SET		ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
+#define ASN1_ID_BOOLEAN		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x01)
+#define ASN1_ID_INTEGER		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
+#define ASN1_ID_BIT_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
+#define ASN1_ID_OCTET_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
+#define ASN1_ID_NULL		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x05)
+#define ASN1_ID_OID		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
+#define ASN1_ID_UTF8STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
+#define ASN1_ID_PRINTABLESTRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
+#define ASN1_ID_IA5STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x16)
+#define ASN1_ID_UTCTIME		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x17)
+#define ASN1_ID_GENERALIZEDTIME	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x18)
+
+struct asn1_oid {
+	uint8_t asn1_len;
+	uint8_t asn1[11];
+};
+
+#define asn1_oid_eq(oid1, oid2_len, oid2_string) \
+	((oid1)->asn1_len == (oid2_len) && \
+	 !memcmp((oid1)->asn1, (oid2_string), (oid2_len)))
+
+#if __STDC_VERSION__ <= 199409L
+#define inline __inline__
+#endif
+
+static inline int asn1_parse_definite_length(const uint8_t **buf,
+						size_t *len)
+{
+	int n;
+	size_t result = 0;
+
+	/* Decrease the buffer length left */
+	if ((*len)-- < 1)
+		return -1;
+
+	/*
+	 * If short form length, move the pointer to start of data and
+	 * return the data length.
+	 */
+	if (!(**buf & 0x80))
+		return *(*buf)++;
+
+	n = *(*buf)++ & 0x7f;
+	if ((size_t) n > *len)
+		return -1;
+
+	*len -= n;
+	while (n--)
+		result = (result << 8) | *(*buf)++;
+
+	return result;
+}
+
+static inline void asn1_write_definite_length(uint8_t **buf, size_t len)
+{
+	int n;
+
+	if (len < 0x80) {
+		*(*buf)++ = len;
+		return;
+	}
+
+	for (n = 1; len >> (n * 8); n++);
+	*(*buf)++ = 0x80 | n;
+
+	while (n--)
+		*(*buf)++ = len >> (n * 8);
+}
+
+#define ASN1_CONTEXT_IMPLICIT(tag) (0x1000 | (tag))
+#define ASN1_CONTEXT_EXPLICIT(tag) (0x2000 | (tag))
+
+/*
+ * Return the tag, length and value of the @index'th
+ * non-context-specific-tagged element in a DER SEQUENCE or one who's
+ * ASN1_CONTEXT_IMPLICIT(tag) matches @index or the inner element of
+ * the one who's ASN1_CONTEXT_EXPLICIT(tag) matches @index.
+ */
+static inline const uint8_t *asn1_der_find_elem(const uint8_t *buf,
+						size_t len_in, int index,
+						uint8_t *tag, size_t *len_out)
+{
+	int n = 0;
+
+	while (1) {
+		int tlv_len;
+
+		if (len_in < 2)
+			return NULL;
+
+		*tag = *buf++;
+		len_in--;
+
+		tlv_len = asn1_parse_definite_length((void *) &buf, &len_in);
+		if (tlv_len < 0 || (size_t) tlv_len > len_in)
+			return NULL;
+
+		if (*tag >> 6 != ASN1_CLASS_CONTEXT) {
+			if (n++ == index) {
+				*len_out = tlv_len;
+				return buf;
+			}
+		} else if ((*tag & 0x1f) == (index & 0xfff)) {
+			/* Context-specific tag */
+			if (index & 0x1000) {		/* Implicit */
+				*len_out = tlv_len;
+				return buf;
+			} else if (index & 0x2000) {	/* Explicit */
+				const uint8_t *outer = buf;
+				int inner_len;
+
+				if (!(*tag & 0x20))	/* Primitive */
+					return NULL;
+
+				if (tlv_len < 2)
+					return NULL;
+
+				*tag = *buf++;
+
+				inner_len = asn1_parse_definite_length(
+							(void *) &buf, &len_in);
+				if (outer + tlv_len != buf + inner_len)
+					return NULL;
+
+				*len_out = inner_len;
+				return buf;
+			}
+		}
+
+		buf += tlv_len;
+		len_in -= tlv_len;
+	}
+}
+
+/* Return an element in a DER SEQUENCE structure by path */
+static inline const uint8_t *asn1_der_find_elem_by_path(const uint8_t *buf,
+						size_t len_in, uint8_t tag,
+						size_t *len_out, ...)
+{
+	int index;
+	va_list vl;
+
+	va_start(vl, len_out);
+
+	index = va_arg(vl, int);
+
+	while (index != -1) {
+		uint8_t elem_tag;
+		uint8_t expect_tag;
+		int prev_index = index;
+
+		buf = asn1_der_find_elem(buf, len_in, index,
+						&elem_tag, &len_in);
+		if (!buf) {
+			va_end(vl);
+			return NULL;
+		}
+
+		index = va_arg(vl, int);
+
+		if (prev_index & 0x1000)
+			expect_tag = ASN1_ID(ASN1_CLASS_CONTEXT,
+						index != -1 ? 1 :
+						((elem_tag >> 5) & 1),
+						prev_index & 0xfff);
+		else
+			expect_tag = (index == -1) ? tag : ASN1_ID_SEQUENCE;
+
+		if (elem_tag != expect_tag) {
+			va_end(vl);
+			return NULL;
+		}
+	}
+
+	va_end(vl);
+
+	*len_out = len_in;
+	return buf;
+}
diff --git a/ell/base64.c b/ell/base64.c
new file mode 100644
index 0000000..bfd7857
--- /dev/null
+++ b/ell/base64.c
@@ -0,0 +1,163 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include "utf8.h"
+#include "base64.h"
+#include "private.h"
+#include "useful.h"
+
+#include <stdio.h>
+
+LIB_EXPORT uint8_t *l_base64_decode(const char *in, size_t in_len,
+					size_t *n_written)
+{
+	const char *ptr, *in_end = in + in_len;
+	const char *base64_end = NULL;
+	uint8_t *out_buf, *out;
+	int base64_len = 0, pad_len = 0;
+	uint16_t reg = 0;
+
+	for (ptr = in; ptr < in_end; ptr++) {
+		if (l_ascii_isspace(*ptr))
+			/* Whitespace */
+			continue;
+		else if (*ptr == '=') {
+			/* Final padding */
+			if (!pad_len)
+				base64_end = ptr;
+
+			pad_len++;
+		} else if (!pad_len && (l_ascii_isalnum(*ptr) || *ptr == '+' ||
+					*ptr == '/'))
+			/* Base64 character */
+			base64_len++;
+		else
+			/* Bad character */
+			return NULL;
+	}
+
+	if (ptr != in_end)
+		return NULL;
+
+	if ((base64_len & 3) == 1)
+		/* Invalid length */
+		return NULL;
+
+	if (pad_len != align_len(base64_len, 4) - base64_len)
+		return NULL;
+
+	/* No padding */
+	if (!base64_end)
+		base64_end = ptr;
+
+	*n_written = base64_len * 3 / 4;
+	out_buf = l_malloc(*n_written);
+
+	out = out_buf;
+	base64_len = 0;
+
+	for (ptr = in; ptr < base64_end; ptr++) {
+		if (l_ascii_isspace(*ptr))
+			/* Whitespace */
+			continue;
+
+		/* Base64 character */
+		reg <<= 6;
+		if (l_ascii_isupper(*ptr))
+			reg |= *ptr - 'A' + 0;
+		else if (l_ascii_islower(*ptr))
+			reg |= *ptr - 'a' + 26;
+		else if (l_ascii_isdigit(*ptr))
+			reg |= *ptr - '0' + 52;
+		else if (*ptr == '+')
+			reg |= 62;
+		else if (*ptr == '/')
+			reg |= 63;
+
+		if ((base64_len & 3) == 1)
+			*out++ = reg >> 4;
+		else if ((base64_len & 3) == 2)
+			*out++ = reg >> 2;
+		else if ((base64_len & 3) == 3)
+			*out++ = reg >> 0;
+
+		base64_len++;
+	}
+
+	return out_buf;
+}
+
+LIB_EXPORT char *l_base64_encode(const uint8_t *in, size_t in_len, int columns)
+{
+	const uint8_t *in_end = in + in_len;
+	char *out_buf, *out;
+	size_t out_len;
+	uint32_t reg;
+	uint8_t idx;
+	int i, pad = 4;
+	int col = 0;
+
+	/* For simplicity allow multiples of 4 only */
+	if (columns & 3)
+		return NULL;
+
+	out_len = (in_len + 2) / 3 * 4;
+
+	if (columns && out_len)
+		out_len += (out_len - 4) / columns;
+
+	out_buf = l_malloc(out_len + 1);
+
+	out = out_buf;
+
+	while (in < in_end) {
+		reg = *in++ << 16;
+
+		if (in < in_end)
+			reg |= *in++ << 8;
+		else
+			pad--;
+
+		if (in < in_end)
+			reg |= *in++ << 0;
+		else
+			pad--;
+
+		if (columns && col == columns) {
+			*out++ = '\n';
+			col = 0;
+		}
+		col += 4;
+
+		for (i = 0; i < pad; i++) {
+			idx = (reg >> 18) & 63;
+			reg <<= 6;
+
+			if (idx < 26)
+				*out++ = idx + 'A';
+			else if (idx < 52)
+				*out++ = idx - 26 + 'a';
+			else if (idx < 62)
+				*out++ = idx - 52 + '0';
+			else
+				*out++ = (idx == 62) ? '+' : '/';
+		}
+	}
+
+	for (; pad < 4; pad++)
+		*out++ = '=';
+
+	*out = '\0';
+
+	return out_buf;
+}
diff --git a/ell/base64.h b/ell/base64.h
new file mode 100644
index 0000000..9c1cc5e
--- /dev/null
+++ b/ell/base64.h
@@ -0,0 +1,23 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_BASE64_H
+#define __ELL_BASE64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint8_t *l_base64_decode(const char *in, size_t in_len, size_t *n_written);
+
+char *l_base64_encode(const uint8_t *in, size_t in_len, int columns);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_BASE64_H */
diff --git a/ell/cert-crypto.c b/ell/cert-crypto.c
new file mode 100644
index 0000000..b19f85c
--- /dev/null
+++ b/ell/cert-crypto.c
@@ -0,0 +1,787 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2020  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <strings.h>
+
+#include "checksum.h"
+#include "cipher.h"
+#include "useful.h"
+#include "utf8.h"
+#include "asn1-private.h"
+#include "private.h"
+#include "missing.h"
+#include "cert.h"
+#include "cert-private.h"
+
+/* RFC8018 section 5.1 */
+LIB_EXPORT bool l_cert_pkcs5_pbkdf1(enum l_checksum_type type,
+					const char *password,
+					const uint8_t *salt, size_t salt_len,
+					unsigned int iter_count,
+					uint8_t *out_dk, size_t dk_len)
+{
+	size_t hash_len, t_len;
+	uint8_t t[20 + salt_len + strlen(password)];
+	struct l_checksum *checksum;
+
+	switch (type) {
+	case L_CHECKSUM_MD5:
+		hash_len = 16;
+		break;
+	case L_CHECKSUM_SHA1:
+		hash_len = 20;
+		break;
+	case L_CHECKSUM_NONE:
+	case L_CHECKSUM_MD4:
+	case L_CHECKSUM_SHA224:
+	case L_CHECKSUM_SHA256:
+	case L_CHECKSUM_SHA384:
+	case L_CHECKSUM_SHA512:
+		return false;
+	default:
+		return false;
+	}
+
+	if (dk_len > hash_len)
+		return false;
+
+	checksum = l_checksum_new(type);
+	if (!checksum)
+		return false;
+
+	memcpy(t, password, strlen(password));
+	memcpy(t + strlen(password), salt, salt_len);
+	t_len = strlen(password) + salt_len;
+
+	while (iter_count) {
+		l_checksum_reset(checksum);
+
+		if (!l_checksum_update(checksum, t, t_len))
+			break;
+
+		if (l_checksum_get_digest(checksum, t, hash_len) !=
+				(ssize_t) hash_len)
+			break;
+
+		t_len = hash_len;
+		iter_count--;
+	}
+
+	l_checksum_free(checksum);
+
+	if (!iter_count)
+		memcpy(out_dk, t, dk_len);
+
+	explicit_bzero(t, sizeof(t));
+	return !iter_count;
+}
+
+/* RFC8018 section 5.2 */
+LIB_EXPORT bool l_cert_pkcs5_pbkdf2(enum l_checksum_type type,
+					const char *password,
+					const uint8_t *salt, size_t salt_len,
+					unsigned int iter_count,
+					uint8_t *out_dk, size_t dk_len)
+{
+	size_t h_len;
+	struct l_checksum *checksum;
+	unsigned int i;
+
+	switch (type) {
+	case L_CHECKSUM_SHA1:
+		h_len = 20;
+		break;
+	case L_CHECKSUM_SHA224:
+		h_len = 28;
+		break;
+	case L_CHECKSUM_SHA256:
+		h_len = 32;
+		break;
+	case L_CHECKSUM_SHA384:
+		h_len = 48;
+		break;
+	case L_CHECKSUM_SHA512:
+		h_len = 64;
+		break;
+	case L_CHECKSUM_NONE:
+	case L_CHECKSUM_MD4:
+	case L_CHECKSUM_MD5:
+		return false;
+	default:
+		return false;
+	}
+
+	checksum = l_checksum_new_hmac(type, password, strlen(password));
+	if (!checksum)
+		return false;
+
+	for (i = 1; dk_len; i++) {
+		unsigned int j, k;
+		uint8_t u[salt_len + 64];
+		size_t u_len;
+		size_t block_len = h_len;
+
+		if (block_len > dk_len)
+			block_len = dk_len;
+
+		memset(out_dk, 0, block_len);
+
+		memcpy(u, salt, salt_len);
+		l_put_be32(i, u + salt_len);
+		u_len = salt_len + 4;
+
+		for (j = 0; j < iter_count; j++) {
+			l_checksum_reset(checksum);
+
+			if (!l_checksum_update(checksum, u, u_len))
+				break;
+
+			if (l_checksum_get_digest(checksum, u, h_len) !=
+					(ssize_t) h_len)
+				break;
+
+			u_len = h_len;
+
+			for (k = 0; k < block_len; k++)
+				out_dk[k] ^= u[k];
+		}
+
+		if (j < iter_count)
+			break;
+
+		out_dk += block_len;
+		dk_len -= block_len;
+	}
+
+	l_checksum_free(checksum);
+
+	return !dk_len;
+}
+
+/* RFC7292 Appendix B */
+uint8_t *cert_pkcs12_pbkdf(const char *password,
+				const struct cert_pkcs12_hash *hash,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iterations, uint8_t id,
+				size_t key_len)
+{
+	/* All lengths in bytes instead of bits */
+	size_t passwd_len = password ? 2 * strlen(password) + 2 : 0;
+	uint8_t *bmpstring;
+	/* Documented as v(ceiling(s/v)), usually will just equal v */
+	unsigned int s_len = (salt_len + hash->v - 1) & ~(hash->v - 1);
+	/* Documented as p(ceiling(s/p)), usually will just equal v */
+	unsigned int p_len = password ?
+			(passwd_len + hash->v - 1) & ~(hash->v - 1) : 0;
+	uint8_t di[hash->v + s_len + p_len];
+	uint8_t *ptr;
+	unsigned int j;
+	uint8_t *key;
+	unsigned int bytes;
+	struct l_checksum *h = l_checksum_new(hash->alg);
+
+	if (!h)
+		return NULL;
+
+	/*
+	 * The BMPString encoding, in practice same as UCS-2, can end up
+	 * at 2 * strlen(password) + 2 bytes or shorter depending on the
+	 * characters used.  Recalculate p_len after we know it.
+	 * Important: The password must be valid UTF-8 here.
+	 */
+	if (p_len) {
+		if (!(bmpstring = l_utf8_to_ucs2be(password, &passwd_len))) {
+			l_checksum_free(h);
+			return NULL;
+		}
+
+		p_len = (passwd_len + hash->v - 1) & ~(hash->v - 1);
+	}
+
+	memset(di, id, hash->v);
+	ptr = di + hash->v;
+
+	for (j = salt_len; j < s_len; j += salt_len, ptr += salt_len)
+		memcpy(ptr, salt, salt_len);
+
+	if (s_len) {
+		memcpy(ptr, salt, s_len + salt_len - j);
+		ptr += s_len + salt_len - j;
+	}
+
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+	if (p_len) {
+		for (j = passwd_len; j < p_len;
+					j += passwd_len, ptr += passwd_len)
+			memcpy(ptr, bmpstring, passwd_len);
+
+		memcpy(ptr, bmpstring, p_len + passwd_len - j);
+
+		explicit_bzero(bmpstring, passwd_len);
+		l_free(bmpstring);
+	}
+_Pragma("GCC diagnostic pop")
+
+	key = l_malloc(key_len + hash->len);
+
+	for (bytes = 0; bytes < key_len; bytes += hash->u) {
+		uint8_t b[hash->v];
+		uint8_t *input = di;
+		unsigned int input_len = hash->v + s_len + p_len;
+
+		for (j = 0; j < iterations; j++) {
+			if (!l_checksum_update(h, input, input_len) ||
+					l_checksum_get_digest(h,
+							key + bytes,
+							hash->len) <= 0) {
+				l_checksum_free(h);
+				l_free(key);
+				return NULL;
+			}
+
+			input = key + bytes;
+			input_len = hash->u;
+			l_checksum_reset(h);
+		}
+
+		if (bytes + hash->u >= key_len)
+			break;
+
+		for (j = 0; j < hash->v - hash->u; j += hash->u)
+			memcpy(b + j, input, hash->u);
+
+		memcpy(b + j, input, hash->v - j);
+
+		ptr = di + hash->v;
+		for (j = 0; j < s_len + p_len; j += hash->v, ptr += hash->v) {
+			unsigned int k;
+			uint16_t carry = 1;
+
+			/*
+			 * Not specified in the RFC7292 but implementations
+			 * sum these octet strings as big-endian integers.
+			 * We could use 64-bit additions here but the benefit
+			 * may not compensate the cost of the byteswapping.
+			 */
+			for (k = hash->v - 1; k > 0; k--) {
+				carry = ptr[k] + b[k] + carry;
+				ptr[k] = carry;
+				carry >>= 8;
+			}
+
+			ptr[k] += b[k] + carry;
+			explicit_bzero(&carry, sizeof(carry));
+		}
+
+		explicit_bzero(b, sizeof(b));
+	}
+
+	explicit_bzero(di, sizeof(di));
+	l_checksum_free(h);
+	return key;
+}
+
+/* RFC7292 Appendix A */
+static const struct cert_pkcs12_hash pkcs12_sha1_hash = {
+	.alg = L_CHECKSUM_SHA1,
+	.len = 20,
+	.u   = 20,
+	.v   = 64,
+	.oid = { 5, { 0x2b, 0x0e, 0x03, 0x02, 0x1a } },
+};
+
+/* RFC8018 Section A.2 */
+static struct asn1_oid pkcs5_pbkdf2_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c }
+};
+
+/* RFC8018 Section A.4 */
+static struct asn1_oid pkcs5_pbes2_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d }
+};
+
+/* RFC8018 Section A.3 */
+static const struct pkcs5_pbes1_encryption_oid {
+	enum l_checksum_type checksum_type;
+	enum l_cipher_type cipher_type;
+	struct asn1_oid oid;
+} pkcs5_pbes1_encryption_oids[] = {
+	{ /* pbeWithMD5AndDES-CBC */
+		L_CHECKSUM_MD5, L_CIPHER_DES_CBC,
+		{ 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x03 } },
+	},
+	{ /* pbeWithSHA1AndDES-CBC */
+		L_CHECKSUM_SHA1, L_CIPHER_DES_CBC,
+		{ 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0a } },
+	},
+	/* MD2- and RC2-based schemes 1, 4, 6 and 11 not supported */
+};
+
+/* RFC7292 Appendix C */
+static const struct pkcs12_encryption_oid {
+	enum l_cipher_type cipher_type;
+	unsigned int key_length;
+	unsigned int iv_length;
+	bool copy_k1;	/* Expand the 2-Key 3DES key for 3-Key 3DES */
+	bool is_block;
+	struct asn1_oid oid;
+} pkcs12_encryption_oids[] = {
+	{ /* pbeWithSHAAnd128BitRC4 */
+		.cipher_type = L_CIPHER_ARC4,
+		.key_length = 16,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x01,
+		} }
+	},
+	{ /* pbeWithSHAAnd40BitRC4 */
+		.cipher_type = L_CIPHER_ARC4,
+		.key_length = 5,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x02,
+		} }
+	},
+	{ /* pbeWithSHAAnd3-KeyTripleDES-CBC */
+		.cipher_type = L_CIPHER_DES3_EDE_CBC,
+		.key_length = 24,
+		.iv_length = 8,
+		.is_block = true,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x03,
+		} }
+	},
+	{ /* pbeWithSHAAnd2-KeyTripleDES-CBC */
+		.cipher_type = L_CIPHER_DES3_EDE_CBC,
+		.key_length = 16,
+		.iv_length = 8,
+		.copy_k1 = true,
+		.is_block = true,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x04,
+		} }
+	},
+	{ /* pbeWithSHAAnd128BitRC2-CBC */
+		.cipher_type = L_CIPHER_RC2_CBC,
+		.key_length = 16,
+		.iv_length = 8,
+		.is_block = true,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x05,
+		} }
+	},
+	{ /* pbeWithSHAAnd40BitRC2-CBC */
+		.cipher_type = L_CIPHER_RC2_CBC,
+		.key_length = 5,
+		.iv_length = 8,
+		.is_block = true,
+		.oid = { 10, {
+			0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x0c, 0x01, 0x06,
+		} }
+	},
+};
+
+static const struct pkcs5_digest_alg_oid {
+	enum l_checksum_type type;
+	struct asn1_oid oid;
+} pkcs5_digest_alg_oids[] = {
+	{ /* hmacWithSHA1 */
+		L_CHECKSUM_SHA1,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07 } },
+	},
+	{ /* hmacWithSHA224 */
+		L_CHECKSUM_SHA224,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x08 } },
+	},
+	{ /* hmacWithSHA256 */
+		L_CHECKSUM_SHA256,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09 } },
+	},
+	{ /* hmacWithSHA384 */
+		L_CHECKSUM_SHA384,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0a } },
+	},
+	{ /* hmacWithSHA512 */
+		L_CHECKSUM_SHA512,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0b } },
+	},
+	/* hmacWithSHA512-224 and hmacWithSHA512-256 not supported */
+};
+
+static const struct pkcs5_enc_alg_oid {
+	enum l_cipher_type cipher_type;
+	uint8_t key_size, iv_size;
+	struct asn1_oid oid;
+} pkcs5_enc_alg_oids[] = {
+	{ /* desCBC */
+		L_CIPHER_DES_CBC, 8, 8,
+		{ 5, { 0x2b, 0x0e, 0x03, 0x02, 0x07 } },
+	},
+	{ /* des-EDE3-CBC */
+		L_CIPHER_DES3_EDE_CBC, 24, 8,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07 } },
+	},
+	/* RC2/RC5-based schemes 2 and 9 not supported */
+	{ /* aes128-CBC-PAD */
+		L_CIPHER_AES_CBC, 16, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02 } },
+	},
+	{ /* aes192-CBC-PAD */
+		L_CIPHER_AES_CBC, 24, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16 } },
+	},
+	{ /* aes256-CBC-PAD */
+		L_CIPHER_AES_CBC, 32, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a } },
+	},
+};
+
+static struct l_cipher *cipher_from_pkcs5_pbes2_params(
+						const uint8_t *pbes2_params,
+						size_t pbes2_params_len,
+						const char *password)
+{
+	uint8_t tag;
+	const uint8_t *kdf_sequence, *enc_sequence, *oid, *params,
+		*salt, *iter_count_buf, *key_len_buf, *prf_sequence;
+	size_t kdf_len, enc_len, params_len, salt_len, key_len, tmp_len;
+	unsigned int i, iter_count, pos;
+	enum l_checksum_type prf_alg = L_CHECKSUM_NONE;
+	const struct pkcs5_enc_alg_oid *enc_scheme = NULL;
+	uint8_t derived_key[64];
+	struct l_cipher *cipher;
+
+	/* RFC8018 section A.4 */
+
+	kdf_sequence = asn1_der_find_elem(pbes2_params, pbes2_params_len, 0,
+						&tag, &kdf_len);
+	if (!kdf_sequence || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	enc_sequence = asn1_der_find_elem(pbes2_params, pbes2_params_len, 1,
+						&tag, &enc_len);
+	if (!enc_sequence || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (asn1_der_find_elem(pbes2_params, pbes2_params_len, 2,
+						&tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section A.2 */
+
+	oid = asn1_der_find_elem(kdf_sequence, kdf_len, 0, &tag, &tmp_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	if (!asn1_oid_eq(&pkcs5_pbkdf2_oid, tmp_len, oid))
+		return NULL;
+
+	params = asn1_der_find_elem(kdf_sequence, kdf_len, 1,
+						&tag, &params_len);
+	if (!params || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (asn1_der_find_elem(kdf_sequence, kdf_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	salt = asn1_der_find_elem(params, params_len, 0, &tag, &salt_len);
+	if (!salt || tag != ASN1_ID_OCTET_STRING ||
+			salt_len < 1 || salt_len > 512)
+		return NULL;
+
+	iter_count_buf = asn1_der_find_elem(params, params_len, 1,
+						&tag, &tmp_len);
+	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
+			tmp_len < 1 || tmp_len > 4)
+		return NULL;
+
+	iter_count = 0;
+
+	while (tmp_len--)
+		iter_count = (iter_count << 8) | *iter_count_buf++;
+
+	pos = 2;
+	key_len_buf = asn1_der_find_elem(params, params_len, pos,
+						&tag, &tmp_len);
+	if (key_len_buf && tag == ASN1_ID_INTEGER) {
+		if (tmp_len != 1)
+			return NULL;
+
+		pos++;
+		key_len = 0;
+
+		while (tmp_len--)
+			key_len = (key_len << 8) | *key_len_buf++;
+	} else
+		key_len = 0;
+
+	prf_sequence = asn1_der_find_elem(params, params_len, pos,
+						&tag, &tmp_len);
+	if (prf_sequence && tag == ASN1_ID_SEQUENCE) {
+		pos++;
+
+		oid = asn1_der_find_elem(prf_sequence, tmp_len, 0,
+						&tag, &tmp_len);
+		if (!oid || tag != ASN1_ID_OID)
+			return NULL;
+
+		for (i = 0; i < L_ARRAY_SIZE(pkcs5_digest_alg_oids); i++)
+			if (asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
+						tmp_len, oid))
+				prf_alg = pkcs5_digest_alg_oids[i].type;
+
+		if (prf_alg == L_CHECKSUM_NONE)
+			return NULL;
+	} else
+		prf_alg = L_CHECKSUM_SHA1;
+
+	oid = asn1_der_find_elem(enc_sequence, enc_len, 0, &tag, &tmp_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	for (i = 0; i < L_ARRAY_SIZE(pkcs5_enc_alg_oids); i++) {
+		if (asn1_oid_eq(&pkcs5_enc_alg_oids[i].oid, tmp_len, oid)) {
+			enc_scheme = &pkcs5_enc_alg_oids[i];
+			break;
+		}
+	}
+
+	if (!enc_scheme)
+		return NULL;
+
+	params = asn1_der_find_elem(enc_sequence, enc_len, 1,
+						&tag, &params_len);
+	if (!params)
+		return NULL;
+
+	/* RFC8018 section B.2 */
+
+	/*
+	 * Since we don't support the RC2/RC5 PBES2 ciphers, our parameters
+	 * only have an obligatory OCTET STRING IV parameter and a fixed key
+	 * length.
+	 */
+	if (tag != ASN1_ID_OCTET_STRING || params_len != enc_scheme->iv_size)
+		return NULL;
+
+	if (key_len && enc_scheme->key_size != key_len)
+		return NULL;
+
+	key_len = enc_scheme->key_size;
+
+	if (asn1_der_find_elem(enc_sequence, enc_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section 6.2 */
+
+	if (!l_cert_pkcs5_pbkdf2(prf_alg, password, salt, salt_len, iter_count,
+					derived_key, key_len))
+		return NULL;
+
+	cipher = l_cipher_new(enc_scheme->cipher_type, derived_key, key_len);
+	if (cipher && !l_cipher_set_iv(cipher, params, enc_scheme->iv_size)) {
+		l_cipher_free(cipher);
+		cipher = NULL;
+	}
+
+	explicit_bzero(derived_key, 16);
+	return cipher;
+}
+
+static struct l_cipher *cipher_from_pkcs12_alg_id(
+				const struct pkcs12_encryption_oid *scheme,
+				const uint8_t *params, size_t params_len,
+				const char *password, bool *out_is_block)
+{
+	uint8_t tag;
+	const uint8_t *salt;
+	const uint8_t *iterations_data;
+	size_t salt_len;
+	size_t iterations_len;
+	unsigned int iterations;
+	uint8_t *key;
+	size_t key_len;
+	struct l_cipher *cipher;
+
+	/* Same parameters as in PKCS#5 */
+	salt = asn1_der_find_elem(params, params_len, 0, &tag, &salt_len);
+	if (!salt || tag != ASN1_ID_OCTET_STRING)
+		return NULL;
+
+	iterations_data = asn1_der_find_elem(params, params_len, 1,
+						&tag, &iterations_len);
+	if (!iterations_data || tag != ASN1_ID_INTEGER ||
+			iterations_len < 1 || iterations_len > 4)
+		return NULL;
+
+	for (iterations = 0; iterations_len; iterations_len--)
+		iterations = (iterations << 8) | *iterations_data++;
+
+	if (iterations < 1 || iterations > 8192)
+		return NULL;
+
+	if (iterations_data != params + params_len)
+		return NULL;
+
+	key_len = scheme->key_length;
+	key = cert_pkcs12_pbkdf(password, &pkcs12_sha1_hash, salt, salt_len,
+				iterations, 1, key_len);
+	if (!key)
+		return NULL;
+
+	if (scheme->copy_k1) {
+		/*
+		 * 2-Key 3DES is like L_CIPHER_DES3_EDE_CBC except the last
+		 * of the 3 8-byte keys is not generated using a KDF and
+		 * instead is a copy of the first key.  In other words
+		 * the first half of the 16-byte key material is appended
+		 * at the end to produce the 24 bytes for DES3_EDE_CBC.
+		 */
+		uint8_t *key2 = l_malloc(24);
+
+		memcpy(key2, key, 16);
+		memcpy(key2 + 16, key, 8);
+		explicit_bzero(key, key_len);
+		l_free(key);
+		key = key2;
+		key_len = 24;
+	}
+
+	cipher = l_cipher_new(scheme->cipher_type, key, key_len);
+	explicit_bzero(key, key_len);
+	l_free(key);
+
+	if (!cipher)
+		return NULL;
+
+	if (scheme->iv_length) {
+		uint8_t *iv = cert_pkcs12_pbkdf(password, &pkcs12_sha1_hash,
+						salt, salt_len, iterations, 2,
+						scheme->iv_length);
+
+		if (!iv || !l_cipher_set_iv(cipher, iv, scheme->iv_length)) {
+			l_cipher_free(cipher);
+			cipher = NULL;
+		}
+
+		if (iv)
+			explicit_bzero(iv, scheme->iv_length);
+
+		l_free(iv);
+	}
+
+	if (out_is_block)
+		*out_is_block = scheme->is_block;
+
+	return cipher;
+}
+
+struct l_cipher *cert_cipher_from_pkcs_alg_id(const uint8_t *id_asn1,
+						size_t id_asn1_len,
+						const char *password,
+						bool *out_is_block)
+{
+	uint8_t tag;
+	const uint8_t *oid, *params, *salt, *iter_count_buf;
+	size_t oid_len, params_len, tmp_len;
+	unsigned int i, iter_count;
+	const struct pkcs5_pbes1_encryption_oid *pbes1_scheme = NULL;
+	uint8_t derived_key[16];
+	struct l_cipher *cipher;
+
+	oid = asn1_der_find_elem(id_asn1, id_asn1_len, 0, &tag, &oid_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	params = asn1_der_find_elem(id_asn1, id_asn1_len, 1, &tag, &params_len);
+	if (!params || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (asn1_der_find_elem(id_asn1, id_asn1_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	if (asn1_oid_eq(&pkcs5_pbes2_oid, oid_len, oid)) {
+		if (out_is_block)
+			*out_is_block = true;
+
+		return cipher_from_pkcs5_pbes2_params(params, params_len,
+							password);
+	}
+
+	/* RFC8018 section A.3 */
+
+	for (i = 0; i < L_ARRAY_SIZE(pkcs5_pbes1_encryption_oids); i++) {
+		if (asn1_oid_eq(&pkcs5_pbes1_encryption_oids[i].oid,
+					oid_len, oid)) {
+			pbes1_scheme = &pkcs5_pbes1_encryption_oids[i];
+			break;
+		}
+	}
+
+	/* Check if this is a PKCS#12 OID */
+	if (!pbes1_scheme) {
+		for (i = 0; i < L_ARRAY_SIZE(pkcs12_encryption_oids); i++)
+			if (asn1_oid_eq(&pkcs12_encryption_oids[i].oid,
+					oid_len, oid))
+				return cipher_from_pkcs12_alg_id(
+						&pkcs12_encryption_oids[i],
+						params, params_len, password,
+						out_is_block);
+
+		return NULL;
+	}
+
+	salt = asn1_der_find_elem(params, params_len, 0, &tag, &tmp_len);
+	if (!salt || tag != ASN1_ID_OCTET_STRING || tmp_len != 8)
+		return NULL;
+
+	iter_count_buf = asn1_der_find_elem(params, params_len, 1,
+						&tag, &tmp_len);
+	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
+			tmp_len < 1 || tmp_len > 4)
+		return NULL;
+
+	iter_count = 0;
+
+	while (tmp_len--)
+		iter_count = (iter_count << 8) | *iter_count_buf++;
+
+	if (asn1_der_find_elem(params, params_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section 6.1 */
+
+	if (!l_cert_pkcs5_pbkdf1(pbes1_scheme->checksum_type, password,
+					salt, 8, iter_count, derived_key, 16))
+		return NULL;
+
+	cipher = l_cipher_new(pbes1_scheme->cipher_type, derived_key + 0, 8);
+	if (cipher && !l_cipher_set_iv(cipher, derived_key + 8, 8)) {
+		l_cipher_free(cipher);
+		cipher = NULL;
+	}
+
+	explicit_bzero(derived_key, 16);
+
+	if (out_is_block)
+		*out_is_block = true;
+
+	return cipher;
+}
diff --git a/ell/cert-private.h b/ell/cert-private.h
new file mode 100644
index 0000000..c1b2e01
--- /dev/null
+++ b/ell/cert-private.h
@@ -0,0 +1,42 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+struct asn1_oid;
+
+struct l_certchain *certchain_new_from_leaf(struct l_cert *leaf);
+void certchain_link_issuer(struct l_certchain *chain, struct l_cert *ca);
+
+const uint8_t *cert_get_extension(struct l_cert *cert,
+					const struct asn1_oid *ext_id,
+					bool *out_critical, size_t *out_len);
+
+struct l_key *cert_key_from_pkcs8_private_key_info(const uint8_t *der,
+							size_t der_len);
+struct l_key *cert_key_from_pkcs8_encrypted_private_key_info(const uint8_t *der,
+							size_t der_len,
+							const char *passphrase);
+struct l_key *cert_key_from_pkcs1_rsa_private_key(const uint8_t *der,
+							size_t der_len);
+
+struct cert_pkcs12_hash {
+	enum l_checksum_type alg;
+	unsigned int len;
+	unsigned int u;
+	unsigned int v;
+	struct asn1_oid oid;
+};
+
+uint8_t *cert_pkcs12_pbkdf(const char *password,
+				const struct cert_pkcs12_hash *hash,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iterations, uint8_t id,
+				size_t key_len);
+
+struct l_cipher *cert_cipher_from_pkcs_alg_id(const uint8_t *id_asn1,
+						size_t id_asn1_len,
+						const char *password,
+						bool *out_is_block);
diff --git a/ell/cert.c b/ell/cert.c
new file mode 100644
index 0000000..38bb01a
--- /dev/null
+++ b/ell/cert.c
@@ -0,0 +1,1954 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+
+#include "private.h"
+#include "useful.h"
+#include "key.h"
+#include "queue.h"
+#include "asn1-private.h"
+#include "cipher.h"
+#include "pem-private.h"
+#include "time.h"
+#include "time-private.h"
+#include "utf8.h"
+#include "cert.h"
+#include "cert-private.h"
+#include "tls.h"
+#include "tls-private.h"
+#include "missing.h"
+
+#define X509_CERTIFICATE_POS			0
+#define   X509_TBSCERTIFICATE_POS		  0
+#define     X509_TBSCERT_VERSION_POS		    ASN1_CONTEXT_EXPLICIT(0)
+#define     X509_TBSCERT_SERIAL_POS		    0
+#define     X509_TBSCERT_SIGNATURE_POS		    1
+#define       X509_ALGORITHM_ID_ALGORITHM_POS	      0
+#define       X509_ALGORITHM_ID_PARAMS_POS	      1
+#define     X509_TBSCERT_ISSUER_DN_POS		    2
+#define     X509_TBSCERT_VALIDITY_POS		    3
+#define     X509_TBSCERT_SUBJECT_DN_POS		    4
+#define     X509_TBSCERT_SUBJECT_KEY_POS	    5
+#define       X509_SUBJECT_KEY_ALGORITHM_POS	      0
+#define       X509_SUBJECT_KEY_VALUE_POS	      1
+#define     X509_TBSCERT_ISSUER_UID_POS		    ASN1_CONTEXT_IMPLICIT(1)
+#define     X509_TBSCERT_SUBJECT_UID_POS	    ASN1_CONTEXT_IMPLICIT(2)
+#define     X509_TBSCERT_EXTENSIONS_POS		    ASN1_CONTEXT_EXPLICIT(3)
+#define   X509_SIGNATURE_ALGORITHM_POS		  1
+#define   X509_SIGNATURE_VALUE_POS		  2
+
+struct l_cert {
+	enum l_cert_key_type pubkey_type;
+	struct l_cert *issuer;
+	struct l_cert *issued;
+	size_t asn1_len;
+	uint8_t asn1[];
+};
+
+struct l_certchain {
+	struct l_cert *leaf;	/* Bottom of the doubly-linked list */
+	struct l_cert *ca;	/* Top of the doubly-linked list */
+};
+
+static const struct pkcs1_encryption_oid {
+	enum l_cert_key_type key_type;
+	struct asn1_oid oid;
+} pkcs1_encryption_oids[] = {
+	{ /* rsaEncryption */
+		L_CERT_KEY_RSA,
+		{ .asn1_len = 9, .asn1 = {
+			0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }
+		},
+	},
+	{ /* ecPublicKey */
+		L_CERT_KEY_ECC,
+		{ .asn1_len = 7, .asn1 = {
+			0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 }
+		},
+	},
+};
+
+static bool cert_set_pubkey_type(struct l_cert *cert)
+{
+	const uint8_t *key_type;
+	size_t key_type_len;
+	int i;
+
+	key_type = asn1_der_find_elem_by_path(cert->asn1, cert->asn1_len,
+						ASN1_ID_OID, &key_type_len,
+						X509_CERTIFICATE_POS,
+						X509_TBSCERTIFICATE_POS,
+						X509_TBSCERT_SUBJECT_KEY_POS,
+						X509_SUBJECT_KEY_ALGORITHM_POS,
+						X509_ALGORITHM_ID_ALGORITHM_POS,
+						-1);
+	if (!key_type)
+		return false;
+
+	for (i = 0; i < (int) L_ARRAY_SIZE(pkcs1_encryption_oids); i++)
+		if (asn1_oid_eq(&pkcs1_encryption_oids[i].oid,
+					key_type_len, key_type))
+			break;
+
+	if (i == L_ARRAY_SIZE(pkcs1_encryption_oids))
+		cert->pubkey_type = L_CERT_KEY_UNKNOWN;
+	else
+		cert->pubkey_type = pkcs1_encryption_oids[i].key_type;
+
+	return true;
+}
+
+LIB_EXPORT struct l_cert *l_cert_new_from_der(const uint8_t *buf,
+						size_t buf_len)
+{
+	const uint8_t *seq = buf;
+	size_t seq_len = buf_len;
+	size_t content_len;
+	struct l_cert *cert;
+
+	/* Sanity check: outer element is a SEQUENCE */
+	if (seq_len-- < 1 || *seq++ != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	/* Sanity check: the SEQUENCE spans the whole buffer */
+	content_len = asn1_parse_definite_length(&seq, &seq_len);
+	if (content_len < 64 || content_len != seq_len)
+		return NULL;
+
+	/*
+	 * We could require the signature algorithm and the key algorithm
+	 * to be one of our supported types here but instead we only
+	 * require that when the user wants to verify this certificate or
+	 * get the public key respectively.
+	 */
+
+	cert = l_malloc(sizeof(struct l_cert) + buf_len);
+	cert->issuer = NULL;
+	cert->issued = NULL;
+	cert->asn1_len = buf_len;
+	memcpy(cert->asn1, buf, buf_len);
+
+	/* Sanity check: structure is correct up to the Public Key Algorithm */
+	if (!cert_set_pubkey_type(cert)) {
+		l_free(cert);
+		return NULL;
+	}
+
+	return cert;
+}
+
+LIB_EXPORT void l_cert_free(struct l_cert *cert)
+{
+	l_free(cert);
+}
+
+LIB_EXPORT const uint8_t *l_cert_get_der_data(struct l_cert *cert,
+						size_t *out_len)
+{
+	if (unlikely(!cert))
+		return NULL;
+
+	*out_len = cert->asn1_len;
+	return cert->asn1;
+}
+
+LIB_EXPORT const uint8_t *l_cert_get_dn(struct l_cert *cert, size_t *out_len)
+{
+	if (unlikely(!cert))
+		return NULL;
+
+	return asn1_der_find_elem_by_path(cert->asn1, cert->asn1_len,
+						ASN1_ID_SEQUENCE, out_len,
+						X509_CERTIFICATE_POS,
+						X509_TBSCERTIFICATE_POS,
+						X509_TBSCERT_SUBJECT_DN_POS,
+						-1);
+}
+
+static uint64_t cert_parse_asn1_time(const uint8_t *data, size_t len,
+					uint8_t tag)
+{
+	struct tm tm = {};
+	int tz_hours;
+	int tz_mins;
+	int century;
+	int msecs = 0;
+	time_t tt;
+	unsigned int i;
+
+	for (i = 0; i < len && i < 15; i++)
+		if (unlikely(!l_ascii_isdigit(data[i])))
+			break;
+
+	if (tag == ASN1_ID_UTCTIME) {
+		if (unlikely(!L_IN_SET(i, 10, 12)))
+			return L_TIME_INVALID;
+
+		century = 19;
+	} else if (tag == ASN1_ID_GENERALIZEDTIME) {
+		if (unlikely(!L_IN_SET(i, 10, 12, 14)))
+			return L_TIME_INVALID;
+
+		century = (data[0] - '0') * 10 + (data[1] - '0');
+		if (century < 19)
+				return L_TIME_INVALID;
+
+		if (len >= i + 4 && data[i] == '.') {
+			if (unlikely(!l_ascii_isdigit(data[i + 1]) ||
+						!l_ascii_isdigit(data[i + 2]) ||
+						!l_ascii_isdigit(data[i + 3])))
+				return L_TIME_INVALID;
+
+			i++;
+			msecs += (data[i++] - '0') * 100;
+			msecs += (data[i++] - '0') * 10;
+			msecs += (data[i++] - '0');
+		}
+
+		data += 2;
+		len -= 2;
+		i -= 2;
+	} else
+		return L_TIME_INVALID;
+
+	if (unlikely((len != i + 1 || data[i] != 'Z') &&
+			(len != i + 5 || (data[i] != '+' && data[i] != '-'))))
+		return L_TIME_INVALID;
+
+	tm.tm_year = (data[0] - '0') * 10 + (data[1] - '0');
+	tm.tm_mon = (data[2] - '0') * 10 + (data[3] - '0');
+	tm.tm_mday = (data[4] - '0') * 10 + (data[5] - '0');
+	tm.tm_hour = (data[6] - '0') * 10 + (data[7] - '0');
+
+	if (unlikely(tm.tm_mon < 1 || tm.tm_mon > 12 ||
+				tm.tm_mday < 1 || tm.tm_mday > 31 ||
+				tm.tm_hour > 23))
+		return L_TIME_INVALID;
+
+	if (i >= 10) {
+		tm.tm_min = (data[8] - '0') * 10 + (data[9] - '0');
+		if (unlikely(tm.tm_min > 59))
+			return L_TIME_INVALID;
+	}
+
+	if (i >= 12) {
+		tm.tm_sec = (data[10] - '0') * 10 + (data[11] - '0');
+		if (unlikely(tm.tm_sec > 59))
+			return L_TIME_INVALID;
+	}
+
+	/* RFC5280 Section 4.1.2.5.1 */
+	if (tag == ASN1_ID_UTCTIME && tm.tm_year < 50)
+		century = 20;
+
+	tm.tm_year += (century - 19) * 100;
+
+	/* Month number is 1-based in UTCTime and 0-based in struct tm */
+	tm.tm_mon -= 1;
+
+	tt = timegm(&tm);
+	if (unlikely(tt == (time_t) -1))
+		return L_TIME_INVALID;
+
+	if (len == i + 5) {
+		data += i;
+
+		for (i = 1; i < 5; i++)
+			if (unlikely(!l_ascii_isdigit(data[i])))
+				return L_TIME_INVALID;
+
+		tz_hours = (data[1] - '0') * 10 + (data[2] - '0');
+		tz_mins = (data[3] - '0') * 10 + (data[4] - '0');
+
+		if (unlikely(tz_hours > 14 || tz_mins > 59))
+			return L_TIME_INVALID;
+
+		/* The sign converts UTC to local so invert it */
+		if (data[0] == '+')
+			tt -= tz_hours * 3600 + tz_mins * 60;
+		else
+			tt += tz_hours * 3600 + tz_mins * 60;
+	}
+
+	return (uint64_t) tt * L_USEC_PER_SEC + msecs * L_USEC_PER_MSEC;
+}
+
+LIB_EXPORT bool l_cert_get_valid_times(struct l_cert *cert,
+					uint64_t *out_not_before_time,
+					uint64_t *out_not_after_time)
+{
+	const uint8_t *validity;
+	const uint8_t *not_before;
+	const uint8_t *not_after;
+	size_t seq_size;
+	size_t not_before_size;
+	size_t not_after_size;
+	uint8_t not_before_tag;
+	uint8_t not_after_tag;
+	uint64_t not_before_time = 0;
+	uint64_t not_after_time = 0;
+
+	if (unlikely(!cert))
+		return false;
+
+	validity = asn1_der_find_elem_by_path(cert->asn1, cert->asn1_len,
+						ASN1_ID_SEQUENCE, &seq_size,
+						X509_CERTIFICATE_POS,
+						X509_TBSCERTIFICATE_POS,
+						X509_TBSCERT_VALIDITY_POS,
+						-1);
+	if (unlikely(!validity))
+		return false;
+
+	not_before = asn1_der_find_elem(validity, seq_size, 0, &not_before_tag,
+					&not_before_size);
+	if (!not_before)
+		return false;
+
+	seq_size -= not_before_size + (not_before - validity);
+	validity = not_before + not_before_size;
+	not_after = asn1_der_find_elem(validity, seq_size, 0, &not_after_tag,
+					&not_after_size);
+	if (!not_after)
+		return false;
+
+	if (out_not_before_time) {
+		not_before_time = cert_parse_asn1_time(not_before,
+							not_before_size,
+							not_before_tag);
+		if (not_before_time == L_TIME_INVALID)
+			return false;
+	}
+
+	if (out_not_after_time) {
+		/*
+		 * RFC5280 Section 4.1.2.5: "To indicate that a certificate
+		 * has no well-defined expiration date, the notAfter SHOULD
+		 * be assigned the GeneralizedTime value of 99991231235959Z."
+		 */
+		if (not_after_size == 15 &&
+				!memcmp(not_after, "99991231235959Z", 15))
+			not_after_time = 0;
+		else {
+			not_after_time = cert_parse_asn1_time(not_after,
+								not_after_size,
+								not_after_tag);
+			if (not_after_time == L_TIME_INVALID)
+				return false;
+		}
+	}
+
+	if (out_not_before_time)
+		*out_not_before_time = not_before_time;
+
+	if (out_not_after_time)
+		*out_not_after_time = not_after_time;
+
+	return true;
+}
+
+const uint8_t *cert_get_extension(struct l_cert *cert,
+					const struct asn1_oid *ext_id,
+					bool *out_critical, size_t *out_len)
+{
+	const uint8_t *ext, *end;
+	size_t ext_len;
+
+	if (unlikely(!cert))
+		return NULL;
+
+	ext = asn1_der_find_elem_by_path(cert->asn1, cert->asn1_len,
+						ASN1_ID_SEQUENCE, &ext_len,
+						X509_CERTIFICATE_POS,
+						X509_TBSCERTIFICATE_POS,
+						X509_TBSCERT_EXTENSIONS_POS,
+						-1);
+	if (unlikely(!ext))
+		return NULL;
+
+	end = ext + ext_len;
+	while (ext < end) {
+		const uint8_t *seq, *oid, *data;
+		uint8_t tag;
+		size_t len, oid_len, data_len;
+		bool critical;
+
+		seq = asn1_der_find_elem(ext, end - ext, 0, &tag, &len);
+		if (unlikely(!seq || tag != ASN1_ID_SEQUENCE))
+			return false;
+
+		ext = seq + len;
+
+		oid = asn1_der_find_elem(seq, len, 0, &tag, &oid_len);
+		if (unlikely(!oid || tag != ASN1_ID_OID))
+			return false;
+
+		if (!asn1_oid_eq(ext_id, oid_len, oid))
+			continue;
+
+		data = asn1_der_find_elem(seq, len, 1, &tag, &data_len);
+		critical = false;
+
+		if (data && tag == ASN1_ID_BOOLEAN) {
+			if (data_len != 1)
+				return false;
+
+			critical = *data != 0;	/* Tolerate BER booleans */
+
+			data = asn1_der_find_elem(seq, len, 2, &tag, &data_len);
+		}
+
+		if (unlikely(!data || tag != ASN1_ID_OCTET_STRING))
+			return false;
+
+		if (out_critical)
+			*out_critical = critical;
+
+		if (out_len)
+			*out_len = data_len;
+
+		return data;
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert)
+{
+	if (unlikely(!cert))
+		return L_CERT_KEY_UNKNOWN;
+
+	return cert->pubkey_type;
+}
+
+/*
+ * Note: Returns a new l_key object to be freed by the caller.
+ */
+LIB_EXPORT struct l_key *l_cert_get_pubkey(struct l_cert *cert)
+{
+	if (unlikely(!cert))
+		return NULL;
+
+	/* Use kernel's ASN.1 certificate parser to find the key data for us */
+	switch (cert->pubkey_type) {
+	case L_CERT_KEY_RSA:
+		return l_key_new(L_KEY_RSA, cert->asn1, cert->asn1_len);
+	case L_CERT_KEY_ECC:
+		return l_key_new(L_KEY_ECC, cert->asn1, cert->asn1_len);
+	case L_CERT_KEY_UNKNOWN:
+		break;
+	}
+
+	return NULL;
+}
+
+/*
+ * Note: takes ownership of the certificate.  The certificate is
+ * assumed to be new and not linked into any certchain object.
+ */
+struct l_certchain *certchain_new_from_leaf(struct l_cert *leaf)
+{
+	struct l_certchain *chain;
+
+	chain = l_new(struct l_certchain, 1);
+	chain->leaf = leaf;
+	chain->ca = leaf;
+	return chain;
+}
+
+/*
+ * Note: takes ownership of the certificate.  The certificate is
+ * assumed to be new and not linked into any certchain object.
+ */
+void certchain_link_issuer(struct l_certchain *chain, struct l_cert *ca)
+{
+	ca->issued = chain->ca;
+	chain->ca->issuer = ca;
+	chain->ca = ca;
+}
+
+static struct l_cert *certchain_pop_ca(struct l_certchain *chain)
+{
+	struct l_cert *ca = chain->ca;
+
+	if (!ca)
+		return NULL;
+
+	if (ca->issued) {
+		chain->ca = ca->issued;
+		ca->issued->issuer = NULL;
+		ca->issued = NULL;
+	} else {
+		chain->ca = NULL;
+		chain->leaf = NULL;
+	}
+
+	return ca;
+}
+
+LIB_EXPORT void l_certchain_free(struct l_certchain *chain)
+{
+	while (chain && chain->ca)
+		l_cert_free(certchain_pop_ca(chain));
+
+	l_free(chain);
+}
+
+LIB_EXPORT struct l_cert *l_certchain_get_leaf(struct l_certchain *chain)
+{
+	if (unlikely(!chain))
+		return NULL;
+
+	return chain->leaf;
+}
+
+/*
+ * Call @cb for each certificate in the chain starting from the leaf
+ * certificate.  Stop if a call returns @true.
+ */
+LIB_EXPORT void l_certchain_walk_from_leaf(struct l_certchain *chain,
+						l_cert_walk_cb_t cb,
+						void *user_data)
+{
+	struct l_cert *cert;
+
+	if (unlikely(!chain))
+		return;
+
+	for (cert = chain->leaf; cert; cert = cert->issuer)
+		if (cb(cert, user_data))
+			break;
+}
+
+/*
+ * Call @cb for each certificate in the chain starting from the root
+ * certificate.  Stop if a call returns @true.
+ */
+LIB_EXPORT void l_certchain_walk_from_ca(struct l_certchain *chain,
+						l_cert_walk_cb_t cb,
+						void *user_data)
+{
+	struct l_cert *cert;
+
+	if (unlikely(!chain))
+		return;
+
+	for (cert = chain->ca; cert; cert = cert->issued)
+		if (cb(cert, user_data))
+			break;
+}
+
+static struct l_keyring *cert_set_to_keyring(struct l_cert **certs, char *error)
+{
+	struct l_keyring *ring;
+	int i = 1;
+	int count;
+
+	ring = l_keyring_new();
+	if (!ring)
+		return NULL;
+
+	for (count = 0; certs[count]; count++);
+
+	for (; *certs; certs++) {
+		struct l_cert *cert = *certs;
+		struct l_key *key = l_cert_get_pubkey(cert);
+
+		if (!key) {
+			sprintf(error, "Can't get public key from certificate "
+				"%i / %i in certificate set", i, count);
+			goto cleanup;
+		}
+
+		if (!l_keyring_link(ring, key)) {
+			l_key_free(key);
+			sprintf(error, "Can't link the public key from "
+				"certificate %i / %i to target keyring",
+				i, count);
+			goto cleanup;
+		}
+
+		l_key_free_norevoke(key);
+		i++;
+	}
+
+	return ring;
+
+cleanup:
+	l_keyring_free(ring);
+	return NULL;
+}
+
+static bool cert_is_in_set(struct l_cert *cert, struct l_cert **set)
+{
+	for (; *set; set++) {
+		struct l_cert *cert2 = *set;
+
+		if (cert == cert2)
+			return true;
+
+		if (cert->asn1_len == cert2->asn1_len &&
+				!memcmp(cert->asn1, cert2->asn1,
+					cert->asn1_len))
+			return true;
+	}
+
+	return false;
+}
+
+static struct l_cert **cert_set_filter_by_validity(struct l_queue *set,
+							uint64_t now,
+							int *out_total,
+							int *out_valid)
+{
+	const struct l_queue_entry *entry;
+	_auto_(l_free) struct l_cert **valid;
+
+	*out_total = l_queue_length(set);
+	*out_valid = 0;
+	valid = l_new(struct l_cert *, *out_total + 1);
+
+	for (entry = l_queue_get_entries(set); entry; entry = entry->next) {
+		struct l_cert *cert = entry->data;
+		uint64_t not_before;
+		uint64_t not_after;
+
+		if (!l_cert_get_valid_times(cert, &not_before, &not_after))
+			return NULL;
+
+		if (now < not_before || (not_after && now > not_after))
+			continue;
+
+		valid[(*out_valid)++] = cert;
+	}
+
+	return l_steal_ptr(valid);
+}
+
+static struct l_key *cert_try_link(struct l_cert *cert, struct l_keyring *ring)
+{
+	struct l_key *key;
+
+	key = l_key_new(L_KEY_RSA, cert->asn1, cert->asn1_len);
+	if (!key)
+		return NULL;
+
+	if (l_keyring_link(ring, key))
+		return key;
+
+	l_key_free(key);
+	return NULL;
+}
+
+#define RETURN_ERROR(msg, args...)	\
+	do {	\
+		if (error) {	\
+			*error = error_buf;	\
+			snprintf(error_buf, sizeof(error_buf), msg, ## args); \
+		}	\
+		return false;	\
+	} while (0)
+
+LIB_EXPORT bool l_certchain_verify(struct l_certchain *chain,
+					struct l_queue *ca_certs,
+					const char **error)
+{
+	struct l_keyring *ca_ring = NULL;
+	_auto_(l_keyring_free) struct l_keyring *verify_ring = NULL;
+	struct l_cert *cert;
+	struct l_key *prev_key = NULL;
+	int verified = 0;
+	int ca_match = 0;
+	int i;
+	static char error_buf[1024];
+	int total = 0;
+	uint64_t now;
+	_auto_(l_free) struct l_cert **ca_certs_valid = NULL;
+	int ca_certs_total_count = 0;
+	int ca_certs_valid_count = 0;
+
+	if (unlikely(!chain || !chain->leaf))
+		RETURN_ERROR("Chain empty");
+
+	for (cert = chain->ca; cert; cert = cert->issued, total++);
+
+	now = time_realtime_now();
+
+	for (cert = chain->ca, i = 0; cert; cert = cert->issued, i++) {
+		uint64_t not_before;
+		uint64_t not_after;
+		char time_str[100];
+
+		if (unlikely(!l_cert_get_valid_times(cert, &not_before,
+							&not_after)))
+			RETURN_ERROR("Can't parse validity in certificate "
+					"%i / %i", i + 1, total);
+
+		if (unlikely(now < not_before)) {
+			time_t t = not_before / L_USEC_PER_SEC;
+			struct tm *tm = gmtime(&t);
+
+			if (!tm || !strftime(time_str, sizeof(time_str),
+						"%a %F %T UTC", tm))
+				strcpy(time_str, "<error>");
+
+			RETURN_ERROR("Certificate %i / %i not valid before %s",
+					i + 1, total, time_str);
+		}
+
+		if (unlikely(not_after && now > not_after)) {
+			time_t t = not_after / L_USEC_PER_SEC;
+			struct tm *tm = gmtime(&t);
+
+			if (!tm || !strftime(time_str, sizeof(time_str),
+						"%a %F %T UTC", tm))
+				strcpy(time_str, "<error>");
+
+			RETURN_ERROR("Certificate %i / %i expired on %s",
+					i + 1, total, time_str);
+		}
+	}
+
+	if (ca_certs) {
+		if (unlikely(l_queue_isempty(ca_certs)))
+			RETURN_ERROR("No trusted CA certificates");
+
+		ca_certs_valid = cert_set_filter_by_validity(ca_certs, now,
+							&ca_certs_total_count,
+							&ca_certs_valid_count);
+		if (unlikely(!ca_certs_valid))
+			RETURN_ERROR("Can't parse validity in CA cert(s)");
+
+		if (unlikely(!ca_certs_valid_count))
+			RETURN_ERROR("All trusted CA certs are expired or "
+					"not-yet-valid");
+
+		for (cert = chain->ca, i = 0; cert; cert = cert->issued, i++)
+			if (cert_is_in_set(cert, ca_certs_valid)) {
+				ca_match = i + 1;
+				break;
+			}
+	}
+
+	verify_ring = l_keyring_new();
+	if (!verify_ring)
+		RETURN_ERROR("Can't create verify keyring");
+
+	cert = chain->ca;
+
+	/*
+	 * For TLS compatibility the trusted root CA certificate is
+	 * optionally present in the chain.
+	 *
+	 * RFC5246 7.4.2:
+	 * "Because certificate validation requires that root keys be
+	 * distributed independently, the self-signed certificate that
+	 * specifies the root certificate authority MAY be omitted from
+	 * the chain, under the assumption that the remote end must
+	 * already possess it in order to validate it in any case."
+	 *
+	 * The following is an optimization to skip verifying the root
+	 * cert in the chain if it is bitwise-identical to one of the
+	 * trusted CA certificates.  In that case we don't have to load
+	 * all of the trusted certificates into the kernel, link them
+	 * to @ca_ring or link @ca_ring to @verify_ring, instead we
+	 * load the first certificate into @verify_ring before we set
+	 * the restrict mode on it, same as when no trusted CAs are
+	 * provided.
+	 *
+	 * Note this happens to work around a kernel issue preventing
+	 * self-signed certificates missing the optional AKID extension
+	 * from being linked to a restricted keyring.  That issue would
+	 * have affected us if the trusted CA set included such
+	 * certificate and the same certificate was at the root of
+	 * the chain.
+	 */
+	if (ca_certs && !ca_match) {
+		ca_ring = cert_set_to_keyring(ca_certs_valid, error_buf);
+		if (!ca_ring) {
+			if (error)
+				*error = error_buf;
+			return false;
+		}
+
+		if (!l_keyring_link_nested(verify_ring, ca_ring)) {
+			l_keyring_free(ca_ring);
+			RETURN_ERROR("Can't link CA ring to verify ring");
+		}
+	} else
+		prev_key = cert_try_link(cert, verify_ring);
+
+	/*
+	 * The top, unverified certificate(s) are linked to the keyring and
+	 * we can now force verification of any new certificates linked.
+	 */
+	if (!l_keyring_restrict(verify_ring, L_KEYRING_RESTRICT_ASYM_CHAIN,
+				NULL)) {
+		l_key_free(prev_key);
+		l_keyring_free(ca_ring);
+		RETURN_ERROR("Can't restrict verify keyring");
+	}
+
+	if (ca_ring) {
+		/*
+		 * Verify the first certificate outside of the loop, then
+		 * revoke the trusted CAs' keys so that only the newly
+		 * verified cert's public key remains in the ring.
+		 */
+		prev_key = cert_try_link(cert, verify_ring);
+		l_keyring_free(ca_ring);
+	}
+
+	cert = cert->issued;
+
+	/* Verify the rest of the chain */
+	while (prev_key && cert) {
+		struct l_key *new_key = cert_try_link(cert, verify_ring);
+
+		/*
+		 * Free and revoke the issuer's public key again leaving only
+		 * new_key in verify_ring to ensure the next certificate linked
+		 * is signed by the owner of this key.
+		 */
+		l_key_free(prev_key);
+		prev_key = new_key;
+		cert = cert->issued;
+		verified++;
+	}
+
+	if (!prev_key) {
+		char str1[100];
+		char str2[100] = "";
+
+		if (ca_match)
+			snprintf(str1, sizeof(str1), "%i / %i matched a trusted"
+					" certificate, root not verified",
+					ca_match, total);
+		else
+			snprintf(str1, sizeof(str1), "root %sverified against "
+					"trusted CA(s)",
+					ca_certs && verified ? "" : "not ");
+
+		if (ca_certs && !ca_match && !verified &&
+				ca_certs_valid_count < ca_certs_total_count)
+			snprintf(str2, sizeof(str2), ", %i out of %i trused "
+					"CA(s) were expired or not-yet-valid",
+					ca_certs_total_count -
+					ca_certs_valid_count,
+					ca_certs_total_count);
+
+		RETURN_ERROR("Linking certificate %i / %i failed, %s%s",
+				verified + 1, total, str1, str2);
+	}
+
+	l_key_free(prev_key);
+	return true;
+}
+
+struct l_key *cert_key_from_pkcs8_private_key_info(const uint8_t *der,
+							size_t der_len)
+{
+	return l_key_new(L_KEY_RSA, der, der_len);
+}
+
+/*
+ * The passphrase, if given, must have been validated as UTF-8 unless the
+ * caller knows that PKCS#12 encryption algorithms are not used.
+ * Use l_utf8_validate.
+ */
+struct l_key *cert_key_from_pkcs8_encrypted_private_key_info(const uint8_t *der,
+							size_t der_len,
+							const char *passphrase)
+{
+	const uint8_t *key_info, *alg_id, *data;
+	uint8_t tag;
+	size_t key_info_len, alg_id_len, data_len, tmp_len;
+	struct l_cipher *alg;
+	uint8_t *decrypted;
+	struct l_key *pkey;
+	bool r;
+	bool is_block;
+	size_t decrypted_len;
+
+	/* Technically this is BER, not limited to DER */
+	key_info = asn1_der_find_elem(der, der_len, 0, &tag, &key_info_len);
+	if (!key_info || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	alg_id = asn1_der_find_elem(key_info, key_info_len, 0, &tag,
+					&alg_id_len);
+	if (!alg_id || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	data = asn1_der_find_elem(key_info, key_info_len, 1, &tag, &data_len);
+	if (!data || tag != ASN1_ID_OCTET_STRING || data_len < 8 ||
+			(data_len & 7) != 0)
+		return NULL;
+
+	if (asn1_der_find_elem(der, der_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	alg = cert_cipher_from_pkcs_alg_id(alg_id, alg_id_len, passphrase,
+						&is_block);
+	if (!alg)
+		return NULL;
+
+	decrypted = l_malloc(data_len);
+
+	r = l_cipher_decrypt(alg, data, decrypted, data_len);
+	l_cipher_free(alg);
+
+	if (!r) {
+		l_free(decrypted);
+		return NULL;
+	}
+
+	decrypted_len = data_len;
+
+	/*
+	 * For block ciphers strip padding as defined in RFC8018
+	 * (for PKCS#5 v1) or RFC1423 / RFC5652 (for v2).
+	 */
+	if (is_block) {
+		uint8_t pad = decrypted[data_len - 1];
+
+		pkey = NULL;
+
+		if (pad > data_len || pad > 16 || pad == 0)
+			goto cleanup;
+
+		if (!l_secure_memeq(decrypted + data_len - pad, pad - 1U, pad))
+			goto cleanup;
+
+		decrypted_len -= pad;
+	}
+
+	pkey = cert_key_from_pkcs8_private_key_info(decrypted, decrypted_len);
+
+cleanup:
+	explicit_bzero(decrypted, data_len);
+	l_free(decrypted);
+	return pkey;
+}
+
+struct l_key *cert_key_from_pkcs1_rsa_private_key(const uint8_t *der,
+							size_t der_len)
+{
+	const uint8_t *data;
+	uint8_t tag;
+	size_t data_len;
+	const uint8_t *key_data;
+	size_t key_data_len;
+	int i;
+	uint8_t *private_key;
+	size_t private_key_len;
+	uint8_t *one_asymmetric_key;
+	uint8_t *ptr;
+	struct l_key *pkey;
+
+	static const uint8_t version0[] = {
+		ASN1_ID_INTEGER, 0x01, 0x00
+	};
+	static const uint8_t pkcs1_rsa_encryption[] = {
+		ASN1_ID_SEQUENCE, 0x0d,
+		ASN1_ID_OID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+		0x01, 0x01, 0x01,
+		ASN1_ID_NULL, 0x00,
+	};
+
+	/*
+	 * Sanity check that it's a version 0 or 1 RSAPrivateKey structure
+	 * with the 8 integers.
+	 */
+	key_data = asn1_der_find_elem(der, der_len, 0, &tag, &key_data_len);
+	if (!key_data || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	data = asn1_der_find_elem(key_data, key_data_len, 0, &tag,
+					&data_len);
+	if (!data || tag != ASN1_ID_INTEGER || data_len != 1 ||
+			(data[0] != 0x00 && data[0] != 0x01))
+		return NULL;
+
+	for (i = 1; i < 9; i++) {
+		data = asn1_der_find_elem(key_data, key_data_len, i, &tag,
+						&data_len);
+		if (!data || tag != ASN1_ID_INTEGER || data_len < 1)
+			return NULL;
+	}
+
+	private_key = l_malloc(10 + der_len);
+	ptr = private_key;
+	*ptr++ = ASN1_ID_OCTET_STRING;
+	asn1_write_definite_length(&ptr, der_len);
+	memcpy(ptr, der, der_len);
+	ptr += der_len;
+	private_key_len = ptr - private_key;
+
+	one_asymmetric_key = l_malloc(32 + private_key_len);
+	ptr = one_asymmetric_key;
+	*ptr++ = ASN1_ID_SEQUENCE;
+	asn1_write_definite_length(&ptr, sizeof(version0) +
+					sizeof(pkcs1_rsa_encryption) +
+					private_key_len);
+	memcpy(ptr, version0, sizeof(version0));
+	ptr += sizeof(version0);
+	memcpy(ptr, pkcs1_rsa_encryption, sizeof(pkcs1_rsa_encryption));
+	ptr += sizeof(pkcs1_rsa_encryption);
+	memcpy(ptr, private_key, private_key_len);
+	ptr += private_key_len;
+	explicit_bzero(private_key, private_key_len);
+	l_free(private_key);
+
+	pkey = cert_key_from_pkcs8_private_key_info(one_asymmetric_key,
+						ptr - one_asymmetric_key);
+	explicit_bzero(one_asymmetric_key, ptr - one_asymmetric_key);
+	l_free(one_asymmetric_key);
+
+	return pkey;
+}
+
+static const uint8_t *cert_unpack_pkcs7_content_info(const uint8_t *container,
+					size_t container_len, int pos,
+					const struct asn1_oid *expected_oid,
+					struct asn1_oid *out_oid,
+					uint8_t *out_tag, size_t *out_len)
+{
+	const uint8_t *content_info;
+	size_t content_info_len;
+	const uint8_t *type;
+	size_t type_len;
+	const uint8_t *ret;
+	uint8_t tag;
+
+	if (!(content_info = asn1_der_find_elem(container, container_len, pos,
+						&tag, &content_info_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (!(type = asn1_der_find_elem(content_info, content_info_len, 0,
+					&tag, &type_len)) ||
+			tag != ASN1_ID_OID ||
+			type_len > sizeof(out_oid->asn1))
+		return NULL;
+
+	if (expected_oid && !asn1_oid_eq(expected_oid, type_len, type))
+		return NULL;
+
+	if (!(ret = asn1_der_find_elem(content_info, content_info_len,
+					ASN1_CONTEXT_EXPLICIT(0),
+					out_tag, out_len)) ||
+			ret + *out_len != content_info + content_info_len)
+		return NULL;
+
+	if (out_oid) {
+		out_oid->asn1_len = type_len;
+		memcpy(out_oid->asn1, type, type_len);
+	}
+
+	return ret;
+}
+
+/* RFC5652 Section 8 */
+static uint8_t *cert_decrypt_pkcs7_encrypted_data(const uint8_t *data,
+						size_t data_len,
+						const char *password,
+						struct asn1_oid *out_oid,
+						size_t *out_len)
+{
+	const uint8_t *version;
+	size_t version_len;
+	const uint8_t *encrypted_info;
+	size_t encrypted_info_len;
+	const uint8_t *type;
+	size_t type_len;
+	const uint8_t *alg_id;
+	size_t alg_id_len;
+	const uint8_t *encrypted;
+	size_t encrypted_len;
+	uint8_t tag;
+	struct l_cipher *alg;
+	uint8_t *plaintext;
+	int i;
+	bool ok;
+	bool is_block;
+
+	if (!(version = asn1_der_find_elem(data, data_len, 0, &tag,
+						&version_len)) ||
+			tag != ASN1_ID_INTEGER || version_len != 1 ||
+			!L_IN_SET(version[0], 0, 2))
+		return NULL;
+
+	if (!(encrypted_info = asn1_der_find_elem(data, data_len, 1, &tag,
+							&encrypted_info_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (!(type = asn1_der_find_elem(encrypted_info, encrypted_info_len, 0,
+					&tag, &type_len)) ||
+			tag != ASN1_ID_OID ||
+			type_len > sizeof(out_oid->asn1))
+		return NULL;
+
+	if (!(alg_id = asn1_der_find_elem(encrypted_info, encrypted_info_len, 1,
+					&tag, &alg_id_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	/* Not optional in our case, defined [0] IMPLICIT OCTET STRING */
+	if (!(encrypted = asn1_der_find_elem(encrypted_info, encrypted_info_len,
+						ASN1_CONTEXT_IMPLICIT(0),
+						&tag, &encrypted_len)) ||
+			tag != ASN1_ID(ASN1_CLASS_CONTEXT, 0, 0) ||
+			encrypted_len < 8)
+		return NULL;
+
+	if (!(alg = cert_cipher_from_pkcs_alg_id(alg_id, alg_id_len, password,
+							&is_block)))
+		return NULL;
+
+	plaintext = l_malloc(encrypted_len);
+	ok = l_cipher_decrypt(alg, encrypted, plaintext, encrypted_len);
+	l_cipher_free(alg);
+
+	if (!ok) {
+		l_free(plaintext);
+		return NULL;
+	}
+
+	if (is_block) {
+		bool ok = true;
+
+		/* Also validate the padding */
+		if (encrypted_len < plaintext[encrypted_len - 1] ||
+				plaintext[encrypted_len - 1] > 16) {
+			plaintext[encrypted_len - 1] = 1;
+			ok = false;
+		}
+
+		for (i = 1; i < plaintext[encrypted_len - 1]; i++)
+			if (plaintext[encrypted_len - 1 - i] !=
+					plaintext[encrypted_len - 1])
+				ok = false;
+
+		if (!ok) {
+			explicit_bzero(plaintext, encrypted_len);
+			l_free(plaintext);
+			return NULL;
+		}
+
+		encrypted_len -= plaintext[encrypted_len - 1];
+	}
+
+	if (out_oid) {
+		out_oid->asn1_len = type_len;
+		memcpy(out_oid->asn1, type, type_len);
+	}
+
+	*out_len = encrypted_len;
+	return plaintext;
+}
+
+/* RFC7292 Appendix A. */
+static const struct cert_pkcs12_hash pkcs12_mac_algs[] = {
+	{
+		L_CHECKSUM_MD5,    16, 16, 64,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0f, 0x02, 0x05 } }
+	},
+	{
+		L_CHECKSUM_SHA1,   20, 20, 64,
+		{ 5, { 0x2b, 0x0e, 0x03, 0x02, 0x1a } }
+	},
+	{
+		L_CHECKSUM_SHA224, 28, 28, 64,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 } }
+	},
+	{
+		L_CHECKSUM_SHA256, 32, 32, 64,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 } }
+	},
+	{
+		L_CHECKSUM_SHA384, 48, 48, 128,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 } }
+	},
+	{
+		L_CHECKSUM_SHA512, 64, 64, 128,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 } }
+	},
+	{
+		L_CHECKSUM_SHA512, 64, 28, 128,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05 } }
+	},
+	{
+		L_CHECKSUM_SHA512, 64, 32, 128,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06 } }
+	},
+};
+
+static const struct asn1_oid pkcs12_key_bag_oid = {
+	11, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x01 }
+};
+
+static const struct asn1_oid pkcs12_pkcs8_shrouded_key_bag_oid = {
+	11, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 }
+};
+
+static const struct asn1_oid pkcs12_cert_bag_oid = {
+	11, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x03 }
+};
+
+static const struct asn1_oid pkcs12_safe_contents_bag_oid = {
+	11, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x06 }
+};
+
+static const struct asn1_oid pkcs9_x509_certificate_oid = {
+	10, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x16, 0x01 }
+};
+
+/* RFC7292 Section 4.2.3 */
+static bool cert_parse_pkcs12_cert_bag(const uint8_t *data, size_t data_len,
+					struct l_certchain **out_certchain)
+{
+	const uint8_t *cert_bag;
+	size_t cert_bag_len;
+	const uint8_t *cert_id;
+	size_t cert_id_len;
+	const uint8_t *cert_value;
+	size_t cert_value_len;
+	uint8_t tag;
+	struct l_cert *cert;
+
+	if (!(cert_bag = asn1_der_find_elem(data, data_len, 0,
+						&tag, &cert_bag_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return false;
+
+	if (!(cert_id = asn1_der_find_elem(cert_bag, cert_bag_len, 0,
+						&tag, &cert_id_len)) ||
+			tag != ASN1_ID_OID)
+		return false;
+
+	if (!(cert_value = asn1_der_find_elem(cert_bag, cert_bag_len,
+						ASN1_CONTEXT_EXPLICIT(0),
+						&tag, &cert_value_len)) ||
+			tag != ASN1_ID_OCTET_STRING ||
+			cert_value + cert_value_len != data + data_len)
+		return false;
+
+	/* Skip unsupported certificate types */
+	if (!asn1_oid_eq(&pkcs9_x509_certificate_oid, cert_id_len, cert_id))
+		return true;
+
+	if (!(cert = l_cert_new_from_der(cert_value, cert_value_len)))
+		return false;
+
+	if (!*out_certchain)
+		*out_certchain = certchain_new_from_leaf(cert);
+	else
+		certchain_link_issuer(*out_certchain, cert);
+
+	return true;
+}
+
+static bool cert_parse_pkcs12_safe_contents(const uint8_t *data,
+					size_t data_len, const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey)
+{
+	const uint8_t *safe_contents;
+	size_t safe_contents_len;
+	uint8_t tag;
+
+	if (!(safe_contents = asn1_der_find_elem(data, data_len, 0, &tag,
+							&safe_contents_len)) ||
+			tag != ASN1_ID_SEQUENCE ||
+			data + data_len != safe_contents + safe_contents_len)
+		return false;
+
+	/* RFC7292 Section 4.2 */
+	while (safe_contents_len) {
+		const uint8_t *safe_bag;
+		size_t safe_bag_len;
+		const uint8_t *bag_id;
+		size_t bag_id_len;
+		const uint8_t *bag_value;
+		int bag_value_len;
+
+		/* RFC7292 Section 4.2 */
+		if (!(safe_bag = asn1_der_find_elem(safe_contents,
+							safe_contents_len, 0,
+							&tag, &safe_bag_len)) ||
+				tag != ASN1_ID_SEQUENCE)
+			return false;
+
+		if (!(bag_id = asn1_der_find_elem(safe_bag, safe_bag_len, 0,
+							&tag, &bag_id_len)) ||
+				tag != ASN1_ID_OID)
+			return false;
+
+		/*
+		 * The bagValue is EXPLICITly tagged but we don't want to
+		 * unpack the inner TLV yet so don't use asn1_der_find_elem.
+		 */
+		safe_bag_len -= bag_id + bag_id_len - safe_bag;
+		safe_bag = bag_id + bag_id_len;
+
+		if (safe_bag_len < 4)
+			return false;
+
+		tag = *safe_bag++;
+		safe_bag_len--;
+		bag_value_len = asn1_parse_definite_length(&safe_bag,
+								&safe_bag_len);
+		bag_value = safe_bag;
+
+		if (bag_value_len < 0 || bag_value_len > (int) safe_bag_len ||
+				tag != ASN1_ID(ASN1_CLASS_CONTEXT, 1, 0))
+			return false;
+
+		/* PKCS#9 attributes ignored */
+
+		safe_contents_len -= (safe_bag + safe_bag_len - safe_contents);
+		safe_contents = safe_bag + safe_bag_len;
+
+		if (asn1_oid_eq(&pkcs12_key_bag_oid, bag_id_len, bag_id)) {
+			if (!out_privkey || *out_privkey)
+				continue;
+
+			*out_privkey =
+				cert_key_from_pkcs8_private_key_info(bag_value,
+								bag_value_len);
+			if (!*out_privkey)
+				return false;
+		} else if (asn1_oid_eq(&pkcs12_pkcs8_shrouded_key_bag_oid,
+					bag_id_len, bag_id)) {
+			if (!out_privkey || *out_privkey)
+				continue;
+
+			*out_privkey =
+				cert_key_from_pkcs8_encrypted_private_key_info(
+								bag_value,
+								bag_value_len,
+								password);
+			if (!*out_privkey)
+				return false;
+		} else if (asn1_oid_eq(&pkcs12_cert_bag_oid,
+					bag_id_len, bag_id)) {
+			if (!out_certchain)
+				continue;
+
+			if (!cert_parse_pkcs12_cert_bag(bag_value, bag_value_len,
+							out_certchain))
+				return false;
+		} else if (asn1_oid_eq(&pkcs12_safe_contents_bag_oid,
+					bag_id_len, bag_id)) {
+			/* TODO: depth check */
+			if (!(cert_parse_pkcs12_safe_contents(bag_value,
+								bag_value_len,
+								password,
+								out_certchain,
+								out_privkey)))
+				return false;
+		}
+	}
+
+	return true;
+}
+
+static bool cert_check_pkcs12_integrity(const uint8_t *mac_data,
+					size_t mac_data_len,
+					const uint8_t *auth_safe,
+					size_t auth_safe_len,
+					const char *password)
+{
+	const uint8_t *mac;
+	size_t mac_len;
+	const uint8_t *mac_salt;
+	size_t mac_salt_len;
+	const uint8_t *iterations_data;
+	size_t iterations_len;
+	unsigned int iterations;
+	const uint8_t *digest_alg;
+	size_t digest_alg_len;
+	const uint8_t *digest;
+	size_t digest_len;
+	const uint8_t *alg_id;
+	size_t alg_id_len;
+	const struct cert_pkcs12_hash *mac_hash;
+	L_AUTO_FREE_VAR(uint8_t *, key) = NULL;
+	struct l_checksum *hmac;
+	uint8_t hmac_val[64];
+	uint8_t tag;
+	bool ok;
+	unsigned int i;
+
+	if (!(mac = asn1_der_find_elem(mac_data, mac_data_len, 0, &tag,
+					&mac_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return false;
+
+	if (!(mac_salt = asn1_der_find_elem(mac_data, mac_data_len, 1, &tag,
+						&mac_salt_len)) ||
+			tag != ASN1_ID_OCTET_STRING || mac_salt_len > 1024)
+		return false;
+
+	if (!(iterations_data = asn1_der_find_elem(mac_data, mac_data_len, 2,
+							&tag,
+							&iterations_len)) ||
+			tag != ASN1_ID_INTEGER || iterations_len > 4)
+		return false;
+
+	for (iterations = 0; iterations_len; iterations_len--)
+		iterations = (iterations << 8) | *iterations_data++;
+
+	if (iterations < 1 || iterations > 8192)
+		return false;
+
+	/* RFC2315 Section 9.4 */
+	if (!(digest_alg = asn1_der_find_elem(mac, mac_len, 0, &tag,
+						&digest_alg_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return false;
+
+	if (!(digest = asn1_der_find_elem(mac, mac_len, 1, &tag,
+						&digest_len)) ||
+			tag != ASN1_ID_OCTET_STRING)
+		return false;
+
+	if (!(alg_id = asn1_der_find_elem(digest_alg, digest_alg_len,
+						0, &tag, &alg_id_len)) ||
+			tag != ASN1_ID_OID)
+		return false;
+
+	/* This is going to be used for both the MAC and its key derivation */
+	for (i = 0; i < L_ARRAY_SIZE(pkcs12_mac_algs); i++)
+		if (asn1_oid_eq(&pkcs12_mac_algs[i].oid, alg_id_len, alg_id)) {
+			mac_hash = &pkcs12_mac_algs[i];
+			break;
+		}
+
+	if (i == L_ARRAY_SIZE(pkcs12_mac_algs) || digest_len != mac_hash->u)
+		return false;
+
+	if (!(key = cert_pkcs12_pbkdf(password, mac_hash,
+					mac_salt, mac_salt_len,
+					iterations, 3, mac_hash->u)))
+		return false;
+
+	hmac = l_checksum_new_hmac(mac_hash->alg, key, mac_hash->u);
+	explicit_bzero(key, mac_hash->u);
+
+	if (!hmac)
+		return false;
+
+	ok = l_checksum_update(hmac, auth_safe, auth_safe_len) &&
+		l_checksum_get_digest(hmac, hmac_val, mac_hash->len) > 0;
+	l_checksum_free(hmac);
+
+	if (!ok)
+		return false;
+
+	/*
+	 * SHA-512/224 and SHA-512/256 are not supported.  We can truncate the
+	 * output for key derivation but we can't do this inside the HMAC
+	 * algorithms based on these hashes.  We skip the MAC verification
+	 * if one of these hashes is used (identified by .u != .len)
+	 */
+	if (mac_hash->u != mac_hash->len)
+		return true;
+
+	return l_secure_memcmp(hmac_val, digest, digest_len) == 0;
+}
+
+/* RFC5652 Section 4 */
+static const struct asn1_oid pkcs7_data_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }
+};
+
+/* RFC5652 Section 8 */
+static const struct asn1_oid pkcs7_encrypted_data_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 }
+};
+
+static bool cert_parse_auth_safe_content(const uint8_t *data, size_t data_len,
+					uint8_t tag,
+					const struct asn1_oid *data_oid,
+					const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey)
+{
+	if (asn1_oid_eq(&pkcs7_encrypted_data_oid,
+			data_oid->asn1_len, data_oid->asn1)) {
+		uint8_t *plaintext;
+		size_t plaintext_len;
+		struct asn1_oid oid;
+		bool ok;
+
+		if (tag != ASN1_ID_SEQUENCE)
+			return false;
+
+		/*
+		 * This is same as PKCS#7 encryptedData but the ciphers
+		 * used are from PKCS#12 (broken but still the default
+		 * everywhere) and PKCS#5 (recommended).
+		 */
+		plaintext = cert_decrypt_pkcs7_encrypted_data(data,
+								data_len,
+								password, &oid,
+								&plaintext_len);
+		if (!plaintext)
+			return false;
+
+		/*
+		 * Since we only support PKCS#7 data and encryptedData
+		 * types, and there's no point re-encrypting
+		 * encryptedData, the plaintext must be a PKCS#7
+		 * "data".
+		 */
+		ok = asn1_oid_eq(&pkcs7_data_oid,
+					oid.asn1_len, oid.asn1) &&
+			cert_parse_pkcs12_safe_contents(plaintext,
+							plaintext_len,
+							password,
+							out_certchain,
+							out_privkey);
+		explicit_bzero(plaintext, plaintext_len);
+		l_free(plaintext);
+
+		if (!ok)
+			return false;
+	} else if (asn1_oid_eq(&pkcs7_data_oid,
+				data_oid->asn1_len, data_oid->asn1)) {
+		if (tag != ASN1_ID_OCTET_STRING)
+			return false;
+
+		if (!cert_parse_pkcs12_safe_contents(data, data_len,
+							password,
+							out_certchain,
+							out_privkey))
+			return false;
+	}
+	/* envelopedData support not needed */
+
+	return true;
+}
+
+static bool cert_parse_pkcs12_pfx(const uint8_t *ptr, size_t len,
+					const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey)
+{
+	const uint8_t *version;
+	size_t version_len;
+	const uint8_t *auth_safe;
+	size_t auth_safe_len;
+	const uint8_t *mac_data;
+	size_t mac_data_len;
+	const uint8_t *auth_safe_seq;
+	size_t auth_safe_seq_len;
+	uint8_t tag;
+	unsigned int i;
+	struct l_certchain *certchain = NULL;
+	struct l_key *privkey = NULL;
+
+	/* RFC7292 Section 4 */
+	if (!(version = asn1_der_find_elem(ptr, len, 0, &tag, &version_len)) ||
+			tag != ASN1_ID_INTEGER)
+		return false;
+
+	if (version_len != 1 || version[0] != 3)
+		return false;
+
+	/*
+	 * Since we only support the password-based integrity mode,  the
+	 * authSafe must be of PKCS#7 type "data" and not "signedData".
+	 */
+	if (!(auth_safe = cert_unpack_pkcs7_content_info(ptr, len, 1,
+							&pkcs7_data_oid, NULL,
+							&tag,
+							&auth_safe_len)) ||
+			tag != ASN1_ID_OCTET_STRING)
+		return false;
+
+	/*
+	 * openssl can generate PFX structures without macData not signed
+	 * with a public key so handle this case, otherwise the macData
+	 * would not be optional.
+	 */
+	if (auth_safe + auth_safe_len == ptr + len)
+		goto integrity_check_done;
+
+	if (!(mac_data = asn1_der_find_elem(ptr, len, 2, &tag,
+						&mac_data_len)) ||
+			tag != ASN1_ID_SEQUENCE)
+		return false;
+
+	if (!cert_check_pkcs12_integrity(mac_data, mac_data_len,
+						auth_safe, auth_safe_len,
+						password))
+		return false;
+
+integrity_check_done:
+	if (!(auth_safe_seq = asn1_der_find_elem(auth_safe, auth_safe_len, 0,
+						&tag, &auth_safe_seq_len)) ||
+			tag != ASN1_ID_SEQUENCE ||
+			auth_safe + auth_safe_len !=
+			auth_safe_seq + auth_safe_seq_len)
+		return false;
+
+	i = 0;
+	while (1) {
+		struct asn1_oid data_oid;
+		const uint8_t *data;
+		size_t data_len;
+
+		if (!(data = cert_unpack_pkcs7_content_info(auth_safe_seq,
+							auth_safe_seq_len, i++,
+							NULL, &data_oid, &tag,
+							&data_len)))
+			goto error;
+
+		if (!cert_parse_auth_safe_content(data, data_len, tag,
+							&data_oid, password,
+							out_certchain ?
+							&certchain : NULL,
+							out_privkey ?
+							&privkey : NULL))
+			goto error;
+
+		if (data + data_len == auth_safe_seq + auth_safe_seq_len)
+			break;
+	}
+
+	if (out_certchain)
+		*out_certchain = certchain;
+
+	if (out_privkey)
+		*out_privkey = privkey;
+
+	return true;
+
+error:
+	if (certchain)
+		l_certchain_free(certchain);
+
+	if (privkey)
+		l_key_free(privkey);
+
+	return false;
+}
+
+static int cert_try_load_der_format(const uint8_t *content, size_t content_len,
+					const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey,
+					bool *out_encrypted)
+{
+	const uint8_t *seq;
+	size_t seq_len;
+	size_t elem_len;
+	uint8_t tag;
+
+	if (!(seq = asn1_der_find_elem(content, content_len,
+					0, &tag, &seq_len)))
+		/* May not have been a DER file after all */
+		return -ENOMSG;
+
+	/*
+	 * See if the first sub-element is another sequence, then, out of
+	 * the formats that we currently support this can only be a raw
+	 * certificate.  If integer, it's going to be PKCS#12.  If we wish
+	 * to add any more formats we'll probably need to start guessing
+	 * from the filename suffix.
+	 */
+	if (!asn1_der_find_elem(seq, seq_len,0, &tag, &elem_len))
+		return -ENOMSG;
+
+	if (tag == ASN1_ID_SEQUENCE) {
+		if (out_certchain) {
+			struct l_cert *cert;
+
+			if (!(cert = l_cert_new_from_der(content, content_len)))
+				return -EINVAL;
+
+			*out_certchain = certchain_new_from_leaf(cert);
+
+			if (out_privkey)
+				*out_privkey = NULL;
+
+			if (out_encrypted)
+				*out_encrypted = false;
+
+			return 0;
+		}
+
+		return -EINVAL;
+	}
+
+	if (tag == ASN1_ID_INTEGER) {
+		/*
+		 * Since we don't support public key-protected PKCS#12
+		 * modes, we always require the password at least for the
+		 * integrity check.  Strictly speaking encryption may not
+		 * actually be in use.  We also don't support files with
+		 * different integrity and privacy passwords, they must
+		 * be identical if privacy is enabled.
+		 */
+		if (out_encrypted)
+			*out_encrypted = true;
+
+		if (!password) {
+			if (!out_encrypted)
+				return -EINVAL;
+
+			if (out_certchain)
+				*out_certchain = NULL;
+
+			if (out_privkey)
+				*out_privkey = NULL;
+
+			return 0;
+		}
+
+		if (cert_parse_pkcs12_pfx(seq, seq_len, password,
+						out_certchain, out_privkey))
+			return 0;
+		else
+			return -EINVAL;
+	}
+
+	return -ENOMSG;
+}
+
+static bool cert_try_load_pem_format(const char *content, size_t content_len,
+					const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey,
+					bool *out_encrypted)
+{
+	bool error = false;
+	bool done = false;
+	struct l_certchain *certchain = NULL;
+	struct l_key *privkey = NULL;
+	bool encrypted = false;
+
+	while (!done && !error && content_len) {
+		uint8_t *der;
+		size_t der_len;
+		char *type_label;
+		char *headers;
+		const char *endp;
+
+		if (!(der = pem_load_buffer(content, content_len, &type_label,
+						&der_len, &headers, &endp)))
+			break;
+
+		content_len -= endp - content;
+		content = endp;
+
+		if (out_certchain && L_IN_STRSET(type_label, "CERTIFICATE")) {
+			struct l_cert *cert;
+
+			if (!(cert = l_cert_new_from_der(der, der_len))) {
+				error = true;
+				goto next;
+			}
+
+			if (!certchain)
+				certchain = certchain_new_from_leaf(cert);
+			else
+				certchain_link_issuer(certchain, cert);
+
+			goto next;
+		}
+
+		/* Only use the first private key found */
+		if (out_privkey && !privkey && L_IN_STRSET(type_label,
+							"PRIVATE KEY",
+							"ENCRYPTED PRIVATE KEY",
+							"RSA PRIVATE KEY")) {
+			privkey = pem_load_private_key(der, der_len, type_label,
+							password, headers,
+							&encrypted);
+			if (!privkey) {
+				if (certchain) {
+					l_certchain_free(certchain);
+					certchain = NULL;
+				}
+
+				if (password)
+					error = true;
+				else
+					error = !encrypted || !out_encrypted;
+
+				done = true;
+			}
+
+			continue;
+		}
+
+		/* Cisco/gnutls-type PEM-encoded PKCS#12, probably rare */
+		if (L_IN_STRSET(type_label, "PKCS12")) {
+			encrypted = true;
+
+			if (!password) {
+				if (certchain && out_privkey) {
+					l_certchain_free(certchain);
+					certchain = NULL;
+				}
+
+				error = !out_encrypted;
+				done = true;
+				goto next;
+			}
+
+			error = !cert_parse_pkcs12_pfx(der, der_len, password,
+							out_certchain ?
+							&certchain : NULL,
+							out_privkey ?
+							&privkey : NULL);
+			goto next;
+		}
+
+next:
+		explicit_bzero(der, der_len);
+		l_free(der);
+		l_free(type_label);
+		l_free(headers);
+	}
+
+	if (error) {
+		if (certchain)
+			l_certchain_free(certchain);
+
+		if (privkey)
+			l_key_free(privkey);
+
+		return false;
+	}
+
+	if (out_certchain)
+		*out_certchain = certchain;
+
+	if (out_privkey)
+		*out_privkey = privkey;
+
+	if (out_encrypted)
+		*out_encrypted = encrypted;
+
+	return true;
+}
+
+/*
+ * Look at a file, try to detect which of the few X.509 certificate and/or
+ * private key container formats it uses and load any certificates in it as
+ * a certificate chain object, and load the first private key as an l_key
+ * object.
+ *
+ * Currently supported are:
+ *  PEM X.509 certificates
+ *  PEM PKCS#8 encrypted and unencrypted private keys
+ *  PEM legacy PKCS#1 encrypted and unencrypted private keys
+ *  Raw X.509 certificates (.cer, .der, .crt)
+ *  PKCS#12 certificates
+ *  PKCS#12 encrypted private keys
+ *
+ * The raw format contains exactly one certificate, PEM and PKCS#12 files
+ * can contain any combination of certificates and private keys.
+ *
+ * The password must have been validated as UTF-8 (use l_utf8_validate)
+ * unless the caller knows that no PKCS#12-defined encryption algorithm
+ * or MAC is used.
+ *
+ * Returns false on "unrecoverable" errors, and *out_certchain,
+ * *out_privkey and *out_encrypted (if provided) are not modified.  However
+ * when true is returned, *out_certchain and *out_privkey (if provided) may
+ * be set to NULL when nothing could be loaded only due to missing password,
+ * and *out_encrypted (if provided) will be set accordingly.  It will also
+ * be set on success to indicate whether the password was used.
+ * *out_certchain and/or *out_privkey will also be NULL if the container
+ * was loaded but there were no certificates or private keys in it.
+ */
+LIB_EXPORT bool l_cert_load_container_file(const char *filename,
+					const char *password,
+					struct l_certchain **out_certchain,
+					struct l_key **out_privkey,
+					bool *out_encrypted)
+{
+	struct pem_file_info file;
+	bool error = true;
+
+	if (unlikely(!filename))
+		return false;
+
+	if (pem_file_open(&file, filename) < 0)
+		return false;
+
+	if (file.st.st_size < 1)
+		goto close;
+
+	/* See if we have a DER sequence tag at the start */
+	if (file.data[0] == ASN1_ID_SEQUENCE) {
+		int err;
+
+		err = cert_try_load_der_format(file.data, file.st.st_size,
+						password, out_certchain,
+						out_privkey, out_encrypted);
+		if (!err) {
+			error = false;
+			goto close;
+		}
+
+		if (err != -ENOMSG)
+			goto close;
+
+		/* Try other formats */
+	}
+
+	/*
+	 * For backwards compatibility try the TLS internal struct Certificate
+	 * format as may be captured by PCAP (no future support guaranteed).
+	 */
+	if (out_certchain && !password && file.st.st_size &&
+			tls_parse_certificate_list(file.data, file.st.st_size,
+							out_certchain) == 0) {
+		error = false;
+
+		if (out_privkey)
+			*out_privkey = NULL;
+
+		if (out_encrypted)
+			*out_encrypted = false;
+
+		goto close;
+	}
+
+	/*
+	 * RFC 7486 allows whitespace and possibly other data before the
+	 * PEM "encapsulation boundary" so rather than check if the start
+	 * of the data looks like PEM, we fall back to this format if the
+	 * data didn't look like anything else we knew about.  Note this
+	 * succeeds for empty files and files without any PEM markers,
+	 * returning NULL chain and privkey.
+	 */
+	if (cert_try_load_pem_format((const char *) file.data, file.st.st_size,
+					password, out_certchain, out_privkey,
+					out_encrypted))
+		error = false;
+
+close:
+	pem_file_close(&file);
+	return !error;
+}
diff --git a/ell/cert.h b/ell/cert.h
new file mode 100644
index 0000000..78b2e54
--- /dev/null
+++ b/ell/cert.h
@@ -0,0 +1,71 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_CERT_H
+#define __ELL_CERT_H
+
+#include <stddef.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_queue;
+struct l_cert;
+struct l_certchain;
+
+enum l_cert_key_type {
+	L_CERT_KEY_RSA,
+	L_CERT_KEY_ECC,
+	L_CERT_KEY_UNKNOWN,
+};
+
+typedef bool (*l_cert_walk_cb_t)(struct l_cert *cert, void *user_data);
+
+struct l_cert *l_cert_new_from_der(const uint8_t *buf, size_t buf_len);
+void l_cert_free(struct l_cert *cert);
+DEFINE_CLEANUP_FUNC(l_cert_free);
+
+const uint8_t *l_cert_get_der_data(struct l_cert *cert, size_t *out_len);
+const uint8_t *l_cert_get_dn(struct l_cert *cert, size_t *out_len);
+bool l_cert_get_valid_times(struct l_cert *cert, uint64_t *out_not_before_time,
+				uint64_t *out_not_after_time);
+enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert);
+struct l_key *l_cert_get_pubkey(struct l_cert *cert);
+
+void l_certchain_free(struct l_certchain *chain);
+DEFINE_CLEANUP_FUNC(l_certchain_free);
+
+struct l_cert *l_certchain_get_leaf(struct l_certchain *chain);
+void l_certchain_walk_from_leaf(struct l_certchain *chain,
+				l_cert_walk_cb_t cb, void *user_data);
+void l_certchain_walk_from_ca(struct l_certchain *chain,
+				l_cert_walk_cb_t cb, void *user_data);
+
+bool l_certchain_verify(struct l_certchain *chain, struct l_queue *ca_certs,
+			const char **error);
+
+bool l_cert_load_container_file(const char *filename, const char *password,
+				struct l_certchain **out_certchain,
+				struct l_key **out_privkey,
+				bool *out_encrypted);
+
+bool l_cert_pkcs5_pbkdf1(enum l_checksum_type type, const char *password,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iter_count,
+				uint8_t *out_dk, size_t dk_len);
+bool l_cert_pkcs5_pbkdf2(enum l_checksum_type type, const char *password,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iter_count,
+				uint8_t *out_dk, size_t dk_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_CERT_H */
diff --git a/ell/checksum.c b/ell/checksum.c
new file mode 100644
index 0000000..74defdd
--- /dev/null
+++ b/ell/checksum.c
@@ -0,0 +1,445 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+#include "useful.h"
+#include "checksum.h"
+#include "private.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
+
+#ifndef AF_ALG
+#define AF_ALG	38
+#define PF_ALG	AF_ALG
+#endif
+
+struct sockaddr_alg {
+	__u16	salg_family;
+	__u8	salg_type[14];
+	__u32	salg_feat;
+	__u32	salg_mask;
+	__u8	salg_name[64];
+};
+
+/* Socket options */
+#define ALG_SET_KEY	1
+
+#else
+#include <linux/if_alg.h>
+#endif
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+struct checksum_info {
+	const char *name;
+	uint8_t digest_len;
+	bool supported;
+};
+
+static struct checksum_info checksum_algs[] = {
+	[L_CHECKSUM_MD4] = { .name = "md4", .digest_len = 16 },
+	[L_CHECKSUM_MD5] = { .name = "md5", .digest_len = 16 },
+	[L_CHECKSUM_SHA1] = { .name = "sha1", .digest_len = 20 },
+	[L_CHECKSUM_SHA256] = { .name = "sha256", .digest_len = 32 },
+	[L_CHECKSUM_SHA384] = { .name = "sha384", .digest_len = 48 },
+	[L_CHECKSUM_SHA512] = { .name = "sha512", .digest_len = 64 },
+};
+
+static struct checksum_info checksum_cmac_aes_alg =
+	{ .name = "cmac(aes)", .digest_len = 16 };
+
+static struct checksum_info checksum_hmac_algs[] = {
+	[L_CHECKSUM_MD4] = { .name = "hmac(md4)", .digest_len = 16 },
+	[L_CHECKSUM_MD5] = { .name = "hmac(md5)", .digest_len = 16 },
+	[L_CHECKSUM_SHA1] = { .name = "hmac(sha1)", .digest_len = 20 },
+	[L_CHECKSUM_SHA256] = { .name = "hmac(sha256)", .digest_len = 32 },
+	[L_CHECKSUM_SHA384] = { .name = "hmac(sha384)", .digest_len = 48 },
+	[L_CHECKSUM_SHA512] = { .name = "hmac(sha512)", .digest_len = 64 },
+};
+
+static const struct {
+	struct checksum_info *list;
+	size_t n;
+} checksum_info_table[] = {
+	{ checksum_algs, L_ARRAY_SIZE(checksum_algs) },
+	{ &checksum_cmac_aes_alg, 1 },
+	{ checksum_hmac_algs, L_ARRAY_SIZE(checksum_hmac_algs) },
+	{}
+};
+
+/**
+ * SECTION:checksum
+ * @short_description: Checksum handling
+ *
+ * Checksum handling
+ */
+
+#define is_valid_index(array, i) ((i) >= 0 && (i) < L_ARRAY_SIZE(array))
+
+/**
+ * l_checksum:
+ *
+ * Opaque object representing the checksum.
+ */
+struct l_checksum {
+	int sk;
+	const struct checksum_info *alg_info;
+};
+
+static int create_alg(const char *alg)
+{
+	struct sockaddr_alg salg;
+	int sk;
+
+	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -1;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, "hash");
+	strcpy((char *) salg.salg_name, alg);
+
+	if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
+		close(sk);
+		return -1;
+	}
+
+	return sk;
+}
+
+static struct l_checksum *checksum_new_common(const char *alg, int sockopt,
+						const void *data, size_t len,
+						struct checksum_info *info)
+{
+	struct l_checksum *checksum;
+	int fd;
+
+	fd = create_alg(alg);
+	if (fd < 0)
+		return NULL;
+
+	if (data) {
+		if (setsockopt(fd, SOL_ALG, sockopt, data, len) < 0) {
+			close(fd);
+			return NULL;
+		}
+	}
+
+	checksum = l_new(struct l_checksum, 1);
+	checksum->sk = accept4(fd, NULL, 0, SOCK_CLOEXEC);
+	close(fd);
+
+	if (checksum->sk < 0) {
+		l_free(checksum);
+		return NULL;
+	}
+
+	checksum->alg_info = info;
+	return checksum;
+}
+
+/**
+ * l_checksum_new:
+ * @type: checksum type
+ *
+ * Creates new #l_checksum, using the checksum algorithm @type.
+ *
+ * Returns: a newly allocated #l_checksum object.
+ **/
+LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
+{
+	if (!is_valid_index(checksum_algs, type) || !checksum_algs[type].name)
+		return NULL;
+
+	return checksum_new_common(checksum_algs[type].name, 0, NULL, 0,
+					&checksum_algs[type]);
+}
+
+LIB_EXPORT struct l_checksum *l_checksum_new_cmac_aes(const void *key,
+							size_t key_len)
+{
+	return checksum_new_common("cmac(aes)", ALG_SET_KEY, key, key_len,
+					&checksum_cmac_aes_alg);
+}
+
+LIB_EXPORT struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
+					const void *key, size_t key_len)
+{
+	if (!is_valid_index(checksum_hmac_algs, type) ||
+			!checksum_hmac_algs[type].name)
+		return NULL;
+
+	return checksum_new_common(checksum_hmac_algs[type].name,
+					ALG_SET_KEY, key, key_len,
+					&checksum_hmac_algs[type]);
+}
+
+/**
+ * l_checksum_clone:
+ * @checksum: parent checksum object
+ *
+ * Creates a new checksum with an independent copy of parent @checksum's
+ * state.  l_checksum_get_digest can then be called on the parent or the
+ * clone without affecting the state of the other object.
+ **/
+LIB_EXPORT struct l_checksum *l_checksum_clone(struct l_checksum *checksum)
+{
+	struct l_checksum *clone;
+
+	if (unlikely(!checksum))
+		return NULL;
+
+	clone = l_new(struct l_checksum, 1);
+	clone->sk = accept4(checksum->sk, NULL, 0, SOCK_CLOEXEC);
+
+	if (clone->sk < 0) {
+		l_free(clone);
+		return NULL;
+	}
+
+	clone->alg_info = checksum->alg_info;
+	return clone;
+}
+
+/**
+ * l_checksum_free:
+ * @checksum: checksum object
+ *
+ * Frees the memory allocated for @checksum.
+ **/
+LIB_EXPORT void l_checksum_free(struct l_checksum *checksum)
+{
+	if (unlikely(!checksum))
+		return;
+
+	close(checksum->sk);
+	l_free(checksum);
+}
+
+/**
+ * l_checksum_reset:
+ * @checksum: checksum object
+ *
+ * Resets the internal state of @checksum.
+ **/
+LIB_EXPORT void l_checksum_reset(struct l_checksum *checksum)
+{
+	if (unlikely(!checksum))
+		return;
+
+	send(checksum->sk, NULL, 0, 0);
+}
+
+/**
+ * l_checksum_update:
+ * @checksum: checksum object
+ * @data: data pointer
+ * @len: length of data
+ *
+ * Updates checksum from @data pointer with @len bytes.
+ *
+ * Returns: true if the operation succeeded, false otherwise.
+ **/
+LIB_EXPORT bool l_checksum_update(struct l_checksum *checksum,
+					const void *data, size_t len)
+{
+	ssize_t written;
+
+	if (unlikely(!checksum))
+		return false;
+
+	written = send(checksum->sk, data, len, MSG_MORE);
+	if (written < 0)
+		return false;
+
+	return true;
+}
+
+/**
+ * l_checksum_updatev:
+ * @checksum: checksum object
+ * @iov: iovec pointer
+ * @iov_len: Number of iovec entries
+ *
+ * This is a iovec based version of l_checksum_update; it updates the checksum
+ * based on contents of @iov and @iov_len.
+ *
+ * Returns: true if the operation succeeded, false otherwise.
+ **/
+LIB_EXPORT bool l_checksum_updatev(struct l_checksum *checksum,
+					const struct iovec *iov, size_t iov_len)
+{
+	struct msghdr msg;
+	ssize_t written;
+
+	if (unlikely(!checksum))
+		return false;
+
+	if (unlikely(!iov) || unlikely(!iov_len))
+		return false;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = (struct iovec *) iov;
+	msg.msg_iovlen = iov_len;
+
+	written = sendmsg(checksum->sk, &msg, MSG_MORE);
+	if (written < 0)
+		return false;
+
+	return true;
+}
+
+/**
+ * l_checksum_get_digest:
+ * @checksum: checksum object
+ * @digest: output data buffer
+ * @len: length of output buffer
+ *
+ * Writes the digest from @checksum as raw binary data into the provided
+ * buffer or, if the buffer is shorter, the initial @len bytes of the digest
+ * data.
+ *
+ * Returns: Number of bytes written, or negative value if an error occurred.
+ **/
+LIB_EXPORT ssize_t l_checksum_get_digest(struct l_checksum *checksum,
+						void *digest, size_t len)
+{
+	ssize_t result;
+
+	if (unlikely(!checksum))
+		return -EINVAL;
+
+	if (unlikely(!digest))
+		return -EFAULT;
+
+	if (unlikely(!len))
+		return -EINVAL;
+
+	result = recv(checksum->sk, digest, len, 0);
+	if (result < 0)
+		return -errno;
+
+	if ((size_t) result < len && result < checksum->alg_info->digest_len)
+		return -EIO;
+
+	return result;
+}
+
+/**
+ * l_checksum_get_string:
+ * @checksum: checksum object
+ *
+ * Gets the digest from @checksum as hex encoded string.
+ *
+ * Returns: a newly allocated hex string
+ **/
+LIB_EXPORT char *l_checksum_get_string(struct l_checksum *checksum)
+{
+	unsigned char digest[64];
+
+	if (unlikely(!checksum))
+		return NULL;
+
+	l_checksum_get_digest(checksum, digest, sizeof(digest));
+
+	return l_util_hexstring(digest, checksum->alg_info->digest_len);
+}
+
+static void init_supported()
+{
+	static bool initialized = false;
+	struct sockaddr_alg salg;
+	int sk;
+	unsigned int i, j;
+
+	if (likely(initialized))
+		return;
+
+	initialized = true;
+
+	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, "hash");
+
+	for (i = 0; checksum_info_table[i].list; i++)
+		for (j = 0; j < checksum_info_table[i].n; j++) {
+			struct checksum_info *info;
+
+			info = &checksum_info_table[i].list[j];
+			if (!info->name)
+				continue;
+
+			strcpy((char *) salg.salg_name, info->name);
+
+			if (bind(sk, (struct sockaddr *) &salg,
+						sizeof(salg)) < 0)
+				continue;
+
+			info->supported = true;
+		}
+
+	close(sk);
+}
+
+LIB_EXPORT bool l_checksum_is_supported(enum l_checksum_type type,
+							bool check_hmac)
+{
+	const struct checksum_info *list;
+
+	init_supported();
+
+	if (!check_hmac) {
+		if (!is_valid_index(checksum_algs, type))
+			return false;
+
+		list = checksum_algs;
+	} else {
+		if (!is_valid_index(checksum_hmac_algs, type))
+			return false;
+
+		list = checksum_hmac_algs;
+	}
+
+	return list[type].supported;
+}
+
+LIB_EXPORT bool l_checksum_cmac_aes_supported()
+{
+	init_supported();
+
+	return checksum_cmac_aes_alg.supported;
+}
+
+LIB_EXPORT ssize_t l_checksum_digest_length(enum l_checksum_type type)
+{
+	return is_valid_index(checksum_algs, type) ?
+		checksum_algs[type].digest_len : 0;
+}
diff --git a/ell/checksum.h b/ell/checksum.h
new file mode 100644
index 0000000..cc03b03
--- /dev/null
+++ b/ell/checksum.h
@@ -0,0 +1,60 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_CHECKSUM_H
+#define __ELL_CHECKSUM_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/uio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_checksum;
+
+enum l_checksum_type {
+	L_CHECKSUM_NONE,
+	L_CHECKSUM_MD4,
+	L_CHECKSUM_MD5,
+	L_CHECKSUM_SHA1,
+	L_CHECKSUM_SHA224,
+	L_CHECKSUM_SHA256,
+	L_CHECKSUM_SHA384,
+	L_CHECKSUM_SHA512,
+};
+
+struct l_checksum *l_checksum_new(enum l_checksum_type type);
+struct l_checksum *l_checksum_new_cmac_aes(const void *key, size_t key_len);
+struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
+					const void *key, size_t key_len);
+struct l_checksum *l_checksum_clone(struct l_checksum *checksum);
+
+void l_checksum_free(struct l_checksum *checksum);
+
+void l_checksum_reset(struct l_checksum *checksum);
+
+bool l_checksum_update(struct l_checksum *checksum,
+					const void *data, size_t len);
+bool l_checksum_updatev(struct l_checksum *checksum,
+					const struct iovec *iov,
+					size_t iov_len);
+ssize_t l_checksum_get_digest(struct l_checksum *checksum,
+					void *digest, size_t len);
+char *l_checksum_get_string(struct l_checksum *checksum);
+
+bool l_checksum_is_supported(enum l_checksum_type type, bool check_hmac);
+bool l_checksum_cmac_aes_supported(void);
+
+ssize_t l_checksum_digest_length(enum l_checksum_type type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_CHECKSUM_H */
diff --git a/ell/cipher.c b/ell/cipher.c
new file mode 100644
index 0000000..a1c0e25
--- /dev/null
+++ b/ell/cipher.c
@@ -0,0 +1,1102 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <alloca.h>
+
+#include "useful.h"
+#include "cipher.h"
+#include "private.h"
+#include "random.h"
+#include "missing.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
+
+#ifndef AF_ALG
+#define AF_ALG	38
+#define PF_ALG	AF_ALG
+#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];
+};
+
+/* Socket options */
+#define ALG_SET_KEY	1
+#define ALG_SET_IV	2
+#define ALG_SET_OP	3
+
+/* Operations */
+#define ALG_OP_DECRYPT	0
+#define ALG_OP_ENCRYPT	1
+#else
+#include <linux/if_alg.h>
+#endif
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+#ifndef ALG_SET_AEAD_ASSOCLEN
+#define ALG_SET_AEAD_ASSOCLEN	4
+#endif
+
+#ifndef ALG_SET_AEAD_AUTHSIZE
+#define ALG_SET_AEAD_AUTHSIZE	5
+#endif
+
+#define is_valid_type(type)  ((type) <= L_CIPHER_RC2_CBC)
+
+static uint32_t supported_ciphers;
+static uint32_t supported_aead_ciphers;
+
+struct l_cipher {
+	int type;
+	const struct local_impl *local;
+	union {
+		int sk;
+		void *local_data;
+	};
+};
+
+struct l_aead_cipher {
+	int type;
+	int sk;
+};
+
+struct local_impl {
+	void *(*cipher_new)(enum l_cipher_type,
+				const void *key, size_t key_length);
+	void (*cipher_free)(void *data);
+	bool (*set_iv)(void *data, const uint8_t *iv, size_t iv_length);
+	ssize_t (*operate)(void *data, __u32 operation,
+				const struct iovec *in, size_t in_cnt,
+				const struct iovec *out, size_t out_cnt);
+};
+
+static int create_alg(const char *alg_type, const char *alg_name,
+			const void *key, size_t key_length, size_t tag_length)
+{
+	struct sockaddr_alg salg;
+	int sk;
+	int ret;
+
+	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -errno;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, alg_type);
+	strcpy((char *) salg.salg_name, alg_name);
+
+	if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
+		close(sk);
+		return -1;
+	}
+
+	if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
+		close(sk);
+		return -1;
+	}
+
+	if (tag_length && setsockopt(sk, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL,
+					tag_length)) {
+		close(sk);
+		return -1;
+	}
+
+	ret = accept4(sk, NULL, 0, SOCK_CLOEXEC);
+	close(sk);
+
+	return ret;
+}
+
+static const char *cipher_type_to_name(enum l_cipher_type type)
+{
+	switch (type) {
+	case L_CIPHER_AES:
+		return "ecb(aes)";
+	case L_CIPHER_AES_CBC:
+		return "cbc(aes)";
+	case L_CIPHER_AES_CTR:
+		return "ctr(aes)";
+	case L_CIPHER_ARC4:
+		return NULL;
+	case L_CIPHER_DES:
+		return "ecb(des)";
+	case L_CIPHER_DES_CBC:
+		return "cbc(des)";
+	case L_CIPHER_DES3_EDE_CBC:
+		return "cbc(des3_ede)";
+	case L_CIPHER_RC2_CBC:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+static const struct local_impl local_arc4;
+static const struct local_impl local_rc2_cbc;
+
+static const struct local_impl *local_impl_ciphers[] = {
+	[L_CIPHER_ARC4] = &local_arc4,
+	[L_CIPHER_RC2_CBC] = &local_rc2_cbc,
+};
+
+#define HAVE_LOCAL_IMPLEMENTATION(type)			\
+	((type) < L_ARRAY_SIZE(local_impl_ciphers) &&	\
+	 local_impl_ciphers[(type)])
+
+LIB_EXPORT struct l_cipher *l_cipher_new(enum l_cipher_type type,
+						const void *key,
+						size_t key_length)
+{
+	struct l_cipher *cipher;
+	const char *alg_name;
+
+	if (unlikely(!key))
+		return NULL;
+
+	if (!is_valid_type(type))
+		return NULL;
+
+	cipher = l_new(struct l_cipher, 1);
+	cipher->type = type;
+	alg_name = cipher_type_to_name(type);
+
+	if (HAVE_LOCAL_IMPLEMENTATION(type)) {
+		cipher->local = local_impl_ciphers[type];
+		cipher->local_data = cipher->local->cipher_new(type,
+							key, key_length);
+
+		if (!cipher->local_data)
+			goto error_free;
+
+		return cipher;
+	}
+
+	cipher->sk = create_alg("skcipher", alg_name, key, key_length, 0);
+	if (cipher->sk < 0)
+		goto error_free;
+
+	return cipher;
+
+error_free:
+	l_free(cipher);
+	return NULL;
+}
+
+static const char *aead_cipher_type_to_name(enum l_aead_cipher_type type)
+{
+	switch (type) {
+	case L_AEAD_CIPHER_AES_CCM:
+		return "ccm(aes)";
+	case L_AEAD_CIPHER_AES_GCM:
+		return "gcm(aes)";
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT struct l_aead_cipher *l_aead_cipher_new(enum l_aead_cipher_type type,
+							const void *key,
+							size_t key_length,
+							size_t tag_length)
+{
+	struct l_aead_cipher *cipher;
+	const char *alg_name;
+
+	if (unlikely(!key))
+		return NULL;
+
+	if (type != L_AEAD_CIPHER_AES_CCM && type != L_AEAD_CIPHER_AES_GCM)
+		return NULL;
+
+	cipher = l_new(struct l_aead_cipher, 1);
+	cipher->type = type;
+	alg_name = aead_cipher_type_to_name(type);
+
+	cipher->sk = create_alg("aead", alg_name, key, key_length, tag_length);
+	if (cipher->sk >= 0)
+		return cipher;
+
+	l_free(cipher);
+	return NULL;
+}
+
+LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
+{
+	if (unlikely(!cipher))
+		return;
+
+	if (cipher->local)
+		cipher->local->cipher_free(cipher->local_data);
+	else
+		close(cipher->sk);
+
+	l_free(cipher);
+}
+
+LIB_EXPORT void l_aead_cipher_free(struct l_aead_cipher *cipher)
+{
+	if (unlikely(!cipher))
+		return;
+
+	close(cipher->sk);
+
+	l_free(cipher);
+}
+
+static ssize_t operate_cipher(int sk, __u32 operation,
+				const void *in, size_t in_len,
+				const void *ad, size_t ad_len,
+				const void *iv, size_t iv_len,
+				void *out, size_t out_len)
+{
+	char *c_msg_buf;
+	size_t c_msg_size;
+	struct msghdr msg;
+	struct cmsghdr *c_msg;
+	struct iovec iov[2];
+	ssize_t result;
+
+	c_msg_size = CMSG_SPACE(sizeof(operation));
+	c_msg_size += ad_len ? CMSG_SPACE(sizeof(uint32_t)) : 0;
+	c_msg_size += iv_len ?
+		CMSG_SPACE(sizeof(struct af_alg_iv) + iv_len) : 0;
+
+	c_msg_buf = alloca(c_msg_size);
+
+	memset(c_msg_buf, 0, c_msg_size);
+	memset(&msg, 0, sizeof(msg));
+
+	msg.msg_iov = iov;
+
+	msg.msg_control = c_msg_buf;
+	msg.msg_controllen = c_msg_size;
+
+	c_msg = CMSG_FIRSTHDR(&msg);
+	c_msg->cmsg_level = SOL_ALG;
+	c_msg->cmsg_type = ALG_SET_OP;
+	c_msg->cmsg_len = CMSG_LEN(sizeof(operation));
+	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
+
+	if (ad_len) {
+		uint32_t *ad_data;
+
+		c_msg = CMSG_NXTHDR(&msg, c_msg);
+		c_msg->cmsg_level = SOL_ALG;
+		c_msg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
+		c_msg->cmsg_len = CMSG_LEN(sizeof(*ad_data));
+		ad_data = (void *) CMSG_DATA(c_msg);
+		*ad_data = ad_len;
+
+		iov[0].iov_base = (void *) ad;
+		iov[0].iov_len = ad_len;
+
+		msg.msg_iovlen = 1;
+
+		if (in) {
+			iov[1].iov_base = (void *) in;
+			iov[1].iov_len = in_len;
+			msg.msg_iovlen = 2;
+		}
+	} else {
+		iov[0].iov_base = (void *) in;
+		iov[0].iov_len = in_len;
+		msg.msg_iovlen = 1;
+	}
+
+	if (iv_len) {
+		struct af_alg_iv *algiv;
+
+		c_msg = CMSG_NXTHDR(&msg, c_msg);
+		c_msg->cmsg_level = SOL_ALG;
+		c_msg->cmsg_type = ALG_SET_IV;
+		c_msg->cmsg_len = CMSG_LEN(sizeof(*algiv) + iv_len);
+
+		algiv = (void *)CMSG_DATA(c_msg);
+		algiv->ivlen = iv_len;
+		memcpy(algiv->iv, iv, iv_len);
+	}
+
+	result = sendmsg(sk, &msg, 0);
+	if (result < 0)
+		return -errno;
+
+	if (ad_len) {
+		/*
+		 * When AEAD additional data is passed to sendmsg() for
+		 * use in computing the tag, those bytes also appear at
+		 * the beginning of the encrypt or decrypt results.  Rather
+		 * than force the caller to pad their result buffer with
+		 * the correct number of bytes for the additional data,
+		 * the necessary space is allocated here and then the
+		 * duplicate AAD is discarded.
+		 */
+		iov[0].iov_base = l_malloc(ad_len);
+		iov[0].iov_len = ad_len;
+		iov[1].iov_base = (void *) out;
+		iov[1].iov_len = out_len;
+		msg.msg_iovlen = 2;
+
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+
+		result = recvmsg(sk, &msg, 0);
+
+		if (result >= (ssize_t) ad_len)
+			result -= ad_len;
+		else if (result > 0)
+			result = 0;
+
+		l_free(iov[0].iov_base);
+	} else {
+		result = read(sk, out, out_len);
+	}
+
+	if (result < 0)
+		return -errno;
+
+	return result;
+}
+
+static ssize_t operate_cipherv(int sk, __u32 operation,
+				const struct iovec *in, size_t in_cnt,
+				const struct iovec *out, size_t out_cnt)
+{
+	char *c_msg_buf;
+	size_t c_msg_size;
+	struct msghdr msg;
+	struct cmsghdr *c_msg;
+	ssize_t result;
+
+	c_msg_size = CMSG_SPACE(sizeof(operation));
+	c_msg_buf = alloca(c_msg_size);
+
+	memset(c_msg_buf, 0, c_msg_size);
+	memset(&msg, 0, sizeof(msg));
+
+	msg.msg_iov = (struct iovec *) in;
+	msg.msg_iovlen = in_cnt;
+
+	msg.msg_control = c_msg_buf;
+	msg.msg_controllen = c_msg_size;
+
+	c_msg = CMSG_FIRSTHDR(&msg);
+	c_msg->cmsg_level = SOL_ALG;
+	c_msg->cmsg_type = ALG_SET_OP;
+	c_msg->cmsg_len = CMSG_LEN(sizeof(operation));
+	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
+
+	result = sendmsg(sk, &msg, 0);
+	if (result < 0)
+		return -errno;
+
+	result = readv(sk, out, out_cnt);
+
+	if (result < 0)
+		return -errno;
+
+	return result;
+}
+
+LIB_EXPORT bool l_cipher_encrypt(struct l_cipher *cipher,
+					const void *in, void *out, size_t len)
+{
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	if (cipher->local) {
+		struct iovec in_iov = { (void *) in, len };
+		struct iovec out_iov = { out, len };
+
+		return cipher->local->operate(cipher->local_data,
+						ALG_OP_ENCRYPT,
+						&in_iov, 1, &out_iov, 1) >= 0;
+	}
+
+	return operate_cipher(cipher->sk, ALG_OP_ENCRYPT, in, len,
+				NULL, 0, NULL, 0, out, len) >= 0;
+}
+
+LIB_EXPORT bool l_cipher_encryptv(struct l_cipher *cipher,
+					const struct iovec *in, size_t in_cnt,
+					const struct iovec *out, size_t out_cnt)
+{
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	if (cipher->local)
+		return cipher->local->operate(cipher->local_data,
+						ALG_OP_ENCRYPT,
+						in, in_cnt, out, out_cnt) >= 0;
+
+	return operate_cipherv(cipher->sk, ALG_OP_ENCRYPT, in, in_cnt,
+				out, out_cnt) >= 0;
+}
+
+LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
+					const void *in, void *out, size_t len)
+{
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	if (cipher->local) {
+		struct iovec in_iov = { (void *) in, len };
+		struct iovec out_iov = { out, len };
+
+		return cipher->local->operate(cipher->local_data,
+						ALG_OP_DECRYPT,
+						&in_iov, 1, &out_iov, 1) >= 0;
+	}
+
+	return operate_cipher(cipher->sk, ALG_OP_DECRYPT, in, len,
+				NULL, 0, NULL, 0, out, len) >= 0;
+}
+
+LIB_EXPORT bool l_cipher_decryptv(struct l_cipher *cipher,
+					const struct iovec *in, size_t in_cnt,
+					const struct iovec *out, size_t out_cnt)
+{
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	if (cipher->local)
+		return cipher->local->operate(cipher->local_data,
+						ALG_OP_DECRYPT,
+						in, in_cnt, out, out_cnt) >= 0;
+
+	return operate_cipherv(cipher->sk, ALG_OP_DECRYPT, in, in_cnt,
+				out, out_cnt) >= 0;
+}
+
+LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
+				size_t iv_length)
+{
+	char c_msg_buf[CMSG_SPACE(4 + iv_length)];
+	struct msghdr msg;
+	struct cmsghdr *c_msg;
+	uint32_t len = iv_length;
+
+	if (unlikely(!cipher))
+		return false;
+
+	if (cipher->local) {
+		if (!cipher->local->set_iv)
+			return false;
+
+		return cipher->local->set_iv(cipher->local_data, iv, iv_length);
+	}
+
+	memset(&c_msg_buf, 0, sizeof(c_msg_buf));
+	memset(&msg, 0, sizeof(struct msghdr));
+
+	msg.msg_control = c_msg_buf;
+	msg.msg_controllen = sizeof(c_msg_buf);
+
+	c_msg = CMSG_FIRSTHDR(&msg);
+	c_msg->cmsg_level = SOL_ALG;
+	c_msg->cmsg_type = ALG_SET_IV;
+	c_msg->cmsg_len = CMSG_LEN(4 + iv_length);
+	memcpy(CMSG_DATA(c_msg) + 0, &len, 4);
+	memcpy(CMSG_DATA(c_msg) + 4, iv, iv_length);
+
+	msg.msg_iov = NULL;
+	msg.msg_iovlen = 0;
+
+	if (sendmsg(cipher->sk, &msg, MSG_MORE) < 0)
+		return false;
+
+	return true;
+}
+
+#define CCM_IV_SIZE 16
+
+static size_t l_aead_cipher_get_ivlen(struct l_aead_cipher *cipher)
+{
+	switch (cipher->type) {
+	case L_AEAD_CIPHER_AES_CCM:
+		return CCM_IV_SIZE;
+	case L_AEAD_CIPHER_AES_GCM:
+		return 12;
+	}
+
+	return 0;
+}
+
+/* RFC3610 Section 2.3 */
+static ssize_t build_ccm_iv(const void *nonce, uint8_t nonce_len,
+				uint8_t (*iv)[CCM_IV_SIZE])
+{
+	const size_t iv_overhead = 2;
+	int lprime = 15 - nonce_len - 1;
+
+	if (unlikely(nonce_len + iv_overhead > CCM_IV_SIZE || lprime > 7))
+		return -EINVAL;
+
+	(*iv)[0] = lprime;
+	memcpy(*iv + 1, nonce, nonce_len);
+	memset(*iv + 1 + nonce_len, 0, lprime + 1);
+
+	return CCM_IV_SIZE;
+}
+
+LIB_EXPORT bool l_aead_cipher_encrypt(struct l_aead_cipher *cipher,
+					const void *in, size_t in_len,
+					const void *ad, size_t ad_len,
+					const void *nonce, size_t nonce_len,
+					void *out, size_t out_len)
+{
+	uint8_t ccm_iv[CCM_IV_SIZE];
+	const uint8_t *iv;
+	ssize_t iv_len;
+
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in && !ad) || unlikely(!out))
+		return false;
+
+	if (unlikely(!in && in_len) || unlikely(!ad && ad_len))
+		return false;
+
+	if (cipher->type == L_AEAD_CIPHER_AES_CCM) {
+		iv_len = build_ccm_iv(nonce, nonce_len, &ccm_iv);
+		if (unlikely(iv_len < 0))
+			return false;
+
+		iv = ccm_iv;
+	} else {
+		if (unlikely(nonce_len != l_aead_cipher_get_ivlen(cipher)))
+			return false;
+
+		iv = nonce;
+		iv_len = nonce_len;
+	}
+
+	return operate_cipher(cipher->sk, ALG_OP_ENCRYPT, in, in_len,
+				ad, ad_len, iv, iv_len, out, out_len) ==
+			(ssize_t)out_len;
+}
+
+LIB_EXPORT bool l_aead_cipher_decrypt(struct l_aead_cipher *cipher,
+					const void *in, size_t in_len,
+					const void *ad, size_t ad_len,
+					const void *nonce, size_t nonce_len,
+					void *out, size_t out_len)
+{
+	uint8_t ccm_iv[CCM_IV_SIZE];
+	const uint8_t *iv;
+	ssize_t iv_len;
+
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	if (cipher->type == L_AEAD_CIPHER_AES_CCM) {
+		iv_len = build_ccm_iv(nonce, nonce_len, &ccm_iv);
+		if (unlikely(iv_len < 0))
+			return false;
+
+		iv = ccm_iv;
+	} else {
+		if (unlikely(nonce_len != l_aead_cipher_get_ivlen(cipher)))
+			return false;
+
+		iv = nonce;
+		iv_len = nonce_len;
+	}
+
+	return operate_cipher(cipher->sk, ALG_OP_DECRYPT, in, in_len,
+				ad, ad_len, iv, iv_len, out, out_len) ==
+			(ssize_t)out_len;
+}
+
+static void init_supported()
+{
+	static bool initialized = false;
+	struct sockaddr_alg salg;
+	int sk;
+	enum l_cipher_type c;
+	enum l_aead_cipher_type a;
+
+	if (likely(initialized))
+		return;
+
+	initialized = true;
+
+	for (c = 0; c < L_ARRAY_SIZE(local_impl_ciphers); c++)
+		if (HAVE_LOCAL_IMPLEMENTATION(c))
+			supported_ciphers |= 1 << c;
+
+	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, "skcipher");
+
+	for (c = L_CIPHER_AES; c <= L_CIPHER_DES3_EDE_CBC; c++) {
+		const char *name = cipher_type_to_name(c);
+
+		if (!name)
+			continue;
+		strcpy((char *) salg.salg_name, name);
+
+		if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0)
+			continue;
+
+		supported_ciphers |= 1 << c;
+	}
+
+	strcpy((char *) salg.salg_type, "aead");
+
+	for (a = L_AEAD_CIPHER_AES_CCM; a <= L_AEAD_CIPHER_AES_GCM; a++) {
+		strcpy((char *) salg.salg_name, aead_cipher_type_to_name(a));
+
+		if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0)
+			continue;
+
+		supported_aead_ciphers |= 1 << a;
+	}
+
+	close(sk);
+}
+
+LIB_EXPORT bool l_cipher_is_supported(enum l_cipher_type type)
+{
+	if (!is_valid_type(type))
+		return false;
+
+	init_supported();
+
+	return supported_ciphers & (1 << type);
+}
+
+LIB_EXPORT bool l_aead_cipher_is_supported(enum l_aead_cipher_type type)
+{
+	if (type != L_AEAD_CIPHER_AES_CCM && type != L_AEAD_CIPHER_AES_GCM)
+		return false;
+
+	init_supported();
+
+	return supported_aead_ciphers & (1 << type);
+}
+
+/* ARC4 implementation copyright (c) 2001 Niels Möller */
+
+static void arc4_set_key(uint8_t *S, const uint8_t *key, size_t key_length)
+{
+	unsigned int i;
+	uint8_t j;
+
+	for (i = 0; i < 256; i++)
+		S[i] = i;
+
+	for (i = j = 0; i < 256; i++) {
+		j += S[i] + key[i % key_length];
+		SWAP(S[i], S[j]);
+	}
+}
+
+struct arc4_state {
+	struct arc4_state_ctx {
+		uint8_t S[256];
+		uint8_t i;
+		uint8_t j;
+	} ctx[2];
+};
+
+static void *local_arc4_new(enum l_cipher_type type,
+				const void *key, size_t key_length)
+{
+	struct arc4_state *s;
+
+	if (unlikely(key_length == 0 || key_length > 256))
+		return NULL;
+
+	s = l_new(struct arc4_state, 1);
+	arc4_set_key(s->ctx[0].S, key, key_length);
+	s->ctx[1] = s->ctx[0];
+	return s;
+}
+
+static void local_arc4_free(void *data)
+{
+	explicit_bzero(data, sizeof(struct arc4_state));
+	l_free(data);
+}
+
+static ssize_t local_arc4_operate(void *data, __u32 operation,
+					const struct iovec *in, size_t in_cnt,
+					const struct iovec *out, size_t out_cnt)
+{
+	struct arc4_state *s = data;
+	struct iovec cur_in;
+	struct iovec cur_out;
+	struct arc4_state_ctx *ctx =
+		&s->ctx[operation == ALG_OP_ENCRYPT ? 1 : 0];
+
+	if (!in_cnt || !out_cnt)
+		return 0;
+
+	cur_in = *in;
+	cur_out = *out;
+
+	while (1) {
+		while (!cur_in.iov_len) {
+			cur_in = *in++;
+
+			if (!--in_cnt)
+				return 0;
+		}
+
+		while (!cur_out.iov_len) {
+			cur_out = *out++;
+
+			if (!--out_cnt)
+				return 0;
+		}
+
+		ctx->j += ctx->S[++ctx->i];
+		SWAP(ctx->S[ctx->i], ctx->S[ctx->j]);
+		*(uint8_t *) cur_out.iov_base++ =
+			*(uint8_t *) cur_in.iov_base++ ^
+			ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) & 0xff];
+		cur_in.iov_len--;
+		cur_out.iov_len--;
+	}
+}
+
+static const struct local_impl local_arc4 = {
+	local_arc4_new,
+	local_arc4_free,
+	NULL,
+	local_arc4_operate,
+};
+
+struct rc2_state {
+	union {
+		uint16_t xkey[64];
+		uint8_t xkey8[128];
+	};
+	struct rc2_state_ctx {
+		union {
+			uint16_t x[4];
+			uint64_t x64;
+		};
+	} ctx[2];
+};
+
+/* Simplified from the 1996 public-domain implementation */
+static void rc2_keyschedule(struct rc2_state *s,
+				const uint8_t *key, size_t key_len,
+				size_t bits)
+{
+	static const uint8_t permute[256] = {
+		217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
+		198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
+		 23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
+		189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
+		 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
+		 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
+		111,191, 14,218, 70,105,  7, 87, 39,242, 29,155,188,148, 67,  3,
+		248, 17,199,246,144,239, 62,231,  6,195,213, 47,200,102, 30,215,
+		  8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
+		150, 26,210,113, 90, 21, 73,116, 75,159,208, 94,  4, 24,164,236,
+		194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
+		153,124, 58,133, 35,184,180,122,252,  2, 54, 91, 37, 85,151, 49,
+		 45, 93,250,152,227,138,146,174,  5,223, 41, 16,103,108,186,201,
+		211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
+		 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
+		197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
+	};
+	uint8_t x;
+	unsigned int i;
+
+	memcpy(&s->xkey8, key, key_len);
+
+	/* Step 1: expand input key to 128 bytes */
+	x = s->xkey8[key_len - 1];
+
+	for (i = 0; key_len < 128; key_len++, i++)
+		s->xkey8[key_len] = x = permute[(x + s->xkey8[i]) & 255];
+
+	/* Step 2: reduce effective key size to "bits" */
+	key_len = (bits + 7) >> 3;
+	i = 128 - key_len;
+	s->xkey8[i] = x = permute[s->xkey8[i] & (255 >> (7 & -bits))];
+
+	while (i--)
+		s->xkey8[i] = x = permute[x ^ s->xkey8[i + key_len]];
+
+	/* Step 3: copy to xkey in little-endian order */
+	for (i = 0; i < 64; i++)
+		s->xkey[i] = L_CPU_TO_LE16(s->xkey[i]);
+}
+
+static uint64_t rc2_operate(struct rc2_state *s, uint64_t in, __u32 operation)
+{
+	int i;
+	union {
+		uint16_t x16[4];
+		uint64_t x64;
+	} x;
+
+	x.x64 = in;
+
+	if (operation == ALG_OP_ENCRYPT) {
+		const uint16_t *xkey = s->xkey;
+
+		for (i = 0; i < 16; i++) {
+			x.x16[0] += (x.x16[1] & ~x.x16[3]) +
+				(x.x16[2] & x.x16[3]) + *xkey++;
+			x.x16[0] = (x.x16[0] << 1) | (x.x16[0] >> 15);
+			x.x16[1] += (x.x16[2] & ~x.x16[0]) +
+				(x.x16[3] & x.x16[0]) + *xkey++;
+			x.x16[1] = (x.x16[1] << 2) | (x.x16[1] >> 14);
+			x.x16[2] += (x.x16[3] & ~x.x16[1]) +
+				(x.x16[0] & x.x16[1]) + *xkey++;
+			x.x16[2] = (x.x16[2] << 3) | (x.x16[2] >> 13);
+			x.x16[3] += (x.x16[0] & ~x.x16[2]) +
+				(x.x16[1] & x.x16[2]) + *xkey++;
+			x.x16[3] = (x.x16[3] << 5) | (x.x16[3] >> 11);
+
+			if (i == 4 || i == 10) {
+				x.x16[0] += s->xkey[x.x16[3] & 63];
+				x.x16[1] += s->xkey[x.x16[0] & 63];
+				x.x16[2] += s->xkey[x.x16[1] & 63];
+				x.x16[3] += s->xkey[x.x16[2] & 63];
+			}
+		}
+	} else {
+		const uint16_t *xkey = s->xkey + 63;
+
+		for (i = 0; i < 16; i++) {
+			x.x16[3] = (x.x16[3] << 11) | (x.x16[3] >> 5);
+			x.x16[3] -= (x.x16[0] & ~x.x16[2]) +
+				(x.x16[1] & x.x16[2]) + *xkey--;
+			x.x16[2] = (x.x16[2] << 13) | (x.x16[2] >> 3);
+			x.x16[2] -= (x.x16[3] & ~x.x16[1]) +
+				(x.x16[0] & x.x16[1]) + *xkey--;
+			x.x16[1] = (x.x16[1] << 14) | (x.x16[1] >> 2);
+			x.x16[1] -= (x.x16[2] & ~x.x16[0]) +
+				(x.x16[3] & x.x16[0]) + *xkey--;
+			x.x16[0] = (x.x16[0] << 15) | (x.x16[0] >> 1);
+			x.x16[0] -= (x.x16[1] & ~x.x16[3]) +
+				(x.x16[2] & x.x16[3]) + *xkey--;
+
+			if (i == 4 || i == 10) {
+				x.x16[3] -= s->xkey[x.x16[2] & 63];
+				x.x16[2] -= s->xkey[x.x16[1] & 63];
+				x.x16[1] -= s->xkey[x.x16[0] & 63];
+				x.x16[0] -= s->xkey[x.x16[3] & 63];
+			}
+		}
+	}
+
+	return x.x64;
+}
+
+static void *local_rc2_cbc_new(enum l_cipher_type type,
+				const void *key, size_t key_length)
+{
+	struct rc2_state *s;
+
+	if (unlikely(key_length == 0 || key_length > 128))
+		return NULL;
+
+	/*
+	 * The key length and the effective "strength" bits are separate
+	 * parameters but they match in our current use cases.
+	 */
+	s = l_new(struct rc2_state, 1);
+	rc2_keyschedule(s, key, key_length, key_length * 8);
+	return s;
+}
+
+static void local_rc2_cbc_free(void *data)
+{
+	explicit_bzero(data, sizeof(struct rc2_state));
+	l_free(data);
+}
+
+static bool local_rc2_cbc_set_iv(void *data,
+				const uint8_t *iv, size_t iv_length)
+{
+	struct rc2_state *s = data;
+
+	if (unlikely(iv_length != 8))
+		return false;
+
+	s->ctx[0].x[0] = l_get_le16(iv + 0);
+	s->ctx[0].x[1] = l_get_le16(iv + 2);
+	s->ctx[0].x[2] = l_get_le16(iv + 4);
+	s->ctx[0].x[3] = l_get_le16(iv + 6);
+	s->ctx[1].x64 = s->ctx[0].x64;
+	return true;
+}
+
+static ssize_t local_rc2_cbc_operate(void *data, __u32 operation,
+					const struct iovec *in, size_t in_cnt,
+					const struct iovec *out, size_t out_cnt)
+{
+	struct rc2_state *s = data;
+	struct iovec cur_in = {};
+	struct iovec cur_out = {};
+	struct rc2_state_ctx *ctx =
+		&s->ctx[operation == ALG_OP_ENCRYPT ? 1 : 0];
+
+#define CONSUME_IN(bytes, eof_ok)		\
+	cur_in.iov_len -= (bytes);		\
+	while (!cur_in.iov_len) {		\
+		if (!in_cnt) {			\
+			if (eof_ok)		\
+				break;		\
+			else			\
+				return -1;	\
+		}				\
+						\
+		cur_in = *in++;			\
+		in_cnt--;			\
+	}
+
+#define CONSUME_OUT(bytes)			\
+	cur_out.iov_len -= (bytes);		\
+	while (!cur_out.iov_len) {		\
+		if (!out_cnt)			\
+			return 0;		\
+						\
+		cur_out = *out++;		\
+		out_cnt--;			\
+	}
+
+	CONSUME_IN(0, true)
+	CONSUME_OUT(0)
+
+	while (cur_in.iov_len) {
+		union {
+			uint16_t x16[4];
+			uint64_t x64;
+		} inblk;
+
+		if (cur_in.iov_len >= 8) {
+#define CUR_IN16 (*(uint16_t **) &cur_in.iov_base)
+			inblk.x16[0] = l_get_le16(CUR_IN16++);
+			inblk.x16[1] = l_get_le16(CUR_IN16++);
+			inblk.x16[2] = l_get_le16(CUR_IN16++);
+			inblk.x16[3] = l_get_le16(CUR_IN16++);
+			CONSUME_IN(8, true)
+		} else {
+			inblk.x16[0] = *(uint8_t *) cur_in.iov_base++;
+			CONSUME_IN(1, false)
+			inblk.x16[0] |= (*(uint8_t *) cur_in.iov_base++) << 8;
+			CONSUME_IN(1, false)
+			inblk.x16[1] = *(uint8_t *) cur_in.iov_base++;
+			CONSUME_IN(1, false)
+			inblk.x16[1] |= (*(uint8_t *) cur_in.iov_base++) << 8;
+			CONSUME_IN(1, false)
+			inblk.x16[2] = *(uint8_t *) cur_in.iov_base++;
+			CONSUME_IN(1, false)
+			inblk.x16[2] |= (*(uint8_t *) cur_in.iov_base++) << 8;
+			CONSUME_IN(1, false)
+			inblk.x16[3] = *(uint8_t *) cur_in.iov_base++;
+			CONSUME_IN(1, false)
+			inblk.x16[3] |= (*(uint8_t *) cur_in.iov_base++) << 8;
+			CONSUME_IN(1, true)
+		}
+
+		if (operation == ALG_OP_ENCRYPT)
+			ctx->x64 = rc2_operate(s, inblk.x64 ^ ctx->x64,
+						operation);
+		else
+			ctx->x64 ^= rc2_operate(s, inblk.x64, operation);
+
+		if (cur_out.iov_len >= 8) {
+#define CUR_OUT16 (*(uint16_t **) &cur_out.iov_base)
+			l_put_le16(ctx->x[0], CUR_OUT16++);
+			l_put_le16(ctx->x[1], CUR_OUT16++);
+			l_put_le16(ctx->x[2], CUR_OUT16++);
+			l_put_le16(ctx->x[3], CUR_OUT16++);
+			CONSUME_OUT(8)
+		} else {
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[0];
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[0] >> 8;
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[1];
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[1] >> 8;
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[2];
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[2] >> 8;
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[3];
+			CONSUME_OUT(1)
+			*(uint8_t *) cur_out.iov_base++ = ctx->x[3] >> 8;
+			CONSUME_OUT(1)
+		}
+
+		/* Save ciphertext as IV for next CBC block */
+		if (operation == ALG_OP_DECRYPT)
+			ctx->x64 = inblk.x64;
+
+		inblk.x64 = 0;
+	}
+
+	return 0;
+}
+
+static const struct local_impl local_rc2_cbc = {
+	local_rc2_cbc_new,
+	local_rc2_cbc_free,
+	local_rc2_cbc_set_iv,
+	local_rc2_cbc_operate,
+};
diff --git a/ell/cipher.h b/ell/cipher.h
new file mode 100644
index 0000000..dc581a0
--- /dev/null
+++ b/ell/cipher.h
@@ -0,0 +1,80 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_CIPHER_H
+#define __ELL_CIPHER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_cipher;
+
+enum l_cipher_type {
+	L_CIPHER_AES = 0,
+	L_CIPHER_AES_CBC,
+	L_CIPHER_AES_CTR,
+	L_CIPHER_ARC4,
+	L_CIPHER_DES,
+	L_CIPHER_DES_CBC,
+	L_CIPHER_DES3_EDE_CBC,
+	L_CIPHER_RC2_CBC,
+};
+
+struct l_cipher *l_cipher_new(enum l_cipher_type type,
+				const void *key, size_t key_length);
+
+void l_cipher_free(struct l_cipher *cipher);
+
+bool l_cipher_encrypt(struct l_cipher *cipher,
+			const void *in, void *out, size_t len);
+bool l_cipher_encryptv(struct l_cipher *cipher,
+				const struct iovec *in, size_t in_cnt,
+				const struct iovec *out, size_t out_cnt);
+
+bool l_cipher_decrypt(struct l_cipher *cipher,
+			const void *in, void *out, size_t len);
+bool l_cipher_decryptv(struct l_cipher *cipher,
+				const struct iovec *in, size_t in_cnt,
+				const struct iovec *out, size_t out_cnt);
+
+bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
+			size_t iv_length);
+
+struct l_aead_cipher;
+
+enum l_aead_cipher_type {
+	L_AEAD_CIPHER_AES_CCM = 0,
+	L_AEAD_CIPHER_AES_GCM,
+};
+
+struct l_aead_cipher *l_aead_cipher_new(enum l_aead_cipher_type type,
+					const void *key, size_t key_length,
+					size_t tag_length);
+
+void l_aead_cipher_free(struct l_aead_cipher *cipher);
+
+bool l_aead_cipher_encrypt(struct l_aead_cipher *cipher,
+				const void *in, size_t in_len,
+				const void *ad, size_t ad_len,
+				const void *nonce, size_t nonce_len,
+				void *out, size_t out_len);
+
+bool l_aead_cipher_decrypt(struct l_aead_cipher *cipher,
+				const void *in, size_t in_len,
+				const void *ad, size_t ad_len,
+				const void *nonce, size_t nonce_len,
+				void *out, size_t out_len);
+
+bool l_cipher_is_supported(enum l_cipher_type type);
+bool l_aead_cipher_is_supported(enum l_aead_cipher_type type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_CIPHER_H */
diff --git a/ell/cleanup.h b/ell/cleanup.h
new file mode 100644
index 0000000..ac9f5a8
--- /dev/null
+++ b/ell/cleanup.h
@@ -0,0 +1,15 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2021  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#define __L_AUTODESTRUCT(func)				\
+	__attribute((cleanup(_l_ ## func ## _cleanup)))
+
+#define DEFINE_CLEANUP_FUNC(func)			\
+	inline __attribute__((always_inline))		\
+	void _l_ ## func ## _cleanup(void *p) { func(*(void **) p); }
diff --git a/ell/dbus-client.c b/ell/dbus-client.c
new file mode 100644
index 0000000..e29c6fa
--- /dev/null
+++ b/ell/dbus-client.c
@@ -0,0 +1,722 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ * Copyright (C) 2017  Codecoup
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dbus.h"
+#include "dbus-client.h"
+#include "queue.h"
+#include "useful.h"
+#include "private.h"
+
+struct l_dbus_client {
+	struct l_dbus *dbus;
+	unsigned int watch;
+	unsigned int added_watch;
+	unsigned int removed_watch;
+	char *service;
+	uint32_t objects_call;
+
+	l_dbus_watch_func_t connect_cb;
+	void *connect_cb_data;
+	l_dbus_destroy_func_t connect_cb_data_destroy;
+
+	l_dbus_watch_func_t disconnect_cb;
+	void *disconnect_cb_data;
+	l_dbus_destroy_func_t disconnect_cb_data_destroy;
+
+	l_dbus_client_ready_func_t ready_cb;
+	void *ready_cb_data;
+	l_dbus_destroy_func_t ready_cb_data_destroy;
+
+	l_dbus_client_proxy_func_t proxy_added_cb;
+	l_dbus_client_proxy_func_t proxy_removed_cb;
+	l_dbus_client_property_function_t properties_changed_cb;
+	void *proxy_cb_data;
+	l_dbus_destroy_func_t proxy_cb_data_destroy;
+
+	struct l_queue *proxies;
+};
+
+struct proxy_property {
+	char *name;
+	struct l_dbus_message *msg;
+};
+
+struct l_dbus_proxy {
+	struct l_dbus_client *client;
+	char *interface;
+	char *path;
+	uint32_t properties_watch;
+	bool ready;
+
+	struct l_queue *properties;
+	struct l_queue *pending_calls;
+};
+
+LIB_EXPORT const char *l_dbus_proxy_get_path(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return NULL;
+
+	return proxy->path;
+}
+
+LIB_EXPORT const char *l_dbus_proxy_get_interface(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return NULL;
+
+	return proxy->interface;
+}
+
+static bool property_match_by_name(const void *a, const void *b)
+{
+	const struct proxy_property *prop = a;
+	const char *name = b;
+
+	return !strcmp(prop->name, name);
+}
+
+static struct proxy_property *find_property(struct l_dbus_proxy *proxy,
+							const char *name)
+{
+	return l_queue_find(proxy->properties, property_match_by_name, name);
+}
+
+static struct proxy_property *get_property(struct l_dbus_proxy *proxy,
+							const char *name)
+{
+	struct proxy_property *prop;
+
+	prop = find_property(proxy, name);
+	if (prop)
+		return prop;
+
+	prop = l_new(struct proxy_property, 1);
+	prop->name = l_strdup(name);
+
+	l_queue_push_tail(proxy->properties, prop);
+
+	return prop;
+}
+
+LIB_EXPORT bool l_dbus_proxy_get_property(struct l_dbus_proxy *proxy,
+						const char *name,
+						const char *signature, ...)
+{
+	struct proxy_property *prop;
+	va_list args;
+	bool res;
+
+	if (unlikely(!proxy))
+		return false;
+
+	prop = find_property(proxy, name);
+	if (!prop)
+		return false;
+
+	va_start(args, signature);
+	res = l_dbus_message_get_arguments_valist(prop->msg, signature, args);
+	va_end(args);
+
+	return res;
+}
+
+static void property_free(void *data)
+{
+	struct proxy_property *prop = data;
+
+	if (prop->msg)
+		l_dbus_message_unref(prop->msg);
+
+	l_free(prop->name);
+	l_free(prop);
+}
+
+static void cancel_pending_calls(struct l_dbus_proxy *proxy)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(proxy->pending_calls); entry;
+							entry = entry->next) {
+		uint32_t call_id = L_PTR_TO_UINT(entry->data);
+
+		l_dbus_cancel(proxy->client->dbus, call_id);
+	}
+}
+
+static void dbus_proxy_destroy(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return;
+
+	if (proxy->properties_watch)
+		l_dbus_remove_signal_watch(proxy->client->dbus,
+						proxy->properties_watch);
+
+	cancel_pending_calls(proxy);
+	l_queue_destroy(proxy->pending_calls, NULL);
+	l_queue_destroy(proxy->properties, property_free);
+	l_free(proxy->interface);
+	l_free(proxy->path);
+	l_free(proxy);
+}
+
+struct method_call_request
+{
+	struct l_dbus_proxy *proxy;
+	uint32_t call_id;
+	l_dbus_message_func_t setup;
+	l_dbus_client_proxy_result_func_t result;
+	void *user_data;
+	l_dbus_destroy_func_t destroy;
+};
+
+static void method_call_request_free(void *user_data)
+{
+	struct method_call_request *req = user_data;
+
+	l_queue_remove(req->proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	if (req->destroy)
+		req->destroy(req->user_data);
+
+	l_free(req);
+}
+
+static void method_call_setup(struct l_dbus_message *message, void *user_data)
+{
+	struct method_call_request *req = user_data;
+
+	if (req->setup)
+		req->setup(message, req->user_data);
+	else
+		l_dbus_message_set_arguments(message, "");
+}
+
+static void method_call_reply(struct l_dbus_message *message, void *user_data)
+{
+	struct method_call_request *req = user_data;
+
+	if (req->result)
+		req->result(req->proxy, message, req->user_data);
+}
+
+LIB_EXPORT bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
+				l_dbus_client_proxy_result_func_t result,
+				void *user_data, l_dbus_destroy_func_t destroy,
+				const char *name, const char *signature, ...)
+{
+	struct l_dbus_client *client = proxy->client;
+	struct l_dbus_message_builder *builder;
+	struct method_call_request *req;
+	struct l_dbus_message *message;
+	struct proxy_property *prop;
+	va_list args;
+
+	if (unlikely(!proxy))
+		return false;
+
+	prop = find_property(proxy, name);
+	if (!prop)
+		return false;
+
+	if (strcmp(l_dbus_message_get_signature(prop->msg), signature))
+		return false;
+
+	message = l_dbus_message_new_method_call(client->dbus, client->service,
+						proxy->path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						"Set");
+	if (!message)
+		return false;
+
+	builder = l_dbus_message_builder_new(message);
+	if (!builder) {
+		l_dbus_message_unref(message);
+		return false;
+	}
+
+	l_dbus_message_builder_append_basic(builder, 's', proxy->interface);
+	l_dbus_message_builder_append_basic(builder, 's', name);
+
+	l_dbus_message_builder_enter_variant(builder, signature);
+
+	va_start(args, signature);
+	l_dbus_message_builder_append_from_valist(builder, signature, args);
+	va_end(args);
+
+	l_dbus_message_builder_leave_variant(builder);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	req = l_new(struct method_call_request, 1);
+	req->proxy = proxy;
+	req->result = result;
+	req->user_data = user_data;
+	req->destroy = destroy;
+
+	req->call_id = l_dbus_send_with_reply(client->dbus, message,
+						method_call_reply, req,
+						method_call_request_free);
+	if (!req->call_id) {
+		l_free(req);
+		return false;
+	}
+
+	l_queue_push_tail(proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	return true;
+}
+
+LIB_EXPORT uint32_t l_dbus_proxy_method_call(struct l_dbus_proxy *proxy,
+					const char *method,
+					l_dbus_message_func_t setup,
+					l_dbus_client_proxy_result_func_t reply,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	struct method_call_request *req;
+
+	if (unlikely(!proxy))
+		return 0;
+
+	req = l_new(struct method_call_request, 1);
+	req->proxy = proxy;
+	req->setup = setup;
+	req->result = reply;
+	req->user_data = user_data;
+	req->destroy = destroy;
+
+	req->call_id = l_dbus_method_call(proxy->client->dbus,
+						proxy->client->service,
+						proxy->path, proxy->interface,
+						method, method_call_setup,
+						method_call_reply, req,
+						method_call_request_free);
+	if (!req->call_id) {
+		l_free(req);
+		return 0;
+	}
+
+	l_queue_push_tail(proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	return req->call_id;
+}
+
+static void proxy_update_property(struct l_dbus_proxy *proxy,
+					const char *name,
+					struct l_dbus_message_iter *property)
+{
+	struct l_dbus_message_builder *builder;
+	struct proxy_property *prop = get_property(proxy, name);
+
+	l_dbus_message_unref(prop->msg);
+
+	if (!property) {
+		prop->msg = NULL;
+		goto done;
+	}
+
+	prop->msg = l_dbus_message_new_signal(proxy->client->dbus, proxy->path,
+							proxy->interface, name);
+	if (!prop->msg)
+		return;
+
+	builder = l_dbus_message_builder_new(prop->msg);
+	l_dbus_message_builder_append_from_iter(builder, property);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+done:
+	if (proxy->client->properties_changed_cb && proxy->ready)
+		proxy->client->properties_changed_cb(proxy, name, prop->msg,
+					proxy->client->proxy_cb_data);
+}
+
+static void proxy_invalidate_properties(struct l_dbus_proxy *proxy,
+					struct l_dbus_message_iter* props)
+{
+	const char *name;
+
+	while (l_dbus_message_iter_next_entry(props, &name))
+		proxy_update_property(proxy, name, NULL);
+}
+
+static void proxy_update_properties(struct l_dbus_proxy *proxy,
+					struct l_dbus_message_iter* props)
+{
+	struct l_dbus_message_iter variant;
+	const char *name;
+
+	while (l_dbus_message_iter_next_entry(props, &name, &variant))
+		proxy_update_property(proxy, name, &variant);
+}
+
+static void properties_changed_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_proxy *proxy = user_data;
+	const char *interface;
+	struct l_dbus_message_iter changed;
+	struct l_dbus_message_iter invalidated;
+
+	if (!l_dbus_message_get_arguments(message, "sa{sv}as", &interface,
+							&changed, &invalidated))
+		return;
+
+	proxy_update_properties(proxy, &changed);
+	proxy_invalidate_properties(proxy, &invalidated);
+}
+
+static struct l_dbus_proxy *dbus_proxy_new(struct l_dbus_client *client,
+					const char *path, const char *interface)
+{
+	struct l_dbus_proxy *proxy = l_new(struct l_dbus_proxy, 1);
+
+	proxy->properties_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						"PropertiesChanged",
+						L_DBUS_MATCH_ARGUMENT(0),
+						interface, L_DBUS_MATCH_NONE,
+						properties_changed_callback,
+						proxy);
+	if (!proxy->properties_watch) {
+		l_free(proxy);
+		return NULL;
+	}
+
+	proxy->client = client;
+	proxy->interface = l_strdup(interface);
+	proxy->path = l_strdup(path);
+	proxy->properties = l_queue_new();
+	proxy->pending_calls = l_queue_new();
+
+	l_queue_push_tail(client->proxies, proxy);
+
+	return proxy;
+}
+
+static bool is_ignorable(const char *interface)
+{
+	static const struct {
+		const char *interface;
+	} interfaces_to_ignore[] = {
+		{ L_DBUS_INTERFACE_OBJECT_MANAGER },
+		{ L_DBUS_INTERFACE_INTROSPECTABLE },
+		{ L_DBUS_INTERFACE_PROPERTIES },
+	};
+	size_t i;
+
+	for (i = 0; i < L_ARRAY_SIZE(interfaces_to_ignore); i++)
+		if (!strcmp(interfaces_to_ignore[i].interface, interface))
+			return true;
+
+	return false;
+}
+
+static struct l_dbus_proxy *find_proxy(struct l_dbus_client *client,
+					const char *path, const char *interface)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(client->proxies); entry;
+							entry = entry->next) {
+		struct l_dbus_proxy *proxy = entry->data;
+
+		if (!strcmp(proxy->interface, interface) &&
+						!strcmp(proxy->path, path))
+			return proxy;
+	}
+
+	return NULL;
+}
+
+static void parse_interface(struct l_dbus_client *client, const char *path,
+					const char *interface,
+					struct l_dbus_message_iter *properties)
+{
+	struct l_dbus_proxy *proxy;
+
+	if (is_ignorable(interface))
+		return;
+
+	proxy = find_proxy(client, path, interface);
+	if (!proxy)
+		proxy = dbus_proxy_new(client, path, interface);
+
+	if (!proxy)
+		return;
+
+	proxy_update_properties(proxy, properties);
+
+	if (!proxy->ready) {
+		proxy->ready = true;
+
+		if (client->proxy_added_cb)
+			client->proxy_added_cb(proxy, client->proxy_cb_data);
+	}
+}
+
+static void parse_object(struct l_dbus_client *client, const char *path,
+					struct l_dbus_message_iter *object)
+{
+	const char *interface;
+	struct l_dbus_message_iter properties;
+
+	if (!path)
+		return;
+
+	while (l_dbus_message_iter_next_entry(object, &interface, &properties))
+		parse_interface(client, path, interface, &properties);
+}
+
+static void interfaces_added_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter object;
+	const char *path;
+
+	if (!l_dbus_message_get_arguments(message, "oa{sa{sv}}", &path,
+								&object))
+		return;
+
+	parse_object(client, path, &object);
+}
+
+static void interfaces_removed_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter interfaces;
+	const char *interface;
+	const char *path;
+
+	if (!l_dbus_message_get_arguments(message, "oas", &path, &interfaces))
+		return;
+
+	while (l_dbus_message_iter_next_entry(&interfaces, &interface)) {
+		struct l_dbus_proxy *proxy;
+
+		proxy = find_proxy(client, path, interface);
+		if (!proxy)
+			continue;
+
+		l_queue_remove(proxy->client->proxies, proxy);
+
+		if (client->proxy_removed_cb)
+			client->proxy_removed_cb(proxy, client->proxy_cb_data);
+
+		dbus_proxy_destroy(proxy);
+	}
+}
+
+static void get_managed_objects_reply(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter objects;
+	struct l_dbus_message_iter object;
+	const char *path;
+
+	client->objects_call = 0;
+
+	if (l_dbus_message_is_error(message))
+		return;
+
+	if (!l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects))
+		return;
+
+	while (l_dbus_message_iter_next_entry(&objects, &path, &object))
+		parse_object(client, path, &object);
+
+	client->added_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesAdded",
+						L_DBUS_MATCH_NONE,
+						interfaces_added_callback,
+						client);
+
+	client->removed_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesRemoved",
+						L_DBUS_MATCH_NONE,
+						interfaces_removed_callback,
+						client);
+
+	if (client->ready_cb)
+		client->ready_cb(client, client->ready_cb_data);
+}
+
+static void service_appeared_callback(struct l_dbus *dbus, void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+
+	/* TODO should we allow to set different root? */
+	client->objects_call = l_dbus_method_call(dbus, client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"GetManagedObjects", NULL,
+						get_managed_objects_reply,
+						client, NULL);
+
+	if (client->connect_cb)
+		client->connect_cb(client->dbus, client->connect_cb_data);
+}
+
+static void service_disappeared_callback(struct l_dbus *dbus, void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+
+	if (client->disconnect_cb)
+		client->disconnect_cb(client->dbus, client->disconnect_cb_data);
+
+	l_queue_clear(client->proxies,
+				(l_queue_destroy_func_t)dbus_proxy_destroy);
+}
+
+LIB_EXPORT struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
+					const char *service, const char *path)
+{
+	struct l_dbus_client *client = l_new(struct l_dbus_client, 1);
+
+	client->dbus = dbus;
+
+	client->watch = l_dbus_add_service_watch(dbus, service,
+						service_appeared_callback,
+						service_disappeared_callback,
+						client, NULL);
+
+	if (!client->watch) {
+		l_free(client);
+		return NULL;
+	}
+
+	client->service = l_strdup(service);
+	client->proxies = l_queue_new();
+
+	return client;
+}
+
+LIB_EXPORT void l_dbus_client_destroy(struct l_dbus_client *client)
+{
+	if (unlikely(!client))
+		return;
+
+	if (client->watch)
+		l_dbus_remove_signal_watch(client->dbus, client->watch);
+
+	if (client->added_watch)
+		l_dbus_remove_signal_watch(client->dbus, client->added_watch);
+
+	if (client->removed_watch)
+		l_dbus_remove_signal_watch(client->dbus, client->removed_watch);
+
+	if (client->connect_cb_data_destroy)
+		client->connect_cb_data_destroy(client->connect_cb_data);
+
+	if (client->disconnect_cb_data_destroy)
+		client->disconnect_cb_data_destroy(client->disconnect_cb_data);
+
+	if (client->ready_cb_data_destroy)
+		client->ready_cb_data_destroy(client->ready_cb_data);
+
+	if (client->proxy_cb_data_destroy)
+		client->proxy_cb_data_destroy(client->proxy_cb_data);
+
+	if (client->objects_call)
+		l_dbus_cancel(client->dbus, client->objects_call);
+
+	l_queue_destroy(client->proxies,
+				(l_queue_destroy_func_t)dbus_proxy_destroy);
+
+	l_free(client->service);
+	l_free(client);
+}
+
+LIB_EXPORT bool l_dbus_client_set_connect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	if (client->connect_cb_data_destroy)
+		client->connect_cb_data_destroy(client->connect_cb_data);
+
+	client->connect_cb = function;
+	client->connect_cb_data = user_data;
+	client->connect_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_disconnect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	if(client->disconnect_cb_data_destroy)
+		client->disconnect_cb_data_destroy(client->disconnect_cb_data);
+
+	client->disconnect_cb = function;
+	client->disconnect_cb_data = user_data;
+	client->disconnect_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_ready_handler(struct l_dbus_client *client,
+					l_dbus_client_ready_func_t function,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	if (client->ready_cb_data_destroy)
+		client->ready_cb_data_destroy(client->ready_cb_data);
+
+	client->ready_cb = function;
+	client->ready_cb_data = user_data;
+	client->ready_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_proxy_handlers(struct l_dbus_client *client,
+			l_dbus_client_proxy_func_t proxy_added,
+			l_dbus_client_proxy_func_t proxy_removed,
+			l_dbus_client_property_function_t property_changed,
+			void *user_data, l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	if (client->proxy_cb_data_destroy)
+		client->proxy_cb_data_destroy(client->proxy_cb_data);
+
+	client->proxy_added_cb = proxy_added;
+	client->proxy_removed_cb = proxy_removed;
+	client->properties_changed_cb = property_changed;
+	client->proxy_cb_data = user_data;
+	client->proxy_cb_data_destroy = destroy;
+
+	return true;
+}
diff --git a/ell/dbus-client.h b/ell/dbus-client.h
new file mode 100644
index 0000000..b812861
--- /dev/null
+++ b/ell/dbus-client.h
@@ -0,0 +1,83 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ * Copyright (C) 2017  Codecoup
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_DBUS_CLIENT_H
+#define __ELL_DBUS_CLIENT_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_dbus;
+struct l_dbus_message;
+struct l_dbus_client;
+struct l_dbus_proxy;
+
+typedef void (*l_dbus_client_ready_func_t)(struct l_dbus_client *client,
+							void *user_data);
+typedef void (*l_dbus_client_proxy_func_t) (struct l_dbus_proxy *proxy,
+							void *user_data);
+typedef void (*l_dbus_client_proxy_result_func_t) (struct l_dbus_proxy *proxy,
+						struct l_dbus_message *result,
+						void *user_data);
+typedef void (*l_dbus_client_property_function_t) (struct l_dbus_proxy *proxy,
+						const char *name,
+						struct l_dbus_message *msg,
+						void *user_data);
+
+struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
+					const char *service, const char *path);
+void l_dbus_client_destroy(struct l_dbus_client *client);
+
+bool l_dbus_client_set_connect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_disconnect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_ready_handler(struct l_dbus_client *client,
+					l_dbus_client_ready_func_t function,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_proxy_handlers(struct l_dbus_client *client,
+			l_dbus_client_proxy_func_t proxy_added,
+			l_dbus_client_proxy_func_t proxy_removed,
+			l_dbus_client_property_function_t property_changed,
+			void *user_data, l_dbus_destroy_func_t destroy);
+
+const char *l_dbus_proxy_get_path(struct l_dbus_proxy *proxy);
+
+const char *l_dbus_proxy_get_interface(struct l_dbus_proxy *proxy);
+
+bool l_dbus_proxy_get_property(struct l_dbus_proxy *proxy, const char *name,
+						const char *signature, ...);
+
+bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
+				l_dbus_client_proxy_result_func_t result,
+				void *user_data, l_dbus_destroy_func_t destroy,
+				const char *name, const char *signature, ...);
+
+uint32_t l_dbus_proxy_method_call(struct l_dbus_proxy *proxy,
+					const char *method,
+					l_dbus_message_func_t setup,
+					l_dbus_client_proxy_result_func_t reply,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_DBUS_CLIENT_H */
diff --git a/ell/dbus-filter.c b/ell/dbus-filter.c
new file mode 100644
index 0000000..7853c2b
--- /dev/null
+++ b/ell/dbus-filter.c
@@ -0,0 +1,414 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2016  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util.h"
+#include "queue.h"
+#include "hashmap.h"
+#include "string.h"
+#include "dbus.h"
+#include "dbus-private.h"
+#include "gvariant-private.h"
+#include "private.h"
+#include "useful.h"
+
+#define NODE_TYPE_CALLBACK	L_DBUS_MATCH_NONE
+
+struct filter_node {
+	enum l_dbus_match_type type;
+	union {
+		struct {
+			char *value;
+			struct filter_node *children;
+			bool remote_rule;
+		} match;
+		struct {
+			l_dbus_message_func_t func;
+			void *user_data;
+		} callback;
+	};
+	unsigned int id;
+	struct filter_node *next;
+};
+
+struct _dbus_filter {
+	struct l_dbus *dbus;
+	struct filter_node *root;
+	unsigned int signal_id;
+	unsigned int last_id;
+	const struct _dbus_filter_ops *driver;
+	struct _dbus_name_cache *name_cache;
+};
+
+static void filter_subtree_free(struct filter_node *node)
+{
+	struct filter_node *child, *next;
+
+	if (node->type == NODE_TYPE_CALLBACK) {
+		l_free(node);
+		return;
+	}
+
+	next = node->match.children;
+
+	l_free(node->match.value);
+	l_free(node);
+
+	while (next) {
+		child = next;
+		next = child->next;
+
+		filter_subtree_free(child);
+	}
+}
+
+static void dbus_filter_destroy(void *data)
+{
+	struct _dbus_filter *filter = data;
+
+	if (filter->root)
+		filter_subtree_free(filter->root);
+
+	l_free(filter);
+}
+
+static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
+						struct filter_node *node,
+						struct l_dbus_message *message)
+{
+	const char *value = NULL;
+	const char *alt_value = NULL;
+	struct filter_node *child;
+
+	switch ((int) node->type) {
+	case NODE_TYPE_CALLBACK:
+		node->callback.func(message, node->callback.user_data);
+		return;
+
+	case L_DBUS_MATCH_SENDER:
+		value = l_dbus_message_get_sender(message);
+		break;
+
+	case L_DBUS_MATCH_TYPE:
+		value = _dbus_message_get_type_as_string(message);
+		break;
+
+	case L_DBUS_MATCH_PATH:
+		value = l_dbus_message_get_path(message);
+		break;
+
+	case L_DBUS_MATCH_INTERFACE:
+		value = l_dbus_message_get_interface(message);
+		break;
+
+	case L_DBUS_MATCH_MEMBER:
+		value = l_dbus_message_get_member(message);
+		break;
+
+	case L_DBUS_MATCH_ARG0...(L_DBUS_MATCH_ARG0 + 63):
+		value = _dbus_message_get_nth_string_argument(message,
+						node->type - L_DBUS_MATCH_ARG0);
+		break;
+	}
+
+	if (!value)
+		return;
+
+	if (node->type == L_DBUS_MATCH_SENDER && filter->name_cache)
+		alt_value = _dbus_name_cache_lookup(filter->name_cache,
+							node->match.value);
+
+	if (strcmp(value, node->match.value) &&
+			(!alt_value || strcmp(value, alt_value)))
+		return;
+
+	for (child = node->match.children; child; child = child->next)
+		filter_dispatch_match_recurse(filter, child, message);
+}
+
+void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data)
+{
+	struct _dbus_filter *filter = user_data;
+
+	filter_dispatch_match_recurse(filter, filter->root, message);
+}
+
+struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
+					const struct _dbus_filter_ops *driver,
+					struct _dbus_name_cache *name_cache)
+{
+	struct _dbus_filter *filter;
+
+	filter = l_new(struct _dbus_filter, 1);
+
+	filter->dbus = dbus;
+	filter->driver = driver;
+	filter->name_cache = name_cache;
+
+	if (!filter->driver->skip_register)
+		filter->signal_id = l_dbus_register(dbus, _dbus_filter_dispatch,
+							filter,
+							dbus_filter_destroy);
+
+	return filter;
+}
+
+void _dbus_filter_free(struct _dbus_filter *filter)
+{
+	if (!filter)
+		return;
+
+	if (!filter->driver->skip_register)
+		l_dbus_unregister(filter->dbus, filter->signal_id);
+	else
+		dbus_filter_destroy(filter);
+}
+
+static int condition_compare(const void *a, const void *b)
+{
+	const struct _dbus_filter_condition *condition_a = a, *condition_b = b;
+
+	return condition_a->type - condition_b->type;
+}
+
+static bool remove_recurse(struct _dbus_filter *filter,
+				struct filter_node **node, unsigned int id)
+{
+	struct filter_node *tmp;
+
+	for (; *node; node = &(*node)->next) {
+		if ((*node)->type == NODE_TYPE_CALLBACK && (*node)->id == id)
+			break;
+
+		if ((*node)->type != NODE_TYPE_CALLBACK &&
+				remove_recurse(filter, &(*node)->match.children,
+						id))
+			break;
+	}
+
+	if (!*node)
+		return false;
+
+	if ((*node)->type == NODE_TYPE_CALLBACK || !(*node)->match.children) {
+		tmp = *node;
+		*node = tmp->next;
+
+		if (tmp->match.remote_rule)
+			filter->driver->remove_match(filter->dbus, tmp->id);
+
+		if (tmp->type == L_DBUS_MATCH_SENDER && filter->name_cache &&
+				!_dbus_parse_unique_name(tmp->match.value,
+								NULL))
+			_dbus_name_cache_remove(filter->name_cache,
+						tmp->match.value);
+
+		filter_subtree_free(tmp);
+	}
+
+	return true;
+}
+
+unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
+				const struct _dbus_filter_condition *rule,
+				int rule_len,
+				l_dbus_message_func_t signal_func,
+				void *user_data)
+{
+	struct filter_node **node_ptr = &filter->root;
+	struct filter_node *node;
+	struct filter_node *parent = filter->root;
+	bool remote_rule = false;
+	struct _dbus_filter_condition sorted[rule_len];
+	struct _dbus_filter_condition *unused;
+	struct _dbus_filter_condition *condition;
+	struct _dbus_filter_condition *end = sorted + rule_len;
+
+	memcpy(sorted, rule, sizeof(sorted));
+	qsort(sorted, rule_len, sizeof(*condition), condition_compare);
+
+	/*
+	 * Find or create a path in the tree with a node for each
+	 * condition in the rule, loop until all conditions have been
+	 * used.
+	 */
+	unused = sorted;
+	while (unused < end) {
+		/*
+		 * Find a child of the node that matches any unused
+		 * condition.  Note there could be multiple matches, we're
+		 * happy with the first we can find.
+		 */
+		while (*node_ptr) {
+			node = *node_ptr;
+
+			for (condition = unused; condition < end; condition++) {
+				if (condition->type > node->type) {
+					condition = end;
+					break;
+				}
+
+				if (condition->type < node->type ||
+						condition->type ==
+						L_DBUS_MATCH_NONE)
+					continue;
+
+				if (!strcmp(node->match.value,
+						condition->value))
+					break;
+			}
+
+			if (condition < end)
+				break;
+
+			node_ptr = &node->next;
+		}
+
+		/* Add a node */
+		if (!*node_ptr) {
+			condition = unused;
+
+			node = l_new(struct filter_node, 1);
+			node->type = condition->type;
+			node->match.value = l_strdup(condition->value);
+
+			*node_ptr = node;
+
+			if (node->type == L_DBUS_MATCH_SENDER &&
+					filter->name_cache &&
+					!_dbus_parse_unique_name(
+							node->match.value,
+							NULL))
+				_dbus_name_cache_add(filter->name_cache,
+							node->match.value);
+
+		}
+
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+		/*
+		 * Mark the condition used.  We do this by setting
+		 * condition->type to an invalid value unless it is the
+		 * first condition left in which case we can push the
+		 * rule start.  Another option is to always push the rule
+		 * start and memmove the still unused conditions by one
+		 * if necessary.
+		 */
+		condition->type = L_DBUS_MATCH_NONE;
+		while (unused < end && unused[0].type == L_DBUS_MATCH_NONE)
+			unused++;
+
+		node_ptr = &node->match.children;
+
+		parent = node;
+
+		/*
+		 * Only have to call AddMatch if none of the parent nodes
+		 * have yet created an AddMatch rule on the server.
+		 */
+		remote_rule |= node->match.remote_rule;
+_Pragma("GCC diagnostic pop")
+	}
+
+	node = l_new(struct filter_node, 1);
+	node->type = NODE_TYPE_CALLBACK;
+	node->callback.func = signal_func;
+	node->callback.user_data = user_data;
+	node->id = ++filter->last_id;
+	node->next = *node_ptr;
+
+	*node_ptr = node;
+
+	if (!remote_rule) {
+		if (!filter->driver->add_match(filter->dbus, node->id,
+						rule, rule_len))
+			goto err;
+
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+		parent->id = node->id;
+		parent->match.remote_rule = true;
+_Pragma("GCC diagnostic pop")
+	}
+
+	return node->id;
+
+err:
+	/* Remove all the nodes we may have added */
+	node->id = (unsigned int) -1;
+	remove_recurse(filter, &filter->root, node->id);
+
+	return 0;
+}
+
+bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id)
+{
+	return remove_recurse(filter, &filter->root, id);
+}
+
+char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
+				int rule_len)
+{
+	struct l_string *str = l_string_new(63);
+	char *key, arg_buf[6];
+	const char *value, *endp;
+
+	for (; rule_len; rule++, rule_len--) {
+		switch ((int) rule->type) {
+		case L_DBUS_MATCH_SENDER:
+			key = "sender";
+			break;
+		case L_DBUS_MATCH_TYPE:
+			key = "type";
+			break;
+		case L_DBUS_MATCH_PATH:
+			key = "path";
+			break;
+		case L_DBUS_MATCH_INTERFACE:
+			key = "interface";
+			break;
+		case L_DBUS_MATCH_MEMBER:
+			key = "member";
+			break;
+		case L_DBUS_MATCH_ARG0...(L_DBUS_MATCH_ARG0 + 63):
+			key = arg_buf;
+			snprintf(arg_buf, sizeof(arg_buf), "arg%i",
+					rule->type - L_DBUS_MATCH_ARG0);
+			break;
+		default:
+			l_string_free(str);
+			return NULL;
+		}
+
+		l_string_append(str, key);
+		l_string_append(str, "='");
+
+		/* We only need to escape single-quotes in the values */
+		value = rule->value;
+
+		while ((endp = strchr(value, '\''))) {
+			l_string_append_fixed(str, value, endp - value);
+			l_string_append(str, "'\\''");
+
+			value = endp + 1;
+		}
+
+		l_string_append(str, value);
+		l_string_append_c(str, '\'');
+
+		if (rule_len > 1)
+			l_string_append_c(str, ',');
+	}
+
+	return l_string_unwrap(str);
+}
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
new file mode 100644
index 0000000..d85f7f8
--- /dev/null
+++ b/ell/dbus-message.c
@@ -0,0 +1,1974 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "private.h"
+#include "useful.h"
+#include "dbus.h"
+#include "dbus-private.h"
+#include "gvariant-private.h"
+
+#define DBUS_MESSAGE_LITTLE_ENDIAN	('l')
+#define DBUS_MESSAGE_BIG_ENDIAN		('B')
+
+#define DBUS_MESSAGE_PROTOCOL_VERSION	1
+
+#define DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED	0x01
+#define DBUS_MESSAGE_FLAG_NO_AUTO_START		0x02
+
+#define DBUS_MESSAGE_FIELD_PATH		1
+#define DBUS_MESSAGE_FIELD_INTERFACE	2
+#define DBUS_MESSAGE_FIELD_MEMBER	3
+#define DBUS_MESSAGE_FIELD_ERROR_NAME	4
+#define DBUS_MESSAGE_FIELD_REPLY_SERIAL	5
+#define DBUS_MESSAGE_FIELD_DESTINATION	6
+#define DBUS_MESSAGE_FIELD_SENDER	7
+#define DBUS_MESSAGE_FIELD_SIGNATURE	8
+#define DBUS_MESSAGE_FIELD_UNIX_FDS	9
+
+#define DBUS_MAX_NESTING	32
+
+struct l_dbus_message {
+	int refcount;
+	void *header;
+	size_t header_size;
+	size_t header_end;
+	char *signature;
+	void *body;
+	size_t body_size;
+	char *path;
+	char *interface;
+	char *member;
+	char *error_name;
+	uint32_t reply_serial;
+	char *destination;
+	char *sender;
+	int fds[16];
+	uint32_t num_fds;
+
+	bool sealed : 1;
+	bool signature_free : 1;
+};
+
+struct l_dbus_message_builder {
+	struct l_dbus_message *message;
+	struct dbus_builder *builder;
+	struct builder_driver *driver;
+};
+
+static inline bool _dbus_message_is_gvariant(struct l_dbus_message *msg)
+{
+	struct dbus_header *hdr = msg->header;
+
+	return hdr->version == 2;
+}
+
+void *_dbus_message_get_header(struct l_dbus_message *msg, size_t *out_size)
+{
+	if (out_size)
+		*out_size = msg->header_size;
+
+	return msg->header;
+}
+
+void *_dbus_message_get_body(struct l_dbus_message *msg, size_t *out_size)
+{
+	if (out_size)
+		*out_size = msg->body_size;
+
+	return msg->body;
+}
+
+/* Get a buffer containing the final message contents except the header */
+void *_dbus_message_get_footer(struct l_dbus_message *msg, size_t *out_size)
+{
+	size_t size;
+
+	if (_dbus_message_is_gvariant(msg)) {
+		size = _gvariant_message_finalize(msg->header_end,
+						msg->body, msg->body_size,
+						msg->signature);
+		size -= msg->header_size;
+	} else
+		size = msg->body_size;
+
+	if (out_size)
+		*out_size = size;
+
+	return msg->body;
+}
+
+int *_dbus_message_get_fds(struct l_dbus_message *msg, uint32_t *num_fds)
+{
+	*num_fds = msg->num_fds;
+
+	return msg->fds;
+}
+
+void _dbus_message_set_serial(struct l_dbus_message *msg, uint32_t serial)
+{
+	struct dbus_header *hdr = msg->header;
+
+	hdr->dbus1.serial = serial;
+}
+
+uint32_t _dbus_message_get_serial(struct l_dbus_message *msg)
+{
+	struct dbus_header *hdr = msg->header;
+
+	return hdr->dbus1.serial;
+}
+
+LIB_EXPORT bool l_dbus_message_set_no_reply(struct l_dbus_message *msg, bool on)
+{
+	struct dbus_header *hdr;
+
+	if (unlikely(!msg))
+		return false;
+
+	hdr = msg->header;
+
+	if (on)
+		hdr->flags |= DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
+	else
+		hdr->flags &= ~DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_message_get_no_reply(struct l_dbus_message *msg)
+{
+	struct dbus_header *hdr;
+
+	if (unlikely(!msg))
+		return false;
+
+	hdr = msg->header;
+
+	if (hdr->flags & DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED)
+		return true;
+
+	return false;
+}
+
+LIB_EXPORT bool l_dbus_message_set_no_autostart(struct l_dbus_message *msg,
+							bool on)
+{
+	struct dbus_header *hdr;
+
+	if (unlikely(!msg))
+		return false;
+
+	hdr = msg->header;
+
+	if (on)
+		hdr->flags |= DBUS_MESSAGE_FLAG_NO_AUTO_START;
+	else
+		hdr->flags &= ~DBUS_MESSAGE_FLAG_NO_AUTO_START;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_message_get_no_autostart(struct l_dbus_message *msg)
+{
+	struct dbus_header *hdr;
+
+	if (unlikely(!msg))
+		return false;
+
+	hdr = msg->header;
+
+	if (hdr->flags & DBUS_MESSAGE_FLAG_NO_AUTO_START)
+		return true;
+
+	return false;
+
+}
+
+static struct l_dbus_message *message_new_common(uint8_t type, uint8_t flags,
+						uint8_t version)
+{
+	struct l_dbus_message *message;
+	struct dbus_header *hdr;
+
+	message = l_new(struct l_dbus_message, 1);
+	message->refcount = 1;
+
+	/*
+	 * We allocate the header with the initial 12 bytes (up to the field
+	 * length) so that we can store the basic information here.  For
+	 * GVariant we need 16 bytes.
+	 */
+	message->header_size = version == 1 ? 12 : 16;
+	message->header_end = message->header_size;
+	message->header = l_realloc(NULL, message->header_size);
+
+	hdr = message->header;
+	hdr->endian = DBUS_NATIVE_ENDIAN;
+	hdr->message_type = type;
+	hdr->flags = flags;
+	hdr->version = version;
+
+	return message;
+}
+
+struct l_dbus_message *_dbus_message_new_method_call(uint8_t version,
+							const char *destination,
+							const char *path,
+							const char *interface,
+							const char *method)
+{
+	struct l_dbus_message *message;
+
+	message = message_new_common(DBUS_MESSAGE_TYPE_METHOD_CALL, 0, version);
+
+	message->destination = l_strdup(destination);
+	message->path = l_strdup(path);
+	message->interface = l_strdup(interface);
+	message->member = l_strdup(method);
+
+	return message;
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_call(
+							struct l_dbus *dbus,
+							const char *destination,
+							const char *path,
+							const char *interface,
+							const char *method)
+{
+	uint8_t version;
+
+	if (unlikely(!dbus))
+		return NULL;
+
+	version = _dbus_get_version(dbus);
+
+	return _dbus_message_new_method_call(version, destination, path,
+						interface, method);
+}
+
+struct l_dbus_message *_dbus_message_new_signal(uint8_t version,
+						const char *path,
+						const char *interface,
+						const char *name)
+{
+	struct l_dbus_message *message;
+
+	message = message_new_common(DBUS_MESSAGE_TYPE_SIGNAL,
+					DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
+					version);
+
+	message->path = l_strdup(path);
+	message->interface = l_strdup(interface);
+	message->member = l_strdup(name);
+
+	return message;
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_signal(struct l_dbus *dbus,
+							const char *path,
+							const char *interface,
+							const char *name)
+{
+	uint8_t version;
+
+	if (unlikely(!dbus))
+		return NULL;
+
+	version = _dbus_get_version(dbus);
+
+	return _dbus_message_new_signal(version, path, interface, name);
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
+					struct l_dbus_message *method_call)
+{
+	struct l_dbus_message *message;
+	struct dbus_header *hdr = method_call->header;
+	const char *sender;
+
+	message = message_new_common(DBUS_MESSAGE_TYPE_METHOD_RETURN,
+					DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
+					hdr->version);
+
+	if (!l_dbus_message_get_no_reply(method_call))
+		message->reply_serial = _dbus_message_get_serial(method_call);
+
+	sender = l_dbus_message_get_sender(method_call);
+	if (sender)
+		message->destination = l_strdup(sender);
+
+	return message;
+}
+
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+						uint32_t reply_serial,
+						const char *destination,
+						const char *name,
+						const char *error)
+{
+	struct l_dbus_message *reply;
+
+	if (!_dbus_valid_interface(name))
+		return NULL;
+
+	reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
+					DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
+					version);
+
+	reply->error_name = l_strdup(name);
+	reply->destination = l_strdup(destination);
+	reply->reply_serial = reply_serial;
+
+	if (!l_dbus_message_set_arguments(reply, "s", error)) {
+		l_dbus_message_unref(reply);
+		return NULL;
+	}
+
+	return reply;
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
+					struct l_dbus_message *method_call,
+					const char *name,
+					const char *format, va_list args)
+{
+	char str[1024];
+	struct dbus_header *hdr = method_call->header;
+	uint32_t reply_serial = 0;
+
+	vsnprintf(str, sizeof(str), format, args);
+
+	if (!l_dbus_message_get_no_reply(method_call))
+		reply_serial = _dbus_message_get_serial(method_call);
+
+	return _dbus_message_new_error(hdr->version, reply_serial,
+					l_dbus_message_get_sender(method_call),
+					name, str);
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error(
+					struct l_dbus_message *method_call,
+					const char *name,
+					const char *format, ...)
+{
+	va_list args;
+	struct l_dbus_message *reply;
+
+	va_start(args, format);
+	reply = l_dbus_message_new_error_valist(method_call, name,
+								format, args);
+	va_end(args);
+
+	return reply;
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_ref(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	__atomic_fetch_add(&message->refcount, 1, __ATOMIC_SEQ_CST);
+
+	return message;
+}
+
+LIB_EXPORT void l_dbus_message_unref(struct l_dbus_message *message)
+{
+	unsigned int i;
+
+	if (unlikely(!message))
+		return;
+
+	if (__atomic_sub_fetch(&message->refcount, 1, __ATOMIC_SEQ_CST))
+		return;
+
+	for (i = 0; i < message->num_fds; i++)
+		close(message->fds[i]);
+
+	if (!message->sealed) {
+		l_free(message->destination);
+		l_free(message->path);
+		l_free(message->interface);
+		l_free(message->member);
+		l_free(message->error_name);
+		l_free(message->sender);
+	}
+
+	if (message->signature_free)
+		l_free(message->signature);
+
+	l_free(message->header);
+	l_free(message->body);
+	l_free(message);
+}
+
+const char *_dbus_message_get_nth_string_argument(
+					struct l_dbus_message *message, int n)
+{
+	struct l_dbus_message_iter iter;
+	const char *signature, *value;
+	void *body;
+	size_t size;
+	char type;
+	bool (*skip_entry)(struct l_dbus_message_iter *);
+	bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
+
+	signature = l_dbus_message_get_signature(message);
+	body = _dbus_message_get_body(message, &size);
+
+	if (!signature)
+		return NULL;
+
+	if (_dbus_message_is_gvariant(message)) {
+		if (!_gvariant_iter_init(&iter, message, signature, NULL,
+						body, size))
+			return NULL;
+
+		skip_entry = _gvariant_iter_skip_entry;
+		get_basic = _gvariant_iter_next_entry_basic;
+	} else {
+		_dbus1_iter_init(&iter, message, signature, NULL, body, size);
+
+		skip_entry = _dbus1_iter_skip_entry;
+		get_basic = _dbus1_iter_next_entry_basic;
+	}
+
+	while (n--)
+		if (!skip_entry(&iter))
+			return NULL;
+
+	if (!iter.sig_start)
+		return NULL;
+
+	type = iter.sig_start[iter.sig_pos];
+	if (!strchr("sog", type))
+		return NULL;
+
+	if (!get_basic(&iter, type, &value))
+		return NULL;
+
+	return value;
+}
+
+static bool message_iter_next_entry_valist(struct l_dbus_message_iter *orig,
+						va_list args)
+{
+	static const char *simple_types = "sogybnqiuxtd";
+	struct l_dbus_message_iter *iter = orig;
+	const char *signature = orig->sig_start + orig->sig_pos;
+	const char *end;
+	struct l_dbus_message_iter *sub_iter;
+	struct l_dbus_message_iter stack[DBUS_MAX_NESTING];
+	unsigned int indent = 0;
+	uint32_t uint32_val;
+	int fd;
+	void *arg;
+	bool (*get_basic)(struct l_dbus_message_iter *, char ,void *);
+	bool (*enter_struct)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+	bool (*enter_array)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+	bool (*enter_variant)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+
+	if (_dbus_message_is_gvariant(orig->message)) {
+		get_basic = _gvariant_iter_next_entry_basic;
+		enter_struct = _gvariant_iter_enter_struct;
+		enter_array = _gvariant_iter_enter_array;
+		enter_variant = _gvariant_iter_enter_variant;
+	} else {
+		get_basic = _dbus1_iter_next_entry_basic;
+		enter_struct = _dbus1_iter_enter_struct;
+		enter_array = _dbus1_iter_enter_array;
+		enter_variant = _dbus1_iter_enter_variant;
+	}
+
+	while (signature < orig->sig_start + orig->sig_len) {
+		if (strchr(simple_types, *signature)) {
+			arg = va_arg(args, void *);
+			if (!get_basic(iter, *signature, arg))
+				return false;
+
+			signature += 1;
+			continue;
+		}
+
+		switch (*signature) {
+		case 'h':
+			if (!get_basic(iter, 'h', &uint32_val))
+				return false;
+
+			if (uint32_val < iter->message->num_fds)
+				fd = fcntl(iter->message->fds[uint32_val],
+						F_DUPFD_CLOEXEC, 3);
+			else
+				fd = -1;
+
+			*va_arg(args, int *) = fd;
+			signature += 1;
+			break;
+		case '(':
+		case '{':
+			signature += 1;
+			indent += 1;
+
+			if (indent > DBUS_MAX_NESTING)
+				return false;
+
+			if (!enter_struct(iter, &stack[indent - 1]))
+				return false;
+
+			iter = &stack[indent - 1];
+
+			break;
+		case ')':
+		case '}':
+			/*
+			 * Sanity check in case of an unmatched paren/brace
+			 * that isn't caught elsewhere.
+			 */
+			if (unlikely(indent == 0))
+				return false;
+
+			signature += 1;
+			indent -= 1;
+
+			if (indent == 0)
+				iter = orig;
+			else
+				iter = &stack[indent - 1];
+			break;
+		case 'a':
+			sub_iter = va_arg(args, void *);
+
+			if (!enter_array(iter, sub_iter))
+				return false;
+
+			end = _dbus_signature_end(signature + 1);
+			signature = end + 1;
+			break;
+		case 'v':
+			sub_iter = va_arg(args, void *);
+
+			if (!enter_variant(iter, sub_iter))
+				return false;
+
+			signature += 1;
+			break;
+		default:
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static inline bool message_iter_next_entry(struct l_dbus_message_iter *iter,
+						...)
+{
+	va_list args;
+	bool result;
+
+        va_start(args, iter);
+	result = message_iter_next_entry_valist(iter, args);
+	va_end(args);
+
+	return result;
+}
+
+static bool get_header_field_from_iter_valist(struct l_dbus_message *message,
+						uint8_t type, char data_type,
+						va_list args)
+{
+	struct l_dbus_message_iter header;
+	struct l_dbus_message_iter array, iter;
+	uint8_t endian, message_type, flags, version;
+	uint32_t body_length, serial;
+	bool found;
+
+	if (!message->sealed)
+		return false;
+
+	if (_dbus_message_is_gvariant(message)) {
+		uint64_t field_type;
+
+		if (!_gvariant_iter_init(&header, message, "a(tv)", NULL,
+						message->header + 16,
+						message->header_end - 16))
+			return false;
+
+		if (!_gvariant_iter_enter_array(&header, &array))
+			return false;
+
+		while ((found = message_iter_next_entry(&array,
+							&field_type, &iter)))
+			if (field_type == type)
+				break;
+	} else {
+		uint8_t field_type;
+
+		_dbus1_iter_init(&header, message, "yyyyuua(yv)", NULL,
+				message->header, message->header_size);
+
+		if (!message_iter_next_entry(&header, &endian,
+						&message_type, &flags, &version,
+						&body_length, &serial, &array))
+			return false;
+
+		while ((found = message_iter_next_entry(&array,
+							&field_type, &iter)))
+			if (field_type == type)
+				break;
+	}
+
+	if (!found)
+		return false;
+
+	if (iter.sig_start[iter.sig_pos] != data_type)
+		return false;
+
+	return message_iter_next_entry_valist(&iter, args);
+}
+
+static inline bool get_header_field(struct l_dbus_message *message,
+					uint8_t type, int data_type, ...)
+{
+	va_list args;
+	bool result;
+
+	va_start(args, data_type);
+	result = get_header_field_from_iter_valist(message, type, data_type,
+							args);
+	va_end(args);
+
+	return result;
+}
+
+static bool valid_header(const struct dbus_header *hdr)
+{
+	if (hdr->endian != DBUS_MESSAGE_LITTLE_ENDIAN &&
+			hdr->endian != DBUS_MESSAGE_BIG_ENDIAN)
+		return false;
+
+	if (hdr->message_type < DBUS_MESSAGE_TYPE_METHOD_CALL ||
+			hdr->message_type > DBUS_MESSAGE_TYPE_SIGNAL)
+		return false;
+
+	if (hdr->version != 1 && hdr->version != 2)
+		return false;
+
+	if (hdr->version == 1) {
+		if (hdr->dbus1.serial == 0)
+			return false;
+	}
+
+	return true;
+}
+
+unsigned int _dbus_message_unix_fds_from_header(const void *data, size_t size)
+{
+	struct l_dbus_message message;
+	uint32_t unix_fds;
+
+	message.header = (uint8_t *) data;
+	message.header_size = size;
+	message.body_size = 0;
+	message.sealed = true;
+
+	if (!get_header_field(&message, DBUS_MESSAGE_FIELD_UNIX_FDS,
+				'u', &unix_fds))
+		return 0;
+
+	return unix_fds;
+}
+
+struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size,
+						int fds[], uint32_t num_fds)
+{
+	const struct dbus_header *hdr = data;
+	struct l_dbus_message *message;
+	size_t body_pos;
+	unsigned int i;
+
+	if (unlikely(size < DBUS_HEADER_SIZE))
+		return NULL;
+
+	message = l_new(struct l_dbus_message, 1);
+
+	message->refcount = 1;
+
+	if (hdr->version == 1) {
+		message->header_size = align_len(DBUS_HEADER_SIZE +
+						hdr->dbus1.field_length, 8);
+		message->body_size = hdr->dbus1.body_length;
+
+		if (message->header_size + message->body_size < size)
+			goto free;
+
+		body_pos = message->header_size;
+	} else {
+		struct l_dbus_message_iter iter;
+		struct l_dbus_message_iter header, variant, body;
+
+		/*
+		 * GVariant message structure as per
+		 * https://wiki.gnome.org/Projects/GLib/GDBus/Version2
+		 * is "(yyyyuta{tv}v)".  As noted this is equivalent to
+		 * some other types, this one lets us get iterators for
+		 * the header and the body in the fewest steps.
+		 */
+		if (!_gvariant_iter_init(&iter, message, "(yyyyuta{tv})v",
+						NULL, data, size))
+			goto free;
+
+		if (!_gvariant_iter_enter_struct(&iter, &header))
+			goto free;
+
+		if (!_gvariant_iter_enter_variant(&iter, &variant))
+			goto free;
+
+		if (!_gvariant_iter_enter_struct(&variant, &body))
+			goto free;
+
+		message->header_size = align_len(header.len - header.pos, 8);
+		message->body_size = body.len - body.pos;
+		message->signature = l_strndup(body.sig_start + body.sig_pos,
+						body.sig_len - body.sig_pos);
+		message->signature_free = true;
+		message->header_end = header.len;
+		body_pos = body.data + body.pos - data;
+	}
+
+	message->header = l_malloc(message->header_size);
+	message->body = l_malloc(message->body_size);
+
+	memcpy(message->header, data, message->header_size);
+	memcpy(message->body, data + body_pos, message->body_size);
+
+	message->sealed = true;
+
+	/* If the field is absent message->signature will remain NULL */
+	if (hdr->version == 1)
+		get_header_field(message, DBUS_MESSAGE_FIELD_SIGNATURE,
+					'g', &message->signature);
+
+	if (num_fds) {
+		uint32_t unix_fds, orig_fds = num_fds;
+
+		if (!get_header_field(message, DBUS_MESSAGE_FIELD_UNIX_FDS,
+					'u', &unix_fds))
+			goto free;
+
+		if (num_fds > unix_fds)
+			num_fds = unix_fds;
+
+		if (num_fds > L_ARRAY_SIZE(message->fds))
+			num_fds = L_ARRAY_SIZE(message->fds);
+
+		for (i = num_fds; i < orig_fds; i++)
+			close(fds[i]);
+
+		message->num_fds = num_fds;
+		memcpy(message->fds, fds, num_fds * sizeof(int));
+	}
+
+	return message;
+
+free:
+	l_dbus_message_unref(message);
+
+	return NULL;
+}
+
+struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
+						void *body, size_t body_size,
+						int fds[], uint32_t num_fds)
+{
+	const struct dbus_header *hdr = header;
+	struct l_dbus_message *message;
+	unsigned int i;
+
+	if (unlikely(header_size < DBUS_HEADER_SIZE))
+		return NULL;
+
+	if (unlikely(!valid_header(hdr)))
+		return NULL;
+
+	/*
+	 * With GVariant we need to know the signature, use
+	 * dbus_message_from_blob instead.
+	 */
+	if (unlikely(hdr->version != 1))
+		return NULL;
+
+	message = l_new(struct l_dbus_message, 1);
+
+	message->refcount = 1;
+	message->header_size = header_size;
+	message->header = header;
+	message->body_size = body_size;
+	message->body = body;
+	message->sealed = true;
+
+	if (num_fds) {
+		uint32_t unix_fds, orig_fds = num_fds;
+
+		if (!get_header_field(message, DBUS_MESSAGE_FIELD_UNIX_FDS,
+					'u', &unix_fds)) {
+			l_free(message);
+			return NULL;
+		}
+
+		if (num_fds > unix_fds)
+			num_fds = unix_fds;
+
+		if (num_fds > L_ARRAY_SIZE(message->fds))
+			num_fds = L_ARRAY_SIZE(message->fds);
+
+		for (i = num_fds; i < orig_fds; i++)
+			close(fds[i]);
+
+		message->num_fds = num_fds;
+		memcpy(message->fds, fds, num_fds * sizeof(int));
+	}
+
+	/* If the field is absent message->signature will remain NULL */
+	get_header_field(message, DBUS_MESSAGE_FIELD_SIGNATURE, 'g',
+						&message->signature);
+
+	return message;
+}
+
+bool dbus_message_compare(struct l_dbus_message *message,
+					const void *data, size_t size)
+{
+	struct l_dbus_message *other;
+	bool ret = false;
+
+	other = dbus_message_from_blob(data, size, NULL, 0);
+
+	if (message->signature) {
+		if (!other->signature)
+			goto done;
+
+		if (strcmp(message->signature, other->signature))
+			goto done;
+	} else {
+		if (other->signature)
+			goto done;
+	}
+
+	if (message->body_size != other->body_size)
+		goto done;
+
+	if (message->header_size != other->header_size)
+		goto done;
+
+	ret = !memcmp(message->body, other->body, message->body_size);
+
+done:
+	l_dbus_message_unref(other);
+
+	return ret;
+}
+
+struct builder_driver {
+	bool (*append_basic)(struct dbus_builder *, char, const void *);
+	bool (*enter_struct)(struct dbus_builder *, const char *);
+	bool (*leave_struct)(struct dbus_builder *);
+	bool (*enter_dict)(struct dbus_builder *, const char *);
+	bool (*leave_dict)(struct dbus_builder *);
+	bool (*enter_array)(struct dbus_builder *, const char *);
+	bool (*leave_array)(struct dbus_builder *);
+	bool (*enter_variant)(struct dbus_builder *, const char *);
+	bool (*leave_variant)(struct dbus_builder *);
+	char *(*finish)(struct dbus_builder *, void **, size_t *);
+	bool (*mark)(struct dbus_builder *);
+	bool (*rewind)(struct dbus_builder *);
+	struct dbus_builder *(*new)(void *, size_t);
+	void (*free)(struct dbus_builder *);
+};
+
+static struct builder_driver dbus1_driver = {
+	.append_basic = _dbus1_builder_append_basic,
+	.enter_struct = _dbus1_builder_enter_struct,
+	.leave_struct = _dbus1_builder_leave_struct,
+	.enter_dict = _dbus1_builder_enter_dict,
+	.leave_dict = _dbus1_builder_leave_dict,
+	.enter_variant = _dbus1_builder_enter_variant,
+	.leave_variant = _dbus1_builder_leave_variant,
+	.enter_array = _dbus1_builder_enter_array,
+	.leave_array = _dbus1_builder_leave_array,
+	.finish = _dbus1_builder_finish,
+	.mark = _dbus1_builder_mark,
+	.rewind = _dbus1_builder_rewind,
+	.new = _dbus1_builder_new,
+	.free = _dbus1_builder_free,
+};
+
+static struct builder_driver gvariant_driver = {
+	.append_basic = _gvariant_builder_append_basic,
+	.enter_struct = _gvariant_builder_enter_struct,
+	.leave_struct = _gvariant_builder_leave_struct,
+	.enter_dict = _gvariant_builder_enter_dict,
+	.leave_dict = _gvariant_builder_leave_dict,
+	.enter_variant = _gvariant_builder_enter_variant,
+	.leave_variant = _gvariant_builder_leave_variant,
+	.enter_array = _gvariant_builder_enter_array,
+	.leave_array = _gvariant_builder_leave_array,
+	.finish = _gvariant_builder_finish,
+	.mark = _gvariant_builder_mark,
+	.rewind = _gvariant_builder_rewind,
+	.new = _gvariant_builder_new,
+	.free = _gvariant_builder_free,
+};
+
+static void add_field(struct dbus_builder *builder,
+			struct builder_driver *driver,
+			uint8_t field, const char *type, const void *value)
+{
+	if (driver == &gvariant_driver) {
+		uint64_t long_field = field;
+
+		driver->enter_struct(builder, "tv");
+		driver->append_basic(builder, 't', &long_field);
+	} else {
+		driver->enter_struct(builder, "yv");
+		driver->append_basic(builder, 'y', &field);
+	}
+	driver->enter_variant(builder, type);
+	driver->append_basic(builder, type[0], value);
+	driver->leave_variant(builder);
+	driver->leave_struct(builder);
+}
+
+static void build_header(struct l_dbus_message *message, const char *signature)
+{
+	struct dbus_builder *builder;
+	struct builder_driver *driver;
+	char *generated_signature;
+	size_t header_size;
+	bool gvariant;
+
+	gvariant = _dbus_message_is_gvariant(message);
+
+	if (gvariant)
+		driver = &gvariant_driver;
+	else
+		driver = &dbus1_driver;
+
+	builder = driver->new(message->header, message->header_size);
+
+	driver->enter_array(builder, gvariant ? "(tv)" : "(yv)");
+
+	if (message->path) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_PATH,
+					"o", message->path);
+		l_free(message->path);
+		message->path = NULL;
+	}
+
+	if (message->member) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_MEMBER,
+					"s", message->member);
+		l_free(message->member);
+		message->member = NULL;
+	}
+
+	if (message->interface) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_INTERFACE,
+					"s", message->interface);
+		l_free(message->interface);
+		message->interface = NULL;
+	}
+
+	if (message->destination) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_DESTINATION,
+					"s", message->destination);
+		l_free(message->destination);
+		message->destination = NULL;
+	}
+
+	if (message->error_name != 0) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_ERROR_NAME,
+					"s", message->error_name);
+		l_free(message->error_name);
+		message->error_name = NULL;
+	}
+
+	if (message->reply_serial != 0) {
+		if (gvariant) {
+			uint64_t reply_serial = message->reply_serial;
+
+			add_field(builder, driver,
+					DBUS_MESSAGE_FIELD_REPLY_SERIAL,
+					"t", &reply_serial);
+		} else {
+			add_field(builder, driver,
+					DBUS_MESSAGE_FIELD_REPLY_SERIAL,
+					"u", &message->reply_serial);
+		}
+
+		message->reply_serial = 0;
+	}
+
+	if (message->sender) {
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_SENDER,
+					"s", message->sender);
+		l_free(message->sender);
+		message->sender = NULL;
+	}
+
+	if (signature[0] != '\0' && !gvariant)
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_SIGNATURE,
+				"g", signature);
+
+	if (message->num_fds)
+		add_field(builder, driver, DBUS_MESSAGE_FIELD_UNIX_FDS,
+					"u", &message->num_fds);
+
+	driver->leave_array(builder);
+
+	generated_signature = driver->finish(builder, &message->header,
+						&header_size);
+	l_free(generated_signature);
+
+	driver->free(builder);
+
+	if (!_dbus_message_is_gvariant(message)) {
+		struct dbus_header *hdr = message->header;
+
+		hdr->dbus1.body_length = message->body_size;
+	}
+
+	/* We must align the end of the header to an 8-byte boundary */
+	message->header_size = align_len(header_size, 8);
+	message->header = l_realloc(message->header, message->header_size);
+	memset(message->header + header_size, 0,
+			message->header_size - header_size);
+	message->header_end = header_size;
+}
+
+struct container {
+	char type;
+	const char *sig_start;
+	const char *sig_end;
+	unsigned int n_items;
+};
+
+static bool append_arguments(struct l_dbus_message *message,
+					const char *signature, va_list args)
+{
+	struct l_dbus_message_builder *builder;
+	bool ret;
+
+	builder = l_dbus_message_builder_new(message);
+	if (!builder)
+		return false;
+
+	if (!l_dbus_message_builder_append_from_valist(builder, signature,
+									args)) {
+		l_dbus_message_builder_destroy(builder);
+		return false;
+	}
+
+	l_dbus_message_builder_finalize(builder);
+
+	ret = strcmp(signature, builder->message->signature) == 0;
+
+	l_dbus_message_builder_destroy(builder);
+
+	return ret;
+}
+
+LIB_EXPORT bool l_dbus_message_get_error(struct l_dbus_message *message,
+					const char **name, const char **text)
+{
+	struct dbus_header *hdr;
+	const char *str;
+
+	if (unlikely(!message))
+		return false;
+
+	hdr = message->header;
+
+	if (hdr->message_type != DBUS_MESSAGE_TYPE_ERROR)
+		return false;
+
+	if (!message->signature)
+		return false;
+
+	if (message->signature[0] != 's')
+		return false;
+
+	str = _dbus_message_get_nth_string_argument(message, 0);
+	if (!str)
+		return false;
+
+	if (!message->error_name)
+		get_header_field(message, DBUS_MESSAGE_FIELD_ERROR_NAME, 's',
+					&message->error_name);
+
+	if (name)
+		*name = message->error_name;
+
+	if (text)
+		*text = str;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_message_is_error(struct l_dbus_message *message)
+{
+	struct dbus_header *hdr;
+
+	if (unlikely(!message))
+		return false;
+
+	hdr = message->header;
+	return hdr->message_type == DBUS_MESSAGE_TYPE_ERROR;
+}
+
+LIB_EXPORT bool l_dbus_message_get_arguments_valist(
+					struct l_dbus_message *message,
+					const char *signature, va_list args)
+{
+	struct l_dbus_message_iter iter;
+
+	if (unlikely(!message))
+		return false;
+
+	if (!message->signature) {
+		/* An empty signature is valid */
+		if (!signature || *signature == '\0')
+			return true;
+
+		return false;
+	}
+
+	if (!signature || strcmp(message->signature, signature))
+		return false;
+
+	if (_dbus_message_is_gvariant(message)) {
+		if (!_gvariant_iter_init(&iter, message, message->signature,
+						NULL, message->body,
+						message->body_size))
+			return false;
+	} else
+		_dbus1_iter_init(&iter, message, message->signature, NULL,
+				message->body, message->body_size);
+
+	return message_iter_next_entry_valist(&iter, args);
+}
+
+LIB_EXPORT bool l_dbus_message_get_arguments(struct l_dbus_message *message,
+						const char *signature, ...)
+{
+	va_list args;
+	bool result;
+
+	va_start(args, signature);
+	result = l_dbus_message_get_arguments_valist(message, signature, args);
+	va_end(args);
+
+	return result;
+}
+
+LIB_EXPORT bool l_dbus_message_set_arguments(struct l_dbus_message *message,
+						const char *signature, ...)
+{
+	va_list args;
+	bool result;
+
+	if (unlikely(!message))
+		return false;
+
+	if (unlikely(message->sealed))
+		return false;
+
+	if (!signature)
+		return true;
+
+	va_start(args, signature);
+	result = append_arguments(message, signature, args);
+	va_end(args);
+
+	return result;
+}
+
+LIB_EXPORT bool l_dbus_message_set_arguments_valist(
+					struct l_dbus_message *message,
+					const char *signature, va_list args)
+{
+	bool result;
+
+	if (unlikely(!message))
+		return false;
+
+	if (!signature)
+		return true;
+
+	result = append_arguments(message, signature, args);
+
+	return result;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_path(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	if (!message->path && message->sealed)
+		get_header_field(message, DBUS_MESSAGE_FIELD_PATH, 'o',
+					&message->path);
+
+	return message->path;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_interface(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	if (!message->interface && message->sealed)
+		get_header_field(message, DBUS_MESSAGE_FIELD_INTERFACE, 's',
+					&message->interface);
+
+	return message->interface;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_member(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	if (!message->member && message->sealed)
+		get_header_field(message, DBUS_MESSAGE_FIELD_MEMBER, 's',
+					&message->member);
+
+	return message->member;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_destination(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	if (!message->destination && message->sealed)
+		get_header_field(message, DBUS_MESSAGE_FIELD_DESTINATION, 's',
+							&message->destination);
+
+	return message->destination;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_sender(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	if (!message->sender && message->sealed)
+		get_header_field(message, DBUS_MESSAGE_FIELD_SENDER, 's',
+					&message->sender);
+
+	return message->sender;
+}
+
+LIB_EXPORT const char *l_dbus_message_get_signature(
+						struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return NULL;
+
+	return message->signature;
+}
+
+uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message)
+{
+	if (unlikely(!message))
+		return 0;
+
+	if (message->reply_serial == 0 && message->sealed) {
+		if (_dbus_message_is_gvariant(message)) {
+			uint64_t reply_serial = 0;
+
+			get_header_field(message,
+					DBUS_MESSAGE_FIELD_REPLY_SERIAL, 't',
+					&reply_serial);
+
+			message->reply_serial = reply_serial;
+		} else
+			get_header_field(message,
+					DBUS_MESSAGE_FIELD_REPLY_SERIAL, 'u',
+					&message->reply_serial);
+	}
+
+	return message->reply_serial;
+}
+
+enum dbus_message_type _dbus_message_get_type(struct l_dbus_message *message)
+{
+	struct dbus_header *header;
+
+	header = message->header;
+	return header->message_type;
+}
+
+const char * _dbus_message_get_type_as_string(struct l_dbus_message *message)
+{
+	struct dbus_header *header;
+
+	header = message->header;
+
+	switch (header->message_type) {
+	case DBUS_MESSAGE_TYPE_METHOD_CALL:
+		return "method_call";
+	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+		return "method_return";
+	case DBUS_MESSAGE_TYPE_ERROR:
+		return "error";
+	case DBUS_MESSAGE_TYPE_SIGNAL:
+		return "signal";
+	}
+
+	return NULL;
+}
+
+uint8_t _dbus_message_get_endian(struct l_dbus_message *message)
+{
+	struct dbus_header *header = message->header;
+
+	return header->endian;
+}
+
+uint8_t _dbus_message_get_version(struct l_dbus_message *message)
+{
+	struct dbus_header *header = message->header;
+
+	return header->version;
+}
+
+LIB_EXPORT bool l_dbus_message_iter_next_entry(struct l_dbus_message_iter *iter,
+									...)
+{
+	va_list args;
+	bool result;
+
+	if (unlikely(!iter))
+		return false;
+
+	va_start(args, iter);
+	result = message_iter_next_entry_valist(iter, args);
+	va_end(args);
+
+	return result;
+}
+
+LIB_EXPORT bool l_dbus_message_iter_get_variant(
+					struct l_dbus_message_iter *iter,
+					const char *signature, ...)
+{
+	va_list args;
+	bool result;
+
+	if (unlikely(!iter))
+		return false;
+
+	if (!iter->sig_start || strlen(signature) != iter->sig_len ||
+			memcmp(iter->sig_start, signature, iter->sig_len))
+		return false;
+
+	va_start(args, signature);
+	result = message_iter_next_entry_valist(iter, args);
+	va_end(args);
+
+	return result;
+}
+
+LIB_EXPORT bool l_dbus_message_iter_get_fixed_array(
+					struct l_dbus_message_iter *iter,
+					void *out, uint32_t *n_elem)
+{
+	if (unlikely(!iter))
+		return false;
+
+	if (_dbus_message_is_gvariant(iter->message))
+		return false;
+
+	return _dbus1_iter_get_fixed_array(iter, out, n_elem);
+}
+
+void _dbus_message_set_sender(struct l_dbus_message *message,
+					const char *sender)
+{
+	if (!_dbus_message_is_gvariant(message))
+		return;
+
+	l_free(message->sender);
+
+	message->sender = l_strdup(sender);
+}
+
+void _dbus_message_set_destination(struct l_dbus_message *message,
+					const char *destination)
+{
+	if (!_dbus_message_is_gvariant(message))
+		return;
+
+	l_free(message->destination);
+
+	message->destination = l_strdup(destination);
+}
+
+LIB_EXPORT struct l_dbus_message_builder *l_dbus_message_builder_new(
+						struct l_dbus_message *message)
+{
+	struct l_dbus_message_builder *ret;
+
+	if (unlikely(!message))
+		return NULL;
+
+	if (message->sealed)
+		return NULL;
+
+	ret = l_new(struct l_dbus_message_builder, 1);
+	ret->message = l_dbus_message_ref(message);
+
+	if (_dbus_message_is_gvariant(message))
+		ret->driver = &gvariant_driver;
+	else
+		ret->driver = &dbus1_driver;
+
+	ret->builder = ret->driver->new(NULL, 0);
+
+	return ret;
+}
+
+LIB_EXPORT void l_dbus_message_builder_destroy(
+					struct l_dbus_message_builder *builder)
+{
+	if (unlikely(!builder))
+		return;
+
+	builder->driver->free(builder->builder);
+	l_dbus_message_unref(builder->message);
+
+	l_free(builder);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_append_basic(
+					struct l_dbus_message_builder *builder,
+					char type, const void *value)
+{
+	if (unlikely(!builder))
+		return false;
+
+	return builder->driver->append_basic(builder->builder, type, value);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_enter_container(
+					struct l_dbus_message_builder *builder,
+					char container_type,
+					const char *signature)
+{
+	if (unlikely(!builder))
+		return false;
+
+	switch (container_type) {
+	case DBUS_CONTAINER_TYPE_ARRAY:
+		return builder->driver->enter_array(builder->builder,
+								signature);
+	case DBUS_CONTAINER_TYPE_DICT_ENTRY:
+		return builder->driver->enter_dict(builder->builder, signature);
+	case DBUS_CONTAINER_TYPE_STRUCT:
+		return builder->driver->enter_struct(builder->builder,
+								signature);
+	case DBUS_CONTAINER_TYPE_VARIANT:
+		return builder->driver->enter_variant(builder->builder,
+								signature);
+	default:
+		break;
+	}
+
+	return false;
+}
+
+LIB_EXPORT bool l_dbus_message_builder_leave_container(
+					struct l_dbus_message_builder *builder,
+					char container_type)
+{
+	if (unlikely(!builder))
+		return false;
+
+	switch (container_type) {
+	case DBUS_CONTAINER_TYPE_ARRAY:
+		return builder->driver->leave_array(builder->builder);
+	case DBUS_CONTAINER_TYPE_DICT_ENTRY:
+		return builder->driver->leave_dict(builder->builder);
+	case DBUS_CONTAINER_TYPE_STRUCT:
+		return builder->driver->leave_struct(builder->builder);
+	case DBUS_CONTAINER_TYPE_VARIANT:
+		return builder->driver->leave_variant(builder->builder);
+	default:
+		break;
+	}
+
+	return false;
+}
+
+LIB_EXPORT bool l_dbus_message_builder_enter_struct(
+					struct l_dbus_message_builder *builder,
+					const char *signature)
+{
+	return l_dbus_message_builder_enter_container(builder, 'r', signature);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_leave_struct(
+					struct l_dbus_message_builder *builder)
+{
+	return l_dbus_message_builder_leave_container(builder, 'r');
+}
+
+LIB_EXPORT bool l_dbus_message_builder_enter_array(
+					struct l_dbus_message_builder *builder,
+					const char *signature)
+{
+	return l_dbus_message_builder_enter_container(builder, 'a', signature);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_leave_array(
+					struct l_dbus_message_builder *builder)
+{
+	return l_dbus_message_builder_leave_container(builder, 'a');
+}
+
+LIB_EXPORT bool l_dbus_message_builder_enter_dict(
+					struct l_dbus_message_builder *builder,
+					const char *signature)
+{
+	return l_dbus_message_builder_enter_container(builder, 'e', signature);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_leave_dict(
+					struct l_dbus_message_builder *builder)
+{
+	return l_dbus_message_builder_leave_container(builder, 'e');
+}
+
+LIB_EXPORT bool l_dbus_message_builder_enter_variant(
+					struct l_dbus_message_builder *builder,
+					const char *signature)
+{
+	return l_dbus_message_builder_enter_container(builder, 'v', signature);
+}
+
+LIB_EXPORT bool l_dbus_message_builder_leave_variant(
+					struct l_dbus_message_builder *builder)
+{
+	return l_dbus_message_builder_leave_container(builder, 'v');
+}
+
+/**
+ * l_dbus_message_builder_append_from_iter:
+ * @builder: message builder to receive a new value
+ * @from: message iterator to have its position moved by one value
+ *
+ * Copy one value from a message iterator onto a message builder.  The
+ * value's signature is also copied.
+ *
+ * Returns: whether the value was correctly copied.  On failure both
+ *          the @from iterator and the @builder may have their positions
+ *          moved to somewhere within the new value if it's of a
+ *          container type.
+ **/
+LIB_EXPORT bool l_dbus_message_builder_append_from_iter(
+					struct l_dbus_message_builder *builder,
+					struct l_dbus_message_iter *from)
+{
+	static const char *simple_types = "sogybnqiuxtd";
+	char type = from->sig_start[from->sig_pos];
+	char container_type;
+	char signature[256];
+	struct l_dbus_message_iter iter;
+	void *basic_ptr;
+	uint64_t basic;
+	uint32_t uint32_val;
+	bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
+	bool (*enter_func)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+	bool (*enter_struct)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+	bool (*enter_array)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+	bool (*enter_variant)(struct l_dbus_message_iter *,
+				struct l_dbus_message_iter *);
+
+	if (_dbus_message_is_gvariant(from->message)) {
+		get_basic = _gvariant_iter_next_entry_basic;
+		enter_struct = _gvariant_iter_enter_struct;
+		enter_array = _gvariant_iter_enter_array;
+		enter_variant = _gvariant_iter_enter_variant;
+	} else {
+		get_basic = _dbus1_iter_next_entry_basic;
+		enter_struct = _dbus1_iter_enter_struct;
+		enter_array = _dbus1_iter_enter_array;
+		enter_variant = _dbus1_iter_enter_variant;
+	}
+
+	if (strchr(simple_types, type)) {
+		if (strchr("sog", type)) {
+			if (!get_basic(from, type, &basic_ptr))
+				return false;
+		} else {
+			basic_ptr = &basic;
+
+			if (!get_basic(from, type, basic_ptr))
+				return false;
+		}
+
+		if (!l_dbus_message_builder_append_basic(builder, type,
+								basic_ptr))
+			return false;
+
+		return true;
+	}
+
+	switch (type) {
+	case 'h':
+		if (!get_basic(from, type, &uint32_val))
+			return false;
+
+		if (!l_dbus_message_builder_append_basic(builder, type,
+						&builder->message->num_fds))
+			return false;
+
+		if (builder->message->num_fds <
+				L_ARRAY_SIZE(builder->message->fds)) {
+			int fd;
+
+			if (uint32_val < from->message->num_fds)
+				fd = fcntl(from->message->fds[uint32_val],
+						F_DUPFD_CLOEXEC, 3);
+			else
+				fd = -1;
+
+			builder->message->fds[builder->message->num_fds++] = fd;
+		}
+
+		return true;
+	case '(':
+		enter_func = enter_struct;
+		container_type = DBUS_CONTAINER_TYPE_STRUCT;
+		break;
+	case '{':
+		enter_func = enter_struct;
+		container_type = DBUS_CONTAINER_TYPE_DICT_ENTRY;
+		break;
+	case 'a':
+		enter_func = enter_array;
+		container_type = DBUS_CONTAINER_TYPE_ARRAY;
+		break;
+	case 'v':
+		enter_func = enter_variant;
+		container_type = DBUS_CONTAINER_TYPE_VARIANT;
+		break;
+	default:
+		return false;
+	}
+
+	if (!enter_func(from, &iter))
+		return false;
+
+	memcpy(signature, iter.sig_start, iter.sig_len);
+	signature[iter.sig_len] = '\0';
+
+	if (!l_dbus_message_builder_enter_container(builder,
+						container_type, signature))
+		return false;
+
+	if (container_type == DBUS_CONTAINER_TYPE_ARRAY)
+		while(l_dbus_message_builder_append_from_iter(builder, &iter));
+	else
+		while (iter.sig_pos < iter.sig_len)
+			if (!l_dbus_message_builder_append_from_iter(builder,
+									&iter))
+				return false;
+
+	if (!l_dbus_message_builder_leave_container(builder,
+						container_type))
+		return false;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_message_builder_append_from_valist(
+					struct l_dbus_message_builder *builder,
+					const char *signature, va_list args)
+{
+	struct builder_driver *driver;
+	char subsig[256];
+	const char *sigend;
+	/* Nesting requires an extra stack entry for the base level */
+	struct container stack[DBUS_MAX_NESTING + 1];
+	unsigned int stack_index = 0;
+
+	if (unlikely(!builder))
+		return false;
+
+	driver = builder->driver;
+
+	stack[stack_index].type = DBUS_CONTAINER_TYPE_STRUCT;
+	stack[stack_index].sig_start = signature;
+	stack[stack_index].sig_end = signature + strlen(signature);
+	stack[stack_index].n_items = 0;
+
+	while (stack_index != 0 || stack[0].sig_start != stack[0].sig_end) {
+		const char *s;
+		const char *str;
+
+		if (stack[stack_index].type == DBUS_CONTAINER_TYPE_ARRAY &&
+				stack[stack_index].n_items == 0)
+			stack[stack_index].sig_start =
+				stack[stack_index].sig_end;
+
+		if (stack[stack_index].sig_start ==
+				stack[stack_index].sig_end) {
+			bool ret;
+
+			/*
+			 * Sanity check in case of an invalid signature that
+			 * isn't caught elsewhere.
+			 */
+			if (unlikely(stack_index == 0))
+				return false;
+
+			switch (stack[stack_index].type) {
+			case DBUS_CONTAINER_TYPE_STRUCT:
+				ret = driver->leave_struct(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_DICT_ENTRY:
+				ret = driver->leave_dict(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_VARIANT:
+				ret = driver->leave_variant(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_ARRAY:
+				ret = driver->leave_array(builder->builder);
+				break;
+			default:
+				ret = false;
+			}
+
+			if (!ret)
+				return false;
+
+			stack_index -= 1;
+			continue;
+		}
+
+		s = stack[stack_index].sig_start;
+
+		if (stack[stack_index].type != DBUS_CONTAINER_TYPE_ARRAY)
+			stack[stack_index].sig_start += 1;
+		else
+			stack[stack_index].n_items -= 1;
+
+		switch (*s) {
+		case 'o':
+		case 's':
+		case 'g':
+			str = va_arg(args, const char *);
+
+			if (!driver->append_basic(builder->builder, *s, str))
+				return false;
+			break;
+		case 'b':
+		case 'y':
+		{
+			uint8_t y = (uint8_t) va_arg(args, int);
+
+			if (!driver->append_basic(builder->builder, *s, &y))
+				return false;
+
+			break;
+		}
+		case 'n':
+		case 'q':
+		{
+			uint16_t n = (uint16_t) va_arg(args, int);
+
+			if (!driver->append_basic(builder->builder, *s, &n))
+				return false;
+
+			break;
+		}
+		case 'i':
+		case 'u':
+		{
+			uint32_t u = va_arg(args, uint32_t);
+
+			if (!driver->append_basic(builder->builder, *s, &u))
+				return false;
+
+			break;
+		}
+		case 'h':
+		{
+			int fd = va_arg(args, int);
+			struct l_dbus_message *message = builder->message;
+
+			if (!driver->append_basic(builder->builder, *s,
+							&message->num_fds))
+				return false;
+
+			if (message->num_fds < L_ARRAY_SIZE(message->fds))
+				message->fds[message->num_fds++] =
+					fcntl(fd, F_DUPFD_CLOEXEC, 3);
+
+			break;
+		}
+		case 'x':
+		case 't':
+		{
+			uint64_t x = va_arg(args, uint64_t);
+
+			if (!driver->append_basic(builder->builder, *s, &x))
+				return false;
+			break;
+		}
+		case 'd':
+		{
+			double d = va_arg(args, double);
+
+			if (!driver->append_basic(builder->builder, *s, &d))
+				return false;
+			break;
+		}
+		case '(':
+		case '{':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			sigend = _dbus_signature_end(s);
+			memcpy(subsig, s + 1, sigend - s - 1);
+			subsig[sigend - s - 1] = '\0';
+
+			if (*s == '(' && !driver->enter_struct(builder->builder,
+									subsig))
+				return false;
+
+			if (*s == '{' && !driver->enter_dict(builder->builder,
+									subsig))
+				return false;
+
+			if (stack[stack_index].type !=
+					DBUS_CONTAINER_TYPE_ARRAY)
+				stack[stack_index].sig_start = sigend + 1;
+
+			stack_index += 1;
+			stack[stack_index].sig_start = s + 1;
+			stack[stack_index].sig_end = sigend;
+			stack[stack_index].n_items = 0;
+			stack[stack_index].type = *s == '(' ?
+						DBUS_CONTAINER_TYPE_STRUCT :
+						DBUS_CONTAINER_TYPE_DICT_ENTRY;
+
+			break;
+		case 'v':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			str = va_arg(args, const char *);
+
+			if (!str)
+				return false;
+
+			if (!driver->enter_variant(builder->builder, str))
+				return false;
+
+			stack_index += 1;
+			stack[stack_index].type = DBUS_CONTAINER_TYPE_VARIANT;
+			stack[stack_index].sig_start = str;
+			stack[stack_index].sig_end = str + strlen(str);
+			stack[stack_index].n_items = 0;
+
+			break;
+		case 'a':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			sigend = _dbus_signature_end(s + 1) + 1;
+			memcpy(subsig, s + 1, sigend - s - 1);
+			subsig[sigend - s - 1] = '\0';
+
+			if (!driver->enter_array(builder->builder, subsig))
+				return false;
+
+			if (stack[stack_index].type !=
+					DBUS_CONTAINER_TYPE_ARRAY)
+				stack[stack_index].sig_start = sigend;
+
+			stack_index += 1;
+			stack[stack_index].sig_start = s + 1;
+			stack[stack_index].sig_end = sigend;
+			stack[stack_index].n_items = va_arg(args, unsigned int);
+			stack[stack_index].type = DBUS_CONTAINER_TYPE_ARRAY;
+
+			break;
+		default:
+			return false;
+		}
+	}
+
+	return true;
+}
+
+LIB_EXPORT struct l_dbus_message *l_dbus_message_builder_finalize(
+					struct l_dbus_message_builder *builder)
+{
+	char *generated_signature;
+
+	if (unlikely(!builder))
+		return NULL;
+
+	generated_signature = builder->driver->finish(builder->builder,
+						&builder->message->body,
+						&builder->message->body_size);
+
+	build_header(builder->message, generated_signature);
+	builder->message->sealed = true;
+	builder->message->signature = generated_signature;
+	builder->message->signature_free = true;
+
+	return builder->message;
+}
+
+bool _dbus_message_builder_mark(struct l_dbus_message_builder *builder)
+{
+	if (unlikely(!builder))
+		return false;
+
+	return builder->driver->mark(builder->builder);
+}
+
+bool _dbus_message_builder_rewind(struct l_dbus_message_builder *builder)
+{
+	if (unlikely(!builder))
+		return false;
+
+	return builder->driver->rewind(builder->builder);
+}
diff --git a/ell/dbus-name-cache.c b/ell/dbus-name-cache.c
new file mode 100644
index 0000000..d26e8a5
--- /dev/null
+++ b/ell/dbus-name-cache.c
@@ -0,0 +1,298 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2016  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util.h"
+#include "hashmap.h"
+#include "idle.h"
+#include "dbus.h"
+#include "dbus-private.h"
+
+struct _dbus_name_cache {
+	struct l_dbus *bus;
+	struct l_hashmap *names;
+	const struct _dbus_name_ops *driver;
+	unsigned int last_watch_id;
+	struct l_idle *watch_remove_work;
+};
+
+struct service_watch {
+	l_dbus_watch_func_t connect_func;
+	l_dbus_watch_func_t disconnect_func;
+	l_dbus_destroy_func_t destroy;
+	void *user_data;
+	unsigned int id;
+	struct service_watch *next;
+};
+
+struct name_cache_entry {
+	int ref_count;
+	char *unique_name;
+	struct service_watch *watches;
+};
+
+struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
+					const struct _dbus_name_ops *driver)
+{
+	struct _dbus_name_cache *cache;
+
+	cache = l_new(struct _dbus_name_cache, 1);
+
+	cache->bus = bus;
+	cache->driver = driver;
+
+	return cache;
+}
+
+static void service_watch_destroy(void *data)
+{
+	struct service_watch *watch = data;
+
+	if (watch->destroy)
+		watch->destroy(watch->user_data);
+
+	l_free(watch);
+}
+
+static void name_cache_entry_destroy(void *data)
+{
+	struct name_cache_entry *entry = data;
+	struct service_watch *watch;
+
+	while (entry->watches) {
+		watch = entry->watches;
+		entry->watches = watch->next;
+
+		service_watch_destroy(watch);
+	}
+
+	l_free(entry->unique_name);
+
+	l_free(entry);
+}
+
+void _dbus_name_cache_free(struct _dbus_name_cache *cache)
+{
+	if (!cache)
+		return;
+
+	if (cache->watch_remove_work)
+		l_idle_remove(cache->watch_remove_work);
+
+	l_hashmap_destroy(cache->names, name_cache_entry_destroy);
+
+	l_free(cache);
+}
+
+bool _dbus_name_cache_add(struct _dbus_name_cache *cache, const char *name)
+{
+	struct name_cache_entry *entry;
+
+	if (!_dbus_valid_bus_name(name))
+		return false;
+
+	if (!cache->names)
+		cache->names = l_hashmap_string_new();
+
+	entry = l_hashmap_lookup(cache->names, name);
+
+	if (!entry) {
+		entry = l_new(struct name_cache_entry, 1);
+
+		l_hashmap_insert(cache->names, name, entry);
+
+		cache->driver->get_name_owner(cache->bus, name);
+	}
+
+	entry->ref_count++;
+
+	return true;
+}
+
+bool _dbus_name_cache_remove(struct _dbus_name_cache *cache, const char *name)
+{
+	struct name_cache_entry *entry;
+
+	entry = l_hashmap_lookup(cache->names, name);
+
+	if (!entry)
+		return false;
+
+	if (--entry->ref_count)
+		return true;
+
+	l_hashmap_remove(cache->names, name);
+
+	name_cache_entry_destroy(entry);
+
+	return true;
+}
+
+const char *_dbus_name_cache_lookup(struct _dbus_name_cache *cache,
+					const char *name)
+{
+	struct name_cache_entry *entry;
+
+	entry = l_hashmap_lookup(cache->names, name);
+
+	if (!entry)
+		return NULL;
+
+	return entry->unique_name;
+}
+
+void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
+				const char *name, const char *owner)
+{
+	struct name_cache_entry *entry;
+	struct service_watch *watch;
+	bool prev_connected, connected;
+
+	if (!cache)
+		return;
+
+	entry = l_hashmap_lookup(cache->names, name);
+
+	if (!entry)
+		return;
+
+	prev_connected = !!entry->unique_name;
+	connected = owner && *owner != '\0';
+
+	l_free(entry->unique_name);
+
+	entry->unique_name = connected ? l_strdup(owner) : NULL;
+
+	/*
+	 * This check also means we notify all watchers who have a connected
+	 * callback when we first learn that the service is in fact connected.
+	 */
+	if (connected == prev_connected)
+		return;
+
+	for (watch = entry->watches; watch; watch = watch->next)
+		if (connected && watch->connect_func)
+			watch->connect_func(cache->bus, watch->user_data);
+		else if (!connected && watch->disconnect_func)
+			watch->disconnect_func(cache->bus, watch->user_data);
+}
+
+unsigned int _dbus_name_cache_add_watch(struct _dbus_name_cache *cache,
+					const char *name,
+					l_dbus_watch_func_t connect_func,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	struct name_cache_entry *entry;
+	struct service_watch *watch;
+
+	if (!_dbus_name_cache_add(cache, name))
+		return 0;
+
+	watch = l_new(struct service_watch, 1);
+	watch->id = ++cache->last_watch_id;
+	watch->connect_func = connect_func;
+	watch->disconnect_func = disconnect_func;
+	watch->user_data = user_data;
+	watch->destroy = destroy;
+
+	entry = l_hashmap_lookup(cache->names, name);
+
+	watch->next = entry->watches;
+	entry->watches = watch;
+
+	if (entry->unique_name && connect_func)
+		watch->connect_func(cache->bus, watch->user_data);
+
+	return watch->id;
+}
+
+static bool service_watch_remove(const void *key, void *value, void *user_data)
+{
+	struct name_cache_entry *entry = value;
+	struct service_watch **watch, *tmp;
+
+	for (watch = &entry->watches; *watch;) {
+		if ((*watch)->id) {
+			watch = &(*watch)->next;
+			continue;
+		}
+
+		tmp = *watch;
+		*watch = tmp->next;
+
+		service_watch_destroy(tmp);
+
+		entry->ref_count--;
+	}
+
+	if (entry->ref_count)
+		return false;
+
+	name_cache_entry_destroy(entry);
+
+	return true;
+}
+
+static void service_watch_remove_all(struct l_idle *idle, void *user_data)
+{
+	struct _dbus_name_cache *cache = user_data;
+
+	l_idle_remove(cache->watch_remove_work);
+	cache->watch_remove_work = NULL;
+
+	l_hashmap_foreach_remove(cache->names, service_watch_remove, cache);
+}
+
+static void service_watch_mark(const void *key, void *value, void *user_data)
+{
+	struct name_cache_entry *entry = value;
+	struct service_watch *watch;
+	unsigned int *id = user_data;
+
+	if (!*id)
+		return;
+
+	for (watch = entry->watches; watch; watch = watch->next)
+		if (watch->id == *id) {
+			watch->id = 0;
+			watch->connect_func = NULL;
+			watch->disconnect_func = NULL;
+
+			if (watch->destroy) {
+				watch->destroy(watch->user_data);
+				watch->destroy = NULL;
+			}
+
+			*id = 0;
+			break;
+		}
+}
+
+bool _dbus_name_cache_remove_watch(struct _dbus_name_cache *cache,
+					unsigned int id)
+{
+	l_hashmap_foreach(cache->names, service_watch_mark, &id);
+
+	if (id)
+		return false;
+
+	if (!cache->watch_remove_work)
+		cache->watch_remove_work = l_idle_create(
+						service_watch_remove_all,
+						cache, NULL);
+
+	return true;
+}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
new file mode 100644
index 0000000..0c06410
--- /dev/null
+++ b/ell/dbus-private.h
@@ -0,0 +1,297 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <endian.h>
+
+enum dbus_message_type {
+	DBUS_MESSAGE_TYPE_METHOD_CALL	= 1,
+	DBUS_MESSAGE_TYPE_METHOD_RETURN	= 2,
+	DBUS_MESSAGE_TYPE_ERROR		= 3,
+	DBUS_MESSAGE_TYPE_SIGNAL	= 4,
+};
+
+enum dbus_container_type {
+	DBUS_CONTAINER_TYPE_ARRAY	= 'a',
+	DBUS_CONTAINER_TYPE_STRUCT	= 'r',
+	DBUS_CONTAINER_TYPE_VARIANT	= 'v',
+	DBUS_CONTAINER_TYPE_DICT_ENTRY	= 'e',
+};
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define DBUS_NATIVE_ENDIAN 'l'
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define DBUS_NATIVE_ENDIAN 'B'
+#else
+#error "Unknown byte order"
+#endif
+
+struct dbus_header {
+	uint8_t  endian;
+	uint8_t  message_type;
+	uint8_t  flags;
+	uint8_t  version;
+
+	union {
+		struct {
+			uint32_t body_length;
+			uint32_t serial;
+			uint32_t field_length;
+		} __attribute__ ((packed)) dbus1;
+	};
+} __attribute__ ((packed));
+#define DBUS_HEADER_SIZE 16
+
+struct dbus_builder;
+struct l_string;
+struct l_dbus_interface;
+struct _dbus_method;
+struct _dbus_signal;
+struct _dbus_property;
+struct l_dbus_message_iter;
+struct l_dbus_message;
+struct l_dbus;
+struct _dbus_filter;
+struct _dbus_filter_condition;
+struct _dbus_filter_ops;
+
+void _dbus1_iter_init(struct l_dbus_message_iter *iter,
+			struct l_dbus_message *message,
+			const char *sig_start, const char *sig_end,
+			const void *data, size_t len);
+bool _dbus1_iter_next_entry_basic(struct l_dbus_message_iter *iter, char type,
+					void *out);
+bool _dbus1_iter_get_fixed_array(struct l_dbus_message_iter *iter,
+					void *out, uint32_t *n_elem);
+bool _dbus1_iter_enter_struct(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *structure);
+bool _dbus1_iter_enter_variant(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *variant);
+bool _dbus1_iter_enter_array(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *array);
+bool _dbus1_iter_skip_entry(struct l_dbus_message_iter *iter);
+
+struct dbus_builder *_dbus1_builder_new(void *body, size_t body_size);
+void _dbus1_builder_free(struct dbus_builder *builder);
+bool _dbus1_builder_append_basic(struct dbus_builder *builder,
+					char type, const void *value);
+bool _dbus1_builder_enter_struct(struct dbus_builder *builder,
+					const char *signature);
+bool _dbus1_builder_leave_struct(struct dbus_builder *builder);
+bool _dbus1_builder_enter_dict(struct dbus_builder *builder,
+					const char *signature);
+bool _dbus1_builder_leave_dict(struct dbus_builder *builder);
+bool _dbus1_builder_enter_variant(struct dbus_builder *builder,
+					const char *signature);
+bool _dbus1_builder_leave_variant(struct dbus_builder *builder);
+bool _dbus1_builder_enter_array(struct dbus_builder *builder,
+					const char *signature);
+bool _dbus1_builder_leave_array(struct dbus_builder *builder);
+char *_dbus1_builder_finish(struct dbus_builder *builder,
+				void **body, size_t *body_size);
+bool _dbus1_builder_mark(struct dbus_builder *builder);
+bool _dbus1_builder_rewind(struct dbus_builder *builder);
+
+void *_dbus_message_get_body(struct l_dbus_message *msg, size_t *out_size);
+void *_dbus_message_get_header(struct l_dbus_message *msg, size_t *out_size);
+void *_dbus_message_get_footer(struct l_dbus_message *msg, size_t *out_size);
+int *_dbus_message_get_fds(struct l_dbus_message *msg, uint32_t *num_fds);
+void _dbus_message_set_serial(struct l_dbus_message *msg, uint32_t serial);
+uint32_t _dbus_message_get_serial(struct l_dbus_message *msg);
+uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message);
+
+void _dbus_message_set_sender(struct l_dbus_message *message,
+					const char *sender);
+void _dbus_message_set_destination(struct l_dbus_message *message,
+					const char *destination);
+
+enum dbus_message_type _dbus_message_get_type(struct l_dbus_message *message);
+const char * _dbus_message_get_type_as_string(struct l_dbus_message *message);
+uint8_t _dbus_message_get_version(struct l_dbus_message *message);
+uint8_t _dbus_message_get_endian(struct l_dbus_message *message);
+const char *_dbus_message_get_nth_string_argument(
+					struct l_dbus_message *message, int n);
+
+struct l_dbus_message *_dbus_message_new_method_call(uint8_t version,
+							const char *destination,
+							const char *path,
+							const char *interface,
+							const char *method);
+struct l_dbus_message *_dbus_message_new_signal(uint8_t version,
+						const char *path,
+						const char *interface,
+						const char *name);
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+						uint32_t reply_serial,
+						const char *destination,
+						const char *name,
+						const char *error);
+
+struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size,
+						int fds[], uint32_t num_fds);
+struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
+						void *body, size_t body_size,
+						int fds[], uint32_t num_fds);
+bool dbus_message_compare(struct l_dbus_message *message,
+					const void *data, size_t size);
+
+bool _dbus_message_builder_mark(struct l_dbus_message_builder *builder);
+bool _dbus_message_builder_rewind(struct l_dbus_message_builder *builder);
+
+unsigned int _dbus_message_unix_fds_from_header(const void *data, size_t size);
+
+const char *_dbus_signature_end(const char *signature);
+
+bool _dbus_valid_object_path(const char *path);
+bool _dbus_valid_signature(const char *sig);
+int _dbus_num_children(const char *sig);
+bool _dbus_valid_interface(const char *interface);
+bool _dbus_valid_method(const char *method);
+bool _dbus_parse_unique_name(const char *name, uint64_t *out_id);
+bool _dbus_valid_bus_name(const char *bus_name);
+
+bool _dbus1_header_is_valid(void *data, size_t size);
+
+void _dbus_method_introspection(struct _dbus_method *info,
+					struct l_string *buf);
+void _dbus_signal_introspection(struct _dbus_signal *info,
+					struct l_string *buf);
+void _dbus_property_introspection(struct _dbus_property *info,
+						struct l_string *buf);
+void _dbus_interface_introspection(struct l_dbus_interface *interface,
+						struct l_string *buf);
+
+struct l_dbus_interface *_dbus_interface_new(const char *name);
+void _dbus_interface_free(struct l_dbus_interface *interface);
+
+struct _dbus_method *_dbus_interface_find_method(struct l_dbus_interface *i,
+							const char *method);
+struct _dbus_signal *_dbus_interface_find_signal(struct l_dbus_interface *i,
+							const char *signal);
+struct _dbus_property *_dbus_interface_find_property(struct l_dbus_interface *i,
+						const char *property);
+
+struct _dbus_object_tree *_dbus_object_tree_new(void);
+void _dbus_object_tree_free(struct _dbus_object_tree *tree);
+
+struct object_node *_dbus_object_tree_makepath(struct _dbus_object_tree *tree,
+						const char *path);
+struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
+						const char *path);
+void _dbus_object_tree_prune_node(struct object_node *node);
+
+struct object_node *_dbus_object_tree_new_object(struct _dbus_object_tree *tree,
+						const char *path,
+						void *user_data,
+						void (*destroy) (void *));
+bool _dbus_object_tree_object_destroy(struct _dbus_object_tree *tree,
+						const char *path);
+
+bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
+				const char *interface,
+				void (*setup_func)(struct l_dbus_interface *),
+				void (*destroy) (void *),
+				bool old_style_properties);
+bool _dbus_object_tree_unregister_interface(struct _dbus_object_tree *tree,
+						const char *interface);
+
+bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
+					const char *path, const char *interface,
+					void *user_data);
+bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
+					const char *path,
+					const char *interface);
+void *_dbus_object_tree_get_interface_data(struct _dbus_object_tree *tree,
+						const char *path,
+						const char *interface);
+bool _dbus_object_tree_set_interface_data(struct _dbus_object_tree *tree,
+						const char *path,
+						const char *interface,
+						void *user_data);
+
+void _dbus_object_tree_introspect(struct _dbus_object_tree *tree,
+					const char *path, struct l_string *buf);
+bool _dbus_object_tree_dispatch(struct _dbus_object_tree *tree,
+					struct l_dbus *dbus,
+					struct l_dbus_message *message);
+struct l_dbus_message *_dbus_object_tree_get_objects(
+					struct _dbus_object_tree *tree,
+					struct l_dbus *dbus,
+					const char *path,
+					struct l_dbus_message *message);
+
+bool _dbus_object_tree_property_changed(struct l_dbus *dbus,
+					const char *path,
+					const char *interface_name,
+					const char *property_name);
+
+void _dbus_object_tree_signals_flush(struct l_dbus *dbus, const char *path);
+
+typedef void (*_dbus_name_owner_change_func_t)(const char *name,
+						uint64_t old_owner,
+						uint64_t new_owner,
+						void *user_data);
+
+uint8_t _dbus_get_version(struct l_dbus *dbus);
+int _dbus_get_fd(struct l_dbus *dbus);
+struct _dbus_object_tree *_dbus_get_tree(struct l_dbus *dbus);
+
+struct _dbus_name_ops {
+	bool (*get_name_owner)(struct l_dbus *bus, const char *name);
+};
+
+struct _dbus_name_cache;
+
+struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
+					const struct _dbus_name_ops *driver);
+void _dbus_name_cache_free(struct _dbus_name_cache *cache);
+
+bool _dbus_name_cache_add(struct _dbus_name_cache *cache, const char *name);
+bool _dbus_name_cache_remove(struct _dbus_name_cache *cache, const char *name);
+const char *_dbus_name_cache_lookup(struct _dbus_name_cache *cache,
+					const char *name);
+
+void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
+				const char *name, const char *owner);
+
+unsigned int _dbus_name_cache_add_watch(struct _dbus_name_cache *cache,
+					const char *name,
+					l_dbus_watch_func_t connect_func,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+bool _dbus_name_cache_remove_watch(struct _dbus_name_cache *cache,
+					unsigned int id);
+
+struct _dbus_filter_condition {
+	enum l_dbus_match_type type;
+	const char *value;
+};
+
+struct _dbus_filter_ops {
+	bool skip_register;
+	bool (*add_match)(struct l_dbus *bus, unsigned int id,
+				const struct _dbus_filter_condition *rule,
+				int rule_len);
+	bool (*remove_match)(struct l_dbus *bus, unsigned int id);
+};
+
+struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
+					const struct _dbus_filter_ops *driver,
+					struct _dbus_name_cache *name_cache);
+void _dbus_filter_free(struct _dbus_filter *filter);
+
+unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
+				const struct _dbus_filter_condition *rule,
+				int rule_len,
+				l_dbus_message_func_t signal_func,
+				void *user_data);
+bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id);
+
+char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
+				int rule_len);
+
+void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data);
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
new file mode 100644
index 0000000..0300bfe
--- /dev/null
+++ b/ell/dbus-service.c
@@ -0,0 +1,2159 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "useful.h"
+#include "queue.h"
+#include "string.h"
+#include "hashmap.h"
+#include "dbus.h"
+#include "dbus-service.h"
+#include "dbus-private.h"
+#include "private.h"
+#include "idle.h"
+
+#define XML_ID "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+#define XML_DTD "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
+#define XML_HEAD "<!DOCTYPE node PUBLIC \""XML_ID"\"\n\""XML_DTD"\">\n"
+
+static const char *static_introspectable =
+		"\t<interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+		"\t\t<method name=\"Introspect\">\n"
+		"\t\t\t<arg name=\"xml\" type=\"s\" direction=\"out\"/>\n"
+		"\t\t</method>\n\t</interface>\n";
+
+struct _dbus_method {
+	l_dbus_interface_method_cb_t cb;
+	uint32_t flags;
+	unsigned char name_len;
+	char metainfo[];
+};
+
+struct _dbus_signal {
+	uint32_t flags;
+	unsigned char name_len;
+	char metainfo[];
+};
+
+struct _dbus_property {
+	l_dbus_property_get_cb_t getter;
+	l_dbus_property_set_cb_t setter;
+	uint32_t flags;
+	unsigned char name_len;
+	char metainfo[];
+};
+
+struct l_dbus_interface {
+	struct l_queue *methods;
+	struct l_queue *signals;
+	struct l_queue *properties;
+	bool handle_old_style_properties;
+	void (*instance_destroy)(void *);
+	char name[];
+};
+
+struct child_node {
+	struct object_node *node;
+	struct child_node *next;
+	char subpath[];
+};
+
+struct interface_instance {
+	struct l_dbus_interface *interface;
+	void *user_data;
+};
+
+struct object_node {
+	struct object_node *parent;
+	struct l_queue *instances;
+	struct child_node *children;
+	void *user_data;
+	void (*destroy) (void *);
+};
+
+struct object_manager {
+	char *path;
+	struct l_dbus *dbus;
+	struct l_queue *announce_added;
+	struct l_queue *announce_removed;
+};
+
+struct interface_add_record {
+	char *path;
+	struct object_node *object;
+	struct l_queue *instances;
+};
+
+struct interface_remove_record {
+	char *path;
+	struct object_node *object;
+	struct l_queue *interface_names;
+};
+
+struct property_change_record {
+	char *path;
+	struct object_node *object;
+	struct interface_instance *instance;
+	struct l_queue *properties;
+};
+
+struct _dbus_object_tree {
+	struct l_hashmap *interfaces;
+	struct l_hashmap *objects;
+	struct object_node *root;
+	struct l_queue *object_managers;
+	struct l_queue *property_changes;
+	struct l_idle *emit_signals_work;
+	bool flushing;
+};
+
+void _dbus_method_introspection(struct _dbus_method *info,
+					struct l_string *buf)
+{
+	const char *sig;
+	const char *end;
+	const char *pname;
+	unsigned int offset = info->name_len + 1;
+
+	l_string_append_printf(buf, "\t\t<method name=\"%s\">\n",
+				info->metainfo);
+
+	sig = info->metainfo + offset;
+	offset += strlen(sig) + 1;
+
+	for (; *sig; sig++) {
+		end = _dbus_signature_end(sig);
+		pname = info->metainfo + offset;
+
+		l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
+					"type=\"%.*s\" direction=\"in\"/>\n",
+					pname, (int) (end - sig + 1), sig);
+		sig = end;
+		offset += strlen(pname) + 1;
+	}
+
+	sig = info->metainfo + offset;
+	offset += strlen(sig) + 1;
+
+	for (; *sig; sig++) {
+		end = _dbus_signature_end(sig);
+		pname = info->metainfo + offset;
+
+		l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
+					"type=\"%.*s\" direction=\"out\"/>\n",
+					pname, (int) (end - sig + 1), sig);
+		sig = end;
+		offset += strlen(pname) + 1;
+	}
+
+	if (info->flags & L_DBUS_METHOD_FLAG_DEPRECATED)
+		l_string_append(buf, "\t\t\t<annotation name=\""
+				"org.freedesktop.DBus.Deprecated\" "
+				"value=\"true\"/>\n");
+
+	if (info->flags & L_DBUS_METHOD_FLAG_NOREPLY)
+		l_string_append(buf, "\t\t\t<annotation name=\""
+				"org.freedesktop.DBus.Method.NoReply\" "
+				"value=\"true\"/>\n");
+
+	l_string_append(buf, "\t\t</method>\n");
+}
+
+void _dbus_signal_introspection(struct _dbus_signal *info,
+					struct l_string *buf)
+{
+	const char *sig;
+	const char *end;
+	const char *pname;
+	unsigned int offset = info->name_len + 1;
+
+	l_string_append_printf(buf, "\t\t<signal name=\"%s\">\n",
+				info->metainfo);
+
+	sig = info->metainfo + offset;
+	offset += strlen(sig) + 1;
+
+	for (; *sig; sig++) {
+		end = _dbus_signature_end(sig);
+		pname = info->metainfo + offset;
+
+		l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
+					"type=\"%.*s\"/>\n",
+					pname, (int) (end - sig + 1), sig);
+		sig = end;
+		offset += strlen(pname) + 1;
+	}
+
+	if (info->flags & L_DBUS_SIGNAL_FLAG_DEPRECATED)
+		l_string_append(buf, "\t\t\t<annotation name=\""
+				"org.freedesktop.DBus.Deprecated\" "
+				"value=\"true\"/>\n");
+
+	l_string_append(buf, "\t\t</signal>\n");
+}
+
+void _dbus_property_introspection(struct _dbus_property *info,
+						struct l_string *buf)
+{
+	unsigned int offset = info->name_len + 1;
+	const char *signature = info->metainfo + offset;
+
+	l_string_append_printf(buf, "\t\t<property name=\"%s\" type=\"%s\" ",
+				info->metainfo, signature);
+
+	if (info->setter)
+		l_string_append(buf, "access=\"readwrite\"");
+	else
+		l_string_append(buf, "access=\"read\"");
+
+	if (info->flags & L_DBUS_METHOD_FLAG_DEPRECATED) {
+		l_string_append(buf, ">\n");
+		l_string_append(buf, "\t\t\t<annotation name=\""
+				"org.freedesktop.DBus.Deprecated\" "
+				"value=\"true\"/>\n");
+		l_string_append(buf, "\t\t</property>\n");
+	} else
+		l_string_append(buf, "/>\n");
+}
+
+void _dbus_interface_introspection(struct l_dbus_interface *interface,
+						struct l_string *buf)
+{
+	l_string_append_printf(buf, "\t<interface name=\"%s\">\n",
+				interface->name);
+
+	l_queue_foreach(interface->methods,
+		(l_queue_foreach_func_t) _dbus_method_introspection, buf);
+	l_queue_foreach(interface->signals,
+		(l_queue_foreach_func_t) _dbus_signal_introspection, buf);
+	l_queue_foreach(interface->properties,
+		(l_queue_foreach_func_t) _dbus_property_introspection, buf);
+
+	l_string_append(buf, "\t</interface>\n");
+}
+
+#define COPY_PARAMS(dest, signature, args)	\
+	do {	\
+		const char *pname;	\
+		const char *sig;	\
+		dest = stpcpy(dest, signature) + 1;	\
+		for (sig = signature; *sig; sig++) {	\
+			sig = _dbus_signature_end(sig);	\
+			pname = va_arg(args, const char *);	\
+			dest = stpcpy(dest, pname) + 1;	\
+		}	\
+	} while(0)
+
+#define SIZE_PARAMS(signature, args)	\
+	({	\
+		unsigned int len = strlen(signature) + 1;	\
+		const char *pname;	\
+		const char *sig;	\
+		for (sig = signature; *sig; sig++) {	\
+			sig = _dbus_signature_end(sig);	\
+			if (!sig) {	\
+				len = 0;	\
+				break;	\
+			}	\
+			pname = va_arg(args, const char *);	\
+			len += strlen(pname) + 1;	\
+		}	\
+		len;	\
+	})
+
+LIB_EXPORT bool l_dbus_interface_method(struct l_dbus_interface *interface,
+					const char *name, uint32_t flags,
+					l_dbus_interface_method_cb_t cb,
+					const char *return_sig,
+					const char *param_sig, ...)
+{
+	va_list args;
+	unsigned int return_info_len;
+	unsigned int param_info_len;
+	struct _dbus_method *info;
+	char *p;
+
+	if (!_dbus_valid_method(name))
+		return false;
+
+	if (unlikely(!return_sig || !param_sig))
+		return false;
+
+	if (return_sig[0] && !_dbus_valid_signature(return_sig))
+		return false;
+
+	if (param_sig[0] && !_dbus_valid_signature(param_sig))
+		return false;
+
+	/* Pre-calculate the needed meta-info length */
+	va_start(args, param_sig);
+
+	return_info_len = SIZE_PARAMS(return_sig, args);
+	param_info_len = SIZE_PARAMS(param_sig, args);
+
+	va_end(args);
+
+	if (!return_info_len || !param_info_len)
+		return false;
+
+	info = l_malloc(sizeof(*info) + return_info_len +
+					param_info_len + strlen(name) + 1);
+	info->cb = cb;
+	info->flags = flags;
+	info->name_len = strlen(name);
+	strcpy(info->metainfo, name);
+
+	va_start(args, param_sig);
+
+	/*
+	 * We store param signature + parameter names first, to speed up
+	 * lookups during the message dispatch procedures.
+	 */
+	p = info->metainfo + info->name_len + param_info_len + 1;
+	COPY_PARAMS(p, return_sig, args);
+
+	p = info->metainfo + info->name_len + 1;
+	COPY_PARAMS(p, param_sig, args);
+
+	va_end(args);
+
+	l_queue_push_tail(interface->methods, info);
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_interface_signal(struct l_dbus_interface *interface,
+					const char *name, uint32_t flags,
+					const char *signature, ...)
+{
+	va_list args;
+	unsigned int metainfo_len;
+	struct _dbus_signal *info;
+	char *p;
+
+	if (!_dbus_valid_method(name))
+		return false;
+
+	if (unlikely(!signature))
+		return false;
+
+	if (signature[0] && !_dbus_valid_signature(signature))
+		return false;
+
+	/* Pre-calculate the needed meta-info length */
+	va_start(args, signature);
+	metainfo_len = SIZE_PARAMS(signature, args);
+	va_end(args);
+
+	if (!metainfo_len)
+		return false;
+
+	metainfo_len += strlen(name) + 1;
+
+	info = l_malloc(sizeof(*info) + metainfo_len);
+	info->flags = flags;
+	info->name_len = strlen(name);
+
+	p = stpcpy(info->metainfo, name) + 1;
+
+	va_start(args, signature);
+	COPY_PARAMS(p, signature, args);
+	va_end(args);
+
+	l_queue_push_tail(interface->signals, info);
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
+					const char *name, uint32_t flags,
+					const char *signature,
+					l_dbus_property_get_cb_t getter,
+					l_dbus_property_set_cb_t setter)
+{
+	unsigned int metainfo_len;
+	struct _dbus_property *info;
+	char *p;
+
+	if (!_dbus_valid_method(name))
+		return false;
+
+	if (unlikely(!signature || !getter))
+		return false;
+
+	if (_dbus_num_children(signature) != 1)
+		return false;
+
+	/* Pre-calculate the needed meta-info length */
+	metainfo_len = strlen(name) + 1;
+	metainfo_len += strlen(signature) + 1;
+
+	info = l_malloc(sizeof(*info) + metainfo_len);
+	info->flags = flags;
+	info->name_len = strlen(name);
+	info->getter = getter;
+	info->setter = setter;
+
+	p = stpcpy(info->metainfo, name) + 1;
+	strcpy(p, signature);
+
+	l_queue_push_tail(interface->properties, info);
+
+	return true;
+}
+
+struct l_dbus_interface *_dbus_interface_new(const char *name)
+{
+	struct l_dbus_interface *interface;
+
+	interface = l_malloc(sizeof(*interface) + strlen(name) + 1);
+
+	interface->methods = l_queue_new();
+	interface->signals = l_queue_new();
+	interface->properties = l_queue_new();
+
+	strcpy(interface->name, name);
+
+	return interface;
+}
+
+void _dbus_interface_free(struct l_dbus_interface *interface)
+{
+	l_queue_destroy(interface->methods, l_free);
+	l_queue_destroy(interface->signals, l_free);
+	l_queue_destroy(interface->properties, l_free);
+
+	l_free(interface);
+}
+
+static bool match_method(const void *a, const void *b)
+{
+	const struct _dbus_method *method = a;
+	const char *name = b;
+
+	if (!strcmp(method->metainfo, name))
+		return true;
+
+	return false;
+}
+
+struct _dbus_method *_dbus_interface_find_method(struct l_dbus_interface *i,
+							const char *method)
+{
+	return l_queue_find(i->methods, match_method, (char *) method);
+}
+
+static bool match_signal(const void *a, const void *b)
+{
+	const struct _dbus_signal *signal = a;
+	const char *name = b;
+
+	if (!strcmp(signal->metainfo, name))
+		return true;
+
+	return false;
+}
+
+struct _dbus_signal *_dbus_interface_find_signal(struct l_dbus_interface *i,
+							const char *signal)
+{
+	return l_queue_find(i->signals, match_signal, (char *) signal);
+}
+
+static bool match_property(const void *a, const void *b)
+{
+	const struct _dbus_property *property = a;
+	const char *name = b;
+
+	if (!strcmp(property->metainfo, name))
+		return true;
+
+	return false;
+}
+
+struct _dbus_property *_dbus_interface_find_property(struct l_dbus_interface *i,
+							const char *property)
+{
+	return l_queue_find(i->properties, match_property, (char *) property);
+}
+
+static void interface_instance_free(struct interface_instance *instance)
+{
+	if (instance->interface->instance_destroy)
+		instance->interface->instance_destroy(instance->user_data);
+
+	l_free(instance);
+}
+
+static bool match_interface_instance(const void *a, const void *b)
+{
+	const struct interface_instance *instance = a;
+	const char *name = b;
+
+	if (!strcmp(instance->interface->name, name))
+		return true;
+
+	return false;
+}
+
+static bool match_interface_instance_ptr(const void *a, const void *b)
+{
+	const struct interface_instance *instance = a;
+
+	return instance->interface == b;
+}
+
+static void interface_add_record_free(void *data)
+{
+	struct interface_add_record *rec = data;
+
+	l_free(rec->path);
+	l_queue_destroy(rec->instances, NULL);
+	l_free(rec);
+}
+
+static void interface_removed_record_free(void *data)
+{
+	struct interface_remove_record *rec = data;
+
+	l_free(rec->path);
+	l_queue_destroy(rec->interface_names, l_free);
+	l_free(rec);
+}
+
+static void property_change_record_free(void *data)
+{
+	struct property_change_record *rec = data;
+
+	l_free(rec->path);
+	l_queue_destroy(rec->properties, NULL);
+	l_free(rec);
+}
+
+static void properties_setup_func(struct l_dbus_interface *);
+static void object_manager_setup_func(struct l_dbus_interface *);
+
+struct _dbus_object_tree *_dbus_object_tree_new()
+{
+	struct _dbus_object_tree *tree;
+
+	tree = l_new(struct _dbus_object_tree, 1);
+
+	tree->interfaces = l_hashmap_new();
+	l_hashmap_set_hash_function(tree->interfaces, l_str_hash);
+	l_hashmap_set_compare_function(tree->interfaces,
+					(l_hashmap_compare_func_t)strcmp);
+
+	tree->objects = l_hashmap_string_new();
+
+	tree->root = l_new(struct object_node, 1);
+
+	tree->property_changes = l_queue_new();
+
+	_dbus_object_tree_register_interface(tree, L_DBUS_INTERFACE_PROPERTIES,
+						properties_setup_func, NULL,
+						false);
+
+	tree->object_managers = l_queue_new();
+
+	_dbus_object_tree_register_interface(tree,
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						object_manager_setup_func, NULL,
+						false);
+
+	return tree;
+}
+
+static void subtree_free(struct object_node *node)
+{
+	struct child_node *child;
+
+	while (node->children) {
+		child = node->children;
+		node->children = child->next;
+
+		subtree_free(child->node);
+		l_free(child);
+	}
+
+	l_queue_destroy(node->instances,
+			(l_queue_destroy_func_t) interface_instance_free);
+
+	if (node->destroy)
+		node->destroy(node->user_data);
+
+	l_free(node);
+}
+
+static void object_manager_free(void *data)
+{
+	struct object_manager *manager = data;
+
+	l_free(manager->path);
+	l_queue_destroy(manager->announce_added, interface_add_record_free);
+	l_queue_destroy(manager->announce_removed,
+						interface_removed_record_free);
+	l_free(manager);
+}
+
+void _dbus_object_tree_free(struct _dbus_object_tree *tree)
+{
+	subtree_free(tree->root);
+
+	l_hashmap_destroy(tree->interfaces,
+			(l_hashmap_destroy_func_t) _dbus_interface_free);
+	l_hashmap_destroy(tree->objects, NULL);
+
+	l_queue_destroy(tree->object_managers, object_manager_free);
+
+	l_queue_destroy(tree->property_changes, property_change_record_free);
+
+	if (tree->emit_signals_work)
+		l_idle_remove(tree->emit_signals_work);
+
+	l_free(tree);
+}
+
+static struct object_node *makepath_recurse(struct object_node *node,
+						const char *path)
+{
+	const char *end;
+	struct child_node *child;
+
+	if (*path == '\0')
+		return node;
+
+	path += 1;
+	end = strchrnul(path, '/');
+	child = node->children;
+
+	while (child) {
+		if (!strncmp(child->subpath, path, end - path) &&
+				child->subpath[end - path] == '\0')
+			goto done;
+
+		child = child->next;
+	}
+
+	child = l_malloc(sizeof(*child) + end - path + 1);
+	child->node = l_new(struct object_node, 1);
+	child->node->parent = node;
+	memcpy(child->subpath, path, end - path);
+	child->subpath[end-path] = '\0';
+	child->next = node->children;
+	node->children = child;
+
+done:
+	return makepath_recurse(child->node, end);
+}
+
+struct object_node *_dbus_object_tree_makepath(struct _dbus_object_tree *tree,
+						const char *path)
+{
+	if (path[0] == '/' && path[1] == '\0')
+		return tree->root;
+
+	return makepath_recurse(tree->root, path);
+}
+
+static struct object_node *lookup_recurse(struct object_node *node,
+						const char *path)
+{
+	const char *end;
+	struct child_node *child;
+
+	if (*path == '\0')
+		return node;
+
+	path += 1;
+	end = strchrnul(path, '/');
+	child = node->children;
+
+	while (child) {
+		if (!strncmp(child->subpath, path, end - path) &&
+				child->subpath[end - path] == '\0')
+			return lookup_recurse(child->node, end);
+
+		child = child->next;
+	}
+
+	return NULL;
+}
+
+struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
+						const char *path)
+{
+	if (path[0] == '/' && path[1] == '\0')
+		return tree->root;
+
+	return lookup_recurse(tree->root, path);
+}
+
+void _dbus_object_tree_prune_node(struct object_node *node)
+{
+	struct object_node *parent = node->parent;
+	struct child_node *p = NULL, *c;
+
+	while (parent) {
+		for (c = parent->children, p = NULL; c; p = c, c = c->next) {
+			if (c->node != node)
+				continue;
+
+			if (p)
+				p->next = c->next;
+			else
+				parent->children = c->next;
+
+			subtree_free(c->node);
+			l_free(c);
+
+			break;
+		}
+
+		if (parent->children != NULL)
+			return;
+
+		if (parent->instances)
+			return;
+
+		node = parent;
+		parent = node->parent;
+	}
+}
+
+struct object_node *_dbus_object_tree_new_object(struct _dbus_object_tree *tree,
+						const char *path,
+						void *user_data,
+						void (*destroy) (void *))
+{
+	struct object_node *node;
+
+	if (!_dbus_valid_object_path(path))
+		return NULL;
+
+	if (l_hashmap_lookup(tree->objects, path))
+		return NULL;
+
+	node = _dbus_object_tree_makepath(tree, path);
+	node->user_data = user_data;
+	node->destroy = destroy;
+
+	/*
+	 * Registered objects in the tree are marked by being present in the
+	 * tree->objects hash and having non-null node->instances.  Remaining
+	 * nodes are intermediate path elements added and removed
+	 * automatically.
+	 */
+	node->instances = l_queue_new();
+
+	l_hashmap_insert(tree->objects, path, node);
+
+	return node;
+}
+
+bool _dbus_object_tree_object_destroy(struct _dbus_object_tree *tree,
+					const char *path)
+{
+	struct object_node *node;
+	const struct l_queue_entry *entry;
+	const struct interface_instance *instance;
+
+	node = l_hashmap_lookup(tree->objects, path);
+	if (!node)
+		return false;
+
+	while ((entry = l_queue_get_entries(node->instances))) {
+		instance = entry->data;
+
+		if (!_dbus_object_tree_remove_interface(tree, path,
+						instance->interface->name))
+			return false;
+	}
+
+	l_hashmap_remove(tree->objects, path);
+
+	l_queue_destroy(node->instances, NULL);
+	node->instances = NULL;
+
+	if (node->destroy) {
+		node->destroy(node->user_data);
+		node->destroy = NULL;
+	}
+
+	if (!node->children)
+		_dbus_object_tree_prune_node(node);
+
+	return true;
+}
+
+static bool get_properties_dict(struct l_dbus *dbus,
+				struct l_dbus_message *message,
+				struct l_dbus_message_builder *builder,
+				const struct l_dbus_interface *interface,
+				void *user_data)
+{
+	const struct l_queue_entry *entry;
+	const struct _dbus_property *property;
+	const char *signature;
+
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+	_dbus_message_builder_mark(builder);
+
+	for (entry = l_queue_get_entries(interface->properties); entry;
+			entry = entry->next) {
+		property = entry->data;
+		signature = property->metainfo + strlen(property->metainfo) + 1;
+
+		l_dbus_message_builder_enter_dict(builder, "sv");
+		l_dbus_message_builder_append_basic(builder, 's',
+							property->metainfo);
+		l_dbus_message_builder_enter_variant(builder, signature);
+
+		if (!property->getter(dbus, message, builder, user_data)) {
+			if (!_dbus_message_builder_rewind(builder))
+				return false;
+
+			continue;
+		}
+
+		l_dbus_message_builder_leave_variant(builder);
+		l_dbus_message_builder_leave_dict(builder);
+		_dbus_message_builder_mark(builder);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+
+	return true;
+}
+
+static struct l_dbus_message *build_interfaces_removed_signal(
+				const struct object_manager *manager,
+				const struct interface_remove_record *rec)
+{
+	struct l_dbus_message *signal;
+	struct l_dbus_message_builder *builder;
+	const struct l_queue_entry *entry;
+
+	signal = l_dbus_message_new_signal(manager->dbus, manager->path,
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesRemoved");
+
+	builder = l_dbus_message_builder_new(signal);
+
+	l_dbus_message_builder_append_basic(builder, 'o', rec->path);
+	l_dbus_message_builder_enter_array(builder, "s");
+
+	for (entry = l_queue_get_entries(rec->interface_names); entry;
+			entry = entry->next)
+		l_dbus_message_builder_append_basic(builder, 's', entry->data);
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	return signal;
+}
+
+static struct l_dbus_message *build_interfaces_added_signal(
+					const struct object_manager *manager,
+					const struct interface_add_record *rec)
+{
+	struct l_dbus_message *signal;
+	struct l_dbus_message_builder *builder;
+	const struct l_queue_entry *entry;
+	const struct interface_instance *instance;
+
+	signal = l_dbus_message_new_signal(manager->dbus, manager->path,
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesAdded");
+
+	builder = l_dbus_message_builder_new(signal);
+
+	l_dbus_message_builder_append_basic(builder, 'o', rec->path);
+	l_dbus_message_builder_enter_array(builder, "{sa{sv}}");
+
+	for (entry = l_queue_get_entries(rec->instances); entry;
+			entry = entry->next) {
+		instance = entry->data;
+
+		l_dbus_message_builder_enter_dict(builder, "sa{sv}");
+		l_dbus_message_builder_append_basic(builder, 's',
+						instance->interface->name);
+
+		if (!get_properties_dict(manager->dbus, signal, builder,
+						instance->interface,
+						instance->user_data)) {
+			l_dbus_message_builder_destroy(builder);
+			l_dbus_message_unref(signal);
+
+			return NULL;
+		}
+
+		l_dbus_message_builder_leave_dict(builder);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	return signal;
+}
+
+static struct l_dbus_message *build_old_property_changed_signal(
+				struct l_dbus *dbus,
+				const struct property_change_record *rec,
+				const struct _dbus_property *property)
+{
+	struct l_dbus_message *signal;
+	struct l_dbus_message_builder *builder;
+	const char *signature;
+
+	signature = property->metainfo + strlen(property->metainfo) + 1;
+
+	signal = l_dbus_message_new_signal(dbus, rec->path,
+						rec->instance->interface->name,
+						"PropertyChanged");
+
+	builder = l_dbus_message_builder_new(signal);
+
+	l_dbus_message_builder_append_basic(builder, 's', property->metainfo);
+	l_dbus_message_builder_enter_variant(builder, signature);
+
+	if (!property->getter(dbus, signal, builder,
+				rec->instance->user_data)) {
+		l_dbus_message_builder_destroy(builder);
+		l_dbus_message_unref(signal);
+
+		return NULL;
+	}
+
+	l_dbus_message_builder_leave_variant(builder);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	return signal;
+}
+
+static struct l_dbus_message *build_properties_changed_signal(
+				struct l_dbus *dbus,
+				const struct property_change_record *rec)
+{
+	struct l_dbus_message *signal;
+	struct l_dbus_message_builder *builder;
+	const struct l_queue_entry *entry;
+	const struct _dbus_property *property;
+	const char *signature;
+	struct l_queue *invalidated;
+
+	signal = l_dbus_message_new_signal(dbus, rec->path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						"PropertiesChanged");
+
+	builder = l_dbus_message_builder_new(signal);
+
+	invalidated = l_queue_new();
+
+	l_dbus_message_builder_append_basic(builder, 's',
+						rec->instance->interface->name);
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+
+	for (entry = l_queue_get_entries(rec->properties); entry;
+			entry = entry->next) {
+		property = entry->data;
+		signature = property->metainfo + strlen(property->metainfo) + 1;
+
+		_dbus_message_builder_mark(builder);
+
+		l_dbus_message_builder_enter_dict(builder, "sv");
+		l_dbus_message_builder_append_basic(builder, 's',
+							property->metainfo);
+		l_dbus_message_builder_enter_variant(builder, signature);
+
+		if (!property->getter(dbus, signal, builder,
+					rec->instance->user_data)) {
+			if (!_dbus_message_builder_rewind(builder)) {
+				l_dbus_message_unref(signal);
+				signal = NULL;
+
+				goto done;
+			}
+
+			l_queue_push_tail(invalidated, (void *) property);
+
+			continue;
+		}
+
+		l_dbus_message_builder_leave_variant(builder);
+		l_dbus_message_builder_leave_dict(builder);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_enter_array(builder, "s");
+
+	while ((property = l_queue_pop_head(invalidated)))
+		l_dbus_message_builder_append_basic(builder, 's',
+							property->metainfo);
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_finalize(builder);
+
+done:
+	l_dbus_message_builder_destroy(builder);
+
+	l_queue_destroy(invalidated, NULL);
+
+	return signal;
+}
+
+struct emit_signals_data {
+	struct l_dbus *dbus;
+	struct object_manager *manager;
+	struct object_node *node;
+};
+
+static bool emit_interfaces_removed(void *data, void *user_data)
+{
+	struct interface_remove_record *rec = data;
+	struct emit_signals_data *es = user_data;
+	struct l_dbus_message *signal;
+
+	if (es->node && rec->object != es->node)
+		return false;
+
+	signal = build_interfaces_removed_signal(es->manager, rec);
+	interface_removed_record_free(rec);
+
+	if (signal)
+		l_dbus_send(es->manager->dbus, signal);
+
+	return true;
+}
+
+static bool emit_interfaces_added(void *data, void *user_data)
+{
+	struct interface_add_record *rec = data;
+	struct emit_signals_data *es = user_data;
+	struct l_dbus_message *signal;
+
+	if (es->node && rec->object != es->node)
+		return false;
+
+	signal = build_interfaces_added_signal(es->manager, rec);
+	interface_add_record_free(rec);
+
+	if (signal)
+		l_dbus_send(es->manager->dbus, signal);
+
+	return true;
+}
+
+static bool emit_properties_changed(void *data, void *user_data)
+{
+	struct property_change_record *rec = data;
+	struct emit_signals_data *es = user_data;
+	struct l_dbus_message *signal;
+	const struct l_queue_entry *entry;
+
+	if (es->node && rec->object != es->node)
+		return false;
+
+	if (rec->instance->interface->handle_old_style_properties)
+		for (entry = l_queue_get_entries(rec->properties);
+				entry; entry = entry->next) {
+			signal = build_old_property_changed_signal(es->dbus,
+							rec, entry->data);
+			if (signal)
+				l_dbus_send(es->dbus, signal);
+		}
+
+	if (l_queue_find(rec->object->instances, match_interface_instance,
+				L_DBUS_INTERFACE_PROPERTIES)) {
+		signal = build_properties_changed_signal(es->dbus, rec);
+		if (signal)
+			l_dbus_send(es->dbus, signal);
+	}
+
+	property_change_record_free(rec);
+
+	return true;
+}
+
+void _dbus_object_tree_signals_flush(struct l_dbus *dbus, const char *path)
+{
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	const struct l_queue_entry *entry;
+	struct emit_signals_data data;
+	bool all_done = true;
+
+	if (!tree->emit_signals_work || tree->flushing)
+		return;
+
+	tree->flushing = true;
+
+	data.dbus = dbus;
+	data.node = path ? _dbus_object_tree_lookup(tree, path) : NULL;
+
+	for (entry = l_queue_get_entries(tree->object_managers); entry;
+			entry = entry->next) {
+		data.manager = entry->data;
+
+		l_queue_foreach_remove(data.manager->announce_removed,
+					emit_interfaces_removed, &data);
+
+		if (!l_queue_isempty(data.manager->announce_removed))
+			all_done = false;
+
+		l_queue_foreach_remove(data.manager->announce_added,
+					emit_interfaces_added, &data);
+
+		if (!l_queue_isempty(data.manager->announce_added))
+			all_done = false;
+	}
+
+	l_queue_foreach_remove(tree->property_changes,
+				emit_properties_changed, &data);
+
+	if (!l_queue_isempty(tree->property_changes))
+		all_done = false;
+
+	if (all_done) {
+		l_idle_remove(tree->emit_signals_work);
+		tree->emit_signals_work = NULL;
+	}
+
+	tree->flushing = false;
+}
+
+static void emit_signals(struct l_idle *idle, void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+
+	_dbus_object_tree_signals_flush(dbus, NULL);
+}
+
+static void schedule_emit_signals(struct l_dbus *dbus)
+{
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+	if (tree->emit_signals_work)
+		return;
+
+	tree->emit_signals_work = l_idle_create(emit_signals, dbus, NULL);
+}
+
+static bool match_property_changes_instance(const void *a, const void *b)
+{
+	const struct property_change_record *rec = a;
+
+	return rec->instance == b;
+}
+
+static bool match_pointer(const void *a, const void *b)
+{
+	return a == b;
+}
+
+bool _dbus_object_tree_property_changed(struct l_dbus *dbus,
+					const char *path,
+					const char *interface_name,
+					const char *property_name)
+{
+	struct property_change_record *rec;
+	struct object_node *object;
+	struct interface_instance *instance;
+	struct _dbus_property *property;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+	object = l_hashmap_lookup(tree->objects, path);
+	if (!object)
+		return false;
+
+	instance = l_queue_find(object->instances, match_interface_instance,
+				interface_name);
+	if (!instance)
+		return false;
+
+	property = _dbus_interface_find_property(instance->interface,
+							property_name);
+	if (!property)
+		return false;
+
+	rec = l_queue_find(tree->property_changes,
+				match_property_changes_instance, instance);
+
+	if (rec) {
+		if (l_queue_find(rec->properties, match_pointer, property))
+			return true;
+	} else {
+		rec = l_new(struct property_change_record, 1);
+		rec->path = l_strdup(path);
+		rec->object = object;
+		rec->instance = instance;
+		rec->properties = l_queue_new();
+
+		l_queue_push_tail(tree->property_changes, rec);
+	}
+
+	l_queue_push_tail(rec->properties, property);
+
+	schedule_emit_signals(dbus);
+
+	return true;
+}
+
+static void pending_property_set_done_common(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message *reply,
+					bool auto_emit)
+{
+	const char *member;
+	const char *interface_name;
+	const char *property_name;
+	struct l_dbus_message_iter variant;
+
+	if (!reply) {
+		reply = l_dbus_message_new_method_return(message);
+		l_dbus_message_set_arguments(reply, "");
+	}
+
+	l_dbus_send(dbus, l_dbus_message_ref(reply));
+
+	member = l_dbus_message_get_member(message);
+	if (!strcmp(member, "SetProperty")) {
+		if (!l_dbus_message_get_arguments(message, "sv",
+						&property_name, &variant))
+			goto done;
+
+		interface_name = l_dbus_message_get_interface(message);
+	} else if (strcmp(member, "Set") ||
+			!l_dbus_message_get_arguments(message, "ssv",
+							&interface_name,
+							&property_name,
+							&variant))
+		goto done;
+
+	if (auto_emit)
+		_dbus_object_tree_property_changed(dbus,
+					l_dbus_message_get_path(message),
+					interface_name, property_name);
+done:
+	l_dbus_message_unref(message);
+	l_dbus_message_unref(reply);
+}
+
+static void pending_property_set_done_emit(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message *reply)
+{
+	pending_property_set_done_common(dbus, message, reply, true);
+}
+
+static void pending_property_set_done(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message *reply)
+{
+	pending_property_set_done_common(dbus, message, reply, false);
+}
+
+static struct l_dbus_message *old_set_property(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_interface *interface;
+	const char *property_name;
+	const struct _dbus_property *property;
+	struct l_dbus_message_iter variant;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	struct l_dbus_message *reply;
+	l_dbus_property_complete_cb_t complete_cb;
+
+	interface = l_hashmap_lookup(tree->interfaces,
+					l_dbus_message_get_interface(message));
+	/* If we got here the interface must exist */
+
+	if (!l_dbus_message_get_arguments(message, "sv", &property_name,
+						&variant))
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Invalid arguments");
+
+	property = _dbus_interface_find_property(interface, property_name);
+	if (!property)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Unknown Property %s",
+						property_name);
+
+	if (!property->setter)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Property %s is read-only",
+						property_name);
+
+	if (property->flags & L_DBUS_PROPERTY_FLAG_AUTO_EMIT)
+		complete_cb = pending_property_set_done_emit;
+	else
+		complete_cb = pending_property_set_done;
+
+	reply = property->setter(dbus, l_dbus_message_ref(message), &variant,
+					complete_cb, user_data);
+
+	if (reply)
+		complete_cb(dbus, message, reply);
+
+	return NULL;
+}
+
+static struct l_dbus_message *old_get_properties(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	const struct l_dbus_interface *interface;
+	struct l_dbus_message *reply;
+	struct l_dbus_message_builder *builder;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+	interface = l_hashmap_lookup(tree->interfaces,
+					l_dbus_message_get_interface(message));
+	/* If we got here the interface must exist */
+
+	reply = l_dbus_message_new_method_return(message);
+	builder = l_dbus_message_builder_new(reply);
+
+	if (!get_properties_dict(dbus, message, builder, interface,
+					user_data)) {
+		l_dbus_message_unref(reply);
+
+		reply = l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"Failed",
+						"Getting properties failed");
+	} else
+		l_dbus_message_builder_finalize(builder);
+
+	l_dbus_message_builder_destroy(builder);
+
+	return reply;
+}
+
+bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
+				const char *interface,
+				void (*setup_func)(struct l_dbus_interface *),
+				void (*destroy) (void *),
+				bool old_style_properties)
+{
+	struct l_dbus_interface *dbi;
+
+	if (!_dbus_valid_interface(interface))
+		return false;
+
+	/*
+	 * Check to make sure we do not have this interface already
+	 * registered
+	 */
+	dbi = l_hashmap_lookup(tree->interfaces, interface);
+	if (dbi)
+		return false;
+
+	dbi = _dbus_interface_new(interface);
+	dbi->instance_destroy = destroy;
+	dbi->handle_old_style_properties = old_style_properties;
+
+	/* Add our methods first so we don't have to check for conflicts. */
+	if (old_style_properties) {
+		l_dbus_interface_method(dbi, "SetProperty", 0,
+					old_set_property, "", "sv",
+					"name", "value");
+		l_dbus_interface_method(dbi, "GetProperties", 0,
+					old_get_properties, "a{sv}", "",
+					"properties");
+
+		l_dbus_interface_signal(dbi, "PropertyChanged", 0, "sv",
+					"name", "value");
+	}
+
+	setup_func(dbi);
+
+	l_hashmap_insert(tree->interfaces, dbi->name, dbi);
+
+	return true;
+}
+
+struct interface_check {
+	struct _dbus_object_tree *tree;
+	const char *interface;
+};
+
+static void check_interface_used(const void *key, void *value, void *user_data)
+{
+	const char *path = key;
+	struct object_node *node = value;
+	struct interface_check *state = user_data;
+
+	if (!l_queue_find(node->instances, match_interface_instance,
+				(char *) state->interface))
+		return;
+
+	_dbus_object_tree_remove_interface(state->tree, path, state->interface);
+}
+
+bool _dbus_object_tree_unregister_interface(struct _dbus_object_tree *tree,
+						const char *interface_name)
+{
+	struct l_dbus_interface *interface;
+	struct interface_check state = { tree, interface_name };
+
+	interface = l_hashmap_lookup(tree->interfaces, interface_name);
+	if (!interface)
+		return false;
+
+	/* Check that the interface is not in use */
+	l_hashmap_foreach(tree->objects, check_interface_used, &state);
+
+	l_hashmap_remove(tree->interfaces, interface_name);
+
+	_dbus_interface_free(interface);
+
+	return true;
+}
+
+static void collect_instances(struct object_node *node,
+				const char *path,
+				struct l_queue *announce)
+{
+	const struct l_queue_entry *entry;
+	struct interface_add_record *change_rec;
+	const struct child_node *child;
+
+	if (!node->instances)
+		goto recurse;
+
+	change_rec = l_new(struct interface_add_record, 1);
+	change_rec->path = l_strdup(path);
+	change_rec->object = node;
+	change_rec->instances = l_queue_new();
+
+	for (entry = l_queue_get_entries(node->instances); entry;
+			entry = entry->next)
+		l_queue_push_tail(change_rec->instances, entry->data);
+
+	l_queue_push_tail(announce, change_rec);
+
+recurse:
+	if (!strcmp(path, "/"))
+		path = "";
+
+	for (child = node->children; child; child = child->next) {
+		char *child_path;
+
+		child_path = l_strdup_printf("%s/%s", path, child->subpath);
+
+		collect_instances(child->node, child_path, announce);
+
+		l_free(child_path);
+	}
+}
+
+static bool match_interfaces_added_object(const void *a, const void *b)
+{
+	const struct interface_add_record *rec = a;
+
+	return rec->object == b;
+}
+
+static bool match_interfaces_removed_object(const void *a, const void *b)
+{
+	const struct interface_remove_record *rec = a;
+
+	return rec->object == b;
+}
+
+bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
+					const char *path, const char *interface,
+					void *user_data)
+{
+	struct object_node *object;
+	struct l_dbus_interface *dbi;
+	struct interface_instance *instance;
+	const struct l_queue_entry *entry;
+	struct object_manager *manager;
+	size_t path_len;
+	struct interface_add_record *change_rec;
+
+	dbi = l_hashmap_lookup(tree->interfaces, interface);
+	if (!dbi)
+		return false;
+
+	object = l_hashmap_lookup(tree->objects, path);
+	if (!object) {
+		object = _dbus_object_tree_new_object(tree, path, NULL, NULL);
+
+		if (!object)
+			return false;
+	}
+
+	/*
+	 * Check to make sure we do not have this interface already
+	 * registered for this object
+	 */
+	if (l_queue_find(object->instances, match_interface_instance_ptr, dbi))
+		return false;
+
+	instance = l_new(struct interface_instance, 1);
+	instance->interface = dbi;
+	instance->user_data = user_data;
+
+	l_queue_push_tail(object->instances, instance);
+
+	for (entry = l_queue_get_entries(tree->object_managers); entry;
+			entry = entry->next) {
+		manager = entry->data;
+		path_len = strlen(manager->path);
+
+		if (strncmp(path, manager->path, path_len) ||
+				(path[path_len] != '\0' &&
+				 path[path_len] != '/' && path_len > 1))
+			continue;
+
+		change_rec = l_queue_find(manager->announce_added,
+						match_interfaces_added_object,
+						object);
+		if (!change_rec) {
+			change_rec = l_new(struct interface_add_record, 1);
+			change_rec->path = l_strdup(path);
+			change_rec->object = object;
+			change_rec->instances = l_queue_new();
+
+			l_queue_push_tail(manager->announce_added, change_rec);
+		}
+
+		/* No need to check for duplicates here */
+		l_queue_push_tail(change_rec->instances, instance);
+
+		schedule_emit_signals(manager->dbus);
+	}
+
+	if (!strcmp(interface, L_DBUS_INTERFACE_OBJECT_MANAGER)) {
+		manager = l_new(struct object_manager, 1);
+		manager->path = l_strdup(path);
+		manager->dbus = instance->user_data;
+		manager->announce_added = l_queue_new();
+		manager->announce_removed = l_queue_new();
+
+		l_queue_push_tail(tree->object_managers, manager);
+
+		/* Emit InterfacesAdded for interfaces added before OM */
+		collect_instances(object, path, manager->announce_added);
+
+		if (manager->dbus && !l_queue_isempty(manager->announce_added))
+			schedule_emit_signals(manager->dbus);
+	}
+
+	return true;
+}
+
+static struct interface_instance *_dbus_object_tree_find_interface(
+						struct _dbus_object_tree *tree,
+						const char *path,
+						const char *interface)
+{
+	struct object_node *object;
+
+	object = l_hashmap_lookup(tree->objects, path);
+	if (!object)
+		return NULL;
+
+	return l_queue_find(object->instances, match_interface_instance,
+				interface);
+}
+
+void *_dbus_object_tree_get_interface_data(struct _dbus_object_tree *tree,
+						const char *path,
+						const char *interface)
+{
+	struct interface_instance *instance;
+
+	instance = _dbus_object_tree_find_interface(tree, path, interface);
+	if (!instance)
+		return NULL;
+
+	return instance->user_data;
+}
+
+bool _dbus_object_tree_set_interface_data(struct _dbus_object_tree *tree,
+						const char *path,
+						const char *interface,
+						void *user_data)
+{
+	struct interface_instance *instance;
+
+	instance = _dbus_object_tree_find_interface(tree, path, interface);
+	if (!instance)
+		return false;
+
+	instance->user_data = user_data;
+
+	return true;
+}
+
+static bool match_object_manager_path(const void *a, const void *b)
+{
+	const struct object_manager *manager = a;
+
+	return !strcmp(manager->path, b);
+}
+
+bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
+					const char *path, const char *interface)
+{
+	struct object_node *node;
+	struct interface_instance *instance;
+	const struct l_queue_entry *entry;
+	struct object_manager *manager;
+	size_t path_len;
+	struct interface_add_record *interfaces_added_rec;
+	struct interface_remove_record *interfaces_removed_rec;
+	struct property_change_record *property_change_rec;
+
+	node = l_hashmap_lookup(tree->objects, path);
+	if (!node)
+		return false;
+
+	instance = l_queue_remove_if(node->instances,
+			match_interface_instance, (char *) interface);
+	if (!instance)
+		return false;
+
+	if (!strcmp(interface, L_DBUS_INTERFACE_OBJECT_MANAGER)) {
+		manager = l_queue_remove_if(tree->object_managers,
+						match_object_manager_path,
+						(char *) path);
+
+		if (manager)
+			object_manager_free(manager);
+	}
+
+	for (entry = l_queue_get_entries(tree->object_managers); entry;
+			entry = entry->next) {
+		manager = entry->data;
+		path_len = strlen(manager->path);
+
+		if (strncmp(path, manager->path, path_len) ||
+				(path[path_len] != '\0' &&
+				 path[path_len] != '/' && path_len > 1))
+			continue;
+
+		interfaces_added_rec = l_queue_find(manager->announce_added,
+						match_interfaces_added_object,
+						node);
+		if (interfaces_added_rec && l_queue_remove(
+						interfaces_added_rec->instances,
+						instance)) {
+			if (l_queue_isempty(interfaces_added_rec->instances)) {
+				l_queue_remove(manager->announce_added,
+						interfaces_added_rec);
+				interface_add_record_free(interfaces_added_rec);
+			}
+
+			continue;
+		}
+
+		interfaces_removed_rec = l_queue_find(manager->announce_removed,
+						match_interfaces_removed_object,
+						node);
+		if (!interfaces_removed_rec) {
+			interfaces_removed_rec =
+				l_new(struct interface_remove_record, 1);
+			interfaces_removed_rec->path = l_strdup(path);
+			interfaces_removed_rec->object = node;
+			interfaces_removed_rec->interface_names =
+				l_queue_new();
+			l_queue_push_tail(manager->announce_removed,
+						interfaces_removed_rec);
+		}
+
+		/* No need to check for duplicates here */
+		l_queue_push_tail(interfaces_removed_rec->interface_names,
+					l_strdup(interface));
+
+		schedule_emit_signals(manager->dbus);
+	}
+
+	property_change_rec = l_queue_remove_if(tree->property_changes,
+						match_property_changes_instance,
+						instance);
+	if (property_change_rec)
+		property_change_record_free(property_change_rec);
+
+	interface_instance_free(instance);
+
+	return true;
+}
+
+static void generate_interface_instance(void *data, void *user)
+{
+	struct interface_instance *instance = data;
+	struct l_string *buf = user;
+
+	_dbus_interface_introspection(instance->interface, buf);
+}
+
+void _dbus_object_tree_introspect(struct _dbus_object_tree *tree,
+					const char *path, struct l_string *buf)
+{
+	struct object_node *node;
+	struct child_node *child;
+	bool path_is_object = true;
+
+	node = l_hashmap_lookup(tree->objects, path);
+	if (!node) {
+		path_is_object = false;
+		node = _dbus_object_tree_lookup(tree, path);
+	}
+
+	l_string_append(buf, XML_HEAD);
+	l_string_append(buf, "<node>\n");
+
+	if (node) {
+		/*
+		 * We emit org.freedesktop.DBus.Introspectable only in case the
+		 * object node corresponds to a registered object, i.e.
+		 * exposes anything other than:
+		 * - org.freedesktop.DBus.Introspectable
+		 * - org.freedesktop.DBus.Peer
+		 * - org.freedesktop.DBus.Properties
+		 */
+		if (path_is_object)
+			l_string_append(buf, static_introspectable);
+
+		l_queue_foreach(node->instances,
+					generate_interface_instance, buf);
+
+		for (child = node->children; child; child = child->next)
+			l_string_append_printf(buf, "\t<node name=\"%s\"/>\n",
+						child->subpath);
+	}
+
+	l_string_append(buf, "</node>\n");
+}
+
+bool _dbus_object_tree_dispatch(struct _dbus_object_tree *tree,
+					struct l_dbus *dbus,
+					struct l_dbus_message *message)
+{
+	const char *path;
+	const char *interface;
+	const char *member;
+	const char *msg_sig;
+	const char *sig;
+	struct object_node *node;
+	struct interface_instance *instance;
+	struct _dbus_method *method;
+	struct l_dbus_message *reply;
+
+	path = l_dbus_message_get_path(message);
+	interface = l_dbus_message_get_interface(message);
+	member = l_dbus_message_get_member(message);
+	msg_sig = l_dbus_message_get_signature(message);
+
+	/*
+	 * Nothing in the spec explicitly forbids this, but handling of such
+	 * messages is left up to the implementation.
+	 *
+	 * TODO: Another route is to go looking for a matching method under this
+	 * object and call it.
+	 */
+	if (!interface)
+		return false;
+
+	if (!msg_sig)
+		msg_sig = "";
+
+	if (!strcmp(interface, "org.freedesktop.DBus.Introspectable") &&
+			!strcmp(member, "Introspect") &&
+			!strcmp(msg_sig, "")) {
+		struct l_string *buf;
+		char *xml;
+
+		buf = l_string_new(0);
+		_dbus_object_tree_introspect(tree, path, buf);
+		xml = l_string_unwrap(buf);
+
+		reply = l_dbus_message_new_method_return(message);
+		l_dbus_message_set_arguments(reply, "s", xml);
+		l_dbus_send(dbus, reply);
+
+		l_free(xml);
+
+		return true;
+	}
+
+	node = l_hashmap_lookup(tree->objects, path);
+	if (!node)
+		return false;
+
+	instance = l_queue_find(node->instances,
+				match_interface_instance, (char *) interface);
+	if (!instance)
+		return false;
+
+	method = _dbus_interface_find_method(instance->interface, member);
+	if (!method)
+		return false;
+
+	sig = method->metainfo + method->name_len + 1;
+
+	if (strcmp(msg_sig, sig))
+		return false;
+
+	reply = method->cb(dbus, message, instance->user_data);
+	if (reply)
+		l_dbus_send(dbus, reply);
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_property_changed(struct l_dbus *dbus, const char *path,
+					const char *interface,
+					const char *property)
+{
+	return _dbus_object_tree_property_changed(dbus, path, interface,
+							property);
+}
+
+static struct l_dbus_message *properties_get(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	const struct interface_instance *instance;
+	const char *interface_name, *property_name, *signature;
+	const struct _dbus_property *property;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	const struct object_node *object;
+	struct l_dbus_message *reply;
+	struct l_dbus_message_builder *builder;
+
+	if (!l_dbus_message_get_arguments(message, "ss", &interface_name,
+						&property_name))
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Invalid arguments");
+
+	object = l_hashmap_lookup(tree->objects,
+					l_dbus_message_get_path(message));
+	/* If we got here the object must exist */
+
+	instance = l_queue_find(object->instances,
+				match_interface_instance,
+				(char *) interface_name);
+	if (!instance)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Object has no interface %s",
+						interface_name);
+
+	property = _dbus_interface_find_property(instance->interface,
+							property_name);
+	if (!property)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Unknown Property %s",
+						property_name);
+
+
+	reply = l_dbus_message_new_method_return(message);
+	builder = l_dbus_message_builder_new(reply);
+
+	signature = property->metainfo + strlen(property->metainfo) + 1;
+
+	l_dbus_message_builder_enter_variant(builder, signature);
+
+	if (property->getter(dbus, message, builder, instance->user_data)) {
+		l_dbus_message_builder_leave_variant(builder);
+		l_dbus_message_builder_finalize(builder);
+	} else {
+		l_dbus_message_unref(reply);
+
+		reply = l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"Failed",
+						"Getting property value "
+						"failed");
+	}
+
+	l_dbus_message_builder_destroy(builder);
+
+	return reply;
+}
+
+static struct l_dbus_message *properties_set(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_interface *interface;
+	const struct interface_instance *instance;
+	const char *interface_name, *property_name;
+	const struct _dbus_property *property;
+	struct l_dbus_message_iter variant;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	const struct object_node *object;
+	struct l_dbus_message *reply;
+	l_dbus_property_complete_cb_t complete_cb;
+
+	if (!l_dbus_message_get_arguments(message, "ssv", &interface_name,
+						&property_name, &variant))
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Invalid arguments");
+
+	interface = l_hashmap_lookup(tree->interfaces, interface_name);
+	if (!interface)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Unknown Interface %s",
+						interface_name);
+
+	property = _dbus_interface_find_property(interface, property_name);
+	if (!property)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Unknown Property %s",
+						property_name);
+
+	if (!property->setter)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Property %s is read-only",
+						property_name);
+
+	object = l_hashmap_lookup(tree->objects,
+					l_dbus_message_get_path(message));
+	/* If we got here the object must exist */
+
+	instance = l_queue_find(object->instances,
+				match_interface_instance_ptr, interface);
+	if (!instance)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Object has no interface %s",
+						interface_name);
+
+	if (property->flags & L_DBUS_PROPERTY_FLAG_AUTO_EMIT)
+		complete_cb = pending_property_set_done_emit;
+	else
+		complete_cb = pending_property_set_done;
+
+	reply = property->setter(dbus, l_dbus_message_ref(message), &variant,
+					complete_cb, instance->user_data);
+
+	if (reply)
+		complete_cb(dbus, message, reply);
+
+	return NULL;
+}
+
+static struct l_dbus_message *properties_get_all(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	const struct interface_instance *instance;
+	const char *interface_name;
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	const struct object_node *object;
+	struct l_dbus_message *reply;
+	struct l_dbus_message_builder *builder;
+
+	if (!l_dbus_message_get_arguments(message, "s", &interface_name))
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Invalid arguments");
+
+	object = l_hashmap_lookup(tree->objects,
+					l_dbus_message_get_path(message));
+	/* If we got here the object must exist */
+
+	instance = l_queue_find(object->instances,
+				match_interface_instance,
+				(char *) interface_name);
+	if (!instance)
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"InvalidArgs",
+						"Object has no interface %s",
+						interface_name);
+
+	reply = l_dbus_message_new_method_return(message);
+	builder = l_dbus_message_builder_new(reply);
+
+	if (!get_properties_dict(dbus, message, builder, instance->interface,
+					instance->user_data)) {
+		l_dbus_message_unref(reply);
+
+		reply = l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"Failed",
+						"Getting property values "
+						"failed");
+	} else
+		l_dbus_message_builder_finalize(builder);
+
+	l_dbus_message_builder_destroy(builder);
+
+	return reply;
+}
+
+static void properties_setup_func(struct l_dbus_interface *interface)
+{
+	l_dbus_interface_method(interface, "Get", 0,
+				properties_get, "v", "ss",
+				"value", "interface_name", "property_name");
+	l_dbus_interface_method(interface, "Set", 0,
+				properties_set, "", "ssv",
+				"interface_name", "property_name", "value");
+	l_dbus_interface_method(interface, "GetAll", 0,
+				properties_get_all, "a{sv}", "s",
+				"props", "interface_name");
+
+	l_dbus_interface_signal(interface, "PropertiesChanged", 0, "sa{sv}as",
+				"interface_name", "changed_properties",
+				"invalidated_properties");
+}
+
+static bool collect_objects(struct l_dbus *dbus, struct l_dbus_message *message,
+				struct l_dbus_message_builder *builder,
+				const struct object_node *node,
+				const char *path)
+{
+	const struct l_queue_entry *entry;
+	const struct child_node *child;
+	char *child_path;
+	const struct interface_instance *instance;
+	bool r;
+
+	if (!node->instances)
+		goto recurse;
+
+	l_dbus_message_builder_enter_dict(builder, "oa{sa{sv}}");
+	l_dbus_message_builder_append_basic(builder, 'o', path);
+	l_dbus_message_builder_enter_array(builder, "{sa{sv}}");
+
+	for (entry = l_queue_get_entries(node->instances); entry;
+			entry = entry->next) {
+		instance = entry->data;
+
+		l_dbus_message_builder_enter_dict(builder, "sa{sv}");
+		l_dbus_message_builder_append_basic(builder, 's',
+						instance->interface->name);
+
+		if (!get_properties_dict(dbus, message, builder,
+						instance->interface,
+						instance->user_data))
+			return false;
+
+		l_dbus_message_builder_leave_dict(builder);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_leave_dict(builder);
+
+recurse:
+	if (!strcmp(path, "/"))
+		path = "";
+
+	for (child = node->children; child; child = child->next) {
+		child_path = l_strdup_printf("%s/%s", path, child->subpath);
+
+		r = collect_objects(dbus, message, builder,
+					child->node, child_path);
+
+		l_free(child_path);
+
+		if (!r)
+			return false;
+	}
+
+	return true;
+}
+
+struct l_dbus_message *_dbus_object_tree_get_objects(
+						struct _dbus_object_tree *tree,
+						struct l_dbus *dbus,
+						const char *path,
+						struct l_dbus_message *message)
+{
+	const struct object_node *node;
+	struct l_dbus_message *reply;
+	struct l_dbus_message_builder *builder;
+
+	node = l_hashmap_lookup(tree->objects, path);
+
+	reply = l_dbus_message_new_method_return(message);
+	builder = l_dbus_message_builder_new(reply);
+
+	l_dbus_message_builder_enter_array(builder, "{oa{sa{sv}}}");
+
+	if (!collect_objects(dbus, message, builder, node, path)) {
+		l_dbus_message_builder_destroy(builder);
+		l_dbus_message_unref(reply);
+
+		return l_dbus_message_new_error(message,
+						"org.freedesktop.DBus.Error."
+						"Failed",
+						"Getting property values "
+						"failed");
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	return reply;
+}
+
+static struct l_dbus_message *get_managed_objects(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+	const char *path = l_dbus_message_get_path(message);
+
+	return _dbus_object_tree_get_objects(tree, dbus, path, message);
+}
+
+static void object_manager_setup_func(struct l_dbus_interface *interface)
+{
+	l_dbus_interface_method(interface, "GetManagedObjects", 0,
+				get_managed_objects, "a{oa{sa{sv}}}", "",
+				"objpath_interfaces_and_properties");
+
+	l_dbus_interface_signal(interface, "InterfacesAdded", 0, "oa{sa{sv}}",
+				"object_path", "interfaces_and_properties");
+	l_dbus_interface_signal(interface, "InterfacesRemoved", 0, "oas",
+				"object_path", "interfaces");
+}
diff --git a/ell/dbus-service.h b/ell/dbus-service.h
new file mode 100644
index 0000000..5ef9710
--- /dev/null
+++ b/ell/dbus-service.h
@@ -0,0 +1,79 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_SERVICE_H
+#define __ELL_SERVICE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_dbus;
+struct l_dbus_interface;
+struct l_dbus_message;
+
+enum l_dbus_method_flag {
+	L_DBUS_METHOD_FLAG_DEPRECATED =	1,
+	L_DBUS_METHOD_FLAG_NOREPLY =	2,
+	L_DBUS_METHOD_FLAG_ASYNC =	4,
+};
+
+enum l_dbus_signal_flag {
+	L_DBUS_SIGNAL_FLAG_DEPRECATED =	1,
+};
+
+enum l_dbus_property_flag {
+	L_DBUS_PROPERTY_FLAG_DEPRECATED = 1,
+	L_DBUS_PROPERTY_FLAG_AUTO_EMIT	= 2,
+};
+
+typedef struct l_dbus_message *(*l_dbus_interface_method_cb_t) (struct l_dbus *,
+						struct l_dbus_message *message,
+						void *user_data);
+
+typedef void (*l_dbus_property_complete_cb_t) (struct l_dbus *,
+						struct l_dbus_message *,
+						struct l_dbus_message *error);
+
+typedef struct l_dbus_message *(*l_dbus_property_set_cb_t) (struct l_dbus *,
+					struct l_dbus_message *message,
+					struct l_dbus_message_iter *new_value,
+					l_dbus_property_complete_cb_t complete,
+					void *user_data);
+
+typedef bool (*l_dbus_property_get_cb_t) (struct l_dbus *,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data);
+
+bool l_dbus_interface_method(struct l_dbus_interface *interface,
+				const char *name, uint32_t flags,
+				l_dbus_interface_method_cb_t cb,
+				const char *return_sig, const char *param_sig,
+				...);
+
+bool l_dbus_interface_signal(struct l_dbus_interface *interface,
+				const char *name, uint32_t flags,
+				const char *signature, ...);
+
+bool l_dbus_interface_property(struct l_dbus_interface *interface,
+				const char *name, uint32_t flags,
+				const char *signature,
+				l_dbus_property_get_cb_t getter,
+				l_dbus_property_set_cb_t setter);
+
+bool l_dbus_property_changed(struct l_dbus *dbus, const char *path,
+				const char *interface, const char *property);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_DBUS_SERVICE_H */
diff --git a/ell/dbus-util.c b/ell/dbus-util.c
new file mode 100644
index 0000000..3de8183
--- /dev/null
+++ b/ell/dbus-util.c
@@ -0,0 +1,1299 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "dbus.h"
+#include "private.h"
+#include "useful.h"
+#include "dbus-private.h"
+#include "string.h"
+#include "queue.h"
+#include "utf8.h"
+
+#define DBUS_MAX_INTERFACE_LEN 255
+#define DBUS_MAX_METHOD_LEN 255
+
+static const char *simple_types = "sogybnqiuxtdh";
+
+static int get_alignment(const char type)
+{
+	switch (type) {
+	case 'b':
+		return 4;
+	case 'y':
+		return 1;
+	case 'n':
+	case 'q':
+		return 2;
+	case 'u':
+	case 'i':
+		return 4;
+	case 'x':
+	case 't':
+	case 'd':
+		return 8;
+	case 's':
+	case 'o':
+		return 4;
+	case 'g':
+		return 1;
+	case 'a':
+		return 4;
+	case '(':
+	case '{':
+		return 8;
+	case 'v':
+		return 1;
+	case 'h':
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+static int get_basic_size(const char type)
+{
+	switch (type) {
+	case 'b':
+		return 4;
+	case 'y':
+		return 1;
+	case 'n':
+	case 'q':
+		return 2;
+	case 'i':
+	case 'u':
+		return 4;
+	case 'x':
+	case 't':
+		return 8;
+	case 'd':
+		return 8;
+	case 'h':
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+static inline bool is_valid_character(const char c, bool bus_name)
+{
+	if (c >= 'a' && c <= 'z')
+		return true;
+
+	if (c >= 'A' && c <= 'Z')
+		return true;
+
+	if (c >= '0' && c <= '9')
+		return true;
+
+	if (c == '_')
+		return true;
+
+	if (c == '-' && bus_name)
+		return true;
+
+	return false;
+}
+
+bool _dbus_valid_object_path(const char *path)
+{
+	unsigned int i;
+	char c = '\0';
+
+	if (path == NULL)
+		return false;
+
+	if (path[0] == '\0')
+		return false;
+
+	if (path[0] && !path[1] && path[0] == '/')
+		return true;
+
+	if (path[0] != '/')
+		return false;
+
+	for (i = 0; path[i]; i++) {
+		if (path[i] == '/' && c == '/')
+			return false;
+
+		c = path[i];
+
+		if (is_valid_character(path[i], false) || path[i] == '/')
+			continue;
+
+		return false;
+	}
+
+	if (path[i-1] == '/')
+		return false;
+
+	return true;
+}
+
+static const char *validate_next_type(const char *sig)
+{
+	char s = *sig;
+
+	if (s == '\0')
+		return NULL;
+
+	if (strchr(simple_types, s) || s == 'v')
+		return sig + 1;
+
+	switch (s) {
+	case 'a':
+		s = *++sig;
+
+		if (s == '{') {
+			s = *++sig;
+
+			/* Dictionary keys can only be simple types */
+			if (!strchr(simple_types, s))
+				return NULL;
+
+			sig = validate_next_type(sig + 1);
+
+			if (!sig)
+				return NULL;
+
+			if (*sig != '}')
+				return NULL;
+
+			return sig + 1;
+		}
+
+		return validate_next_type(sig);
+
+	case '(':
+		sig++;
+
+		do
+			sig = validate_next_type(sig);
+		while (sig && *sig != ')');
+
+		if (!sig)
+			return NULL;
+
+		return sig + 1;
+	}
+
+	return NULL;
+}
+
+static bool valid_dict_signature(const char *sig)
+{
+	char s = *sig;
+
+	if (s != '{')
+		return false;
+
+	s = *++sig;
+
+	if (!strchr(simple_types, s))
+		return false;
+
+	sig = validate_next_type(sig + 1);
+	if (!sig)
+		return false;
+
+	if (sig[0] != '}')
+		return false;
+
+	if (sig[1] != '\0')
+		return false;
+
+	return true;
+}
+
+bool _dbus_valid_signature(const char *sig)
+{
+	const char *s = sig;
+
+	do {
+		s = validate_next_type(s);
+
+		if (!s)
+			return false;
+	} while (*s);
+
+	return true;
+}
+
+int _dbus_num_children(const char *sig)
+{
+	const char *s = sig;
+	int num_children = 0;
+
+	do {
+		s = validate_next_type(s);
+
+		if (!s)
+			return -1;
+
+		num_children += 1;
+	} while (*s);
+
+	return num_children;
+}
+
+static bool valid_member_name(const char *start, const char *end,
+				bool bus_name)
+{
+	const char *p;
+
+	if ((end - start) < 1)
+		return false;
+
+	if (*start >= '0' && *start <= '9')
+		return false;
+
+	for (p = start; p < end; p++)
+		if (!is_valid_character(*p, bus_name))
+			return false;
+
+	return true;
+}
+
+bool _dbus_valid_method(const char *method)
+{
+	unsigned int i;
+
+	if (!method)
+		return false;
+
+	if (method[0] == '\0' || strlen(method) > DBUS_MAX_METHOD_LEN)
+		return false;
+
+	if (method[0] >= '0' && method[0] <= '9')
+		return false;
+
+	for (i = 0; method[i]; i++)
+		if (!is_valid_character(method[i], false))
+			return false;
+
+	return true;
+}
+
+bool _dbus_valid_interface(const char *interface)
+{
+	const char *sep;
+
+	if (!interface)
+		return false;
+
+	if (interface[0] == '\0' || strlen(interface) > DBUS_MAX_INTERFACE_LEN)
+		return false;
+
+	sep = strchrnul(interface, '.');
+	if (*sep == '\0')
+		return false;
+
+	while (true) {
+		if (!valid_member_name(interface, sep, false))
+			return false;
+
+		if (*sep == '\0')
+			break;
+
+		interface = sep + 1;
+		sep = strchrnul(interface, '.');
+	}
+
+	return true;
+}
+
+bool _dbus_parse_unique_name(const char *name, uint64_t *out_id)
+{
+	char *endp = NULL;
+	uint64_t r;
+
+	if (!l_str_has_prefix(name, ":1."))
+		return false;
+
+	name += 3;
+
+	/*
+	 * Disallow '+' or '-' at the beginning of the string
+	 * must have at least one digit
+	 */
+	if (!l_ascii_isdigit(*name))
+		return false;
+
+	errno = 0;
+	r = strtoull(name, &endp, 10);
+	if (!endp || *endp || errno)
+		return false;
+
+	if (out_id)
+		*out_id = r;
+
+	return true;
+}
+
+bool _dbus_valid_bus_name(const char *bus_name)
+{
+	const char *sep;
+
+	if (!bus_name)
+		return false;
+
+	if (bus_name[0] == '\0' || strlen(bus_name) > DBUS_MAX_INTERFACE_LEN)
+		return false;
+
+	if (_dbus_parse_unique_name(bus_name, NULL))
+		return true;
+
+	sep = strchrnul(bus_name, '.');
+	if (*sep == '\0')
+		return false;
+
+	while (true) {
+		if (!valid_member_name(bus_name, sep, true))
+			return false;
+
+		if (*sep == '\0')
+			break;
+
+		bus_name = sep + 1;
+		sep = strchrnul(bus_name, '.');
+	}
+
+	return true;
+}
+
+const char *_dbus_signature_end(const char *signature)
+{
+	const char *ptr = signature;
+	unsigned int indent = 0;
+	char expect;
+
+	switch (*signature) {
+	case '(':
+		expect = ')';
+		break;
+	case '{':
+		expect = '}';
+		break;
+	case 'a':
+		return _dbus_signature_end(signature + 1);
+	default:
+		return signature;
+	}
+
+	for (ptr = signature; *ptr != '\0'; ptr++) {
+		if (*ptr == *signature)
+			indent++;
+		else if (*ptr == expect)
+			if (!--indent)
+				return ptr;
+	}
+
+	return NULL;
+}
+
+bool _dbus1_header_is_valid(void *data, size_t size)
+{
+	struct dbus_header *hdr;
+	size_t header_len;
+
+	if (size < sizeof(struct dbus_header))
+		return false;
+
+	hdr = data;
+
+	if (hdr->endian != DBUS_NATIVE_ENDIAN)
+		header_len = bswap_32(hdr->dbus1.field_length);
+	else
+		header_len = hdr->dbus1.field_length;
+
+	header_len += sizeof(struct dbus_header);
+	return size >= header_len;
+}
+
+static inline void dbus1_iter_init_internal(struct l_dbus_message_iter *iter,
+						struct l_dbus_message *message,
+						enum dbus_container_type type,
+						const char *sig_start,
+						const char *sig_end,
+						const void *data, size_t len,
+						size_t pos)
+{
+	size_t sig_len;
+
+	iter->message = message;
+
+	if (sig_end)
+		sig_len = sig_end - sig_start;
+	else
+		sig_len = strlen(sig_start);
+
+	iter->sig_start = sig_start;
+	iter->sig_len = sig_len;
+	iter->sig_pos = 0;
+	iter->data = data;
+	iter->len = pos + len;
+	iter->pos = pos;
+	iter->container_type = type;
+}
+
+void _dbus1_iter_init(struct l_dbus_message_iter *iter,
+			struct l_dbus_message *message,
+			const char *sig_start, const char *sig_end,
+			const void *data, size_t len)
+{
+	dbus1_iter_init_internal(iter, message, DBUS_CONTAINER_TYPE_STRUCT,
+					sig_start, sig_end, data, len, 0);
+}
+
+static const char *calc_len_next_item(const char *signature, const void *data,
+					size_t data_pos, size_t data_len,
+					size_t *out_len)
+{
+	unsigned int alignment;
+	size_t pos;
+	size_t len;
+	const char *sig_end;
+	const char *var_sig;
+
+	alignment = get_alignment(*signature);
+	if (alignment == 0)
+		return NULL;
+
+	pos = align_len(data_pos, alignment);
+	if (pos > data_len)
+		return NULL;
+
+	switch (*signature) {
+	case 'o':
+	case 's':
+		if (pos + 5 > data_len)
+			return NULL;
+
+		pos += l_get_u32(data + pos) + 5;
+		break;
+	case 'g':
+		if (pos + 2 > data_len)
+			return NULL;
+
+		pos += l_get_u8(data + pos) + 2;
+		break;
+	case 'y':
+		pos += 1;
+		break;
+	case 'n':
+	case 'q':
+		pos += 2;
+		break;
+	case 'b':
+	case 'i':
+	case 'u':
+	case 'h':
+		pos += 4;
+		break;
+	case 'x':
+	case 't':
+	case 'd':
+		pos += 8;
+		break;
+	case 'a':
+		if (pos + 4 > data_len)
+			return NULL;
+
+		len = l_get_u32(data + pos);
+		pos += 4;
+
+		alignment = get_alignment(signature[1]);
+		pos = align_len(pos, alignment);
+		pos += len;
+
+		sig_end = _dbus_signature_end(signature) + 1;
+		goto done;
+	case '(':
+		sig_end = signature + 1;
+
+		while (*sig_end != ')') {
+			sig_end = calc_len_next_item(sig_end, data, pos,
+							data_len, &len);
+
+			if (!sig_end)
+				return NULL;
+
+			pos += len;
+		}
+
+		sig_end += 1;
+		goto done;
+	case '{':
+		sig_end = calc_len_next_item(signature + 1, data, pos,
+						data_len, &len);
+
+		if (!sig_end)
+			return NULL;
+
+		pos += len;
+
+		sig_end = calc_len_next_item(sig_end, data, pos,
+						data_len, &len);
+
+		if (!sig_end)
+			return NULL;
+
+		pos += len;
+		sig_end += 1;
+		goto done;
+	case 'v':
+		if (!calc_len_next_item("g", data, pos, data_len, &len))
+			return NULL;
+
+		var_sig = data + pos + 1;
+		pos += len;
+
+		if (!calc_len_next_item(var_sig, data, pos, data_len, &len))
+			return NULL;
+
+		pos += len;
+		break;
+	default:
+		return NULL;
+	}
+
+	sig_end = signature + 1;
+
+done:
+	if (pos > data_len)
+		return NULL;
+
+	*out_len = pos - data_pos;
+	return sig_end;
+}
+
+bool _dbus1_iter_next_entry_basic(struct l_dbus_message_iter *iter,
+					char type, void *out)
+{
+	const char *str_val;
+	uint8_t uint8_val;
+	uint16_t uint16_val;
+	uint32_t uint32_val;
+	uint64_t uint64_val;
+	int16_t int16_val;
+	int32_t int32_val;
+	int64_t int64_val;
+	size_t pos;
+
+	if (iter->pos >= iter->len)
+		return false;
+
+	pos = align_len(iter->pos, get_alignment(type));
+
+	switch (type) {
+	case 'o':
+	case 's':
+		if (pos + 5 > iter->len)
+			return false;
+		uint32_val = l_get_u32(iter->data + pos);
+		str_val = iter->data + pos + 4;
+		*(const void **) out = str_val;
+		iter->pos = pos + uint32_val + 5;
+		break;
+	case 'g':
+		if (pos + 2 > iter->len)
+			return false;
+		uint8_val = l_get_u8(iter->data + pos);
+		str_val = iter->data + pos + 1;
+		*(const void **) out = str_val;
+		iter->pos = pos + uint8_val + 2;
+		break;
+	case 'b':
+		if (pos + 4 > iter->len)
+			return false;
+		uint32_val = l_get_u32(iter->data + pos);
+		*(bool *) out = !!uint32_val;
+		iter->pos = pos + 4;
+		break;
+	case 'y':
+		if (pos + 1 > iter->len)
+			return false;
+		uint8_val = l_get_u8(iter->data + pos);
+		*(uint8_t *) out = uint8_val;
+		iter->pos = pos + 1;
+		break;
+	case 'n':
+		if (pos + 2 > iter->len)
+			return false;
+		int16_val = l_get_s16(iter->data + pos);
+		*(int16_t *) out = int16_val;
+		iter->pos = pos + 2;
+		break;
+	case 'q':
+		if (pos + 2 > iter->len)
+			return false;
+		uint16_val = l_get_u16(iter->data + pos);
+		*(uint16_t *) out = uint16_val;
+		iter->pos = pos + 2;
+		break;
+	case 'i':
+		if (pos + 4 > iter->len)
+			return false;
+		int32_val = l_get_s32(iter->data + pos);
+		*(int32_t *) out = int32_val;
+		iter->pos = pos + 4;
+		break;
+	case 'u':
+	case 'h':
+		if (pos + 4 > iter->len)
+			return false;
+		uint32_val = l_get_u32(iter->data + pos);
+		*(uint32_t *) out = uint32_val;
+		iter->pos = pos + 4;
+		break;
+	case 'x':
+		if (pos + 8 > iter->len)
+			return false;
+		int64_val = l_get_s64(iter->data + pos);
+		*(int64_t *) out= int64_val;
+		iter->pos = pos + 8;
+		break;
+	case 't':
+	case 'd':
+		if (pos + 8 > iter->len)
+			return false;
+		uint64_val = l_get_u64(iter->data + pos);
+		*(uint64_t *) out = uint64_val;
+		iter->pos = pos + 8;
+		break;
+	default:
+		return false;
+	}
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		iter->sig_pos += 1;
+
+	return true;
+}
+
+bool _dbus1_iter_get_fixed_array(struct l_dbus_message_iter *iter,
+					void *out, uint32_t *n_elem)
+{
+	char type;
+	uint32_t size;
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		return false;
+
+	type = iter->sig_start[iter->sig_pos];
+	size = get_basic_size(type);
+
+	/* Fail if the array is not a fixed size or contains file descriptors */
+	if (!size || type == 'h')
+		return false;
+
+	/*
+	 * enter_array should already align us to our container type, so
+	 * there is no need to align pos here
+	 */
+	*(const void **) out = iter->data + iter->pos;
+	*n_elem = (iter->len - iter->pos) / size;
+
+	return true;
+}
+
+bool _dbus1_iter_enter_struct(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *structure)
+{
+	size_t len;
+	size_t pos;
+	const char *sig_start;
+	const char *sig_end;
+	bool is_dict = iter->sig_start[iter->sig_pos] == '{';
+	bool is_struct = iter->sig_start[iter->sig_pos] == '(';
+
+	if (!is_dict && !is_struct)
+		return false;
+
+	pos = align_len(iter->pos, 8);
+	if (pos >= iter->len)
+		return false;
+
+	sig_start = iter->sig_start + iter->sig_pos + 1;
+	sig_end = _dbus_signature_end(iter->sig_start + iter->sig_pos);
+
+	if (!calc_len_next_item(iter->sig_start + iter->sig_pos,
+				iter->data, pos, iter->len, &len))
+		return false;
+
+	dbus1_iter_init_internal(structure, iter->message,
+					DBUS_CONTAINER_TYPE_STRUCT,
+					sig_start, sig_end, iter->data,
+					len, pos);
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		iter->sig_pos += sig_end - sig_start + 2;
+
+	iter->pos = pos + len;
+
+	return true;
+}
+
+bool _dbus1_iter_enter_variant(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *variant)
+{
+	size_t pos;
+	uint8_t sig_len;
+	size_t len;
+	const char *sig_start;
+
+	if (iter->sig_start[iter->sig_pos] != 'v')
+		return false;
+
+	pos = align_len(iter->pos, 1);
+	if (pos + 2 > iter->len)
+		return false;
+
+	sig_len = l_get_u8(iter->data + pos);
+	sig_start = iter->data + pos + 1;
+
+	if (!calc_len_next_item(sig_start, iter->data, pos + sig_len + 2,
+					iter->len, &len))
+		return false;
+
+	dbus1_iter_init_internal(variant, iter->message,
+					DBUS_CONTAINER_TYPE_VARIANT,
+					sig_start, NULL, iter->data,
+					len, pos + sig_len + 2);
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		iter->sig_pos += 1;
+
+	iter->pos = pos + sig_len + 2 + len;
+
+	return true;
+}
+
+bool _dbus1_iter_enter_array(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *array)
+{
+	size_t pos;
+	size_t len;
+	const char *sig_start;
+	const char *sig_end;
+
+	if (iter->sig_start[iter->sig_pos] != 'a')
+		return false;
+
+	sig_start = iter->sig_start + iter->sig_pos + 1;
+	sig_end = _dbus_signature_end(sig_start) + 1;
+
+	pos = align_len(iter->pos, 4);
+	if (pos + 4 > iter->len)
+		return false;
+
+	len = l_get_u32(iter->data + pos);
+	pos += 4;
+
+	pos = align_len(pos, get_alignment(*sig_start));
+	dbus1_iter_init_internal(array, iter->message,
+					DBUS_CONTAINER_TYPE_ARRAY,
+					sig_start, sig_end,
+					iter->data, len, pos);
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		iter->sig_pos += sig_end - sig_start + 1;
+
+	iter->pos = pos + len;
+
+	return true;
+}
+
+bool _dbus1_iter_skip_entry(struct l_dbus_message_iter *iter)
+{
+	size_t len;
+	const char *sig_end;
+
+	sig_end = calc_len_next_item(iter->sig_start + iter->sig_pos,
+					iter->data, iter->pos, iter->len, &len);
+	if (!sig_end)
+		return false;
+
+	iter->pos += len;
+	iter->sig_pos = sig_end - iter->sig_start;
+
+	return true;
+}
+
+struct dbus_builder {
+	struct l_string *signature;
+	void *body;
+	size_t body_size;
+	size_t body_pos;
+	struct l_queue *containers;
+	struct {
+		struct container *container;
+		int sig_end;
+		size_t body_pos;
+	} mark;
+};
+
+struct container {
+	size_t start;
+	enum dbus_container_type type;
+	char signature[256];
+	uint8_t sigindex;
+};
+
+static struct container *container_new(enum dbus_container_type type,
+					const char *signature, size_t start)
+{
+	struct container *ret;
+
+	ret = l_new(struct container, 1);
+
+	ret->type = type;
+	strcpy(ret->signature, signature);
+	ret->start = start;
+
+	return ret;
+}
+
+static void container_free(struct container *container)
+{
+	l_free(container);
+}
+
+static inline size_t grow_body(struct dbus_builder *builder,
+					size_t len, unsigned int alignment)
+{
+	size_t size = align_len(builder->body_pos, alignment);
+
+	if (size + len > builder->body_size) {
+		builder->body = l_realloc(builder->body, size + len);
+		builder->body_size = size + len;
+	}
+
+	if (size - builder->body_pos > 0)
+		memset(builder->body + builder->body_pos, 0,
+					size - builder->body_pos);
+
+	builder->body_pos = size + len;
+
+	return size;
+}
+
+struct dbus_builder *_dbus1_builder_new(void *body, size_t body_size)
+{
+	struct dbus_builder *builder;
+	struct container *root;
+
+	builder = l_new(struct dbus_builder, 1);
+	builder->signature = l_string_new(63);
+
+	builder->containers = l_queue_new();
+	root = container_new(DBUS_CONTAINER_TYPE_STRUCT, "", 0);
+	l_queue_push_head(builder->containers, root);
+
+	builder->body = body;
+	builder->body_size = body_size;
+	builder->body_pos = body_size;
+
+	builder->mark.container = root;
+	builder->mark.sig_end = 0;
+	builder->mark.body_pos = 0;
+
+	return builder;
+}
+
+void _dbus1_builder_free(struct dbus_builder *builder)
+{
+	if (unlikely(!builder))
+		return;
+
+	l_string_free(builder->signature);
+	l_queue_destroy(builder->containers,
+				(l_queue_destroy_func_t) container_free);
+	l_free(builder->body);
+
+	l_free(builder);
+}
+
+bool _dbus1_builder_append_basic(struct dbus_builder *builder,
+					char type, const void *value)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+	unsigned int alignment;
+	size_t len;
+
+	if (unlikely(!builder))
+		return false;
+
+	if (unlikely(!strchr(simple_types, type)))
+		return false;
+
+	alignment = get_alignment(type);
+	if (!alignment)
+		return false;
+
+	if (l_queue_length(builder->containers) == 1)
+		l_string_append_c(builder->signature, type);
+	else if (container->signature[container->sigindex] != type)
+		return false;
+
+	len = get_basic_size(type);
+
+	if (len) {
+		uint32_t b;
+
+		start = grow_body(builder, len, alignment);
+
+		if (type == 'b') {
+			b = *(bool *)value;
+			memcpy(builder->body + start, &b, len);
+		} else
+			memcpy(builder->body + start, value, len);
+
+		if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
+			container->sigindex += 1;
+
+		return true;
+	}
+
+	len = strlen(value);
+
+	if (type == 'g') {
+		start = grow_body(builder, len + 2, 1);
+		l_put_u8(len, builder->body + start);
+		strcpy(builder->body + start + 1, value);
+	} else {
+		start = grow_body(builder, len + 5, 4);
+		l_put_u32(len, builder->body + start);
+		strcpy(builder->body + start + 4, value);
+	}
+
+	if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
+		container->sigindex += 1;
+
+	return true;
+}
+
+static bool enter_struct_dict_common(struct dbus_builder *builder,
+					const char *signature,
+					enum dbus_container_type type,
+					const char open,
+					const char close)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) +
+				strlen(signature) + 2 > 255)
+			return false;
+	} else {
+		/* Verify Signatures Match */
+		char expect[256];
+		const char *start;
+		const char *end;
+
+		start = container->signature + container->sigindex;
+		end = _dbus_signature_end(start);
+
+		if (*start != open || *end != close)
+			return false;
+
+		memcpy(expect, start + 1, end - start - 1);
+		expect[end - start - 1] = '\0';
+
+		if (strcmp(expect, signature))
+			return false;
+	}
+
+	start = grow_body(builder, 0, 8);
+
+	container = container_new(type, signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _dbus1_builder_enter_struct(struct dbus_builder *builder,
+					const char *signature)
+{
+	if (!_dbus_valid_signature(signature))
+		return false;
+
+	return enter_struct_dict_common(builder, signature,
+					DBUS_CONTAINER_TYPE_STRUCT, '(', ')');
+}
+
+bool _dbus1_builder_enter_dict(struct dbus_builder *builder,
+					const char *signature)
+{
+	if (_dbus_num_children(signature) != 2)
+		return false;
+
+	if (!strchr(simple_types, signature[0]))
+		return false;
+
+	return enter_struct_dict_common(builder, signature,
+					DBUS_CONTAINER_TYPE_DICT_ENTRY,
+					'{', '}');
+}
+
+static bool leave_struct_dict_common(struct dbus_builder *builder,
+					enum dbus_container_type type,
+					const char open,
+					const char close)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != type))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	if (qlen == 1)
+		l_string_append_printf(builder->signature, "%c%s%c",
+						open,
+						container->signature,
+						close);
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += strlen(container->signature) + 2;
+
+	container_free(container);
+
+	return true;
+}
+
+bool _dbus1_builder_leave_struct(struct dbus_builder *builder)
+{
+	return leave_struct_dict_common(builder, DBUS_CONTAINER_TYPE_STRUCT,
+					'(', ')');
+}
+
+bool _dbus1_builder_leave_dict(struct dbus_builder *builder)
+{
+	return leave_struct_dict_common(builder,
+					DBUS_CONTAINER_TYPE_DICT_ENTRY,
+					'{', '}');
+}
+
+bool _dbus1_builder_enter_variant(struct dbus_builder *builder,
+					const char *signature)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+	size_t siglen;
+
+	if (_dbus_num_children(signature) != 1)
+		return false;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) + 1 > 255)
+			return false;
+	} else if (container->signature[container->sigindex] != 'v')
+		return false;
+
+	siglen = strlen(signature);
+	start = grow_body(builder, siglen + 2, 1);
+	l_put_u8(siglen, builder->body + start);
+	strcpy(builder->body + start + 1, signature);
+
+	container = container_new(DBUS_CONTAINER_TYPE_VARIANT,
+					signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _dbus1_builder_leave_variant(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != DBUS_CONTAINER_TYPE_VARIANT))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	if (qlen == 1)
+		l_string_append_c(builder->signature, 'v');
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += 1;
+
+	container_free(container);
+
+	return true;
+}
+
+bool _dbus1_builder_enter_array(struct dbus_builder *builder,
+					const char *signature)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+	int alignment;
+
+	if (_dbus_num_children(signature) != 1 &&
+			!valid_dict_signature(signature))
+		return false;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) +
+				strlen(signature) + 1 > 255)
+			return false;
+	} else {
+		/* Verify Signatures Match */
+		char expect[256];
+		const char *start;
+		const char *end;
+
+		start = container->signature + container->sigindex;
+		end = validate_next_type(start);
+
+		if (*start != 'a')
+			return false;
+
+		memcpy(expect, start + 1, end - start - 1);
+		expect[end - start - 1] = '\0';
+
+		if (strcmp(expect, signature))
+			return false;
+	}
+
+	/* First grow the body enough to cover preceding length */
+	start = grow_body(builder, 4, 4);
+
+	/* Now align to element alignment */
+	alignment = get_alignment(*signature);
+	grow_body(builder, 0, alignment);
+
+	container = container_new(DBUS_CONTAINER_TYPE_ARRAY, signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _dbus1_builder_leave_array(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+	size_t alignment;
+	size_t array_start;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != DBUS_CONTAINER_TYPE_ARRAY))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	if (qlen == 1)
+		l_string_append_printf(builder->signature, "a%s",
+							container->signature);
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += strlen(container->signature) + 1;
+
+	/* Update array length */
+	alignment = get_alignment(container->signature[0]);
+	array_start = align_len(container->start + 4, alignment);
+
+	l_put_u32(builder->body_pos - array_start,
+			builder->body + container->start);
+
+	container_free(container);
+
+	return true;
+}
+
+bool _dbus1_builder_mark(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+
+	builder->mark.container = container;
+
+	if (l_queue_length(builder->containers) == 1)
+		builder->mark.sig_end = l_string_length(builder->signature);
+	else
+		builder->mark.sig_end = container->sigindex;
+
+	builder->mark.body_pos = builder->body_pos;
+
+	return true;
+}
+
+bool _dbus1_builder_rewind(struct dbus_builder *builder)
+{
+	struct container *container;
+
+	while ((container = l_queue_peek_head(builder->containers)) !=
+				builder->mark.container) {
+		container_free(container);
+		l_queue_pop_head(builder->containers);
+	}
+
+	builder->body_pos = builder->mark.body_pos;
+
+	if (l_queue_length(builder->containers) == 1)
+		l_string_truncate(builder->signature, builder->mark.sig_end);
+	else
+		container->sigindex = builder->mark.sig_end;
+
+	return true;
+}
+
+char *_dbus1_builder_finish(struct dbus_builder *builder,
+				void **body, size_t *body_size)
+{
+	char *signature;
+
+	if (unlikely(!builder))
+		return NULL;
+
+	if (unlikely(l_queue_length(builder->containers) != 1))
+		return NULL;
+
+	signature = l_string_unwrap(builder->signature);
+	builder->signature = NULL;
+
+	*body = builder->body;
+	*body_size = builder->body_pos;
+	builder->body = NULL;
+	builder->body_size = 0;
+
+	return signature;
+}
diff --git a/ell/dbus.c b/ell/dbus.c
new file mode 100644
index 0000000..bd6e1b8
--- /dev/null
+++ b/ell/dbus.c
@@ -0,0 +1,1932 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include "util.h"
+#include "io.h"
+#include "idle.h"
+#include "queue.h"
+#include "hashmap.h"
+#include "dbus.h"
+#include "private.h"
+#include "useful.h"
+#include "dbus-private.h"
+
+#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
+
+#define DBUS_SERVICE_DBUS	"org.freedesktop.DBus"
+
+#define DBUS_PATH_DBUS		"/org/freedesktop/DBus"
+
+#define DBUS_MAXIMUM_MATCH_RULE_LENGTH	1024
+
+enum auth_state {
+	WAITING_FOR_OK,
+	WAITING_FOR_AGREE_UNIX_FD,
+	SETUP_DONE
+};
+
+struct l_dbus_ops {
+	char version;
+	bool (*send_message)(struct l_dbus *bus,
+				struct l_dbus_message *message);
+	struct l_dbus_message *(*recv_message)(struct l_dbus *bus);
+	void (*free)(struct l_dbus *bus);
+	struct _dbus_name_ops name_ops;
+	struct _dbus_filter_ops filter_ops;
+	uint32_t (*name_acquire)(struct l_dbus *dbus, const char *name,
+				bool allow_replacement, bool replace_existing,
+				bool queue, l_dbus_name_acquire_func_t callback,
+				void *user_data);
+};
+
+struct l_dbus {
+	struct l_io *io;
+	char *guid;
+	bool negotiate_unix_fd;
+	bool support_unix_fd;
+	bool is_ready;
+	char *unique_name;
+	unsigned int next_id;
+	uint32_t next_serial;
+	struct l_queue *message_queue;
+	struct l_hashmap *message_list;
+	struct l_hashmap *signal_list;
+	l_dbus_ready_func_t ready_handler;
+	l_dbus_destroy_func_t ready_destroy;
+	void *ready_data;
+	l_dbus_disconnect_func_t disconnect_handler;
+	l_dbus_destroy_func_t disconnect_destroy;
+	void *disconnect_data;
+	l_dbus_debug_func_t debug_handler;
+	l_dbus_destroy_func_t debug_destroy;
+	void *debug_data;
+	struct _dbus_object_tree *tree;
+	struct _dbus_name_cache *name_cache;
+	struct _dbus_filter *filter;
+	bool name_notify_enabled;
+
+	const struct l_dbus_ops *driver;
+};
+
+struct l_dbus_classic {
+	struct l_dbus super;
+	void *auth_command;
+	enum auth_state auth_state;
+	bool skip_hello;
+	struct l_hashmap *match_strings;
+	int *fd_buf;
+	unsigned int num_fds;
+};
+
+struct message_callback {
+	uint32_t serial;
+	struct l_dbus_message *message;
+	l_dbus_message_func_t callback;
+	l_dbus_destroy_func_t destroy;
+	void *user_data;
+};
+
+struct signal_callback {
+	unsigned int id;
+	l_dbus_message_func_t callback;
+	l_dbus_destroy_func_t destroy;
+	void *user_data;
+};
+
+static void message_queue_destroy(void *data)
+{
+	struct message_callback *callback = data;
+
+	l_dbus_message_unref(callback->message);
+
+	if (callback->destroy)
+		callback->destroy(callback->user_data);
+
+	l_free(callback);
+}
+
+static void message_list_destroy(void *value)
+{
+	message_queue_destroy(value);
+}
+
+static void signal_list_destroy(void *value)
+{
+	struct signal_callback *callback = value;
+
+	if (callback->destroy)
+		callback->destroy(callback->user_data);
+
+	l_free(callback);
+}
+
+static bool message_write_handler(struct l_io *io, void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+	struct l_dbus_message *message;
+	struct message_callback *callback;
+	const void *header, *body;
+	size_t header_size, body_size;
+
+	callback = l_queue_pop_head(dbus->message_queue);
+	if (!callback)
+		return false;
+
+	message = callback->message;
+	if (_dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
+			callback->callback == NULL)
+		l_dbus_message_set_no_reply(message, true);
+
+	_dbus_message_set_serial(message, callback->serial);
+
+	if (!dbus->driver->send_message(dbus, message)) {
+		message_queue_destroy(callback);
+		return false;
+	}
+
+	header = _dbus_message_get_header(message, &header_size);
+	body = _dbus_message_get_body(message, &body_size);
+	l_util_hexdump_two(false, header, header_size, body, body_size,
+				dbus->debug_handler, dbus->debug_data);
+
+	if (callback->callback == NULL) {
+		message_queue_destroy(callback);
+		goto done;
+	}
+
+	l_hashmap_insert(dbus->message_list,
+				L_UINT_TO_PTR(callback->serial), callback);
+
+done:
+	if (l_queue_isempty(dbus->message_queue))
+		return false;
+
+	/* Only continue sending messges if the connection is ready */
+	return dbus->is_ready;
+}
+
+static void handle_method_return(struct l_dbus *dbus,
+					struct l_dbus_message *message)
+{
+	struct message_callback *callback;
+	uint32_t reply_serial;
+
+	reply_serial = _dbus_message_get_reply_serial(message);
+	if (reply_serial == 0)
+		return;
+
+	callback = l_hashmap_remove(dbus->message_list,
+					L_UINT_TO_PTR(reply_serial));
+	if (!callback)
+		return;
+
+	if (callback->callback)
+		callback->callback(message, callback->user_data);
+
+	message_queue_destroy(callback);
+}
+
+static void handle_error(struct l_dbus *dbus, struct l_dbus_message *message)
+{
+	struct message_callback *callback;
+	uint32_t reply_serial;
+
+	reply_serial = _dbus_message_get_reply_serial(message);
+	if (reply_serial == 0)
+		return;
+
+	callback = l_hashmap_remove(dbus->message_list,
+					L_UINT_TO_PTR(reply_serial));
+	if (!callback)
+		return;
+
+	if (callback->callback)
+		callback->callback(message, callback->user_data);
+
+	message_queue_destroy(callback);
+}
+
+static void process_signal(const void *key, void *value, void *user_data)
+{
+	struct signal_callback *callback = value;
+	struct l_dbus_message *message = user_data;
+
+	if (callback->callback)
+		callback->callback(message, callback->user_data);
+}
+
+static void handle_signal(struct l_dbus *dbus, struct l_dbus_message *message)
+{
+	l_hashmap_foreach(dbus->signal_list, process_signal, message);
+}
+
+static bool message_read_handler(struct l_io *io, void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+	struct l_dbus_message *message;
+	const void *header, *body;
+	size_t header_size, body_size;
+	enum dbus_message_type msgtype;
+
+	message = dbus->driver->recv_message(dbus);
+	if (!message)
+		return true;
+
+	header = _dbus_message_get_header(message, &header_size);
+	body = _dbus_message_get_body(message, &body_size);
+	l_util_hexdump_two(true, header, header_size, body, body_size,
+				dbus->debug_handler, dbus->debug_data);
+
+	msgtype = _dbus_message_get_type(message);
+
+	switch (msgtype) {
+	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+		handle_method_return(dbus, message);
+		break;
+	case DBUS_MESSAGE_TYPE_ERROR:
+		handle_error(dbus, message);
+		break;
+	case DBUS_MESSAGE_TYPE_SIGNAL:
+		handle_signal(dbus, message);
+		break;
+	case DBUS_MESSAGE_TYPE_METHOD_CALL:
+		if (!_dbus_object_tree_dispatch(dbus->tree, dbus, message)) {
+			struct l_dbus_message *error;
+
+			error = l_dbus_message_new_error(message,
+					"org.freedesktop.DBus.Error.NotFound",
+					"No matching method found");
+			l_dbus_send(dbus, error);
+		}
+
+		break;
+	}
+
+	l_dbus_message_unref(message);
+
+	return true;
+}
+
+static uint32_t send_message(struct l_dbus *dbus, bool priority,
+				struct l_dbus_message *message,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	struct message_callback *callback;
+	enum dbus_message_type type;
+	const char *path;
+
+	type = _dbus_message_get_type(message);
+
+	if ((type == DBUS_MESSAGE_TYPE_METHOD_RETURN ||
+				type == DBUS_MESSAGE_TYPE_ERROR) &&
+			_dbus_message_get_reply_serial(message) == 0) {
+		l_dbus_message_unref(message);
+		return 0;
+	}
+
+	/* Default empty signature for method return messages */
+	if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
+			!l_dbus_message_get_signature(message))
+		l_dbus_message_set_arguments(message, "");
+
+	callback = l_new(struct message_callback, 1);
+
+	callback->serial = dbus->next_serial++;
+	callback->message = message;
+	callback->callback = function;
+	callback->destroy = destroy;
+	callback->user_data = user_data;
+
+	if (priority) {
+		l_queue_push_head(dbus->message_queue, callback);
+
+		l_io_set_write_handler(dbus->io, message_write_handler,
+							dbus, NULL);
+
+		return callback->serial;
+	}
+
+	path = l_dbus_message_get_path(message);
+	if (path)
+		_dbus_object_tree_signals_flush(dbus, path);
+
+	l_queue_push_tail(dbus->message_queue, callback);
+
+	if (dbus->is_ready)
+		l_io_set_write_handler(dbus->io, message_write_handler,
+							dbus, NULL);
+
+	return callback->serial;
+}
+
+static void bus_ready(struct l_dbus *dbus)
+{
+	dbus->is_ready = true;
+
+	if (dbus->ready_handler)
+		dbus->ready_handler(dbus->ready_data);
+
+	l_io_set_read_handler(dbus->io, message_read_handler, dbus, NULL);
+
+	/* Check for messages added before the connection was ready */
+	if (l_queue_isempty(dbus->message_queue))
+		return;
+
+	l_io_set_write_handler(dbus->io, message_write_handler, dbus, NULL);
+}
+
+static void hello_callback(struct l_dbus_message *message, void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+	const char *signature;
+	const char *unique_name;
+
+	signature = l_dbus_message_get_signature(message);
+	if (!signature || strcmp(signature, "s")) {
+		close(l_io_get_fd(dbus->io));
+		return;
+	}
+
+	if (!l_dbus_message_get_arguments(message, "s", &unique_name)) {
+		close(l_io_get_fd(dbus->io));
+		return;
+	}
+
+	dbus->unique_name = l_strdup(unique_name);
+
+	bus_ready(dbus);
+}
+
+static bool auth_write_handler(struct l_io *io, void *user_data)
+{
+	struct l_dbus_classic *classic = user_data;
+	struct l_dbus *dbus = &classic->super;
+	ssize_t written, len;
+	int fd;
+
+	fd = l_io_get_fd(io);
+
+	if (!classic->auth_command)
+		return false;
+
+	len = strlen(classic->auth_command);
+	if (!len)
+		return false;
+
+	written = L_TFR(send(fd, classic->auth_command, len, 0));
+	if (written < 0)
+		return false;
+
+	l_util_hexdump(false, classic->auth_command, written,
+					dbus->debug_handler, dbus->debug_data);
+
+	if (written < len) {
+		memmove(classic->auth_command, classic->auth_command + written,
+				len + 1 - written);
+		return true;
+	}
+
+	l_free(classic->auth_command);
+	classic->auth_command = NULL;
+
+	if (classic->auth_state == SETUP_DONE) {
+		struct l_dbus_message *message;
+
+		if (classic->skip_hello) {
+			bus_ready(dbus);
+			return true;
+		}
+
+		l_io_set_read_handler(dbus->io, message_read_handler,
+							dbus, NULL);
+
+		message = l_dbus_message_new_method_call(dbus,
+							DBUS_SERVICE_DBUS,
+							DBUS_PATH_DBUS,
+							L_DBUS_INTERFACE_DBUS,
+							"Hello");
+		l_dbus_message_set_arguments(message, "");
+
+		send_message(dbus, true, message, hello_callback, dbus, NULL);
+
+		return true;
+	}
+
+	return false;
+}
+
+static bool auth_read_handler(struct l_io *io, void *user_data)
+{
+	struct l_dbus_classic *classic = user_data;
+	struct l_dbus *dbus = &classic->super;
+	char buffer[64];
+	char *ptr, *end;
+	ssize_t offset, len;
+	int fd;
+
+	fd = l_io_get_fd(io);
+
+	ptr = buffer;
+	offset = 0;
+
+	while (1) {
+		len = L_TFR(recv(fd, ptr + offset,
+						sizeof(buffer) - offset,
+						MSG_DONTWAIT));
+		if (len < 0) {
+			if (errno != EAGAIN)
+				return false;
+
+			break;
+		}
+
+		offset += len;
+	}
+
+	ptr = buffer;
+	len = offset;
+
+	if (!ptr || len < 3)
+		return true;
+
+	end = strstr(ptr, "\r\n");
+	if (!end)
+		return true;
+
+	if (end - ptr + 2 != len)
+		return true;
+
+	l_util_hexdump(true, ptr, len, dbus->debug_handler, dbus->debug_data);
+
+	*end = '\0';
+
+	switch (classic->auth_state) {
+	case WAITING_FOR_OK:
+		if (!strncmp(ptr, "OK ", 3)) {
+			enum auth_state state;
+			const char *command;
+
+			if (dbus->negotiate_unix_fd) {
+				command = "NEGOTIATE_UNIX_FD\r\n";
+				state = WAITING_FOR_AGREE_UNIX_FD;
+			} else {
+				command = "BEGIN\r\n";
+				state = SETUP_DONE;
+			}
+
+			l_free(dbus->guid);
+			dbus->guid = l_strdup(ptr + 3);
+
+			classic->auth_command = l_strdup(command);
+			classic->auth_state = state;
+			break;
+		} else if (!strncmp(ptr, "REJECTED ", 9)) {
+			static const char *command = "AUTH ANONYMOUS\r\n";
+
+			dbus->negotiate_unix_fd = true;
+
+			classic->auth_command = l_strdup(command);
+			classic->auth_state = WAITING_FOR_OK;
+		}
+		break;
+
+	case WAITING_FOR_AGREE_UNIX_FD:
+		if (!strncmp(ptr, "AGREE_UNIX_FD", 13)) {
+			static const char *command = "BEGIN\r\n";
+
+			dbus->support_unix_fd = true;
+
+			classic->auth_command = l_strdup(command);
+			classic->auth_state = SETUP_DONE;
+			break;
+		} else if (!strncmp(ptr, "ERROR", 5)) {
+			static const char *command = "BEGIN\r\n";
+
+			dbus->support_unix_fd = false;
+
+			classic->auth_command = l_strdup(command);
+			classic->auth_state = SETUP_DONE;
+			break;
+		}
+		break;
+
+	case SETUP_DONE:
+		break;
+	}
+
+	l_io_set_write_handler(io, auth_write_handler, dbus, NULL);
+
+	return true;
+}
+
+static void disconnect_handler(struct l_io *io, void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+
+	dbus->is_ready = false;
+
+	l_util_debug(dbus->debug_handler, dbus->debug_data, "disconnect");
+
+	if (dbus->disconnect_handler)
+		dbus->disconnect_handler(dbus->disconnect_data);
+}
+
+static void dbus_init(struct l_dbus *dbus, int fd)
+{
+	dbus->io = l_io_new(fd);
+	l_io_set_close_on_destroy(dbus->io, true);
+	l_io_set_disconnect_handler(dbus->io, disconnect_handler, dbus, NULL);
+
+	dbus->is_ready = false;
+	dbus->next_id = 1;
+	dbus->next_serial = 1;
+
+	dbus->message_queue = l_queue_new();
+	dbus->message_list = l_hashmap_new();
+	dbus->signal_list = l_hashmap_new();
+
+	dbus->tree = _dbus_object_tree_new();
+}
+
+static void classic_free(struct l_dbus *dbus)
+{
+	struct l_dbus_classic *classic =
+		l_container_of(dbus, struct l_dbus_classic, super);
+	unsigned int i;
+
+	for (i = 0; i < classic->num_fds; i++)
+		close(classic->fd_buf[i]);
+	l_free(classic->fd_buf);
+
+	l_free(classic->auth_command);
+	l_hashmap_destroy(classic->match_strings, l_free);
+	l_free(classic);
+}
+
+static bool classic_send_message(struct l_dbus *dbus,
+					struct l_dbus_message *message)
+{
+	int fd = l_io_get_fd(dbus->io);
+	struct msghdr msg;
+	struct iovec iov[2], *iovpos;
+	ssize_t r;
+	int *fds = NULL;
+	uint32_t num_fds = 0;
+	struct cmsghdr *cmsg;
+	int iovlen;
+
+	iov[0].iov_base = _dbus_message_get_header(message, &iov[0].iov_len);
+	iov[1].iov_base = _dbus_message_get_body(message, &iov[1].iov_len);
+
+	if (dbus->support_unix_fd)
+		fds = _dbus_message_get_fds(message, &num_fds);
+
+	iovpos = iov;
+	iovlen = 2;
+
+	while (1) {
+		memset(&msg, 0, sizeof(msg));
+		msg.msg_iov = iovpos;
+		msg.msg_iovlen = iovlen;
+
+		if (num_fds) {
+			msg.msg_control =
+				alloca(CMSG_SPACE(num_fds * sizeof(int)));
+			msg.msg_controllen = CMSG_LEN(num_fds * sizeof(int));
+
+			cmsg = CMSG_FIRSTHDR(&msg);
+			cmsg->cmsg_len = msg.msg_controllen;
+			cmsg->cmsg_level = SOL_SOCKET;
+			cmsg->cmsg_type = SCM_RIGHTS;
+			memcpy(CMSG_DATA(cmsg), fds, num_fds * sizeof(int));
+		}
+
+		r = L_TFR(sendmsg(fd, &msg, 0));
+		if (r < 0)
+			return false;
+
+		while ((size_t) r >= iovpos->iov_len) {
+			r -= iovpos->iov_len;
+			iovpos++;
+			iovlen--;
+
+			if (!iovlen)
+				break;
+		}
+
+		if (!iovlen)
+			break;
+
+		iovpos->iov_base += r;
+		iovpos->iov_len -= r;
+
+		/* The FDs have been transmitted, don't retransmit */
+		num_fds = 0;
+	}
+
+	return true;
+}
+
+static struct l_dbus_message *classic_recv_message(struct l_dbus *dbus)
+{
+	struct l_dbus_classic *classic =
+		l_container_of(dbus, struct l_dbus_classic, super);
+	int fd = l_io_get_fd(dbus->io);
+	struct dbus_header hdr;
+	struct msghdr msg;
+	struct iovec iov[2], *iovpos;
+	struct cmsghdr *cmsg;
+	ssize_t len, r;
+	void *header, *body;
+	size_t header_size, body_size;
+	union {
+		uint8_t bytes[CMSG_SPACE(16 * sizeof(int))];
+		struct cmsghdr align;
+	} fd_buf;
+	int *fds = NULL;
+	uint32_t num_fds = 0;
+	int iovlen;
+	struct l_dbus_message *message;
+	unsigned int i;
+
+	len = recv(fd, &hdr, DBUS_HEADER_SIZE, MSG_PEEK | MSG_DONTWAIT);
+	if (len != DBUS_HEADER_SIZE)
+		return NULL;
+
+	header_size = align_len(DBUS_HEADER_SIZE + hdr.dbus1.field_length, 8);
+	header = l_malloc(header_size);
+
+	body_size = hdr.dbus1.body_length;
+	body = l_malloc(body_size);
+
+	iov[0].iov_base = header;
+	iov[0].iov_len  = header_size;
+	iov[1].iov_base = body;
+	iov[1].iov_len  = body_size;
+
+	iovpos = iov;
+	iovlen = 2;
+
+	while (1) {
+		memset(&msg, 0, sizeof(msg));
+		msg.msg_iov = iovpos;
+		msg.msg_iovlen = iovlen;
+		msg.msg_control = &fd_buf;
+		msg.msg_controllen = sizeof(fd_buf);
+
+		r = L_TFR(recvmsg(fd, &msg,
+					MSG_CMSG_CLOEXEC | MSG_WAITALL));
+		if (r < 0)
+			goto cmsg_fail;
+
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+				cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level != SOL_SOCKET ||
+					cmsg->cmsg_type != SCM_RIGHTS)
+				continue;
+
+			num_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+			fds = (void *) CMSG_DATA(cmsg);
+
+			/* Set FD_CLOEXEC on all file descriptors */
+			for (i = 0; i < num_fds; i++) {
+				long flags;
+
+				flags = fcntl(fds[i], F_GETFD, NULL);
+				if (flags < 0)
+					continue;
+
+				if (!(flags & FD_CLOEXEC))
+					fcntl(fds[i], F_SETFD,
+						flags | FD_CLOEXEC);
+			}
+
+			classic->fd_buf = l_realloc(classic->fd_buf,
+						(classic->num_fds + num_fds) *
+						sizeof(int));
+			memcpy(classic->fd_buf + classic->num_fds, fds,
+				num_fds * sizeof(int));
+			classic->num_fds += num_fds;
+		}
+
+		while ((size_t) r >= iovpos->iov_len) {
+			r -= iovpos->iov_len;
+			iovpos++;
+			iovlen--;
+
+			if (!iovlen)
+				break;
+		}
+
+		if (!iovlen)
+			break;
+
+		iovpos->iov_base += r;
+		iovpos->iov_len -= r;
+	}
+
+	if (hdr.endian != DBUS_NATIVE_ENDIAN) {
+		l_util_debug(dbus->debug_handler,
+				dbus->debug_data, "Endianness incorrect");
+		goto bad_msg;
+	}
+
+	if (hdr.version != 1) {
+		l_util_debug(dbus->debug_handler,
+				dbus->debug_data, "Protocol version incorrect");
+		goto bad_msg;
+	}
+
+	num_fds = _dbus_message_unix_fds_from_header(header, header_size);
+	if (num_fds > classic->num_fds)
+		goto bad_msg;
+
+	message = dbus_message_build(header, header_size, body, body_size,
+					classic->fd_buf, num_fds);
+
+	if (message && num_fds) {
+		if (classic->num_fds > num_fds) {
+			memmove(classic->fd_buf, classic->fd_buf + num_fds,
+				(classic->num_fds - num_fds) * sizeof(int));
+			classic->num_fds -= num_fds;
+		} else {
+			l_free(classic->fd_buf);
+
+			classic->fd_buf = NULL;
+			classic->num_fds = 0;
+		}
+	}
+
+	if (message)
+		return message;
+
+bad_msg:
+cmsg_fail:
+	for (i = 0; i < classic->num_fds; i++)
+		close(classic->fd_buf[i]);
+
+	l_free(classic->fd_buf);
+
+	classic->fd_buf = NULL;
+	classic->num_fds = 0;
+
+	l_free(header);
+	l_free(body);
+
+	return NULL;
+}
+
+static bool classic_add_match(struct l_dbus *dbus, unsigned int id,
+				const struct _dbus_filter_condition *rule,
+				int rule_len)
+{
+	struct l_dbus_classic *classic =
+		l_container_of(dbus, struct l_dbus_classic, super);
+	char *match_str;
+	struct l_dbus_message *message;
+
+	match_str = _dbus_filter_rule_to_str(rule, rule_len);
+
+	l_hashmap_insert(classic->match_strings, L_UINT_TO_PTR(id), match_str);
+
+	message = l_dbus_message_new_method_call(dbus,
+						DBUS_SERVICE_DBUS,
+						DBUS_PATH_DBUS,
+						L_DBUS_INTERFACE_DBUS,
+						"AddMatch");
+
+	l_dbus_message_set_arguments(message, "s", match_str);
+
+	send_message(dbus, false, message, NULL, NULL, NULL);
+
+	return true;
+}
+
+static bool classic_remove_match(struct l_dbus *dbus, unsigned int id)
+{
+	struct l_dbus_classic *classic =
+		l_container_of(dbus, struct l_dbus_classic, super);
+	char *match_str = l_hashmap_remove(classic->match_strings,
+						L_UINT_TO_PTR(id));
+	struct l_dbus_message *message;
+
+	if (!match_str)
+		return false;
+
+	message = l_dbus_message_new_method_call(dbus,
+						DBUS_SERVICE_DBUS,
+						DBUS_PATH_DBUS,
+						L_DBUS_INTERFACE_DBUS,
+						"RemoveMatch");
+
+	l_dbus_message_set_arguments(message, "s", match_str);
+
+	send_message(dbus, false, message, NULL, NULL, NULL);
+
+	l_free(match_str);
+
+	return true;
+}
+
+static void name_owner_changed_cb(struct l_dbus_message *message,
+					void *user_data)
+{
+	struct l_dbus *dbus = user_data;
+	char *name, *old, *new;
+
+	if (!l_dbus_message_get_arguments(message, "sss", &name, &old, &new))
+		return;
+
+	_dbus_name_cache_notify(dbus->name_cache, name, new);
+}
+
+struct get_name_owner_request {
+	struct l_dbus_message *message;
+	struct l_dbus *dbus;
+};
+
+static void get_name_owner_reply_cb(struct l_dbus_message *reply,
+					void *user_data)
+{
+	struct get_name_owner_request *req = user_data;
+	const char *name, *owner;
+
+	/* No name owner yet */
+	if (l_dbus_message_is_error(reply))
+		return;
+
+	/* Shouldn't happen */
+	if (!l_dbus_message_get_arguments(reply, "s", &owner))
+		return;
+
+	/* Shouldn't happen */
+	if (!l_dbus_message_get_arguments(req->message, "s", &name))
+		return;
+
+	_dbus_name_cache_notify(req->dbus->name_cache, name, owner);
+}
+
+static bool classic_get_name_owner(struct l_dbus *bus, const char *name)
+{
+	struct get_name_owner_request *req;
+
+	/* Name resolution is not performed for DBUS_SERVICE_DBUS */
+	if (!strcmp(name, DBUS_SERVICE_DBUS))
+		return false;
+
+	req = l_new(struct get_name_owner_request, 1);
+	req->dbus = bus;
+	req->message = l_dbus_message_new_method_call(bus,
+							DBUS_SERVICE_DBUS,
+							DBUS_PATH_DBUS,
+							L_DBUS_INTERFACE_DBUS,
+							"GetNameOwner");
+
+	l_dbus_message_set_arguments(req->message, "s", name);
+
+	send_message(bus, false, req->message, get_name_owner_reply_cb,
+			req, l_free);
+
+	if (!bus->name_notify_enabled) {
+		static struct _dbus_filter_condition rule[] = {
+			{ L_DBUS_MATCH_TYPE,		"signal" },
+			{ L_DBUS_MATCH_SENDER,		DBUS_SERVICE_DBUS },
+			{ L_DBUS_MATCH_PATH,		DBUS_PATH_DBUS },
+			{ L_DBUS_MATCH_INTERFACE,	L_DBUS_INTERFACE_DBUS },
+			{ L_DBUS_MATCH_MEMBER,		"NameOwnerChanged" },
+		};
+
+		if (!bus->filter)
+			bus->filter = _dbus_filter_new(bus,
+						&bus->driver->filter_ops,
+						bus->name_cache);
+
+		_dbus_filter_add_rule(bus->filter, rule, L_ARRAY_SIZE(rule),
+					name_owner_changed_cb, bus);
+
+		bus->name_notify_enabled = true;
+	}
+
+	return true;
+}
+
+struct name_request {
+	l_dbus_name_acquire_func_t callback;
+	void *user_data;
+	struct l_dbus *dbus;
+};
+
+enum dbus_name_flag {
+	DBUS_NAME_FLAG_ALLOW_REPLACEMENT	= 0x1,
+	DBUS_NAME_FLAG_REPLACE_EXISTING		= 0x2,
+	DBUS_NAME_FLAG_DO_NOT_QUEUE		= 0x4,
+};
+
+enum dbus_name_reply {
+	DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER	= 1,
+	DBUS_REQUEST_NAME_REPLY_IN_QUEUE	= 2,
+	DBUS_REQUEST_NAME_REPLY_EXISTS		= 3,
+	DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER	= 4,
+};
+
+static void request_name_reply_cb(struct l_dbus_message *reply, void *user_data)
+{
+	struct name_request *req = user_data;
+	bool success = false, queued = false;
+	uint32_t retval;
+
+	if (!req->callback)
+		return;
+
+	/* No name owner yet */
+	if (l_dbus_message_is_error(reply))
+		goto call_back;
+
+	/* Shouldn't happen */
+	if (!l_dbus_message_get_arguments(reply, "u", &retval))
+		goto call_back;
+
+	success = (retval == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) ||
+		(retval == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER) ||
+		(retval == DBUS_REQUEST_NAME_REPLY_IN_QUEUE);
+	queued = (retval == DBUS_REQUEST_NAME_REPLY_IN_QUEUE);
+
+call_back:
+	req->callback(req->dbus, success, queued, req->user_data);
+}
+
+static uint32_t classic_name_acquire(struct l_dbus *dbus, const char *name,
+					bool allow_replacement,
+					bool replace_existing, bool queue,
+					l_dbus_name_acquire_func_t callback,
+					void *user_data)
+{
+	struct name_request *req;
+	struct l_dbus_message *message;
+	uint32_t flags = 0;
+
+	req = l_new(struct name_request, 1);
+	req->dbus = dbus;
+	req->user_data = user_data;
+	req->callback = callback;
+
+	message = l_dbus_message_new_method_call(dbus, DBUS_SERVICE_DBUS,
+							DBUS_PATH_DBUS,
+							L_DBUS_INTERFACE_DBUS,
+							"RequestName");
+
+	if (allow_replacement)
+		flags |= DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
+
+	if (replace_existing)
+		flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
+
+	if (!queue)
+		flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
+
+	l_dbus_message_set_arguments(message, "su", name, flags);
+
+	return send_message(dbus, false, message, request_name_reply_cb,
+				req, free);
+}
+
+static const struct l_dbus_ops classic_ops = {
+	.version = 1,
+	.send_message = classic_send_message,
+	.recv_message = classic_recv_message,
+	.free = classic_free,
+	.name_ops = {
+		.get_name_owner = classic_get_name_owner,
+	},
+	.filter_ops = {
+		.add_match = classic_add_match,
+		.remove_match = classic_remove_match,
+	},
+	.name_acquire = classic_name_acquire,
+};
+
+static struct l_dbus *setup_dbus1(int fd, const char *guid, bool skip_hello)
+{
+	static const unsigned char creds = 0x00;
+	char uid[6], hexuid[12], *ptr = hexuid;
+	struct l_dbus *dbus;
+	struct l_dbus_classic *classic;
+	ssize_t written;
+	unsigned int i;
+
+	if (snprintf(uid, sizeof(uid), "%d", geteuid()) < 1) {
+		close(fd);
+		return NULL;
+	}
+
+	for (i = 0; i < strlen(uid); i++)
+		ptr += sprintf(ptr, "%02x", uid[i]);
+
+	/* Send special credentials-passing nul byte */
+	written = L_TFR(send(fd, &creds, 1, 0));
+	if (written < 1) {
+		close(fd);
+		return NULL;
+	}
+
+	classic = l_new(struct l_dbus_classic, 1);
+	dbus = &classic->super;
+	dbus->driver = &classic_ops;
+
+	classic->match_strings = l_hashmap_new();
+
+	dbus_init(dbus, fd);
+	dbus->guid = l_strdup(guid);
+
+	classic->auth_command = l_strdup_printf("AUTH EXTERNAL %s\r\n", hexuid);
+	classic->auth_state = WAITING_FOR_OK;
+	classic->skip_hello = skip_hello;
+
+	dbus->negotiate_unix_fd = true;
+	dbus->support_unix_fd = false;
+
+	l_io_set_read_handler(dbus->io, auth_read_handler, dbus, NULL);
+	l_io_set_write_handler(dbus->io, auth_write_handler, dbus, NULL);
+
+	return dbus;
+}
+
+static struct l_dbus *setup_unix(char *params)
+{
+	char *path = NULL, *guid = NULL;
+	bool abstract = false;
+	struct sockaddr_un addr;
+	size_t len;
+	int fd;
+
+	while (params) {
+		char *key = strsep(&params, ",");
+		char *value;
+
+		if (!key)
+			break;
+
+		value = strchr(key, '=');
+		if (!value)
+			continue;
+
+		*value++ = '\0';
+
+		if (!strcmp(key, "path")) {
+			path = value;
+			abstract = false;
+		} else if (!strcmp(key, "abstract")) {
+			path = value;
+			abstract = true;
+		} else if (!strcmp(key, "guid"))
+			guid = value;
+	}
+
+	if (!path)
+		return NULL;
+
+	fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (fd < 0)
+		return NULL;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+
+	len = strlen(path);
+
+	if (abstract) {
+		if (len > sizeof(addr.sun_path) - 1) {
+			close(fd);
+			return NULL;
+		}
+
+		addr.sun_path[0] = '\0';
+		strncpy(addr.sun_path + 1, path, sizeof(addr.sun_path) - 2);
+		len++;
+	} else {
+		if (len > sizeof(addr.sun_path)) {
+			close(fd);
+			return NULL;
+		}
+
+		strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
+	}
+
+	if (connect(fd, (struct sockaddr *) &addr,
+				sizeof(addr.sun_family) + len) < 0) {
+		close(fd);
+		return NULL;
+	}
+
+	return setup_dbus1(fd, guid, false);
+}
+
+static bool setup_tcp_cb(struct l_io *io, void *user_data)
+{
+	static const unsigned char creds = 0x00;
+	struct l_dbus *dbus = user_data;
+	struct l_dbus_classic *classic;
+	ssize_t written;
+	int fd = l_io_get_fd(io);
+
+	/* Send special credentials-passing nul byte */
+	written = L_TFR(send(fd, &creds, 1, 0));
+	if (written < 1) {
+		l_util_debug(dbus->debug_handler, dbus->debug_handler,
+						"error writing NUL byte");
+		close(fd);
+		return false;
+	}
+
+	dbus->driver = &classic_ops;
+	dbus->negotiate_unix_fd = false;
+	dbus->support_unix_fd = false;
+
+	classic = l_container_of(dbus, struct l_dbus_classic, super);
+	classic->match_strings = l_hashmap_new();
+	classic->auth_command = l_strdup("AUTH ANONYMOUS\r\n");
+	classic->auth_state = WAITING_FOR_OK;
+
+	l_io_set_read_handler(dbus->io, auth_read_handler, dbus, NULL);
+	l_io_set_write_handler(dbus->io, auth_write_handler, dbus, NULL);
+
+	return auth_write_handler(dbus->io, dbus);
+}
+
+static struct l_dbus *setup_tcp(char *params)
+{
+	char *host = NULL;
+	char *port = NULL;
+	char *family = NULL;
+	struct addrinfo hints = { 0 };
+	struct addrinfo *res;
+	struct addrinfo *iter;
+	struct l_dbus *dbus = NULL;
+
+	while (params) {
+		char *key = strsep(&params, ",");
+		char *value;
+
+		value = strchr(key, '=');
+		if (!value)
+			continue;
+
+		*value++ = '\0';
+
+		if (!strcmp(key, "host"))
+			host = value;
+		else if (!strcmp(key, "port"))
+			port = value;
+		else if (!strcmp(key, "family"))
+			family = value;
+	}
+
+	if (!host || !port)
+		return NULL;
+
+	if (!family)
+		hints.ai_family = AF_UNSPEC;
+	else if (!strcmp(family, "ipv4"))
+		hints.ai_family = AF_INET;
+	else if (!strcmp(family, "ipv6"))
+		hints.ai_family = AF_INET6;
+	else
+		return NULL;
+
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+	hints.ai_protocol = IPPROTO_TCP;
+
+	if (getaddrinfo(host, port, &hints, &res) != 0)
+		return NULL;
+
+	for (iter = res; iter; iter = iter->ai_next) {
+		int fd;
+		struct l_dbus_classic *classic;
+
+		fd = socket(iter->ai_family, iter->ai_socktype | SOCK_NONBLOCK,
+					iter->ai_protocol);
+		if (fd < 0)
+			continue;
+
+		if (connect(fd, iter->ai_addr, iter->ai_addrlen) < 0) {
+			if (errno != EINPROGRESS) {
+				close(fd);
+				continue;
+			}
+		}
+
+		classic = l_new(struct l_dbus_classic, 1);
+		dbus = &classic->super;
+		dbus_init(dbus, fd);
+		l_io_set_write_handler(dbus->io, setup_tcp_cb, dbus, NULL);
+		break;
+	}
+
+	freeaddrinfo(res);
+	return dbus;
+}
+
+static struct l_dbus *setup_address(const char *address)
+{
+	struct l_dbus *dbus = NULL;
+	char *address_copy;
+
+	address_copy = strdupa(address);
+
+	while (address_copy) {
+		char *transport = strsep(&address_copy, ";");
+		char *params;
+
+		if (!transport)
+			break;
+
+		params = strchr(transport, ':');
+		if (params)
+			*params++ = '\0';
+
+		if (!strcmp(transport, "unix")) {
+			/* Function will modify params string */
+			dbus = setup_unix(params);
+			break;
+		} else if (!strcmp(transport, "tcp")) {
+			dbus = setup_tcp(params);
+			break;
+		}
+	}
+
+	return dbus;
+}
+
+LIB_EXPORT struct l_dbus *l_dbus_new(const char *address)
+{
+	if (unlikely(!address))
+		return NULL;
+
+	return setup_address(address);
+}
+
+LIB_EXPORT struct l_dbus *l_dbus_new_default(enum l_dbus_bus bus)
+{
+	const char *address;
+
+	switch (bus) {
+	case L_DBUS_SYSTEM_BUS:
+		address = getenv("DBUS_SYSTEM_BUS_ADDRESS");
+		if (!address)
+			address = DEFAULT_SYSTEM_BUS_ADDRESS;
+		break;
+	case L_DBUS_SESSION_BUS:
+		address = getenv("DBUS_SESSION_BUS_ADDRESS");
+		if (!address)
+			return NULL;
+		break;
+	default:
+		return NULL;
+	}
+
+	return setup_address(address);
+}
+
+LIB_EXPORT struct l_dbus *l_dbus_new_private(int fd)
+{
+	return setup_dbus1(fd, NULL, true);
+}
+
+LIB_EXPORT void l_dbus_destroy(struct l_dbus *dbus)
+{
+	if (unlikely(!dbus))
+		return;
+
+	if (dbus->ready_destroy)
+		dbus->ready_destroy(dbus->ready_data);
+
+	_dbus_filter_free(dbus->filter);
+
+	_dbus_name_cache_free(dbus->name_cache);
+
+	l_hashmap_destroy(dbus->signal_list, signal_list_destroy);
+	l_hashmap_destroy(dbus->message_list, message_list_destroy);
+	l_queue_destroy(dbus->message_queue, message_queue_destroy);
+
+	l_io_destroy(dbus->io);
+
+	if (dbus->disconnect_destroy)
+		dbus->disconnect_destroy(dbus->disconnect_data);
+
+	if (dbus->debug_destroy)
+		dbus->debug_destroy(dbus->debug_data);
+
+	l_free(dbus->guid);
+	l_free(dbus->unique_name);
+
+	_dbus_object_tree_free(dbus->tree);
+
+	dbus->driver->free(dbus);
+}
+
+LIB_EXPORT bool l_dbus_set_ready_handler(struct l_dbus *dbus,
+				l_dbus_ready_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (dbus->ready_destroy)
+		dbus->ready_destroy(dbus->ready_data);
+
+	dbus->ready_handler = function;
+	dbus->ready_destroy = destroy;
+	dbus->ready_data = user_data;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_set_disconnect_handler(struct l_dbus *dbus,
+				l_dbus_disconnect_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (dbus->disconnect_destroy)
+		dbus->disconnect_destroy(dbus->disconnect_data);
+
+	dbus->disconnect_handler = function;
+	dbus->disconnect_destroy = destroy;
+	dbus->disconnect_data = user_data;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_set_debug(struct l_dbus *dbus,
+				l_dbus_debug_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (dbus->debug_destroy)
+		dbus->debug_destroy(dbus->debug_data);
+
+	dbus->debug_handler = function;
+	dbus->debug_destroy = destroy;
+	dbus->debug_data = user_data;
+
+	/* l_io_set_debug(dbus->io, function, user_data, NULL); */
+
+	return true;
+}
+
+LIB_EXPORT uint32_t l_dbus_send_with_reply(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						l_dbus_message_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!dbus || !message))
+		return 0;
+
+	return send_message(dbus, false, message, function, user_data, destroy);
+}
+
+LIB_EXPORT uint32_t l_dbus_send(struct l_dbus *dbus,
+				struct l_dbus_message *message)
+{
+	if (unlikely(!dbus || !message))
+		return 0;
+
+	return send_message(dbus, false, message, NULL, NULL, NULL);
+}
+
+static bool remove_entry(void *data, void *user_data)
+{
+	struct message_callback *callback = data;
+	uint32_t serial = L_PTR_TO_UINT(user_data);
+
+	if (callback->serial == serial) {
+		message_queue_destroy(callback);
+		return true;
+	}
+
+	return false;
+}
+
+LIB_EXPORT bool l_dbus_cancel(struct l_dbus *dbus, uint32_t serial)
+{
+	struct message_callback *callback;
+	unsigned int count;
+
+	if (unlikely(!dbus || !serial))
+		return false;
+
+	callback = l_hashmap_remove(dbus->message_list, L_UINT_TO_PTR(serial));
+        if (callback) {
+		message_queue_destroy(callback);
+		return true;
+	}
+
+	count = l_queue_foreach_remove(dbus->message_queue, remove_entry,
+							L_UINT_TO_PTR(serial));
+	if (!count)
+		return false;
+
+	return true;
+}
+
+LIB_EXPORT unsigned int l_dbus_register(struct l_dbus *dbus,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	struct signal_callback *callback;
+
+	if (unlikely(!dbus))
+		return 0;
+
+	callback = l_new(struct signal_callback, 1);
+
+	callback->id = dbus->next_id++;
+	callback->callback = function;
+	callback->destroy = destroy;
+	callback->user_data = user_data;
+
+	l_hashmap_insert(dbus->signal_list,
+				L_UINT_TO_PTR(callback->id), callback);
+
+	return callback->id;
+}
+
+LIB_EXPORT bool l_dbus_unregister(struct l_dbus *dbus, unsigned int id)
+{
+	struct signal_callback *callback;
+
+	if (unlikely(!dbus || !id))
+		return false;
+
+	callback = l_hashmap_remove(dbus->signal_list, L_UINT_TO_PTR(id));
+	if (!callback)
+		return false;
+
+	signal_list_destroy(callback);
+
+	return true;
+}
+
+LIB_EXPORT uint32_t l_dbus_method_call(struct l_dbus *dbus,
+				const char *destination, const char *path,
+				const char *interface, const char *method,
+				l_dbus_message_func_t setup,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy)
+{
+	struct l_dbus_message *message;
+
+	if (unlikely(!dbus))
+		return 0;
+
+	message = l_dbus_message_new_method_call(dbus, destination, path,
+							interface, method);
+
+	if (setup)
+		setup(message, user_data);
+	else
+		l_dbus_message_set_arguments(message, "");
+
+	return send_message(dbus, false, message, function, user_data, destroy);
+}
+
+uint8_t _dbus_get_version(struct l_dbus *dbus)
+{
+	return dbus->driver->version;
+}
+
+int _dbus_get_fd(struct l_dbus *dbus)
+{
+	return l_io_get_fd(dbus->io);
+}
+
+struct _dbus_object_tree *_dbus_get_tree(struct l_dbus *dbus)
+{
+	return dbus->tree;
+}
+
+/**
+ * l_dbus_register_interface:
+ * @dbus: D-Bus connection as returned by @l_dbus_new*
+ * @interface: interface name string
+ * @setup_func: function that sets up the methods, signals and properties by
+ *              using the #dbus-service.h API.
+ * @destroy: optional destructor to be called every time an instance of this
+ *           interface is being removed from an object on this bus.
+ * @handle_old_style_properties: whether to automatically handle SetProperty and
+ *                               GetProperties for any properties registered by
+ *                               @setup_func.
+ *
+ * Registers an interface.  If successful the interface can then be added
+ * to any number of objects with @l_dbus_object_add_interface.
+ *
+ * Returns: whether the interface was successfully registered
+ **/
+LIB_EXPORT bool l_dbus_register_interface(struct l_dbus *dbus,
+				const char *interface,
+				l_dbus_interface_setup_func_t setup_func,
+				l_dbus_destroy_func_t destroy,
+				bool handle_old_style_properties)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_register_interface(dbus->tree, interface,
+						setup_func, destroy,
+						handle_old_style_properties);
+}
+
+LIB_EXPORT bool l_dbus_unregister_interface(struct l_dbus *dbus,
+						const char *interface)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_unregister_interface(dbus->tree, interface);
+}
+
+/**
+ * l_dbus_register_object:
+ * @dbus: D-Bus connection
+ * @path: new object path
+ * @user_data: user pointer to be passed to @destroy if any
+ * @destroy: optional destructor to be called when object dropped from the tree
+ * @...: NULL-terminated list of 0 or more interfaces to be present on the
+ *       object from the moment of creation.  For every interface the interface
+ *       name string is expected followed by the @user_data pointer same as
+ *       would be passed as @l_dbus_object_add_interface's last two parameters.
+ *
+ * Create a new D-Bus object on the tree visible to D-Bus peers.  For example:
+ * 	success = l_dbus_register_object(bus, "/org/example/ExampleManager",
+ * 						NULL, NULL,
+ * 						"org.example.Manager",
+ * 						manager_data,
+ * 						NULL);
+ *
+ * Returns: whether the object path was successfully registered
+ **/
+LIB_EXPORT bool l_dbus_register_object(struct l_dbus *dbus, const char *path,
+					void *user_data,
+					l_dbus_destroy_func_t destroy, ...)
+{
+	va_list args;
+	const char *interface;
+	void *if_user_data;
+	bool r = true;
+
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	if (!_dbus_object_tree_new_object(dbus->tree, path, user_data, destroy))
+		return false;
+
+	va_start(args, destroy);
+	while ((interface = va_arg(args, const char *))) {
+		if_user_data = va_arg(args, void *);
+
+		if (!_dbus_object_tree_add_interface(dbus->tree, path,
+							interface,
+							if_user_data)) {
+			_dbus_object_tree_object_destroy(dbus->tree, path);
+			r = false;
+
+			break;
+		}
+	}
+	va_end(args);
+
+	return r;
+}
+
+LIB_EXPORT bool l_dbus_unregister_object(struct l_dbus *dbus,
+						const char *object)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_object_destroy(dbus->tree, object);
+}
+
+/**
+ * l_dbus_object_add_interface:
+ * @dbus: D-Bus connection
+ * @object: object path as passed to @l_dbus_register_object
+ * @interface: interface name as passed to @l_dbus_register_interface
+ * @user_data: user data pointer to be passed to any method and property
+ *             callbacks provided by the @setup_func and to the @destroy
+ *             callback as passed to @l_dbus_register_interface
+ *
+ * Creates an instance of given interface at the given path in the
+ * connection's object tree.  If no object was registered at this path
+ * before @l_dbus_register_object gets called automatically.
+ *
+ * The addition of an interface to the object may trigger a query of
+ * all the properties on this interface and
+ * #org.freedesktop.DBus.ObjectManager.InterfacesAdded signals.
+ *
+ * Returns: whether the interface was successfully added.
+ **/
+LIB_EXPORT bool l_dbus_object_add_interface(struct l_dbus *dbus,
+						const char *object,
+						const char *interface,
+						void *user_data)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_add_interface(dbus->tree, object, interface,
+						user_data);
+}
+
+LIB_EXPORT bool l_dbus_object_remove_interface(struct l_dbus *dbus,
+						const char *object,
+						const char *interface)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_remove_interface(dbus->tree, object,
+							interface);
+}
+
+LIB_EXPORT void *l_dbus_object_get_data(struct l_dbus *dbus, const char *object,
+					const char *interface)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_get_interface_data(dbus->tree, object,
+							interface);
+}
+
+LIB_EXPORT bool l_dbus_object_set_data(struct l_dbus *dbus, const char *object,
+				const char *interface, void *user_data)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_set_interface_data(dbus->tree, object,
+							interface, user_data);
+}
+
+LIB_EXPORT bool l_dbus_object_manager_enable(struct l_dbus *dbus,
+						const char *root)
+{
+	if (unlikely(!dbus))
+		return false;
+
+	if (unlikely(!dbus->tree))
+		return false;
+
+	return _dbus_object_tree_add_interface(dbus->tree, root,
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						dbus);
+}
+
+LIB_EXPORT unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
+					const char *name,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	return l_dbus_add_service_watch(dbus, name, NULL, disconnect_func,
+					user_data, destroy);
+}
+
+LIB_EXPORT unsigned int l_dbus_add_service_watch(struct l_dbus *dbus,
+					const char *name,
+					l_dbus_watch_func_t connect_func,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	if (!name)
+		return 0;
+
+	if (!dbus->name_cache)
+		dbus->name_cache = _dbus_name_cache_new(dbus,
+						&dbus->driver->name_ops);
+
+	return _dbus_name_cache_add_watch(dbus->name_cache, name, connect_func,
+						disconnect_func, user_data,
+						destroy);
+}
+
+LIB_EXPORT bool l_dbus_remove_watch(struct l_dbus *dbus, unsigned int id)
+{
+	if (!dbus->name_cache)
+		return false;
+
+	return _dbus_name_cache_remove_watch(dbus->name_cache, id);
+}
+
+/**
+ * l_dbus_add_signal_watch:
+ * @dbus: D-Bus connection
+ * @sender: bus name to match the signal sender against or NULL to
+ *          match any sender
+ * @path: object path to match the signal path against or NULL to
+ *        match any path
+ * @interface: interface name to match the signal interface against
+ *             or NULL to match any interface
+ * @member: name to match the signal name against or NULL to match any
+ *          signal
+ * @...: a list of further conditions to be met by the signal followed
+ *       by three more mandatory parameters:
+ *       enum l_dbus_match_type list_end_marker,
+ *       l_dbus_message_func callback,
+ *       void *user_data,
+ *       The value L_DBUS_MATCH_NONE must be passed as the end of list
+ *       marker, followed by the signal match callback and user_data.
+ *       In the list, every condition is a pair of parameters:
+ *       enum l_dbus_match_type match_type, const char *value.
+ *
+ * Subscribe to a group of signals based on a set of conditions that
+ * compare the signal's header fields and string arguments against given
+ * values.  For example:
+ * 	signal_id = l_dbus_add_signal_watch(bus, "org.example", "/"
+ * 						"org.example.Manager",
+ * 						"PropertyChanged",
+ * 						L_DBUS_MATCH_ARGUMENT(0),
+ * 						"ExampleProperty",
+ * 						L_DBUS_MATCH_NONE
+ * 						manager_property_change_cb,
+ * 						NULL);
+  *
+ * Returns: a non-zero signal filter identifier that can be passed to
+ *          l_dbus_remove_signal_watch to remove this filter rule, or
+ *          zero on failure.
+ **/
+LIB_EXPORT unsigned int l_dbus_add_signal_watch(struct l_dbus *dbus,
+						const char *sender,
+						const char *path,
+						const char *interface,
+						const char *member, ...)
+{
+	struct _dbus_filter_condition *rule;
+	int rule_len;
+	va_list args;
+	const char *value;
+	l_dbus_message_func_t signal_func;
+	enum l_dbus_match_type type;
+	void *user_data;
+	unsigned int id;
+
+	va_start(args, member);
+
+	rule_len = 0;
+	while (va_arg(args, enum l_dbus_match_type) != L_DBUS_MATCH_NONE)
+		rule_len++;
+
+	va_end(args);
+
+	rule = l_new(struct _dbus_filter_condition, rule_len + 5);
+
+	rule_len = 0;
+
+	rule[rule_len].type = L_DBUS_MATCH_TYPE;
+	rule[rule_len++].value = "signal";
+
+	if (sender) {
+		rule[rule_len].type = L_DBUS_MATCH_SENDER;
+		rule[rule_len++].value = sender;
+	}
+
+	if (path) {
+		rule[rule_len].type = L_DBUS_MATCH_PATH;
+		rule[rule_len++].value = path;
+	}
+
+	if (interface) {
+		rule[rule_len].type = L_DBUS_MATCH_INTERFACE;
+		rule[rule_len++].value = interface;
+	}
+
+	if (member) {
+		rule[rule_len].type = L_DBUS_MATCH_MEMBER;
+		rule[rule_len++].value = member;
+	}
+
+	va_start(args, member);
+
+	while (true) {
+		type = va_arg(args, enum l_dbus_match_type);
+		if (type == L_DBUS_MATCH_NONE)
+			break;
+
+		value = va_arg(args, const char *);
+
+		rule[rule_len].type = type;
+		rule[rule_len++].value = value;
+	}
+
+	signal_func = va_arg(args, l_dbus_message_func_t);
+	user_data = va_arg(args, void *);
+
+	va_end(args);
+
+	if (!dbus->filter) {
+		if (!dbus->name_cache)
+			dbus->name_cache = _dbus_name_cache_new(dbus,
+						&dbus->driver->name_ops);
+
+		dbus->filter = _dbus_filter_new(dbus,
+						&dbus->driver->filter_ops,
+						dbus->name_cache);
+	}
+
+	id = _dbus_filter_add_rule(dbus->filter, rule, rule_len,
+					signal_func, user_data);
+
+	l_free(rule);
+
+	return id;
+}
+
+LIB_EXPORT bool l_dbus_remove_signal_watch(struct l_dbus *dbus, unsigned int id)
+{
+	if (!dbus->filter)
+		return false;
+
+	return _dbus_filter_remove_rule(dbus->filter, id);
+}
+
+/**
+ * l_dbus_name_acquire:
+ * @dbus: D-Bus connection
+ * @name: Well-known bus name to be acquired
+ * @allow_replacement: Whether to allow another peer's name request to
+ *                     take the name ownership away from this connection
+ * @replace_existing: Whether to allow D-Bus to take the name's ownership
+ *                    away from another peer in case the name is already
+ *                    owned and allows replacement.  Ignored if name is
+ *                    currently free.
+ * @queue: Whether to allow the name request to be queued by D-Bus in
+ *         case it cannot be acquired now, rather than to return a failure.
+ * @callback: Callback to receive the request result when done.
+ *
+ * Acquire a well-known bus name (service name) on the bus.
+ *
+ * Returns: a non-zero request serial that can be passed to l_dbus_cancel
+ *          while waiting for the callback or zero if the callback has
+ *          has happened while l_dbus_name_acquire was running.
+ **/
+LIB_EXPORT uint32_t l_dbus_name_acquire(struct l_dbus *dbus, const char *name,
+				bool allow_replacement, bool replace_existing,
+				bool queue, l_dbus_name_acquire_func_t callback,
+				void *user_data)
+{
+	return dbus->driver->name_acquire(dbus, name, allow_replacement,
+						replace_existing, queue,
+						callback, user_data);
+}
diff --git a/ell/dbus.h b/ell/dbus.h
new file mode 100644
index 0000000..21777cb
--- /dev/null
+++ b/ell/dbus.h
@@ -0,0 +1,266 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_DBUS_H
+#define __ELL_DBUS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define L_DBUS_INTERFACE_DBUS		"org.freedesktop.DBus"
+#define L_DBUS_INTERFACE_INTROSPECTABLE	"org.freedesktop.DBus.Introspectable"
+#define L_DBUS_INTERFACE_PROPERTIES	"org.freedesktop.DBus.Properties"
+#define L_DBUS_INTERFACE_OBJECT_MANAGER	"org.freedesktop.DBus.ObjectManager"
+
+enum l_dbus_bus {
+	L_DBUS_SYSTEM_BUS,
+	L_DBUS_SESSION_BUS,
+};
+
+enum l_dbus_match_type {
+	L_DBUS_MATCH_NONE = 0,
+	L_DBUS_MATCH_TYPE,
+	L_DBUS_MATCH_SENDER,
+	L_DBUS_MATCH_PATH,
+	L_DBUS_MATCH_INTERFACE,
+	L_DBUS_MATCH_MEMBER,
+	L_DBUS_MATCH_ARG0,
+};
+
+#define L_DBUS_MATCH_ARGUMENT(i)	(L_DBUS_MATCH_ARG0 + (i))
+
+struct l_dbus;
+struct l_dbus_interface;
+struct l_dbus_message_builder;
+
+typedef void (*l_dbus_ready_func_t) (void *user_data);
+typedef void (*l_dbus_disconnect_func_t) (void *user_data);
+
+typedef void (*l_dbus_debug_func_t) (const char *str, void *user_data);
+typedef void (*l_dbus_destroy_func_t) (void *user_data);
+typedef void (*l_dbus_interface_setup_func_t) (struct l_dbus_interface *);
+
+typedef void (*l_dbus_watch_func_t) (struct l_dbus *dbus, void *user_data);
+
+typedef void (*l_dbus_name_acquire_func_t) (struct l_dbus *dbus, bool success,
+						bool queued, void *user_data);
+
+struct l_dbus *l_dbus_new(const char *address);
+struct l_dbus *l_dbus_new_default(enum l_dbus_bus bus);
+struct l_dbus *l_dbus_new_private(int fd);
+void l_dbus_destroy(struct l_dbus *dbus);
+
+bool l_dbus_set_ready_handler(struct l_dbus *dbus, l_dbus_ready_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+bool l_dbus_set_disconnect_handler(struct l_dbus *dbus,
+				l_dbus_disconnect_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+
+bool l_dbus_set_debug(struct l_dbus *dbus, l_dbus_debug_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+
+struct l_dbus_message;
+
+struct l_dbus_message_iter {
+	struct l_dbus_message *message;
+	const char *sig_start;
+	uint8_t sig_len;
+	uint8_t sig_pos;
+	const void *data;
+	size_t len;
+	size_t pos;
+	char container_type;
+	const void *offsets;
+};
+
+struct l_dbus_message *l_dbus_message_new_method_call(struct l_dbus *dbus,
+							const char *destination,
+							const char *path,
+							const char *interface,
+							const char *method);
+
+struct l_dbus_message *l_dbus_message_new_signal(struct l_dbus *dbus,
+							const char *path,
+							const char *interface,
+							const char *name);
+
+struct l_dbus_message *l_dbus_message_new_method_return(
+					struct l_dbus_message *method_call);
+
+struct l_dbus_message *l_dbus_message_new_error_valist(
+					struct l_dbus_message *method_call,
+					const char *name,
+					const char *format, va_list args)
+					__attribute__((format(printf, 3, 0)));
+struct l_dbus_message *l_dbus_message_new_error(
+					struct l_dbus_message *method_call,
+					const char *name,
+					const char *format, ...)
+					__attribute__((format(printf, 3, 4)));
+
+struct l_dbus_message *l_dbus_message_ref(struct l_dbus_message *message);
+void l_dbus_message_unref(struct l_dbus_message *message);
+
+const char *l_dbus_message_get_path(struct l_dbus_message *message);
+const char *l_dbus_message_get_interface(struct l_dbus_message *message);
+const char *l_dbus_message_get_member(struct l_dbus_message *message);
+const char *l_dbus_message_get_destination(struct l_dbus_message *message);
+const char *l_dbus_message_get_sender(struct l_dbus_message *message);
+const char *l_dbus_message_get_signature(struct l_dbus_message *message);
+
+bool l_dbus_message_set_no_reply(struct l_dbus_message *message, bool on);
+bool l_dbus_message_get_no_reply(struct l_dbus_message *message);
+
+bool l_dbus_message_set_no_autostart(struct l_dbus_message *message, bool on);
+bool l_dbus_message_get_no_autostart(struct l_dbus_message *message);
+
+typedef void (*l_dbus_message_func_t) (struct l_dbus_message *message,
+							void *user_data);
+
+uint32_t l_dbus_send_with_reply(struct l_dbus *dbus,
+				struct l_dbus_message *message,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+uint32_t l_dbus_send(struct l_dbus *dbus,
+				struct l_dbus_message *message);
+bool l_dbus_cancel(struct l_dbus *dbus, uint32_t serial);
+
+unsigned int l_dbus_register(struct l_dbus *dbus,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+bool l_dbus_unregister(struct l_dbus *dbus, unsigned int id);
+
+uint32_t l_dbus_method_call(struct l_dbus *dbus,
+				const char *destination, const char *path,
+				const char *interface, const char *method,
+				l_dbus_message_func_t setup,
+				l_dbus_message_func_t function,
+				void *user_data, l_dbus_destroy_func_t destroy);
+
+bool l_dbus_message_is_error(struct l_dbus_message *message);
+bool l_dbus_message_get_error(struct l_dbus_message *message,
+					const char **name, const char **text);
+bool l_dbus_message_get_arguments(struct l_dbus_message *message,
+						const char *signature, ...);
+bool l_dbus_message_get_arguments_valist(struct l_dbus_message *message,
+					const char *signature, va_list args);
+
+bool l_dbus_message_iter_next_entry(struct l_dbus_message_iter *iter, ...);
+bool l_dbus_message_iter_get_variant(struct l_dbus_message_iter *iter,
+						const char *signature, ...);
+bool l_dbus_message_iter_get_fixed_array(struct l_dbus_message_iter *iter,
+						void *out, uint32_t *n_elem);
+
+bool l_dbus_message_set_arguments(struct l_dbus_message *message,
+						const char *signature, ...);
+bool l_dbus_message_set_arguments_valist(struct l_dbus_message *message,
+					 const char *signature, va_list args);
+
+struct l_dbus_message_builder *l_dbus_message_builder_new(
+						struct l_dbus_message *message);
+void l_dbus_message_builder_destroy(struct l_dbus_message_builder *builder);
+
+bool l_dbus_message_builder_append_basic(struct l_dbus_message_builder *builder,
+					char type, const void *value);
+
+bool l_dbus_message_builder_enter_container(
+					struct l_dbus_message_builder *builder,
+					char container_type,
+					const char *signature);
+bool l_dbus_message_builder_leave_container(
+					struct l_dbus_message_builder *builder,
+					char container_type);
+
+bool l_dbus_message_builder_enter_struct(struct l_dbus_message_builder *builder,
+						const char *signature);
+bool l_dbus_message_builder_leave_struct(
+					struct l_dbus_message_builder *builder);
+
+bool l_dbus_message_builder_enter_dict(struct l_dbus_message_builder *builder,
+					const char *signature);
+bool l_dbus_message_builder_leave_dict(struct l_dbus_message_builder *builder);
+
+bool l_dbus_message_builder_enter_array(struct l_dbus_message_builder *builder,
+					const char *signature);
+bool l_dbus_message_builder_leave_array(struct l_dbus_message_builder *builder);
+
+bool l_dbus_message_builder_enter_variant(
+					struct l_dbus_message_builder *builder,
+					const char *signature);
+bool l_dbus_message_builder_leave_variant(
+					struct l_dbus_message_builder *builder);
+
+bool l_dbus_message_builder_append_from_iter(
+					struct l_dbus_message_builder *builder,
+					struct l_dbus_message_iter *from);
+
+bool l_dbus_message_builder_append_from_valist(
+					struct l_dbus_message_builder *builder,
+					const char *signature, va_list args);
+
+struct l_dbus_message *l_dbus_message_builder_finalize(
+					struct l_dbus_message_builder *builder);
+
+bool l_dbus_register_interface(struct l_dbus *dbus, const char *interface,
+				l_dbus_interface_setup_func_t setup_func,
+				l_dbus_destroy_func_t destroy,
+				bool handle_old_style_properties);
+bool l_dbus_unregister_interface(struct l_dbus *dbus, const char *interface);
+
+bool l_dbus_register_object(struct l_dbus *dbus, const char *path,
+				void *user_data, l_dbus_destroy_func_t destroy,
+				...);
+bool l_dbus_unregister_object(struct l_dbus *dbus, const char *object);
+
+bool l_dbus_object_add_interface(struct l_dbus *dbus, const char *object,
+					const char *interface, void *user_data);
+bool l_dbus_object_remove_interface(struct l_dbus *dbus, const char *object,
+					const char *interface);
+void *l_dbus_object_get_data(struct l_dbus *dbus, const char *object,
+				const char *interface);
+bool l_dbus_object_set_data(struct l_dbus *dbus, const char *object,
+				const char *interface, void *user_data);
+
+bool l_dbus_object_manager_enable(struct l_dbus *dbus, const char *root);
+
+unsigned int l_dbus_add_service_watch(struct l_dbus *dbus,
+					const char *name,
+					l_dbus_watch_func_t connect_func,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+
+unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
+					const char *name,
+					l_dbus_watch_func_t disconnect_func,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+bool l_dbus_remove_watch(struct l_dbus *dbus, unsigned int id);
+
+unsigned int l_dbus_add_signal_watch(struct l_dbus *dbus,
+					const char *sender,
+					const char *path,
+					const char *interface,
+					const char *member, ...);
+bool l_dbus_remove_signal_watch(struct l_dbus *dbus, unsigned int id);
+
+uint32_t l_dbus_name_acquire(struct l_dbus *dbus, const char *name,
+				bool allow_replacement, bool replace_existing,
+				bool queue, l_dbus_name_acquire_func_t callback,
+				void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_DBUS_H */
diff --git a/ell/ecc-external.c b/ell/ecc-external.c
new file mode 100644
index 0000000..7a08823
--- /dev/null
+++ b/ell/ecc-external.c
@@ -0,0 +1,1023 @@
+/*
+ * 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 <stdint.h>
+#include <stdbool.h>
+
+#include "private.h"
+#include "ecc.h"
+#include "ecc-private.h"
+#include "random.h"
+
+typedef struct {
+	uint64_t m_low;
+	uint64_t m_high;
+} uint128_t;
+
+static void vli_clear(uint64_t *vli, unsigned int ndigits)
+{
+	unsigned int i;
+
+	for (i = 0; i < ndigits; i++)
+		vli[i] = 0;
+}
+
+/* Returns true if vli == 0, false otherwise. */
+static bool vli_is_zero(const uint64_t *vli, unsigned int ndigits)
+{
+	unsigned int i;
+
+	for (i = 0; i < ndigits; 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)));
+}
+
+/* Sets dest = src. */
+static void vli_set(uint64_t *dest, const uint64_t *src, unsigned int ndigits)
+{
+	unsigned int i;
+
+	for (i = 0; i < ndigits; i++)
+		dest[i] = src[i];
+}
+
+/* Returns sign of left - right. */
+int _vli_cmp(const uint64_t *left, const uint64_t *right, unsigned int ndigits)
+{
+	int i;
+
+	for (i = ndigits - 1; i >= 0; i--) {
+		if (left[i] > right[i])
+			return 1;
+		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,
+							unsigned int ndigits)
+{
+	uint64_t carry = 0;
+	unsigned int i;
+
+	for (i = 0; i < ndigits; i++) {
+		uint64_t temp = in[i];
+
+		result[i] = (temp << shift) | carry;
+		carry = temp >> (64 - shift);
+	}
+
+	return carry;
+}
+
+/* Computes vli = vli >> 1. */
+void _vli_rshift1(uint64_t *vli, unsigned int ndigits)
+{
+	uint64_t *end = vli;
+	uint64_t carry = 0;
+
+	vli += ndigits;
+
+	while (vli-- > end) {
+		uint64_t temp = *vli;
+		*vli = (temp >> 1) | carry;
+		carry = temp << 63;
+	}
+}
+
+/* Computes result = left + right, returning carry. Can modify in place. */
+uint64_t _vli_add(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, unsigned int ndigits)
+{
+	uint64_t carry = 0;
+	unsigned int i;
+
+	for (i = 0; i < ndigits; 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. */
+uint64_t _vli_sub(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, unsigned int ndigits)
+{
+	uint64_t borrow = 0;
+	unsigned int i;
+
+	for (i = 0; i < ndigits; 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,
+							unsigned int ndigits)
+{
+	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 < ndigits * 2 - 1; k++) {
+		unsigned int min;
+
+		if (k < ndigits)
+			min = 0;
+		else
+			min = (k + 1) - ndigits;
+
+		for (i = min; i <= k && i < ndigits; 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[ndigits * 2 - 1] = r01.m_low;
+}
+
+static void vli_square(uint64_t *result, const uint64_t *left,
+			unsigned int ndigits)
+{
+	uint128_t r01 = { 0, 0 };
+	uint64_t r2 = 0;
+	unsigned int i, k;
+
+	for (k = 0; k < ndigits * 2 - 1; k++) {
+		unsigned int min;
+
+		if (k < ndigits)
+			min = 0;
+		else
+			min = (k + 1) - ndigits;
+
+		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[ndigits * 2 - 1] = r01.m_low;
+}
+
+/* Computes result = (left + right) % mod.
+ * Assumes that left < mod and right < mod, result != mod.
+ */
+void _vli_mod_add(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, const uint64_t *mod,
+				unsigned int ndigits)
+{
+	uint64_t carry;
+
+	carry = _vli_add(result, left, right, ndigits);
+
+	/* result > mod (result = mod + remainder), so subtract mod to
+	 * get remainder.
+	 */
+	if (carry || _vli_cmp(result, mod, ndigits) >= 0)
+		_vli_sub(result, result, mod, ndigits);
+}
+
+/* Computes result = (left - right) % mod.
+ * Assumes that left < mod and right < mod, result != mod.
+ */
+void _vli_mod_sub(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, const uint64_t *mod,
+				unsigned int ndigits)
+{
+	uint64_t borrow = _vli_sub(result, left, right, ndigits);
+
+	/* 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, ndigits);
+}
+
+/* Counts the number of 64-bit "digits" in vli. */
+static unsigned int _vli_num_digits(const uint64_t *vli, unsigned int ndigits)
+{
+	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 = ndigits - 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 ndigits)
+{
+	unsigned int i, num_digits;
+	uint64_t digit;
+
+	num_digits = _vli_num_digits(vli, ndigits);
+	if (num_digits == 0)
+		return 0;
+
+	digit = vli[num_digits - 1];
+	for (i = 0; digit; i++)
+		digit >>= 1;
+
+	return ((num_digits - 1) * 64 + i);
+}
+
+/* Computes result = product % mod, where product is 2N words long.
+ * Currently only designed to work for curve_p or curve_n.
+ */
+void _vli_mmod_slow(uint64_t *result, const uint64_t *product,
+				const uint64_t *mod, unsigned int ndigits)
+{
+	uint64_t mod_m[2 * L_ECC_MAX_DIGITS];
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+	uint64_t *v[2] = { tmp, (uint64_t *) product };
+	uint64_t carry = 0;
+	unsigned int i;
+	/* Shift mod so its highest set bit is at the maximum position. */
+	int shift = (ndigits * 2 * 64) - _vli_num_bits(mod, ndigits);
+	int word_shift = shift / 64;
+	int bit_shift = shift % 64;
+
+	vli_clear(mod_m, word_shift);
+	if (bit_shift > 0) {
+		for (i = 0; i < ndigits; ++i) {
+			mod_m[word_shift + i] = (mod[i] << bit_shift) | carry;
+			carry = mod[i] >> (64 - bit_shift);
+		}
+	} else
+		vli_set(mod_m + word_shift, mod, ndigits);
+
+	for (i = 1; shift >= 0; --shift) {
+		uint64_t borrow = 0;
+		unsigned int j;
+
+		for (j = 0; j < ndigits * 2; ++j) {
+			uint64_t diff = v[i][j] - mod_m[j] - borrow;
+
+			if (diff != v[i][j])
+				borrow = (diff > v[i][j]);
+			v[1 - i][j] = diff;
+		}
+		i = !(i ^ borrow); /* Swap the index if there was no borrow */
+		_vli_rshift1(mod_m, ndigits);
+		mod_m[ndigits - 1] |= mod_m[ndigits] << (64 - 1);
+		_vli_rshift1(mod_m + ndigits, ndigits);
+	}
+	vli_set(result, v[i], ndigits);
+}
+
+/* Computes p_result = p_product % curve_p.
+ * See algorithm 5 and 6 from
+ * http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf
+ */
+static void vli_mmod_fast_192(uint64_t *result, const uint64_t *product,
+				const uint64_t *curve_prime, uint64_t *tmp)
+{
+	const unsigned int ndigits = 3;
+	int carry;
+
+	vli_set(result, product, ndigits);
+
+	vli_set(tmp, &product[3], ndigits);
+	carry = _vli_add(result, result, tmp, ndigits);
+
+	tmp[0] = 0;
+	tmp[1] = product[3];
+	tmp[2] = product[4];
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	tmp[0] = tmp[1] = product[5];
+	tmp[2] = 0;
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	while (carry || _vli_cmp(curve_prime, result, ndigits) != 1)
+		carry -= _vli_sub(result, result, curve_prime, ndigits);
+}
+
+/* Computes result = product % curve_prime
+ * from http://www.nsa.gov/ia/_files/nist-routines.pdf
+ */
+static void vli_mmod_fast_256(uint64_t *result, const uint64_t *product,
+				const uint64_t *curve_prime, uint64_t *tmp)
+{
+	int carry;
+	const unsigned int ndigits = 4;
+
+	/* t */
+	vli_set(result, product, ndigits);
+
+	/* s1 */
+	tmp[0] = 0;
+	tmp[1] = product[5] & 0xffffffff00000000ull;
+	tmp[2] = product[6];
+	tmp[3] = product[7];
+	carry = vli_lshift(tmp, tmp, 1, ndigits);
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* 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, ndigits);
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s3 */
+	tmp[0] = product[4];
+	tmp[1] = product[5] & 0xffffffff;
+	tmp[2] = 0;
+	tmp[3] = product[7];
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* 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, ndigits);
+
+	/* 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, ndigits);
+
+	/* 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, ndigits);
+
+	/* 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, ndigits);
+
+	/* 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, ndigits);
+
+	if (carry < 0) {
+		do {
+			carry += _vli_add(result, result, curve_prime, ndigits);
+		} while (carry < 0);
+	} else {
+		while (carry || _vli_cmp(curve_prime, result, ndigits) != 1)
+			carry -= _vli_sub(result, result, curve_prime, ndigits);
+	}
+}
+
+/*
+ * The NIST algorithms define S values, which are comprised of 32 bit C values
+ * of the original product we are trying to reduce. Since we are working with
+ * 64 bit 'digits', we need to convert these C values into 64 bit chunks. This
+ * macro mainly makes code readability easier since we can directly pass the
+ * two C indexes (h and l). Some of these C values are zero, which is also a
+ * value C index. In this case -1 should be passed to indicate zero.
+ */
+#define ECC_SET_S(prod, h, l) ({ 				\
+	uint64_t r = 0;						\
+	if (h == -1) {						\
+		/* zero, don't do anything */			\
+	} else if (h & 1)					\
+		r |= (prod[h / 2] & 0xffffffff00000000ull);	\
+	else							\
+		r |= (prod[h / 2] << 32);			\
+	if (l == -1) {						\
+		/* zero, don't do anything */			\
+	} else if (l & 1)					\
+		r |= (prod[l / 2] >> 32);			\
+	else							\
+		r |= (prod[l / 2] & 0xffffffff);		\
+	r;							\
+})
+
+static void vli_mmod_fast_384(uint64_t *result, const uint64_t *product,
+				const uint64_t *curve_prime, uint64_t *tmp)
+{
+	int carry;
+	const unsigned int ndigits = 6;
+
+	/* t */
+	vli_set(result, product, ndigits);
+
+	/* s1 */
+	tmp[0] = 0;
+	tmp[1] = 0;
+	tmp[2] = ECC_SET_S(product, 22, 21);
+	tmp[3] = ECC_SET_S(product, -1, 23);
+	tmp[4] = 0;
+	tmp[5] = 0;
+	carry = vli_lshift(tmp, tmp, 1, ndigits);
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s2 */
+	tmp[0] = product[6];
+	tmp[1] = product[7];
+	tmp[2] = product[8];
+	tmp[3] = product[9];
+	tmp[4] = product[10];
+	tmp[5] = product[11];
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s3 */
+	tmp[0] = ECC_SET_S(product, 22, 21);
+	tmp[1] = ECC_SET_S(product, 12, 23);
+	tmp[2] = ECC_SET_S(product, 14, 13);
+	tmp[3] = ECC_SET_S(product, 16, 15);
+	tmp[4] = ECC_SET_S(product, 18, 17);
+	tmp[5] = ECC_SET_S(product, 20, 19);
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s4 */
+	tmp[0] = ECC_SET_S(product, 23, -1);
+	tmp[1] = ECC_SET_S(product, 20, -1);
+	tmp[2] = ECC_SET_S(product, 13, 12);
+	tmp[3] = ECC_SET_S(product, 15, 14);
+	tmp[4] = ECC_SET_S(product, 17, 16);
+	tmp[5] = ECC_SET_S(product, 19, 18);
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s5 */
+	tmp[0] = 0;
+	tmp[1] = 0;
+	tmp[2] = ECC_SET_S(product, 21, 20);
+	tmp[3] = ECC_SET_S(product, 23, 22);
+	tmp[4] = 0;
+	tmp[5] = 0;
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s6 */
+	tmp[0] = ECC_SET_S(product, -1, 20);
+	tmp[1] = ECC_SET_S(product, 21, -1);
+	tmp[2] = ECC_SET_S(product, 23, 22);
+	tmp[3] = 0;
+	tmp[4] = 0;
+	tmp[5] = 0;
+	carry += _vli_add(result, result, tmp, ndigits);
+
+	/* s7 */
+	tmp[0] = ECC_SET_S(product, 12, 23);
+	tmp[1] = ECC_SET_S(product, 14, 13);
+	tmp[2] = ECC_SET_S(product, 16, 15);
+	tmp[3] = ECC_SET_S(product, 18, 17);
+	tmp[4] = ECC_SET_S(product, 20, 19);
+	tmp[5] = ECC_SET_S(product, 22, 21);
+	carry -= _vli_sub(result, result, tmp, ndigits);
+
+	/* s8 */
+	tmp[0] = ECC_SET_S(product, 20, -1);
+	tmp[1] = ECC_SET_S(product, 22, 21);
+	tmp[2] = ECC_SET_S(product, -1, 23);
+	tmp[3] = 0;
+	tmp[4] = 0;
+	tmp[5] = 0;
+	carry -= _vli_sub(result, result, tmp, ndigits);
+
+	/* s9 */
+	tmp[0] = 0;
+	tmp[1] = ECC_SET_S(product, 23, -1);
+	tmp[2] = ECC_SET_S(product, -1, 23);
+	tmp[3] = 0;
+	tmp[4] = 0;
+	tmp[5] = 0;
+	carry -= _vli_sub(result, result, tmp, ndigits);
+
+	if (carry < 0) {
+		do {
+			carry += _vli_add(result, result, curve_prime, ndigits);
+		} while (carry < 0);
+	} else {
+		while (carry || _vli_cmp(curve_prime, result, ndigits) != 1)
+			carry -= _vli_sub(result, result, curve_prime, ndigits);
+	}
+}
+
+/* Computes result = product % curve_prime
+ *  from http://www.nsa.gov/ia/_files/nist-routines.pdf
+*/
+bool _vli_mmod_fast(uint64_t *result, const uint64_t *product,
+			const uint64_t *curve_prime, unsigned int ndigits)
+{
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+
+	switch (ndigits) {
+	case 3:
+		vli_mmod_fast_192(result, product, curve_prime, tmp);
+		break;
+	case 4:
+		vli_mmod_fast_256(result, product, curve_prime, tmp);
+		break;
+	case 6:
+		vli_mmod_fast_384(result, product, curve_prime, tmp);
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+/* Computes result = (left * right) % curve_p. */
+void _vli_mod_mult_fast(uint64_t *result, const uint64_t *left,
+			const uint64_t *right, const uint64_t *curve_prime,
+			unsigned int ndigits)
+{
+	uint64_t product[2 * L_ECC_MAX_DIGITS];
+
+	vli_mult(product, left, right, ndigits);
+	_vli_mmod_fast(result, product, curve_prime, ndigits);
+}
+
+/* Computes result = left^2 % curve_p. */
+void _vli_mod_square_fast(uint64_t *result, const uint64_t *left,
+					const uint64_t *curve_prime,
+					unsigned int ndigits)
+{
+	uint64_t product[2 * L_ECC_MAX_DIGITS];
+
+	vli_square(product, left, ndigits);
+	_vli_mmod_fast(result, product, curve_prime, ndigits);
+}
+
+#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
+ */
+void _vli_mod_inv(uint64_t *result, const uint64_t *input,
+						const uint64_t *mod,
+						unsigned int ndigits)
+{
+	uint64_t a[L_ECC_MAX_DIGITS], b[L_ECC_MAX_DIGITS];
+	uint64_t u[L_ECC_MAX_DIGITS], v[L_ECC_MAX_DIGITS];
+	uint64_t carry;
+	int cmp_result;
+
+	if (vli_is_zero(input, ndigits)) {
+		vli_clear(result, ndigits);
+		return;
+	}
+
+	vli_set(a, input, ndigits);
+	vli_set(b, mod, ndigits);
+	vli_clear(u, ndigits);
+	u[0] = 1;
+	vli_clear(v, ndigits);
+
+	while ((cmp_result = _vli_cmp(a, b, ndigits)) != 0) {
+		carry = 0;
+
+		if (EVEN(a)) {
+			_vli_rshift1(a, ndigits);
+
+			if (!EVEN(u))
+				carry = _vli_add(u, u, mod, ndigits);
+
+			_vli_rshift1(u, ndigits);
+			if (carry)
+				u[ndigits - 1] |= 0x8000000000000000ull;
+		} else if (EVEN(b)) {
+			_vli_rshift1(b, ndigits);
+
+			if (!EVEN(v))
+				carry = _vli_add(v, v, mod, ndigits);
+
+			_vli_rshift1(v, ndigits);
+			if (carry)
+				v[ndigits - 1] |= 0x8000000000000000ull;
+		} else if (cmp_result > 0) {
+			_vli_sub(a, a, b, ndigits);
+			_vli_rshift1(a, ndigits);
+
+			if (_vli_cmp(u, v, ndigits) < 0)
+				_vli_add(u, u, mod, ndigits);
+
+			_vli_sub(u, u, v, ndigits);
+			if (!EVEN(u))
+				carry = _vli_add(u, u, mod, ndigits);
+
+			_vli_rshift1(u, ndigits);
+			if (carry)
+				u[ndigits - 1] |= 0x8000000000000000ull;
+		} else {
+			_vli_sub(b, b, a, ndigits);
+			_vli_rshift1(b, ndigits);
+
+			if (_vli_cmp(v, u, ndigits) < 0)
+				_vli_add(v, v, mod, ndigits);
+
+			_vli_sub(v, v, u, ndigits);
+			if (!EVEN(v))
+				carry = _vli_add(v, v, mod, ndigits);
+
+			_vli_rshift1(v, ndigits);
+			if (carry)
+				v[ndigits - 1] |= 0x8000000000000000ull;
+		}
+	}
+
+	vli_set(result, u, ndigits);
+}
+
+/* ------ Point operations ------ */
+
+/* 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,
+					const uint64_t *curve_prime,
+					unsigned int ndigits)
+{
+	/* t1 = x, t2 = y, t3 = z */
+	uint64_t t4[L_ECC_MAX_DIGITS];
+	uint64_t t5[L_ECC_MAX_DIGITS];
+
+	if (vli_is_zero(z1, ndigits))
+		return;
+
+	/* t4 = y1^2 */
+	_vli_mod_square_fast(t4, y1, curve_prime, ndigits);
+	/* t5 = x1*y1^2 = A */
+	_vli_mod_mult_fast(t5, x1, t4, curve_prime, ndigits);
+	/* t4 = y1^4 */
+	_vli_mod_square_fast(t4, t4, curve_prime, ndigits);
+	/* t2 = y1*z1 = z3 */
+	_vli_mod_mult_fast(y1, y1, z1, curve_prime, ndigits);
+	/* t3 = z1^2 */
+	_vli_mod_square_fast(z1, z1, curve_prime, ndigits);
+
+	/* t1 = x1 + z1^2 */
+	_vli_mod_add(x1, x1, z1, curve_prime, ndigits);
+	/* t3 = 2*z1^2 */
+	_vli_mod_add(z1, z1, z1, curve_prime, ndigits);
+	/* t3 = x1 - z1^2 */
+	_vli_mod_sub(z1, x1, z1, curve_prime, ndigits);
+	/* t1 = x1^2 - z1^4 */
+	_vli_mod_mult_fast(x1, x1, z1, curve_prime, ndigits);
+
+	/* t3 = 2*(x1^2 - z1^4) */
+	_vli_mod_add(z1, x1, x1, curve_prime, ndigits);
+	/* t1 = 3*(x1^2 - z1^4) */
+	_vli_mod_add(x1, x1, z1, curve_prime, ndigits);
+	if (vli_test_bit(x1, 0)) {
+		uint64_t carry = _vli_add(x1, x1, curve_prime, ndigits);
+		_vli_rshift1(x1, ndigits);
+		x1[ndigits - 1] |= carry << 63;
+	} else {
+		_vli_rshift1(x1, ndigits);
+	}
+	/* t1 = 3/2*(x1^2 - z1^4) = B */
+
+	/* t3 = B^2 */
+	_vli_mod_square_fast(z1, x1, curve_prime, ndigits);
+	/* t3 = B^2 - A */
+	_vli_mod_sub(z1, z1, t5, curve_prime, ndigits);
+	/* t3 = B^2 - 2A = x3 */
+	_vli_mod_sub(z1, z1, t5, curve_prime, ndigits);
+	/* t5 = A - x3 */
+	_vli_mod_sub(t5, t5, z1, curve_prime, ndigits);
+	/* t1 = B * (A - x3) */
+	_vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
+	/* t4 = B * (A - x3) - y1^4 = y3 */
+	_vli_mod_sub(t4, x1, t4, curve_prime, ndigits);
+
+	vli_set(x1, z1, ndigits);
+	vli_set(z1, y1, ndigits);
+	vli_set(y1, t4, ndigits);
+}
+
+/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
+static void apply_z(uint64_t *x1, uint64_t *y1, uint64_t *z,
+			const uint64_t *curve_prime, unsigned int ndigits)
+{
+	uint64_t t1[L_ECC_MAX_DIGITS];
+
+	_vli_mod_square_fast(t1, z, curve_prime, ndigits);    /* z^2 */
+	_vli_mod_mult_fast(x1, x1, t1, curve_prime, ndigits); /* x1 * z^2 */
+	_vli_mod_mult_fast(t1, t1, z, curve_prime, ndigits);  /* z^3 */
+	_vli_mod_mult_fast(y1, y1, t1, curve_prime, ndigits); /* 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,
+					const uint64_t *curve_prime,
+					unsigned int ndigits)
+{
+	uint64_t z[L_ECC_MAX_DIGITS];
+
+	vli_set(x2, x1, ndigits);
+	vli_set(y2, y1, ndigits);
+
+	vli_clear(z, ndigits);
+	z[0] = 1;
+
+	if (p_initial_z)
+		vli_set(z, p_initial_z, ndigits);
+
+	apply_z(x1, y1, z, curve_prime, ndigits);
+
+	ecc_point_double_jacobian(x1, y1, z, curve_prime, ndigits);
+
+	apply_z(x2, y2, z, curve_prime, ndigits);
+}
+
+/* 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,
+			const uint64_t *curve_prime, unsigned int ndigits)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uint64_t t5[L_ECC_MAX_DIGITS];
+
+	/* t5 = x2 - x1 */
+	_vli_mod_sub(t5, x2, x1, curve_prime, ndigits);
+	/* t5 = (x2 - x1)^2 = A */
+	_vli_mod_square_fast(t5, t5, curve_prime, ndigits);
+	/* t1 = x1*A = B */
+	_vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
+	/* t3 = x2*A = C */
+	_vli_mod_mult_fast(x2, x2, t5, curve_prime, ndigits);
+	/* t4 = y2 - y1 */
+	_vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
+	/* t5 = (y2 - y1)^2 = D */
+	_vli_mod_square_fast(t5, y2, curve_prime, ndigits);
+
+	/* t5 = D - B */
+	_vli_mod_sub(t5, t5, x1, curve_prime, ndigits);
+	/* t5 = D - B - C = x3 */
+	_vli_mod_sub(t5, t5, x2, curve_prime, ndigits);
+	/* t3 = C - B */
+	_vli_mod_sub(x2, x2, x1, curve_prime, ndigits);
+	/* t2 = y1*(C - B) */
+	_vli_mod_mult_fast(y1, y1, x2, curve_prime, ndigits);
+	/* t3 = B - x3 */
+	_vli_mod_sub(x2, x1, t5, curve_prime, ndigits);
+	/* t4 = (y2 - y1)*(B - x3) */
+	_vli_mod_mult_fast(y2, y2, x2, curve_prime, ndigits);
+	/* t4 = y3 */
+	_vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
+
+	vli_set(x2, t5, ndigits);
+}
+
+/* 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,
+			const uint64_t *curve_prime, unsigned int ndigits)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uint64_t t5[L_ECC_MAX_DIGITS];
+	uint64_t t6[L_ECC_MAX_DIGITS];
+	uint64_t t7[L_ECC_MAX_DIGITS];
+
+	/* t5 = x2 - x1 */
+	_vli_mod_sub(t5, x2, x1, curve_prime, ndigits);
+	/* t5 = (x2 - x1)^2 = A */
+	_vli_mod_square_fast(t5, t5, curve_prime, ndigits);
+	/* t1 = x1*A = B */
+	_vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
+	/* t3 = x2*A = C */
+	_vli_mod_mult_fast(x2, x2, t5, curve_prime, ndigits);
+	/* t4 = y2 + y1 */
+	_vli_mod_add(t5, y2, y1, curve_prime, ndigits);
+	/* t4 = y2 - y1 */
+	_vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
+
+	/* t6 = C - B */
+	_vli_mod_sub(t6, x2, x1, curve_prime, ndigits);
+	/* t2 = y1 * (C - B) */
+	_vli_mod_mult_fast(y1, y1, t6, curve_prime, ndigits);
+	/* t6 = B + C */
+	_vli_mod_add(t6, x1, x2, curve_prime, ndigits);
+	/* t3 = (y2 - y1)^2 */
+	_vli_mod_square_fast(x2, y2, curve_prime, ndigits);
+	/* t3 = x3 */
+	_vli_mod_sub(x2, x2, t6, curve_prime, ndigits);
+
+	/* t7 = B - x3 */
+	_vli_mod_sub(t7, x1, x2, curve_prime, ndigits);
+	/* t4 = (y2 - y1)*(B - x3) */
+	_vli_mod_mult_fast(y2, y2, t7, curve_prime, ndigits);
+	/* t4 = y3 */
+	_vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
+
+	/* t7 = (y2 + y1)^2 = F */
+	_vli_mod_square_fast(t7, t5, curve_prime, ndigits);
+	/* t7 = x3' */
+	_vli_mod_sub(t7, t7, t6, curve_prime, ndigits);
+	/* t6 = x3' - B */
+	_vli_mod_sub(t6, t7, x1, curve_prime, ndigits);
+	/* t6 = (y2 + y1)*(x3' - B) */
+	_vli_mod_mult_fast(t6, t6, t5, curve_prime, ndigits);
+	/* t2 = y3' */
+	_vli_mod_sub(y1, t6, y1, curve_prime, ndigits);
+
+	vli_set(x1, t7, ndigits);
+}
+
+void _ecc_point_mult(struct l_ecc_point *result,
+			const struct l_ecc_point *point, const uint64_t *scalar,
+			uint64_t *initial_z, const uint64_t *curve_prime)
+{
+	/* R0 and R1 */
+	const struct l_ecc_curve *curve = point->curve;
+	uint64_t rx[2][L_ECC_MAX_DIGITS];
+	uint64_t ry[2][L_ECC_MAX_DIGITS];
+	uint64_t z[L_ECC_MAX_DIGITS];
+	uint64_t sk[2][L_ECC_MAX_DIGITS];
+	int i, nb;
+	unsigned int ndigits = curve->ndigits;
+	int num_bits;
+	int carry;
+
+	carry = _vli_add(sk[0], scalar, curve->n, ndigits);
+	_vli_add(sk[1], sk[0], curve->n, ndigits);
+	scalar = sk[!carry];
+	num_bits = sizeof(uint64_t) * ndigits * 8 + 1;
+
+	vli_set(rx[1], point->x, ndigits);
+	vli_set(ry[1], point->y, ndigits);
+
+	xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z, curve_prime,
+				ndigits);
+
+	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], curve_prime,
+				ndigits);
+		xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb], curve_prime,
+				ndigits);
+	}
+
+	nb = !vli_test_bit(scalar, 0);
+	xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb], curve_prime,
+			ndigits);
+
+	/* Find final 1/Z value. */
+	/* X1 - X0 */
+	_vli_mod_sub(z, rx[1], rx[0], curve_prime, ndigits);
+	/* Yb * (X1 - X0) */
+	_vli_mod_mult_fast(z, z, ry[1 - nb], curve_prime, ndigits);
+	/* xP * Yb * (X1 - X0) */
+	_vli_mod_mult_fast(z, z, point->x, curve_prime, ndigits);
+
+	/* 1 / (xP * Yb * (X1 - X0)) */
+	_vli_mod_inv(z, z, curve_prime, ndigits);
+
+	/* yP / (xP * Yb * (X1 - X0)) */
+	_vli_mod_mult_fast(z, z, point->y, curve_prime, ndigits);
+	/* Xb * yP / (xP * Yb * (X1 - X0)) */
+	_vli_mod_mult_fast(z, z, rx[1 - nb], curve_prime, ndigits);
+	/* End 1/Z calculation */
+
+	xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb], curve_prime, ndigits);
+
+	apply_z(rx[0], ry[0], z, curve_prime, ndigits);
+
+	vli_set(result->x, rx[0], ndigits);
+	vli_set(result->y, ry[0], ndigits);
+}
+
+/* Returns true if p_point is the point at infinity, false otherwise. */
+bool _ecc_point_is_zero(const struct l_ecc_point *point)
+{
+	return (vli_is_zero(point->x, point->curve->ndigits) &&
+		vli_is_zero(point->y, point->curve->ndigits));
+}
diff --git a/ell/ecc-private.h b/ell/ecc-private.h
new file mode 100644
index 0000000..de84bc6
--- /dev/null
+++ b/ell/ecc-private.h
@@ -0,0 +1,128 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "ecc.h"
+#include "util.h"
+
+struct l_ecc_curve;
+
+struct l_ecc_point {
+	uint64_t x[L_ECC_MAX_DIGITS];
+	uint64_t y[L_ECC_MAX_DIGITS];
+	const struct l_ecc_curve *curve;
+};
+
+struct l_ecc_curve {
+	unsigned int ndigits;
+	unsigned int ike_group;
+	unsigned int tls_group;
+	const char *name;
+	struct l_ecc_point g;
+	uint64_t p[L_ECC_MAX_DIGITS];
+	uint64_t n[L_ECC_MAX_DIGITS];
+	uint64_t b[L_ECC_MAX_DIGITS];
+	int z;
+};
+
+struct l_ecc_scalar {
+	uint64_t c[L_ECC_MAX_DIGITS];
+	const struct l_ecc_curve *curve;
+};
+
+/*
+ * Performs a secure memory comparison of two uint64_t buffers of size bytes
+ * representing an integer. Blobs are ordered in little endian. It returns
+ * a negative, zero or positif value if a < b, a == b or a > b respectively.
+ */
+static inline int secure_memcmp_64(const uint64_t *a, const uint64_t *b,
+					size_t size)
+{
+	uint64_t aa_64, bb_64;
+
+	int res = 0, mask;
+
+	size_t i = 0;
+
+	if (size) {
+		/*
+		 * Arrays store blobs in LE, we will process each blob as a
+		 * byte array of size 8 using l_secure_memcmp. We need to make
+		 * sure to feed a BE byte array to avoid unexpected behavior
+		 * on different architectures.
+		 */
+		do {
+			aa_64 = L_CPU_TO_BE64(a[i]);
+			bb_64 = L_CPU_TO_BE64(b[i]);
+			mask = l_secure_memcmp(&aa_64, &bb_64, 8);
+			res = (mask & res) | mask;
+			i++;
+		} while (i != size);
+	}
+
+	return res;
+}
+
+void _ecc_be2native(uint64_t *dest, const uint64_t *bytes,
+							unsigned int ndigits);
+
+void _ecc_native2be(uint64_t *dest, const uint64_t *native,
+							unsigned int ndigits);
+
+void _vli_mod_inv(uint64_t *result, const uint64_t *input, const uint64_t *mod,
+			unsigned int ndigits);
+
+void _vli_mod_sub(uint64_t *result, const uint64_t *left, const uint64_t *right,
+		const uint64_t *mod, unsigned int ndigits);
+
+void _vli_mod_add(uint64_t *result, const uint64_t *left, const uint64_t *right,
+			const uint64_t *mod, unsigned int ndigits);
+
+void _vli_rshift1(uint64_t *vli, unsigned int ndigits);
+
+void _vli_mmod_slow(uint64_t *result, const uint64_t *product,
+				const uint64_t *mod, unsigned int ndigits);
+
+bool _vli_mmod_fast(uint64_t *result, const uint64_t *product,
+			const uint64_t *curve_prime, unsigned int ndigits);
+
+void _vli_mod_mult_fast(uint64_t *result, const uint64_t *left,
+		const uint64_t *right, const uint64_t *curve_prime,
+		unsigned int ndigits);
+void _vli_mod_square_fast(uint64_t *result, const uint64_t *left,
+					const uint64_t *curve_prime,
+					unsigned int ndigits);
+void _vli_mod_exp(uint64_t *result, const uint64_t *base, const uint64_t *exp,
+		const uint64_t *mod, unsigned int ndigits);
+
+int _vli_cmp(const uint64_t *left, const uint64_t *right, unsigned int ndigits);
+bool _vli_is_zero_or_one(const uint64_t *vli, unsigned int ndigits);
+
+uint64_t _vli_add(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, unsigned int ndigits);
+uint64_t _vli_sub(uint64_t *result, const uint64_t *left,
+				const uint64_t *right, unsigned int ndigits);
+
+int _vli_legendre(uint64_t *val, const uint64_t *p, unsigned int ndigits);
+
+bool _ecc_point_is_zero(const struct l_ecc_point *point);
+
+void _ecc_calculate_p2(const struct l_ecc_curve *curve, uint64_t *p2);
+
+bool _ecc_compute_y(const struct l_ecc_curve *curve, uint64_t *y,
+							const uint64_t *x);
+
+void _ecc_point_mult(struct l_ecc_point *result,
+			const struct l_ecc_point *point, const uint64_t *scalar,
+			uint64_t *initial_z, const uint64_t *curve_prime);
+void _ecc_point_add(struct l_ecc_point *ret, const struct l_ecc_point *p,
+			const struct l_ecc_point *q,
+			const uint64_t *curve_prime);
+struct l_ecc_scalar *_ecc_constant_new(const struct l_ecc_curve *curve,
+						const void *buf, size_t len);
diff --git a/ell/ecc.c b/ell/ecc.c
new file mode 100644
index 0000000..d8d9c1f
--- /dev/null
+++ b/ell/ecc.c
@@ -0,0 +1,1073 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "ecc.h"
+#include "ecc-private.h"
+#include "random.h"
+#include "useful.h"
+#include "private.h"
+#include "missing.h"
+
+/*
+ * RFC 5114 - Section 2.6 256-bit Random ECP Group
+ */
+#define P256_CURVE_P { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
+			0x0000000000000000ull, 0xFFFFFFFF00000001ull }
+#define P256_CURVE_GX { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,   \
+			0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }
+#define P256_CURVE_GY { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,   \
+			0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull }
+#define P256_CURVE_N { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,   \
+			0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
+#define P256_CURVE_B { 0x3BCE3C3E27D2604Bull, 0x651D06B0CC53B0F6ull,   \
+			0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull }
+
+static const struct l_ecc_curve p256 = {
+	.name = "secp256r1",
+	.ike_group = 19,
+	.tls_group = 23,
+	.ndigits = 4,
+	.g = {
+		.x = P256_CURVE_GX,
+		.y = P256_CURVE_GY,
+		.curve = &p256
+	},
+	.p = P256_CURVE_P,
+	.n = P256_CURVE_N,
+	.b = P256_CURVE_B,
+	.z = -10,
+};
+
+/*
+ * RFC 5114 - Section 2.7 384-bit Random ECP Group
+ */
+#define P384_CURVE_P {	0x00000000FFFFFFFFull, 0xFFFFFFFF00000000ull, \
+			0xFFFFFFFFFFFFFFFEull, 0xFFFFFFFFFFFFFFFFull, \
+			0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull }
+#define P384_CURVE_GX {	0x3A545E3872760AB7ull, 0x5502F25DBF55296Cull, \
+			0x59F741E082542A38ull, 0x6E1D3B628BA79B98ull, \
+			0x8EB1C71EF320AD74ull, 0xAA87CA22BE8B0537ull }
+#define P384_CURVE_GY {	0x7A431D7C90EA0E5Full, 0x0A60B1CE1D7E819Dull, \
+			0xE9DA3113B5F0B8C0ull, 0xF8F41DBD289A147Cull, \
+			0x5D9E98BF9292DC29ull, 0x3617DE4A96262C6Full }
+#define P384_CURVE_N {	0xECEC196ACCC52973ull, 0x581A0DB248B0A77Aull, \
+			0xC7634D81F4372DDFull, 0xFFFFFFFFFFFFFFFFull, \
+			0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull }
+#define P384_CURVE_B {	0x2A85C8EDD3EC2AEFull, 0xC656398D8A2ED19Dull, \
+			0x0314088F5013875Aull, 0x181D9C6EFE814112ull, \
+			0x988E056BE3F82D19ull, 0xB3312FA7E23EE7E4ull }
+
+static const struct l_ecc_curve p384 = {
+	.name = "secp384r1",
+	.ike_group = 20,
+	.tls_group = 24,
+	.ndigits = 6,
+	.g = {
+		.x = P384_CURVE_GX,
+		.y = P384_CURVE_GY,
+		.curve = &p384
+	},
+	.p = P384_CURVE_P,
+	.n = P384_CURVE_N,
+	.b = P384_CURVE_B,
+	.z = -12,
+};
+
+static const struct l_ecc_curve *curves[] = {
+	&p384,
+	&p256,
+};
+
+/* Returns supported IKE groups, sorted by the highest effective key size */
+LIB_EXPORT const unsigned int *l_ecc_supported_ike_groups(void)
+{
+	static unsigned int supported_ike_groups[L_ARRAY_SIZE(curves) + 1];
+	static bool ike_first = true;
+
+	if (ike_first) {
+		unsigned int i;
+
+		for (i = 0; i < L_ARRAY_SIZE(curves); i++)
+			supported_ike_groups[i] = curves[i]->ike_group;
+
+		supported_ike_groups[i] = 0;
+		ike_first = false;
+	}
+
+	return supported_ike_groups;
+}
+
+/* Returns supported TLS groups, sorted by the highest effective key size */
+LIB_EXPORT const unsigned int *l_ecc_supported_tls_groups(void)
+{
+	static unsigned int supported_tls_groups[L_ARRAY_SIZE(curves) + 1];
+	static bool tls_first = true;
+
+	if (tls_first) {
+		unsigned int i;
+
+		for (i = 0; i < L_ARRAY_SIZE(curves); i++)
+			supported_tls_groups[i] = curves[i]->tls_group;
+
+		supported_tls_groups[i] = 0;
+		tls_first = false;
+	}
+
+	return supported_tls_groups;
+}
+
+LIB_EXPORT const struct l_ecc_curve *l_ecc_curve_from_name(const char *name)
+{
+	int i;
+
+	if (unlikely(!name))
+		return NULL;
+
+	for (i = 0; curves[i]; i++) {
+		if (!strcmp(curves[i]->name, name))
+			return curves[i];
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT const struct l_ecc_curve *l_ecc_curve_from_ike_group(
+							unsigned int group)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(curves); i++) {
+		if (curves[i]->ike_group == group)
+			return curves[i];
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT const struct l_ecc_curve *l_ecc_curve_from_tls_group(
+							unsigned int group)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(curves); i++) {
+		if (curves[i]->tls_group == group)
+			return curves[i];
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT const char *l_ecc_curve_get_name(const struct l_ecc_curve *curve)
+{
+	if (unlikely(!curve))
+		return NULL;
+
+	return curve->name;
+}
+
+LIB_EXPORT unsigned int l_ecc_curve_get_ike_group(
+					const struct l_ecc_curve *curve)
+{
+	if (unlikely(!curve))
+		return 0;
+
+	return curve->ike_group;
+}
+
+LIB_EXPORT unsigned int l_ecc_curve_get_tls_group(
+					const struct l_ecc_curve *curve)
+{
+	if (unlikely(!curve))
+		return 0;
+
+	return curve->tls_group;
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_curve_get_order(
+						const struct l_ecc_curve *curve)
+{
+	return _ecc_constant_new(curve, curve->n, curve->ndigits * 8);
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_curve_get_prime(
+						const struct l_ecc_curve *curve)
+{
+	if (unlikely(!curve))
+		return NULL;
+
+	return _ecc_constant_new(curve, curve->p, curve->ndigits * 8);
+}
+
+LIB_EXPORT size_t l_ecc_curve_get_scalar_bytes(const struct l_ecc_curve *curve)
+{
+	if (unlikely(!curve))
+		return 0;
+
+	return curve->ndigits * 8;
+}
+
+static bool ecc_valid_point(struct l_ecc_point *point)
+{
+	const struct l_ecc_curve *curve = point->curve;
+	uint64_t tmp1[L_ECC_MAX_DIGITS];
+	uint64_t tmp2[L_ECC_MAX_DIGITS];
+	uint64_t _3[L_ECC_MAX_DIGITS] = { 3 };	/* -a = 3 */
+	unsigned int ndigits = curve->ndigits;
+
+	/* The point at infinity is invalid. */
+	if (_ecc_point_is_zero(point))
+		return false;
+
+	/* x and y must be smaller than p. */
+	if (_vli_cmp(curve->p, point->x, ndigits) != 1 ||
+			_vli_cmp(curve->p, point->y, ndigits) != 1)
+		return false;
+
+	/* Computes result = y^2. */
+	_vli_mod_square_fast(tmp1, point->y, curve->p, ndigits);
+
+	/* Computes result = x^3 + ax + b. result must not overlap x. */
+	/* r = x^2 */
+	_vli_mod_square_fast(tmp2, point->x, curve->p, ndigits);
+	/* r = x^2 - 3 */
+	_vli_mod_sub(tmp2, tmp2, _3, curve->p, ndigits);
+	/* r = x^3 - 3x */
+	_vli_mod_mult_fast(tmp2, tmp2, point->x, curve->p, ndigits);
+	/* r = x^3 - 3x + b */
+	_vli_mod_add(tmp2, tmp2, curve->b, curve->p, ndigits);
+	/* Make sure that y^2 == x^3 + ax + b */
+	return (_vli_cmp(tmp1, tmp2, ndigits) == 0);
+}
+
+void _ecc_be2native(uint64_t *dest, const uint64_t *bytes,
+							unsigned int ndigits)
+{
+	unsigned int i;
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+
+	for (i = 0; i < ndigits; i++)
+		tmp[ndigits - 1 - i] = l_get_be64(&bytes[i]);
+
+	memcpy(dest, tmp, ndigits * 8);
+}
+
+void _ecc_native2be(uint64_t *dest, const uint64_t *native,
+							unsigned int ndigits)
+{
+	unsigned int i;
+	uint64_t tmp[L_ECC_MAX_DIGITS];
+
+	for (i = 0; i < ndigits; i++)
+		l_put_be64(native[ndigits - 1 - i], &tmp[i]);
+
+	memcpy(dest, tmp, ndigits * 8);
+}
+
+static void ecc_compute_y_sqr(const struct l_ecc_curve *curve,
+					uint64_t *y_sqr, const uint64_t *x)
+{
+	uint64_t sum[L_ECC_MAX_DIGITS] = { 0 };
+	uint64_t tmp[L_ECC_MAX_DIGITS] = { 0 };
+	uint64_t _3[L_ECC_MAX_DIGITS] = { 3ull }; /* -a = 3 */
+
+	/* x^3 */
+	_vli_mod_square_fast(sum, x, curve->p, curve->ndigits);
+	_vli_mod_mult_fast(sum, sum, x, curve->p, curve->ndigits);
+	/* x^3 - ax */
+	_vli_mod_mult_fast(tmp, _3, x, curve->p, curve->ndigits);
+	_vli_mod_sub(sum, sum, tmp, curve->p, curve->ndigits);
+	/* x^3 - ax + b */
+	_vli_mod_add(sum, sum, curve->b, curve->p, curve->ndigits);
+
+	memcpy(y_sqr, sum, curve->ndigits * 8);
+}
+
+/*
+ * Compute sqrt(y^2)
+ * Since our prime p satisfies p = 3 (mod 4), we can say:
+ *
+ * y = (y^2)^((p + 1) / 4)
+ *
+ * This avoids the need for a square root function.
+ */
+static void ecc_compute_sqrt(const struct l_ecc_curve *curve,
+					uint64_t *y, const uint64_t *y_sqr)
+{
+	uint64_t expo[L_ECC_MAX_DIGITS];
+	uint64_t one[L_ECC_MAX_DIGITS] = { 1ull };
+
+	memcpy(expo, curve->p, curve->ndigits * 8);
+
+	/* (p + 1) / 4  == (p >> 2) + 1 */
+	_vli_rshift1(expo, curve->ndigits);
+	_vli_rshift1(expo, curve->ndigits);
+	_vli_mod_add(expo, expo, one, curve->p, curve->ndigits);
+	/* sum ^ ((p + 1) / 4) */
+	_vli_mod_exp(y, y_sqr, expo, curve->p, curve->ndigits);
+}
+
+bool _ecc_compute_y(const struct l_ecc_curve *curve, uint64_t *y,
+							const uint64_t *x)
+{
+	uint64_t sum[L_ECC_MAX_DIGITS] = { 0 };
+	uint64_t check[L_ECC_MAX_DIGITS] = { 0 };
+
+	/* y = sqrt(x^3 + ax + b) (mod p) */
+	ecc_compute_y_sqr(curve, sum, x);
+	ecc_compute_sqrt(curve, y, sum);
+
+	/* square y to ensure we have a correct value */
+	_vli_mod_mult_fast(check, y, y, curve->p, curve->ndigits);
+
+	if (_vli_cmp(check, sum, curve->ndigits) != 0)
+		return false;
+
+	return true;
+}
+
+/*
+ * IETF - Compact representation of an elliptic curve point:
+ * https://tools.ietf.org/id/draft-jivsov-ecc-compact-00.xml
+ *
+ * "min(y,p-y) can be calculated with the help of the pre-calculated value
+ *  p2=(p-1)/2. min(y,p-y) is y if y<p2 and p-y otherwise."
+ */
+void _ecc_calculate_p2(const struct l_ecc_curve *curve, uint64_t *p2)
+{
+	uint64_t one[L_ECC_MAX_DIGITS] = { 1 };
+
+	_vli_mod_sub(p2, curve->p, one, curve->p, curve->ndigits);
+	_vli_rshift1(p2, curve->ndigits);
+}
+
+/*
+ * IETF draft-jivsov-ecc-compact-00 Section 4.1
+ * Encoding and decoding of an elliptic curve point
+ * ...
+ * Decoding:
+ * Given the compact representation of Q, return canonical representation
+ * of Q=(x,y) as follows:
+ *     1. y' = sqrt( x^3 + a*x + b ), where y'>0
+ *     2. y = min(y',p-y')
+ *     3. Q=(x,y) is the canonical representation of the point
+ */
+static bool decode_point(const struct l_ecc_curve *curve, uint64_t *x,
+				struct l_ecc_point *point)
+{
+	uint64_t y_min[L_ECC_MAX_DIGITS];
+	uint64_t p2[L_ECC_MAX_DIGITS];
+
+	if (!_ecc_compute_y(curve, y_min, (uint64_t *)x))
+		return false;
+
+	_ecc_calculate_p2(curve, p2);
+
+	if (_vli_cmp(y_min, p2, curve->ndigits) >= 0)
+		_vli_mod_sub(point->y, curve->p, y_min,
+					curve->p, curve->ndigits);
+	else
+		memcpy(point->y, y_min, curve->ndigits * 8);
+
+	memcpy(point->x, x, curve->ndigits * 8);
+
+	return true;
+}
+
+/* (rx, ry) = (px, py) + (qx, qy) */
+void _ecc_point_add(struct l_ecc_point *ret, const struct l_ecc_point *p,
+			const struct l_ecc_point *q,
+			const uint64_t *curve_prime)
+{
+	/*
+	* s = (py - qy)/(px - qx)
+	*
+	* rx = s^2 - px - qx
+	* ry = s(px - rx) - py
+	*/
+	uint64_t s[L_ECC_MAX_DIGITS];
+	uint64_t kp1[L_ECC_MAX_DIGITS];
+	uint64_t kp2[L_ECC_MAX_DIGITS];
+	uint64_t resx[L_ECC_MAX_DIGITS];
+	uint64_t resy[L_ECC_MAX_DIGITS];
+	unsigned int ndigits = p->curve->ndigits;
+
+	memset(s, 0, ndigits * 8);
+
+	/* kp1 = py - qy */
+	_vli_mod_sub(kp1, q->y, p->y, curve_prime, ndigits);
+	/* kp2 = px - qx */
+	_vli_mod_sub(kp2, q->x, p->x, curve_prime, ndigits);
+	/* s = kp1/kp2 */
+	_vli_mod_inv(kp2, kp2, curve_prime, ndigits);
+	_vli_mod_mult_fast(s, kp1, kp2, curve_prime, ndigits);
+	/* rx = s^2 - px - qx */
+	_vli_mod_mult_fast(kp1, s, s, curve_prime, ndigits);
+	_vli_mod_sub(kp1, kp1, p->x, curve_prime, ndigits);
+	_vli_mod_sub(resx, kp1, q->x, curve_prime, ndigits);
+	/* ry = s(px - rx) - py */
+	_vli_mod_sub(kp1, p->x, resx, curve_prime, ndigits);
+	_vli_mod_mult_fast(kp1, s, kp1, curve_prime, ndigits);
+	_vli_mod_sub(resy, kp1, p->y, curve_prime, ndigits);
+
+	memcpy(ret->x, resx, ndigits * 8);
+	memcpy(ret->y, resy, ndigits * 8);
+}
+
+/* result = (base ^ exp) % p */
+void _vli_mod_exp(uint64_t *result, const uint64_t *base, const uint64_t *exp,
+			const uint64_t *mod, unsigned int ndigits)
+{
+	unsigned int i;
+	int bit;
+	uint64_t n[L_ECC_MAX_DIGITS];
+	uint64_t r[L_ECC_MAX_DIGITS] = { 1 };
+
+	memcpy(n, base, ndigits * 8);
+
+	for (i = 0; i < ndigits; i++) {
+		for (bit = 0; bit < 64; bit++) {
+			uint64_t tmp[L_ECC_MAX_DIGITS];
+
+			if (exp[i] & (1ull << bit)) {
+				_vli_mod_mult_fast(tmp, r, n, mod, ndigits);
+				memcpy(r, tmp, ndigits * 8);
+			}
+
+			_vli_mod_mult_fast(tmp, n, n, mod, ndigits);
+			memcpy(n, tmp, ndigits * 8);
+		}
+	}
+
+	memcpy(result, r, ndigits * 8);
+}
+
+__attribute__((noinline)) static int vli_equal(const uint64_t *a,
+							const uint64_t *b,
+							unsigned int ndigits)
+{
+	uint64_t diff = 0;
+	unsigned int i;
+
+	for (i = 0; i < ndigits; i++) {
+		diff |= a[i] ^ b[i];
+		__asm__ ("" : "=r" (diff) : "0" (diff));
+	}
+
+	return (~diff & (diff - 1)) >> 63;
+}
+
+int _vli_legendre(uint64_t *val, const uint64_t *p, unsigned int ndigits)
+{
+	uint64_t tmp[L_ECC_MAX_DIGITS];
+	uint64_t exp[L_ECC_MAX_DIGITS];
+	uint64_t _1[L_ECC_MAX_DIGITS] = { 1ull };
+	uint64_t _0[L_ECC_MAX_DIGITS] = { 0 };
+
+	/* check that val ^ ((p - 1) / 2) == [1, 0 or -1] */
+
+	_vli_sub(exp, p, _1, ndigits);
+	_vli_rshift1(exp, ndigits);
+	_vli_mod_exp(tmp, val, exp, p, ndigits);
+
+	if (_vli_cmp(tmp, _1, ndigits) == 0)
+		return 1;
+	if (_vli_cmp(tmp, _0, ndigits) == 0)
+		return 0;
+	return -1;
+}
+
+bool _vli_is_zero_or_one(const uint64_t *vli, unsigned int ndigits)
+{
+	uint64_t _1[L_ECC_MAX_DIGITS] = { 1ull };
+	int ret;
+
+	ret = secure_select(vli_equal(vli, _1, ndigits), true, false);
+	ret = secure_select(l_secure_memeq(vli, ndigits * 8, 0), true, ret);
+
+	return ret;
+}
+
+LIB_EXPORT struct l_ecc_point *l_ecc_point_new(const struct l_ecc_curve *curve)
+{
+	struct l_ecc_point *p = l_new(struct l_ecc_point, 1);
+
+	p->curve = curve;
+
+	return p;
+}
+
+LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
+					const struct l_ecc_curve *curve,
+					enum l_ecc_point_type type,
+					const void *data, size_t len)
+{
+	struct l_ecc_point *p;
+	size_t bytes = curve->ndigits * 8;
+	uint64_t tmp[L_ECC_MAX_DIGITS];
+	bool sub;
+
+	if (!data)
+		return NULL;
+
+	/* Verify the data length matches a full point or X coordinate */
+	if (type == L_ECC_POINT_TYPE_FULL) {
+		if (len != bytes * 2)
+			return NULL;
+	} else if (len != bytes)
+		return NULL;
+
+	p = l_ecc_point_new(curve);
+
+	_ecc_be2native(p->x, (void *) data, curve->ndigits);
+
+	switch (type) {
+	case L_ECC_POINT_TYPE_COMPLIANT:
+		if (!decode_point(curve, p->x, p))
+			goto failed;
+
+		break;
+	case L_ECC_POINT_TYPE_COMPRESSED_BIT0:
+	case L_ECC_POINT_TYPE_COMPRESSED_BIT1:
+		if (!_ecc_compute_y(curve, p->y, p->x))
+			goto failed;
+
+		/*
+		 * This is determining whether or not to subtract the Y
+		 * coordinate from P. According to ANSI X9.62 an even Y should
+		 * be prefixed with 02 (BIT0) and an odd Y should be prefixed
+		 * with 03 (BIT1). If this is not the case, subtract Y from P.
+		 *
+		 * ANSI X9.62
+		 * 4.3.6 Point-to-Octet-String Conversion
+		 *
+		 * 2. If the compressed form is used, then do the following:
+		 *     2.1. Compute the bit ~Yp . (See Section 4.2.)
+		 *     2.2. Assign the value 02 to the single octet PC if ~Yp
+		 *          is 0, or the value 03 if ~Yp is 1.
+		 *     2.3. The result is the octet string PO = PC || X
+		 */
+
+		sub = secure_select(type == L_ECC_POINT_TYPE_COMPRESSED_BIT0,
+					p->y[0] & 1, !(p->y[0] & 1));
+
+		_vli_mod_sub(tmp, curve->p, p->y, curve->p, curve->ndigits);
+
+		l_secure_select(sub, tmp, p->y, p->y, curve->ndigits * 8);
+
+		break;
+	case L_ECC_POINT_TYPE_FULL:
+		_ecc_be2native(p->y, (void *) data + bytes, curve->ndigits);
+
+		if (!ecc_valid_point(p))
+			goto failed;
+
+		break;
+	}
+
+	return p;
+
+failed:
+	l_free(p);
+	return NULL;
+}
+
+LIB_EXPORT struct l_ecc_point *l_ecc_point_from_sswu(
+						const struct l_ecc_scalar *u)
+{
+	const struct l_ecc_curve *curve = u->curve;
+	unsigned int ndigits = curve->ndigits;
+	uint64_t z[L_ECC_MAX_DIGITS] = { abs(curve->z) };
+	uint64_t _3[L_ECC_MAX_DIGITS] = { 3ull }; /* -a = 3 */
+	uint64_t u2z[L_ECC_MAX_DIGITS];
+	uint64_t t1[L_ECC_MAX_DIGITS];
+	uint64_t t2[L_ECC_MAX_DIGITS];
+	uint64_t m[L_ECC_MAX_DIGITS];
+	uint64_t t[L_ECC_MAX_DIGITS];
+	uint64_t x1l[L_ECC_MAX_DIGITS];
+	uint64_t x1r[L_ECC_MAX_DIGITS];
+	uint64_t x1[L_ECC_MAX_DIGITS];
+	uint64_t gx1[L_ECC_MAX_DIGITS];
+	uint64_t x2[L_ECC_MAX_DIGITS];
+	uint64_t gx2[L_ECC_MAX_DIGITS];
+	/* reuse m/t/x1l,x1r, they are unused by the time x/v/y/p-y is needed */
+	uint64_t *x = m;
+	uint64_t *v = t;
+	uint64_t *yl = x1l;
+	uint64_t *yr = x1r;
+	bool l;
+	struct l_ecc_point *P;
+
+	/*
+	 * m = (z^2 * u^4 + z * u^2) modulo p
+	 * u2z = u^2 * z
+	 * t2 = u2z^2
+	 * m = t2 - u2z since for all our curves z is negative
+	 */
+	_vli_mod_square_fast(u2z, u->c, curve->p, ndigits);
+	_vli_mod_mult_fast(u2z, u2z, z, curve->p, ndigits);
+	_vli_mod_square_fast(t2, u2z, curve->p, ndigits);
+	_vli_mod_sub(m, t2, u2z, curve->p, ndigits);
+
+	/*
+	 * l = CEQ(m, 0)
+	 * t = inv0(m) where inv0(x) is calculated as x^(p-2) modulo p
+	 */
+	l = l_secure_memeq(m, sizeof(m), 0);
+
+	memset(t2, 0, sizeof(t2));
+	t2[0] = 2ull;
+	_vli_mod_sub(t1, curve->p, t2, curve->p, ndigits);
+	_vli_mod_exp(t, m, t1, curve->p, ndigits);
+
+	/* Calculate: b / z*a, both z and a are negative */
+	_vli_mod_mult_fast(t1, z, _3, curve->p, ndigits);
+	_vli_mod_inv(t1, t1, curve->p, ndigits);
+	_vli_mod_mult_fast(x1l, curve->b, t1, curve->p, ndigits);
+
+	/* t = 1 + t */
+	memset(t2, 0, sizeof(t2));
+	t2[0] = 1ull;
+	_vli_mod_add(t, t, t2, curve->p, ndigits);
+
+	/* t1 = 1 / a */
+	_vli_mod_inv(t1, _3, curve->p, ndigits);
+
+	/* x1r = b * t1 * t */
+	_vli_mod_mult_fast(x1r, curve->b, t1, curve->p, ndigits);
+	_vli_mod_mult_fast(x1r, x1r, t, curve->p, ndigits);
+
+	/* x1 = CSEL(l, (b / (z*a) modulo p), ((-b/a) * (1 + t)) modulo p) */
+	l_secure_select(l, x1l, x1r, x1, ndigits * 8);
+
+	/* gx1 = (x1^3 + a*x1 + b) modulo p */
+	ecc_compute_y_sqr(curve, gx1, x1);
+
+	/* x2 = (z*u^2*x1) modulo p, z is negative, hence the second op */
+	_vli_mod_mult_fast(x2, u2z, x1, curve->p, ndigits);
+	_vli_mod_sub(x2, curve->p, x2, curve->p, ndigits);
+
+	/* gx2 = (x2^3 + a*x2 + b) modulo p */
+	ecc_compute_y_sqr(curve, gx2, x2);
+
+	/*
+	 * l = gx1 is a quadratic residue modulo p
+	 * x is a quadratic residue if x^((p-1)/2) modulo p is zero or one
+	 */
+	_vli_mod_sub(t1, curve->p, t2, curve->p, ndigits);
+	_vli_rshift1(t1, ndigits);
+	_vli_mod_exp(t2, gx1, t1, curve->p, ndigits);
+	l = _vli_is_zero_or_one(t2, ndigits);
+
+	/* v = CSEL(l, gx1, gx2) */
+	l_secure_select(l, gx1, gx2, v, ndigits * 8);
+	/* x = CSEL(l, x1, x2) */
+	l_secure_select(l, x1, x2, x, ndigits * 8);
+	/* y = sqrt(v) */
+	ecc_compute_sqrt(curve, yl, v);
+	/* l = CEQ(LSB(u), LSB(y)) */
+	l = !((u->c[0] & 1ull) ^ (yl[0] & 1ull));
+
+	/* p - y */
+	_vli_mod_sub(yr, curve->p, yl, curve->p, ndigits);
+
+	/* P = CSEL(l, (x,y), (x, p-y)) */
+	P = l_ecc_point_new(curve);
+	memcpy(P->x, x, ndigits * 8);
+	l_secure_select(l, yl, yr, P->y, ndigits * 8);
+
+	return P;
+}
+
+LIB_EXPORT struct l_ecc_point *l_ecc_point_clone(const struct l_ecc_point *p)
+{
+	if (!p)
+		return NULL;
+
+	return l_memdup(p, sizeof(*p));
+}
+
+LIB_EXPORT const struct l_ecc_curve *l_ecc_point_get_curve(
+						const struct l_ecc_point *p)
+{
+	if (!p)
+		return NULL;
+
+	return p->curve;
+}
+
+LIB_EXPORT ssize_t l_ecc_point_get_x(const struct l_ecc_point *p, void *x,
+					size_t xlen)
+{
+	if (xlen < p->curve->ndigits * 8)
+		return -EMSGSIZE;
+
+	_ecc_native2be(x, p->x, p->curve->ndigits);
+
+	return p->curve->ndigits * 8;
+}
+
+LIB_EXPORT ssize_t l_ecc_point_get_y(const struct l_ecc_point *p, void *y,
+					size_t ylen)
+{
+	if (ylen < p->curve->ndigits * 8)
+		return -EMSGSIZE;
+
+	_ecc_native2be(y, p->y, p->curve->ndigits);
+
+	return p->curve->ndigits * 8;
+}
+
+LIB_EXPORT bool l_ecc_point_y_isodd(const struct l_ecc_point *p)
+{
+	return p->y[0] & 1;
+}
+
+LIB_EXPORT ssize_t l_ecc_point_get_data(const struct l_ecc_point *p, void *buf,
+					size_t len)
+{
+	if (len < (p->curve->ndigits * 8) * 2)
+		return -EMSGSIZE;
+
+	_ecc_native2be(buf, (uint64_t *) p->x, p->curve->ndigits);
+	_ecc_native2be(buf + (p->curve->ndigits * 8), (uint64_t *) p->y,
+				p->curve->ndigits);
+
+	return (p->curve->ndigits * 8) * 2;
+}
+
+LIB_EXPORT void l_ecc_point_free(struct l_ecc_point *p)
+{
+	if (unlikely(!p))
+		return;
+
+	explicit_bzero(p->x, p->curve->ndigits * 8);
+	explicit_bzero(p->y, p->curve->ndigits * 8);
+	l_free(p);
+}
+
+struct l_ecc_scalar *_ecc_constant_new(const struct l_ecc_curve *curve,
+						const void *buf, size_t len)
+{
+	struct l_ecc_scalar *c;
+
+	if (unlikely(!curve))
+		return NULL;
+
+	if (buf && len != curve->ndigits * 8)
+		return NULL;
+
+	c = l_new(struct l_ecc_scalar, 1);
+
+	c->curve = curve;
+
+	if (buf)
+		memcpy(c->c, buf, len);
+
+	return c;
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new(
+					const struct l_ecc_curve *curve,
+					const void *buf, size_t len)
+{
+	struct l_ecc_scalar *c;
+
+	c = _ecc_constant_new(curve, NULL, 0);
+	if (!c)
+		return NULL;
+
+	if (!buf)
+		return c;
+
+	_ecc_be2native(c->c, buf, curve->ndigits);
+
+	if (!_vli_is_zero_or_one(c->c, curve->ndigits) &&
+			secure_memcmp_64(curve->n, c->c, curve->ndigits) > 0)
+		return c;
+
+	l_ecc_scalar_free(c);
+
+	return NULL;
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_clone(const struct l_ecc_scalar *s)
+{
+	if (!s)
+		return NULL;
+
+	return l_memdup(s, sizeof(*s));
+}
+
+/*
+ * Build a scalar = value modulo p where p is the prime number for a given
+ * curve.  bytes can contain a number with up to 2x number of digits as the
+ * curve.  This is used in Hash to Curve calculations.
+ */
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_modp(
+					const struct l_ecc_curve *curve,
+					const void *bytes, size_t len)
+{
+	struct l_ecc_scalar *c;
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+	unsigned int ndigits = len / 8;
+
+	if (!bytes)
+		return NULL;
+
+	if (len % 8)
+		return NULL;
+
+	if (ndigits > curve->ndigits * 2)
+		return NULL;
+
+	c = _ecc_constant_new(curve, NULL, 0);
+	if (!c)
+		return NULL;
+
+	memset(tmp, 0, sizeof(tmp));
+	_ecc_be2native(tmp, bytes, ndigits);
+
+	_vli_mmod_fast(c->c, tmp, curve->p, curve->ndigits);
+
+	if (!_vli_is_zero_or_one(c->c, curve->ndigits) &&
+			secure_memcmp_64(curve->n, c->c, curve->ndigits) > 0)
+		return c;
+
+	l_ecc_scalar_free(c);
+
+	return NULL;
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_modn(
+					const struct l_ecc_curve *curve,
+					const void *bytes, size_t len)
+{
+	struct l_ecc_scalar *c;
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+	unsigned int ndigits = len / 8;
+
+	if (!bytes)
+		return NULL;
+
+	if (len % 8)
+		return NULL;
+
+	if (ndigits > curve->ndigits * 2)
+		return NULL;
+
+	c = _ecc_constant_new(curve, NULL, 0);
+	if (!c)
+		return NULL;
+
+	memset(tmp, 0, sizeof(tmp));
+	_ecc_be2native(tmp, bytes, ndigits);
+
+	_vli_mmod_slow(c->c, tmp, curve->n, curve->ndigits);
+
+	if (!_vli_is_zero_or_one(c->c, curve->ndigits) &&
+			secure_memcmp_64(curve->n, c->c, curve->ndigits) > 0)
+		return c;
+
+	l_ecc_scalar_free(c);
+
+	return NULL;
+}
+
+/*
+ * Takes a buffer of the same size as the curve and scales it to a range
+ * 1..n using value = (value mod (n - 1)) + 1.  For the curves we support
+ * this can be done using a subtraction operation due to the size of n
+ */
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_reduced_1_to_n(
+					const struct l_ecc_curve *curve,
+					const void *buf, size_t len)
+{
+	uint64_t _1[L_ECC_MAX_DIGITS] = { 1ull };
+	uint64_t tmp[L_ECC_MAX_DIGITS];
+	struct l_ecc_scalar *c;
+
+	if (!buf)
+		return NULL;
+
+	if (len != curve->ndigits * 8)
+		return NULL;
+
+	c = _ecc_constant_new(curve, NULL, 0);
+	if (!c)
+		return NULL;
+
+	_vli_sub(tmp, curve->n, _1, curve->ndigits);
+	_ecc_be2native(c->c, buf, curve->ndigits);
+
+	if (_vli_cmp(c->c, tmp, curve->ndigits) >= 0)
+                _vli_sub(c->c, c->c, tmp, curve->ndigits);
+
+	_vli_add(c->c, c->c, _1, curve->ndigits);
+
+	return c;
+}
+
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_random(
+					const struct l_ecc_curve *curve)
+{
+	uint64_t r[L_ECC_MAX_DIGITS];
+
+	l_getrandom(r, curve->ndigits * 8);
+
+	while (_vli_cmp(r, curve->p, curve->ndigits) > 0 ||
+			_vli_cmp(r, curve->n, curve->ndigits) > 0 ||
+			_vli_is_zero_or_one(r, curve->ndigits))
+		l_getrandom(r, curve->ndigits * 8);
+
+	return _ecc_constant_new(curve, r, curve->ndigits * 8);
+}
+
+LIB_EXPORT ssize_t l_ecc_scalar_get_data(const struct l_ecc_scalar *c,
+						void *buf, size_t len)
+{
+	if (len < c->curve->ndigits * 8)
+		return -EMSGSIZE;
+
+	_ecc_native2be(buf, (uint64_t *) c->c, c->curve->ndigits);
+
+	return c->curve->ndigits * 8;
+}
+
+LIB_EXPORT void l_ecc_scalar_free(struct l_ecc_scalar *c)
+{
+	if (unlikely(!c))
+		return;
+
+	explicit_bzero(c->c, c->curve->ndigits * 8);
+	l_free(c);
+}
+
+LIB_EXPORT bool l_ecc_scalar_add(struct l_ecc_scalar *ret,
+					const struct l_ecc_scalar *a,
+					const struct l_ecc_scalar *b,
+					const struct l_ecc_scalar *mod)
+{
+	if (unlikely(!ret || !a || !b || !mod))
+		return false;
+
+	_vli_mod_add(ret->c, a->c, b->c, mod->c, a->curve->ndigits);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_point_multiply(struct l_ecc_point *ret,
+					const struct l_ecc_scalar *scalar,
+					const struct l_ecc_point *point)
+{
+	if (unlikely(!ret || !scalar || !point))
+		return false;
+
+	_ecc_point_mult(ret, point, scalar->c, NULL, scalar->curve->p);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_point_multiply_g(struct l_ecc_point *ret,
+					const struct l_ecc_scalar *scalar)
+{
+	if (unlikely(!ret || !scalar))
+		return false;
+
+	_ecc_point_mult(ret, &scalar->curve->g, scalar->c, NULL,
+						scalar->curve->p);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_point_add(struct l_ecc_point *ret,
+					const struct l_ecc_point *a,
+					const struct l_ecc_point *b)
+{
+	if (unlikely(!ret || !a || !b))
+		return false;
+
+	_ecc_point_add(ret, a, b, a->curve->p);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_point_inverse(struct l_ecc_point *p)
+{
+	if (unlikely(!p))
+		return false;
+
+	_vli_mod_sub(p->y, p->curve->p, p->y, p->curve->p, p->curve->ndigits);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_scalar_multiply(struct l_ecc_scalar *ret,
+					const struct l_ecc_scalar *a,
+					const struct l_ecc_scalar *b)
+{
+	if (unlikely(!ret || !a || !b))
+		return false;
+
+	_vli_mod_mult_fast(ret->c, a->c, b->c, a->curve->p, a->curve->ndigits);
+
+	return true;
+}
+
+LIB_EXPORT int l_ecc_scalar_legendre(struct l_ecc_scalar *value)
+{
+	if (unlikely(!value))
+		return -1;
+
+	return _vli_legendre(value->c, value->curve->p, value->curve->ndigits);
+}
+
+LIB_EXPORT bool l_ecc_scalar_sum_x(struct l_ecc_scalar *ret,
+					const struct l_ecc_scalar *x)
+{
+	if (unlikely(!ret || !x))
+		return false;
+
+	ecc_compute_y_sqr(x->curve, ret->c, x->c);
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecc_scalars_are_equal(const struct l_ecc_scalar *a,
+						const struct l_ecc_scalar *b)
+{
+	if (unlikely(!a || !b))
+		return false;
+
+	return (memcmp(a->c, b->c, a->curve->ndigits * 8) == 0);
+}
+
+LIB_EXPORT bool l_ecc_points_are_equal(const struct l_ecc_point *a,
+						const struct l_ecc_point *b)
+{
+	if (unlikely(!a || !b))
+		return false;
+
+	return ((memcmp(a->x, b->x, a->curve->ndigits * 8) == 0) &&
+			(memcmp(a->y, b->y, a->curve->ndigits * 8) == 0));
+}
+
+LIB_EXPORT bool l_ecc_point_is_infinity(const struct l_ecc_point *p)
+{
+	return _ecc_point_is_zero(p);
+}
diff --git a/ell/ecc.h b/ell/ecc.h
new file mode 100644
index 0000000..3502b98
--- /dev/null
+++ b/ell/ecc.h
@@ -0,0 +1,113 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_ECC_H
+#define __ELL_ECC_H
+
+#include <sys/types.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define L_ECC_MAX_DIGITS 6
+#define L_ECC_SCALAR_MAX_BYTES		L_ECC_MAX_DIGITS * 8
+#define L_ECC_POINT_MAX_BYTES		L_ECC_SCALAR_MAX_BYTES * 2
+
+struct l_ecc_curve;
+struct l_ecc_point;
+struct l_ecc_scalar;
+
+enum l_ecc_point_type {
+	L_ECC_POINT_TYPE_COMPLIANT = 0x01,
+	L_ECC_POINT_TYPE_COMPRESSED_BIT0 = 0x02,
+	L_ECC_POINT_TYPE_COMPRESSED_BIT1 = 0x03,
+	L_ECC_POINT_TYPE_FULL = 0x04,
+};
+
+const unsigned int *l_ecc_supported_ike_groups(void);
+const unsigned int *l_ecc_supported_tls_groups(void);
+
+const struct l_ecc_curve *l_ecc_curve_from_name(const char *name);
+const struct l_ecc_curve *l_ecc_curve_from_ike_group(unsigned int group);
+const struct l_ecc_curve *l_ecc_curve_from_tls_group(unsigned int group);
+
+const char *l_ecc_curve_get_name(const struct l_ecc_curve *curve);
+unsigned int l_ecc_curve_get_ike_group(const struct l_ecc_curve *curve);
+unsigned int l_ecc_curve_get_tls_group(const struct l_ecc_curve *curve);
+struct l_ecc_scalar *l_ecc_curve_get_order(const struct l_ecc_curve *curve);
+struct l_ecc_scalar *l_ecc_curve_get_prime(const struct l_ecc_curve *curve);
+size_t l_ecc_curve_get_scalar_bytes(const struct l_ecc_curve *curve);
+
+struct l_ecc_point *l_ecc_point_new(const struct l_ecc_curve *curve);
+struct l_ecc_point *l_ecc_point_from_data(const struct l_ecc_curve *curve,
+					enum l_ecc_point_type type,
+					const void *data, size_t len);
+struct l_ecc_point *l_ecc_point_from_sswu(const struct l_ecc_scalar *u);
+struct l_ecc_point *l_ecc_point_clone(const struct l_ecc_point *p);
+
+const struct l_ecc_curve *l_ecc_point_get_curve(const struct l_ecc_point *p);
+ssize_t l_ecc_point_get_x(const struct l_ecc_point *p, void *x, size_t xlen);
+ssize_t l_ecc_point_get_y(const struct l_ecc_point *p, void *y, size_t ylen);
+bool l_ecc_point_y_isodd(const struct l_ecc_point *p);
+
+ssize_t l_ecc_point_get_data(const struct l_ecc_point *p, void *buf, size_t len);
+void l_ecc_point_free(struct l_ecc_point *p);
+DEFINE_CLEANUP_FUNC(l_ecc_point_free);
+
+struct l_ecc_scalar *l_ecc_scalar_new(const struct l_ecc_curve *curve,
+						const void *buf, size_t len);
+struct l_ecc_scalar *l_ecc_scalar_clone(const struct l_ecc_scalar *s);
+struct l_ecc_scalar *l_ecc_scalar_new_random(
+					const struct l_ecc_curve *curve);
+struct l_ecc_scalar *l_ecc_scalar_new_modp(const struct l_ecc_curve *curve,
+						const void *buf, size_t len);
+struct l_ecc_scalar *l_ecc_scalar_new_modn(const struct l_ecc_curve *curve,
+						const void *buf, size_t len);
+struct l_ecc_scalar *l_ecc_scalar_new_reduced_1_to_n(
+					const struct l_ecc_curve *curve,
+					const void *buf, size_t len);
+ssize_t l_ecc_scalar_get_data(const struct l_ecc_scalar *c, void *buf,
+					size_t len);
+void l_ecc_scalar_free(struct l_ecc_scalar *c);
+DEFINE_CLEANUP_FUNC(l_ecc_scalar_free);
+
+/* Constant operations */
+bool l_ecc_scalar_add(struct l_ecc_scalar *ret, const struct l_ecc_scalar *a,
+				const struct l_ecc_scalar *b,
+				const struct l_ecc_scalar *mod);
+
+/* Point operations */
+bool l_ecc_point_multiply(struct l_ecc_point *ret,
+				const struct l_ecc_scalar *scalar,
+				const struct l_ecc_point *point);
+bool l_ecc_point_multiply_g(struct l_ecc_point *ret,
+				const struct l_ecc_scalar *scalar);
+bool l_ecc_point_add(struct l_ecc_point *ret, const struct l_ecc_point *a,
+				const struct l_ecc_point *b);
+bool l_ecc_point_inverse(struct l_ecc_point *p);
+
+/* extra operations needed for SAE */
+bool l_ecc_scalar_multiply(struct l_ecc_scalar *ret,
+				const struct l_ecc_scalar *a,
+				const struct l_ecc_scalar *b);
+int l_ecc_scalar_legendre(struct l_ecc_scalar *value);
+bool l_ecc_scalar_sum_x(struct l_ecc_scalar *ret, const struct l_ecc_scalar *x);
+
+bool l_ecc_scalars_are_equal(const struct l_ecc_scalar *a,
+				const struct l_ecc_scalar *b);
+
+bool l_ecc_points_are_equal(const struct l_ecc_point *a,
+				const struct l_ecc_point *b);
+bool l_ecc_point_is_infinity(const struct l_ecc_point *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_ECC_H */
diff --git a/ell/ecdh.c b/ell/ecdh.c
new file mode 100644
index 0000000..e10a7d4
--- /dev/null
+++ b/ell/ecdh.c
@@ -0,0 +1,99 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include "private.h"
+#include "ecc-private.h"
+#include "ecc.h"
+#include "ecdh.h"
+#include "random.h"
+#include "useful.h"
+
+/*
+ * Some sane maximum for calculating the public key.
+ */
+#define ECDH_MAX_ITERATIONS 20
+
+/*
+ * IETF draft-jivsov-ecc-compact-00 Section 4.2.1
+ *
+ * The following algorithm calculates a key pair {k, Q=k*G=(x,y)}, where k is
+ * the private key and Q=(x,y) is the public key.
+ *
+ * Black box generation:
+ *     1. Generate a key pair {k, Q=k*G=(x,y)} with KG
+ *     2. if( y != min(y,p-y) ) goto step 1
+ *     3. output {k, Q=(x,y)} as a key pair
+ */
+LIB_EXPORT bool l_ecdh_generate_key_pair(const struct l_ecc_curve *curve,
+					struct l_ecc_scalar **out_private,
+					struct l_ecc_point **out_public)
+{
+	bool compliant = false;
+	int iter = 0;
+	uint64_t p2[L_ECC_MAX_DIGITS];
+
+	if (unlikely(!curve || !out_private || !out_public))
+		return false;
+
+	_ecc_calculate_p2(curve, p2);
+
+	*out_public = l_ecc_point_new(curve);
+
+	while (!compliant && iter++ < ECDH_MAX_ITERATIONS) {
+		*out_private = l_ecc_scalar_new_random(curve);
+
+		_ecc_point_mult(*out_public, &curve->g, (*out_private)->c,
+					NULL, curve->p);
+
+		/* ensure public key is compliant */
+		if (_vli_cmp((*out_public)->y, p2, curve->ndigits) >= 0) {
+			compliant = true;
+			break;
+		}
+
+		l_ecc_scalar_free(*out_private);
+	}
+
+	if (!compliant) {
+		l_ecc_point_free(*out_public);
+		return false;
+	}
+
+	return true;
+}
+
+LIB_EXPORT bool l_ecdh_generate_shared_secret(
+				const struct l_ecc_scalar *private_key,
+				const struct l_ecc_point *other_public,
+				struct l_ecc_scalar **secret)
+{
+	const struct l_ecc_curve *curve = private_key->curve;
+	struct l_ecc_scalar *z;
+	struct l_ecc_point *product;
+
+	if (unlikely(!private_key || !other_public || !secret))
+		return false;
+
+	z = l_ecc_scalar_new_random(curve);
+
+	product = l_ecc_point_new(curve);
+
+	_ecc_point_mult(product, other_public, private_key->c, z->c, curve->p);
+
+	*secret = _ecc_constant_new(curve, product->x, curve->ndigits * 8);
+
+	l_ecc_point_free(product);
+	l_ecc_scalar_free(z);
+
+	return true;
+}
diff --git a/ell/ecdh.h b/ell/ecdh.h
new file mode 100644
index 0000000..768a532
--- /dev/null
+++ b/ell/ecdh.h
@@ -0,0 +1,38 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_ECDH_H
+#define __ELL_ECDH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_ecc_curve;
+struct l_ecc_point;
+struct l_ecc_scalar;
+
+/*
+ * Generate a private/public key pair. private/public are out parameters and
+ * must be freed.
+ */
+bool l_ecdh_generate_key_pair(const struct l_ecc_curve *curve,
+					struct l_ecc_scalar **out_private,
+					struct l_ecc_point **out_public);
+/*
+ * Generate a shared secret from a private/public key. secret is an out
+ * parameters and must be freed.
+ */
+bool l_ecdh_generate_shared_secret(const struct l_ecc_scalar *private_key,
+				const struct l_ecc_point *other_public,
+				struct l_ecc_scalar **secret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_ECDH_H */
diff --git a/ell/ell.h b/ell/ell.h
new file mode 100644
index 0000000..5276799
--- /dev/null
+++ b/ell/ell.h
@@ -0,0 +1,38 @@
+#include <ell/util.h>
+#include <ell/log.h>
+#include <ell/queue.h>
+#include <ell/hashmap.h>
+#include <ell/random.h>
+#include <ell/signal.h>
+#include <ell/time.h>
+#include <ell/time-private.h>
+#include <ell/timeout.h>
+#include <ell/cipher.h>
+#include <ell/checksum.h>
+#include <ell/io.h>
+#include <ell/idle.h>
+#include <ell/main.h>
+#include <ell/settings.h>
+#include <ell/strv.h>
+#include <ell/string.h>
+#include <ell/utf8.h>
+#include <ell/dbus.h>
+#include <ell/dbus-service.h>
+#include <ell/dbus-client.h>
+#include <ell/key.h>
+#include <ell/cert.h>
+#include <ell/pem.h>
+#include <ell/base64.h>
+#include <ell/asn1-private.h>
+#include <ell/cert-private.h>
+#include <ell/pem-private.h>
+#include <ell/uuid.h>
+#include <ell/useful.h>
+#include <ell/main-private.h>
+#include <ell/tester.h>
+#include <ell/tls.h>
+#include <ell/tls-private.h>
+#include <ell/ecc.h>
+#include <ell/ecc-private.h>
+#include <ell/cleanup.h>
+#include <ell/ecdh.h>
diff --git a/ell/gvariant-private.h b/ell/gvariant-private.h
new file mode 100644
index 0000000..2aabd2e
--- /dev/null
+++ b/ell/gvariant-private.h
@@ -0,0 +1,54 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+struct l_dbus_message_iter;
+struct dbus_builder;
+
+bool _gvariant_iter_init(struct l_dbus_message_iter *iter,
+				struct l_dbus_message *message,
+				const char *sig_start, const char *sig_end,
+				const void *data, size_t len);
+bool _gvariant_iter_next_entry_basic(struct l_dbus_message_iter *iter,
+					char type, void *out_p);
+bool _gvariant_iter_enter_struct(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *structure);
+bool _gvariant_iter_enter_variant(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *variant);
+bool _gvariant_iter_enter_array(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *array);
+bool _gvariant_iter_skip_entry(struct l_dbus_message_iter *iter);
+
+bool _gvariant_valid_signature(const char *sig);
+int _gvariant_get_alignment(const char *signature);
+bool _gvariant_is_fixed_size(const char *signature);
+int _gvariant_get_fixed_size(const char *signature);
+int _gvariant_num_children(const char *sig);
+
+struct dbus_builder *_gvariant_builder_new(void *body, size_t body_size);
+void _gvariant_builder_free(struct dbus_builder *builder);
+bool _gvariant_builder_append_basic(struct dbus_builder *builder,
+					char type, const void *value);
+bool _gvariant_builder_mark(struct dbus_builder *builder);
+bool _gvariant_builder_rewind(struct dbus_builder *builder);
+char *_gvariant_builder_finish(struct dbus_builder *builder,
+				void **body, size_t *body_size);
+bool _gvariant_builder_enter_struct(struct dbus_builder *builder,
+					const char *signature);
+bool _gvariant_builder_leave_struct(struct dbus_builder *builder);
+bool _gvariant_builder_enter_dict(struct dbus_builder *builder,
+					const char *signature);
+bool _gvariant_builder_leave_dict(struct dbus_builder *builder);
+bool _gvariant_builder_enter_variant(struct dbus_builder *builder,
+					const char *signature);
+bool _gvariant_builder_leave_variant(struct dbus_builder *builder);
+bool _gvariant_builder_enter_array(struct dbus_builder *builder,
+					const char *signature);
+bool _gvariant_builder_leave_array(struct dbus_builder *builder);
+
+size_t _gvariant_message_finalize(size_t header_end,
+					void *body, size_t body_size,
+					const char *signature);
diff --git a/ell/gvariant-util.c b/ell/gvariant-util.c
new file mode 100644
index 0000000..6482e24
--- /dev/null
+++ b/ell/gvariant-util.c
@@ -0,0 +1,1364 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <endian.h>
+#include <limits.h>
+
+#include "private.h"
+#include "useful.h"
+#include "util.h"
+#include "queue.h"
+#include "string.h"
+#include "log.h"
+#include "dbus.h"
+#include "dbus-private.h"
+#include "gvariant-private.h"
+
+static const char *simple_types = "sogybnqiuxtdh";
+static const char *variable_types = "sogav";
+static const char *fixed_types = "bynqhiuxtd";
+
+/*
+ * The alignment of a container type is equal to the largest alignment of
+ * any potential child of that container. This means that, even if an array
+ * of 32-bit integers is empty, it still must be aligned to the nearest
+ * multiple of 4 bytes. It also means that the variant type (described below)
+ * has an alignment of 8 (since it could potentially contain a value of any
+ * other type and the maximum alignment is 8).
+ */
+static int get_basic_alignment(const char type)
+{
+	switch (type) {
+	case 'b':
+		return 1;
+	case 'y':
+		return 1;
+	case 'n':
+	case 'q':
+		return 2;
+	case 'i':
+	case 'u':
+		return 4;
+	case 'x':
+	case 't':
+	case 'd':
+		return 8;
+	case 's':
+	case 'g':
+	case 'o':
+		return 1;
+	case 'h':
+		return 4;
+	case 'v':
+		return 8;
+	default:
+		return 0;
+	}
+}
+
+static int get_basic_fixed_size(const char type)
+{
+	switch (type) {
+	case 'b':
+		return 1;
+	case 'y':
+		return 1;
+	case 'n':
+	case 'q':
+		return 2;
+	case 'i':
+	case 'u':
+		return 4;
+	case 'x':
+	case 't':
+	case 'd':
+		return 8;
+	case 'h':
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+static const char *validate_next_type(const char *sig, int *out_alignment)
+{
+	char s = *sig;
+	int alignment;
+
+	if (s == '\0')
+		return NULL;
+
+	if (strchr(simple_types, s) || s == 'v') {
+		*out_alignment = get_basic_alignment(s);
+		return sig + 1;
+	}
+
+	switch (s) {
+	case 'a':
+		return validate_next_type(++sig, out_alignment);
+
+	case '{':
+		s = *++sig;
+
+		/* Dictionary keys can only be simple types */
+		if (!strchr(simple_types, s))
+			return NULL;
+
+		alignment = get_basic_alignment(s);
+
+		sig = validate_next_type(sig + 1, out_alignment);
+
+		if (!sig)
+			return NULL;
+
+		if (*sig != '}')
+			return NULL;
+
+		if (alignment > *out_alignment)
+			*out_alignment = alignment;
+
+		return sig + 1;
+
+	case '(':
+	{
+		int max_alignment = 1, alignment;
+
+		sig++;
+
+		while (sig && *sig != ')') {
+			sig = validate_next_type(sig, &alignment);
+
+			if (alignment > max_alignment)
+				max_alignment = alignment;
+		}
+
+		if (!sig)
+			return NULL;
+
+		if (*sig != ')')
+			return NULL;
+
+		*out_alignment = max_alignment;
+
+		return sig + 1;
+	}
+	}
+
+	return NULL;
+}
+
+bool _gvariant_valid_signature(const char *sig)
+{
+	const char *s = sig;
+	int a;
+
+	if (strlen(sig) > 255)
+		return false;
+
+	do {
+		s = validate_next_type(s, &a);
+
+		if (!s)
+			return false;
+	} while (*s);
+
+	return true;
+}
+
+int _gvariant_num_children(const char *sig)
+{
+	const char *s = sig;
+	int a;
+	int num_children = 0;
+
+	if (strlen(sig) > 255)
+		return false;
+
+	do {
+		s = validate_next_type(s, &a);
+
+		if (!s)
+			return -1;
+
+		num_children += 1;
+	} while (*s);
+
+	return num_children;
+}
+
+int _gvariant_get_alignment(const char *sig)
+{
+	int max_alignment = 1, alignment;
+	const char *s = sig;
+
+	/* 8 is the largest alignment possible, so quit if we reach it */
+	while (*s && max_alignment != 8) {
+		s = validate_next_type(s, &alignment);
+		if (!s)
+			return 0;
+
+		if (alignment > max_alignment)
+			max_alignment = alignment;
+	}
+
+	return max_alignment;
+}
+
+bool _gvariant_is_fixed_size(const char *sig)
+{
+	while (*sig != 0) {
+		if (strchr(variable_types, sig[0]))
+			return false;
+
+		sig += 1;
+	}
+
+	return true;
+}
+
+int _gvariant_get_fixed_size(const char *sig)
+{
+	const char *s = sig;
+	const char *p;
+	int size = 0;
+	int alignment;
+	int max_alignment = 1;
+	int r;
+
+	while (*s) {
+		if (strchr(variable_types, *s))
+			return 0;
+
+		if (strchr(fixed_types, *s)) {
+			alignment = get_basic_alignment(*s);
+
+			if (alignment > max_alignment)
+				max_alignment = alignment;
+
+			size = align_len(size, alignment);
+			size += get_basic_fixed_size(*s);
+			s++;
+			continue;
+		}
+
+		if (*s == '}' || *s == ')')
+			break;
+
+		p = validate_next_type(s, &alignment);
+
+		if (!p)
+			return 0;
+
+		if (alignment > max_alignment)
+			max_alignment = alignment;
+
+		size = align_len(size, alignment);
+
+		/* Handle special case of unit type */
+		if (s[0] == '(' && s[1] == ')')
+			r = 1;
+		else
+			r = _gvariant_get_fixed_size(s + 1);
+
+		if (r == 0)
+			return 0;
+
+		size += r;
+		s = p;
+	}
+
+	size = align_len(size, max_alignment);
+
+	return size;
+}
+
+static inline size_t offset_length(size_t size, size_t n_offsets)
+{
+	if (size + n_offsets <= 0xff)
+		return 1;
+	if (size + n_offsets * 2 <= 0xffff)
+		return 2;
+	if (size + n_offsets * 4 <= 0xffffffff)
+		return 4;
+	return 8;
+}
+
+static inline size_t read_word_le(const void *p, size_t sz) {
+	union {
+		uint16_t u16;
+		uint32_t u32;
+		uint64_t u64;
+	} x;
+
+	if (sz == 1)
+		return *(uint8_t *) p;
+
+	memcpy(&x, p, sz);
+
+	if (sz == 2)
+		return le16toh(x.u16);
+	if (sz == 4)
+		return le32toh(x.u32);
+	return le64toh(x.u64);
+}
+
+static inline void write_word_le(void *p, size_t value, size_t sz) {
+	union {
+		uint16_t u16;
+		uint32_t u32;
+		uint64_t u64;
+	} x;
+
+	if (sz == 1) {
+		*(uint8_t *) p = value;
+		return;
+	}
+
+	if (sz == 2)
+		x.u16 = htole16((uint16_t) value);
+	else if (sz == 4)
+		x.u32 = htole32((uint32_t) value);
+	else
+		x.u64 = htole64((uint64_t) value);
+
+	memcpy(p, &x, sz);
+}
+
+static bool gvariant_iter_init_internal(struct l_dbus_message_iter *iter,
+					struct l_dbus_message *message,
+					enum dbus_container_type type,
+					const char *sig_start,
+					const char *sig_end, const void *data,
+					size_t len)
+{
+	const char *p;
+	int i;
+	int v;
+	char subsig[256];
+	unsigned int num_variable = 0;
+	unsigned int offset_len = offset_length(len, 0);
+	size_t last_offset;
+	struct gvariant_type_info {
+		uint8_t sig_start;
+		uint8_t sig_end;
+		bool fixed_size : 1;
+		unsigned int alignment : 4;
+		size_t end;		/* Index past the end of the type */
+	} *children;
+	int n_children;
+
+	if (sig_end) {
+		size_t len = sig_end - sig_start;
+		memcpy(subsig, sig_start, len);
+		subsig[len] = '\0';
+	} else
+		strcpy(subsig, sig_start);
+
+	iter->message = message;
+	iter->sig_start = sig_start;
+	iter->sig_len = strlen(subsig);
+	iter->sig_pos = 0;
+	iter->data = data;
+	iter->len = len;
+	iter->pos = 0;
+
+	if (subsig[0] != '\0') {
+		n_children = _gvariant_num_children(subsig);
+		if (n_children < 0)
+			return false;
+
+		children = l_new(struct gvariant_type_info, n_children);
+	} else {
+		n_children = 0;
+
+		children = NULL;
+	}
+
+	for (p = sig_start, i = 0; i < n_children; i++) {
+		int alignment;
+		size_t size;
+		size_t len;
+
+		children[i].sig_start = p - sig_start;
+		p = validate_next_type(p, &alignment);
+		children[i].sig_end = p - sig_start;
+
+		len = children[i].sig_end - children[i].sig_start;
+		memcpy(subsig, sig_start + children[i].sig_start, len);
+		subsig[len] = '\0';
+
+		children[i].alignment = alignment;
+		children[i].fixed_size = _gvariant_is_fixed_size(subsig);
+
+		if (children[i].fixed_size) {
+			size = _gvariant_get_fixed_size(subsig);
+			children[i].end = size;
+		} else if (i + 1 < n_children)
+			num_variable += 1;
+	}
+
+	if (len < num_variable * offset_len)
+		goto fail;
+
+	last_offset = len - num_variable * offset_len;
+
+	if (num_variable > 0)
+		iter->offsets = iter->data + len - offset_len;
+	else
+		iter->offsets = NULL;
+
+	for (i = 0, v = 0; i < n_children; i++) {
+		size_t o;
+
+		if (children[i].fixed_size) {
+			if (i == 0)
+				continue;
+
+			o = align_len(children[i-1].end,
+					children[i].alignment);
+			children[i].end += o;
+
+			if (children[i].end > len)
+				goto fail;
+
+			continue;
+		}
+
+		if (num_variable == 0) {
+			children[i].end = last_offset;
+			continue;
+		}
+
+		v += 1;
+		children[i].end = read_word_le(data + len - offset_len * v,
+						offset_len);
+		num_variable -= 1;
+
+		if (children[i].end > len)
+			goto fail;
+	}
+
+	iter->container_type = type;
+
+	if (type == DBUS_CONTAINER_TYPE_ARRAY &&
+			!children[0].fixed_size) {
+		size_t offset = read_word_le(iter->data + iter->len -
+						offset_len, offset_len);
+		iter->offsets = iter->data + offset;
+	}
+
+	l_free(children);
+
+	return true;
+
+fail:
+	l_free(children);
+	return false;
+}
+
+bool _gvariant_iter_init(struct l_dbus_message_iter *iter,
+				struct l_dbus_message *message,
+				const char *sig_start, const char *sig_end,
+				const void *data, size_t len)
+{
+	return gvariant_iter_init_internal(iter, message,
+						DBUS_CONTAINER_TYPE_STRUCT,
+						sig_start, sig_end, data, len);
+}
+
+static const void *next_item(struct l_dbus_message_iter *iter,
+							size_t *out_item_size)
+{
+	const void *start;
+	const char *p;
+	char sig[256];
+	int alignment;
+	bool fixed_size;
+	bool last_member;
+	unsigned int sig_len;
+	unsigned int offset_len;
+
+	memcpy(sig, iter->sig_start + iter->sig_pos,
+			iter->sig_len - iter->sig_pos);
+	sig[iter->sig_len - iter->sig_pos] = '\0';
+
+	/*
+	 * Find the next type and make a note whether it is the last in the
+	 * structure.  Arrays will always have a single complete type, so
+	 * last_member will always be true.
+	 */
+	p = validate_next_type(sig, &alignment);
+	if (!p)
+		return NULL;
+
+	sig_len = p - sig;
+
+	last_member = *p == '\0';
+	sig[sig_len] = '\0';
+
+	fixed_size = _gvariant_is_fixed_size(sig);
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
+		iter->sig_pos += sig_len;
+
+	iter->pos = align_len(iter->pos, alignment);
+
+	if (fixed_size) {
+		*out_item_size = _gvariant_get_fixed_size(sig);
+		goto done;
+	}
+
+	if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY && last_member) {
+		unsigned int len = iter->len;
+
+		offset_len = offset_length(iter->len, 0);
+
+		if (iter->offsets && iter->offsets + offset_len <
+				iter->data + len)
+			len = iter->offsets + offset_len - iter->data;
+
+		*out_item_size = len - iter->pos;
+		goto done;
+	}
+
+	if (iter->offsets >= iter->data + iter->len)
+			return NULL;
+
+	offset_len = offset_length(iter->len, 0);
+	*out_item_size = read_word_le(iter->offsets, offset_len) - iter->pos;
+
+	/* In structures the offsets are in reverse order */
+	if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
+		iter->offsets += offset_len;
+	else
+		iter->offsets -= offset_len;
+
+done:
+	start = iter->data + iter->pos;
+
+	if (start >= iter->data + iter->len)
+		return NULL;
+
+	iter->pos += *out_item_size;
+
+	return start;
+}
+
+bool _gvariant_iter_next_entry_basic(struct l_dbus_message_iter *iter,
+					char type, void *out)
+{
+	size_t item_size = 0;
+	const void *start;
+	uint8_t uint8_val;
+	uint16_t uint16_val;
+	uint32_t uint32_val;
+	uint64_t uint64_val;
+	int16_t int16_val;
+	int32_t int32_val;
+	int64_t int64_val;
+
+	if (iter->pos >= iter->len)
+		return false;
+
+	if (iter->sig_start[iter->sig_pos] != type)
+		return false;
+
+	start = next_item(iter, &item_size);
+	if (!start)
+		return false;
+
+	switch (type) {
+	case 'o':
+	case 's':
+	case 'g':
+	{
+		const void *end = memchr(start, 0, item_size);
+
+		if (!end)
+			return false;
+
+		*(const char**) out = start;
+		break;
+	}
+	case 'b':
+		uint8_val = l_get_u8(start);
+		*(bool *) out = !!uint8_val;
+		break;
+	case 'y':
+		uint8_val = l_get_u8(start);
+		*(uint8_t *) out = uint8_val;
+		break;
+	case 'n':
+		int16_val = l_get_s16(start);
+		*(int16_t *) out = int16_val;
+		break;
+	case 'q':
+		uint16_val = l_get_u16(start);
+		*(uint16_t *) out = uint16_val;
+		break;
+	case 'i':
+		int32_val = l_get_s32(start);
+		*(int32_t *) out = int32_val;
+		break;
+	case 'h':
+	case 'u':
+		uint32_val = l_get_u32(start);
+		*(uint32_t *) out = uint32_val;
+		break;
+	case 'x':
+		int64_val = l_get_s64(start);
+		*(int64_t *) out = int64_val;
+		break;
+	case 't':
+		uint64_val = l_get_u64(start);
+		*(uint64_t *) out = uint64_val;
+		break;
+	case 'd':
+		uint64_val = l_get_u64(start);
+		*(uint64_t *) out = uint64_val;
+		break;
+	}
+
+	return true;
+}
+
+bool _gvariant_iter_enter_struct(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *structure)
+{
+	bool is_dict = iter->sig_start[iter->sig_pos] == '{';
+	bool is_struct = iter->sig_start[iter->sig_pos] == '(';
+	const char *sig_start = iter->sig_start + iter->sig_pos + 1;
+	const char *sig_end;
+	const void *start;
+	size_t item_size;
+	enum dbus_container_type type;
+
+	if (!is_dict && !is_struct)
+		return false;
+
+	start = next_item(iter, &item_size);
+	if (!start)
+		return false;
+
+	/* For ARRAY containers the sig_pos is never incremented */
+	if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
+		sig_end = iter->sig_start + iter->sig_len - 1;
+	else
+		sig_end = iter->sig_start + iter->sig_pos - 1;
+
+	type = is_dict ? DBUS_CONTAINER_TYPE_DICT_ENTRY :
+			DBUS_CONTAINER_TYPE_STRUCT;
+
+	return gvariant_iter_init_internal(structure, iter->message,
+						type, sig_start, sig_end,
+						start, item_size);
+}
+
+bool _gvariant_iter_enter_variant(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *variant)
+{
+	size_t item_size;
+	const void *start, *end, *nul;
+	char signature[256];
+
+	if (iter->sig_start[iter->sig_pos] != 'v')
+		return false;
+
+	start = next_item(iter, &item_size);
+	if (!start)
+		return false;
+
+	/* Find the signature */
+	end = start + item_size;
+	nul = memrchr(start, 0, end - start);
+
+	if (!nul)
+		return false;
+
+	if (end - nul - 1 > 255)
+		return false;
+
+	memcpy(signature, nul + 1, end - nul - 1);
+	signature[end - nul - 1] = '\0';
+
+	if (_gvariant_num_children(signature) != 1)
+		return false;
+
+	return gvariant_iter_init_internal(variant, iter->message,
+						DBUS_CONTAINER_TYPE_VARIANT,
+						nul + 1, end,
+						start, nul - start);
+}
+
+bool _gvariant_iter_enter_array(struct l_dbus_message_iter *iter,
+					struct l_dbus_message_iter *array)
+{
+	const char *sig_start;
+	const char *sig_end;
+	size_t item_size;
+	const void *start;
+
+	if (iter->sig_start[iter->sig_pos] != 'a')
+		return false;
+
+	sig_start = iter->sig_start + iter->sig_pos + 1;
+
+	start = next_item(iter, &item_size);
+	if (!start)
+		return false;
+
+	/* For ARRAY containers the sig_pos is never incremented */
+	if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
+		sig_end = iter->sig_start + iter->sig_len;
+	else
+		sig_end = iter->sig_start + iter->sig_pos;
+
+	return gvariant_iter_init_internal(array, iter->message,
+						DBUS_CONTAINER_TYPE_ARRAY,
+						sig_start, sig_end,
+						start, item_size);
+}
+
+bool _gvariant_iter_skip_entry(struct l_dbus_message_iter *iter)
+{
+	size_t size;
+
+	if (!next_item(iter, &size))
+		return false;
+
+	return true;
+}
+
+struct dbus_builder {
+	struct l_string *signature;
+	void *body;
+	size_t body_size;
+	size_t body_pos;
+	struct l_queue *containers;
+	struct {
+		struct container *container;
+		int sig_end;
+		size_t body_pos;
+		size_t offset_index;
+		bool variable_is_last : 1;
+	} mark;
+};
+
+struct container {
+	size_t *offsets;
+	size_t offsets_size;
+	size_t offset_index;
+	size_t start;
+	bool variable_is_last : 1;
+	enum dbus_container_type type;
+	char signature[256];
+	uint8_t sigindex;
+};
+
+static inline size_t grow_body(struct dbus_builder *builder,
+					size_t len, unsigned int alignment)
+{
+	size_t size = align_len(builder->body_pos, alignment);
+
+	if (size + len > builder->body_size) {
+		builder->body = l_realloc(builder->body, size + len);
+		builder->body_size = size + len;
+	}
+
+	if (size - builder->body_pos > 0)
+		memset(builder->body + builder->body_pos, 0,
+			size - builder->body_pos);
+
+	builder->body_pos = size + len;
+
+	return size;
+}
+
+static inline bool grow_offsets(struct container *container)
+{
+	size_t needed;
+
+	if (container->offset_index < container->offsets_size)
+		return true;
+
+	needed = container->offsets_size * 2;
+
+	if (needed > USHRT_MAX)
+		return false;
+
+	if (needed == 0)
+		needed = 8;
+
+	container->offsets = l_realloc(container->offsets,
+						needed * sizeof(size_t));
+	container->offsets_size = needed;
+
+	return true;
+}
+
+static struct container *container_new(enum dbus_container_type type,
+					const char *signature, size_t start)
+{
+	struct container *ret;
+
+	ret = l_new(struct container, 1);
+
+	ret->type = type;
+	strcpy(ret->signature, signature);
+	ret->start = start;
+
+	return ret;
+}
+
+static void container_free(struct container *container)
+{
+	l_free(container->offsets);
+	l_free(container);
+}
+
+static void container_append_struct_offsets(struct container *container,
+					struct dbus_builder *builder)
+{
+	size_t offset_size;
+	int i;
+	size_t start;
+
+	if (container->variable_is_last)
+		container->offset_index -= 1;
+
+	if (container->offset_index == 0)
+		return;
+
+	offset_size = offset_length(builder->body_pos,
+						container->offset_index);
+
+	start = grow_body(builder, offset_size * container->offset_index, 1);
+
+	for (i = container->offset_index - 1; i >= 0; i--) {
+		write_word_le(builder->body + start,
+				container->offsets[i], offset_size);
+		start += offset_size;
+	}
+}
+
+static void container_append_array_offsets(struct container *container,
+					struct dbus_builder *builder)
+{
+	size_t offset_size;
+	unsigned int i;
+	size_t start;
+
+	if (container->offset_index == 0)
+		return;
+
+	offset_size = offset_length(builder->body_pos,
+						container->offset_index);
+	start = grow_body(builder, offset_size * container->offset_index, 1);
+
+	for (i = 0; i < container->offset_index; i++) {
+		write_word_le(builder->body + start,
+				container->offsets[i], offset_size);
+		start += offset_size;
+	}
+}
+
+struct dbus_builder *_gvariant_builder_new(void *body, size_t body_size)
+{
+	struct dbus_builder *builder;
+	struct container *root;
+
+	builder = l_new(struct dbus_builder, 1);
+	builder->signature = l_string_new(63);
+
+	builder->containers = l_queue_new();
+	root = container_new(DBUS_CONTAINER_TYPE_STRUCT, "", 0);
+	l_queue_push_head(builder->containers, root);
+
+	builder->body = body;
+	builder->body_size = body_size;
+	builder->body_pos = body_size;
+
+	builder->mark.container = root;
+
+	return builder;
+}
+
+void _gvariant_builder_free(struct dbus_builder *builder)
+{
+	if (unlikely(!builder))
+		return;
+
+	l_string_free(builder->signature);
+	l_queue_destroy(builder->containers,
+				(l_queue_destroy_func_t) container_free);
+	l_free(builder->body);
+
+	l_free(builder);
+}
+
+static bool enter_struct_dict_common(struct dbus_builder *builder,
+					const char *signature,
+					enum dbus_container_type type,
+					const char open,
+					const char close)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	int alignment;
+	size_t start;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) +
+				strlen(signature) + 2 > 255)
+			return false;
+	} else {
+		/* Verify Signatures Match */
+		char expect[256];
+		const char *start;
+		const char *end;
+
+		start = container->signature + container->sigindex;
+		end = validate_next_type(start, &alignment) - 1;
+
+		if (*start != open || *end != close)
+			return false;
+
+		memcpy(expect, start + 1, end - start - 1);
+		expect[end - start - 1] = '\0';
+
+		if (strcmp(expect, signature))
+			return false;
+	}
+
+	alignment = _gvariant_get_alignment(signature);
+	start = grow_body(builder, 0, alignment);
+
+	container = container_new(type, signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _gvariant_builder_enter_struct(struct dbus_builder *builder,
+					const char *signature)
+{
+	if (signature[0] && !_gvariant_valid_signature(signature))
+		return false;
+
+	return enter_struct_dict_common(builder, signature,
+					DBUS_CONTAINER_TYPE_STRUCT, '(', ')');
+}
+
+bool _gvariant_builder_enter_dict(struct dbus_builder *builder,
+					const char *signature)
+{
+	if (_gvariant_num_children(signature) != 2)
+		return false;
+
+	if (!strchr(simple_types, signature[0]))
+		return false;
+
+	return enter_struct_dict_common(builder, signature,
+					DBUS_CONTAINER_TYPE_DICT_ENTRY,
+					'{', '}');
+}
+
+static bool leave_struct_dict_common(struct dbus_builder *builder,
+					enum dbus_container_type type,
+					const char open,
+					const char close)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != type))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	if (_gvariant_is_fixed_size(container->signature)) {
+		int alignment = _gvariant_get_alignment(container->signature);
+		grow_body(builder, 0, alignment);
+
+		/* Empty struct or "unit type" is encoded as a zero byte */
+		if (container->signature[0] == '\0') {
+			size_t start = grow_body(builder, 1, 1);
+
+			memset(builder->body + start, 0, 1);
+		}
+
+		parent->variable_is_last = false;
+	} else {
+		size_t offset;
+
+		if (!grow_offsets(parent))
+			return false;
+
+		container_append_struct_offsets(container, builder);
+		offset = builder->body_pos - parent->start;
+		parent->offsets[parent->offset_index++] = offset;
+		parent->variable_is_last = true;
+	}
+
+	if (qlen == 1)
+		l_string_append_printf(builder->signature, "%c%s%c",
+						open,
+						container->signature,
+						close);
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += strlen(container->signature) + 2;
+
+	container_free(container);
+
+	return true;
+}
+
+bool _gvariant_builder_leave_struct(struct dbus_builder *builder)
+{
+	return leave_struct_dict_common(builder, DBUS_CONTAINER_TYPE_STRUCT,
+					'(', ')');
+}
+
+bool _gvariant_builder_leave_dict(struct dbus_builder *builder)
+{
+	return leave_struct_dict_common(builder,
+					DBUS_CONTAINER_TYPE_DICT_ENTRY,
+					'{', '}');
+}
+
+bool _gvariant_builder_enter_variant(struct dbus_builder *builder,
+					const char *signature)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+
+	if (_gvariant_num_children(signature) != 1)
+		return false;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) + 1 > 255)
+			return false;
+	} else if (container->signature[container->sigindex] != 'v')
+		return false;
+
+	start = grow_body(builder, 0, 8);
+
+	container = container_new(DBUS_CONTAINER_TYPE_VARIANT,
+					signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _gvariant_builder_leave_variant(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+	size_t start;
+	size_t siglen;
+	size_t offset;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != DBUS_CONTAINER_TYPE_VARIANT))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	siglen = strlen(container->signature);
+	start = grow_body(builder, siglen + 1, 1);
+	memset(builder->body + start, 0, 1);
+	memcpy(builder->body + start + 1, container->signature, siglen);
+
+	if (!grow_offsets(parent))
+		return false;
+
+	offset = builder->body_pos - parent->start;
+	parent->offsets[parent->offset_index++] = offset;
+	parent->variable_is_last = true;
+
+	if (qlen == 1)
+		l_string_append_c(builder->signature, 'v');
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += 1;
+
+	container_free(container);
+
+	return true;
+}
+
+bool _gvariant_builder_enter_array(struct dbus_builder *builder,
+					const char *signature)
+{
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+	int alignment;
+
+	if (_gvariant_num_children(signature) != 1)
+		return false;
+
+	if (qlen == 1) {
+		if (l_string_length(builder->signature) +
+				strlen(signature) + 1 > 255)
+			return false;
+	} else {
+		/* Verify Signatures Match */
+		char expect[256];
+		const char *start;
+		const char *end;
+
+		start = container->signature + container->sigindex;
+		end = validate_next_type(start, &alignment);
+
+		if (*start != 'a')
+			return false;
+
+		memcpy(expect, start + 1, end - start - 1);
+		expect[end - start - 1] = '\0';
+
+		if (strcmp(expect, signature))
+			return false;
+	}
+
+	alignment = _gvariant_get_alignment(signature);
+	start = grow_body(builder, 0, alignment);
+
+	container = container_new(DBUS_CONTAINER_TYPE_ARRAY, signature, start);
+	l_queue_push_head(builder->containers, container);
+
+	return true;
+}
+
+bool _gvariant_builder_leave_array(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t qlen = l_queue_length(builder->containers);
+	struct container *parent;
+	size_t offset;
+
+	if (unlikely(qlen <= 1))
+		return false;
+
+	if (unlikely(container->type != DBUS_CONTAINER_TYPE_ARRAY))
+		return false;
+
+	l_queue_pop_head(builder->containers);
+	qlen -= 1;
+	parent = l_queue_peek_head(builder->containers);
+
+	if (!_gvariant_is_fixed_size(container->signature))
+		container_append_array_offsets(container, builder);
+
+	if (!grow_offsets(parent))
+		return false;
+
+	offset = builder->body_pos - parent->start;
+	parent->offsets[parent->offset_index++] = offset;
+	parent->variable_is_last = true;
+
+	if (qlen == 1)
+		l_string_append_printf(builder->signature, "a%s",
+							container->signature);
+	else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
+		parent->sigindex += strlen(container->signature) + 1;
+
+	container_free(container);
+
+	return true;
+}
+
+bool _gvariant_builder_append_basic(struct dbus_builder *builder,
+					char type, const void *value)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+	size_t start;
+	unsigned int alignment;
+	size_t len;
+	size_t offset;
+
+	if (unlikely(!builder))
+		return false;
+
+	if (unlikely(!strchr(simple_types, type)))
+		return false;
+
+	alignment = get_basic_alignment(type);
+	if (!alignment)
+		return false;
+
+	if (l_queue_length(builder->containers) == 1)
+		l_string_append_c(builder->signature, type);
+	else if (container->signature[container->sigindex] != type)
+		return false;
+
+	len = get_basic_fixed_size(type);
+
+	if (len) {
+		start = grow_body(builder, len, alignment);
+		memcpy(builder->body + start, value, len);
+		container->variable_is_last = false;
+
+		if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
+			container->sigindex += 1;
+
+		return true;
+	}
+
+	if (!grow_offsets(container))
+		return false;
+
+	len = strlen(value) + 1;
+	start = grow_body(builder, len, alignment);
+	memcpy(builder->body + start, value, len);
+
+	offset = builder->body_pos - container->start;
+	container->offsets[container->offset_index++] = offset;
+	container->variable_is_last = true;
+
+	if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
+		container->sigindex += 1;
+
+	return true;
+}
+
+bool _gvariant_builder_mark(struct dbus_builder *builder)
+{
+	struct container *container = l_queue_peek_head(builder->containers);
+
+	builder->mark.container = container;
+
+	if (l_queue_length(builder->containers) == 1)
+		builder->mark.sig_end = l_string_length(builder->signature);
+	else
+		builder->mark.sig_end = container->sigindex;
+
+	builder->mark.body_pos = builder->body_pos;
+	builder->mark.offset_index = container->offset_index;
+	builder->mark.variable_is_last = container->variable_is_last;
+
+	return true;
+}
+
+bool _gvariant_builder_rewind(struct dbus_builder *builder)
+{
+	struct container *container;
+
+	while ((container = l_queue_peek_head(builder->containers)) !=
+				builder->mark.container) {
+		container_free(container);
+		l_queue_pop_head(builder->containers);
+	}
+
+	builder->body_pos = builder->mark.body_pos;
+	container->offset_index = builder->mark.offset_index;
+	container->variable_is_last = builder->mark.variable_is_last;
+
+	if (l_queue_length(builder->containers) == 1)
+		l_string_truncate(builder->signature, builder->mark.sig_end);
+	else
+		container->sigindex = builder->mark.sig_end;
+
+	return true;
+}
+
+char *_gvariant_builder_finish(struct dbus_builder *builder,
+				void **body, size_t *body_size)
+{
+	char *signature;
+	struct container *root;
+	uint8_t *variant_buf;
+	size_t size;
+
+	if (unlikely(!builder))
+		return NULL;
+
+	if (unlikely(l_queue_length(builder->containers) != 1))
+		return NULL;
+
+	root = l_queue_peek_head(builder->containers);
+
+	signature = l_string_unwrap(builder->signature);
+	builder->signature = NULL;
+
+	if (_gvariant_is_fixed_size(signature)) {
+		int alignment = _gvariant_get_alignment(signature);
+		grow_body(builder, 0, alignment);
+
+		/* Empty struct or "unit type" is encoded as a zero byte */
+		if (signature[0] == '\0') {
+			size_t start = grow_body(builder, 1, 1);
+
+			memset(builder->body + start, 0, 1);
+		}
+	} else
+		container_append_struct_offsets(root, builder);
+
+	/*
+	 * Make sure there's enough space after the body for the variant
+	 * signature written here but not included in the body size and
+	 * one framing offset value to be written in
+	 * _gvariant_message_finalize.
+	 */
+	size = 3 + strlen(signature) + 8;
+	if (builder->body_pos + size > builder->body_size)
+		builder->body = l_realloc(builder->body,
+						builder->body_pos + size);
+
+	variant_buf = builder->body + builder->body_pos;
+	*variant_buf++ = 0;
+	*variant_buf++ = '(';
+	variant_buf = mempcpy(variant_buf, signature, strlen(signature));
+	*variant_buf++ = ')';
+
+	*body = builder->body;
+	*body_size = builder->body_pos;
+	builder->body = NULL;
+	builder->body_size = 0;
+
+	return signature;
+}
+
+/*
+ * Write the header's framing offset after the body variant which is the
+ * last piece of data in the message after the header, the padding and
+ * the builder has written the message body.
+ */
+size_t _gvariant_message_finalize(size_t header_end,
+					void *body, size_t body_size,
+					const char *signature)
+{
+	size_t offset_start;
+	size_t offset_size;
+
+	offset_start = body_size + 3 + strlen(signature);
+
+	offset_size = offset_length(align_len(header_end, 8) + offset_start, 1);
+
+	write_word_le(body + offset_start, header_end, offset_size);
+
+	return align_len(header_end, 8) + offset_start + offset_size;
+}
diff --git a/ell/hashmap.c b/ell/hashmap.c
new file mode 100644
index 0000000..6769bc1
--- /dev/null
+++ b/ell/hashmap.c
@@ -0,0 +1,718 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "hashmap.h"
+#include "private.h"
+#include "useful.h"
+
+/**
+ * SECTION:hashmap
+ * @short_description: Hash table support
+ *
+ * Hash table support
+ */
+
+#define NBUCKETS 127
+
+struct entry {
+	void *key;
+	void *value;
+	struct entry *next;
+	unsigned int hash;
+};
+
+/**
+ * l_hashmap:
+ *
+ * Opaque object representing the hash table.
+ */
+struct l_hashmap {
+	l_hashmap_hash_func_t hash_func;
+	l_hashmap_compare_func_t compare_func;
+	l_hashmap_key_new_func_t key_new_func;
+	l_hashmap_key_free_func_t key_free_func;
+	unsigned int entries;
+	struct entry buckets[NBUCKETS];
+};
+
+static inline void *get_key_new(const struct l_hashmap *hashmap,
+				const void *key)
+{
+	if (hashmap->key_new_func)
+		return hashmap->key_new_func(key);
+
+	return (void *)key;
+}
+
+static inline void free_key(const struct l_hashmap *hashmap, void *key)
+{
+	if (hashmap->key_free_func)
+		hashmap->key_free_func(key);
+}
+
+static inline unsigned int hash_superfast(const uint8_t *key, unsigned int len)
+{
+	/*
+	 * Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
+	 * used by WebCore (http://webkit.org/blog/8/hashtables-part-2/),
+	 * EFL's eina, kmod and possible others.
+	 */
+	unsigned int tmp, hash = len, rem = len & 3;
+
+	len /= 4;
+
+	/* Main loop */
+	for (; len > 0; len--) {
+		hash += l_get_u16(key);
+		tmp = (l_get_u16(key + 2) << 11) ^ hash;
+		hash = (hash << 16) ^ tmp;
+		key += 4;
+		hash += hash >> 11;
+	}
+
+	/* Handle end cases */
+	switch (rem) {
+	case 3:
+		hash += l_get_u16(key);
+		hash ^= hash << 16;
+		hash ^= key[2] << 18;
+		hash += hash >> 11;
+		break;
+
+	case 2:
+		hash += l_get_u16(key);
+		hash ^= hash << 11;
+		hash += hash >> 17;
+		break;
+
+	case 1:
+		hash += *key;
+		hash ^= hash << 10;
+		hash += hash >> 1;
+		break;
+	}
+
+	/* Force "avalanching" of final 127 bits */
+	hash ^= hash << 3;
+	hash += hash >> 5;
+	hash ^= hash << 4;
+	hash += hash >> 17;
+	hash ^= hash << 25;
+	hash += hash >> 6;
+
+	return hash;
+}
+
+static unsigned int direct_hash_func(const void *p)
+{
+	return L_PTR_TO_UINT(p);
+}
+
+static int direct_compare_func(const void *a, const void *b)
+{
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+/**
+ * l_hashmap_new:
+ *
+ * Create a new hash table. The keys are managed as pointers, that is,
+ * the pointer value is hashed and looked up.
+ *
+ * No error handling is needed since. In case of real memory allocation
+ * problems abort() will be called.
+ *
+ * See also l_hashmap_string_new().
+ *
+ * Returns: a newly allocated #l_hashmap object
+ **/
+LIB_EXPORT struct l_hashmap *l_hashmap_new(void)
+{
+	struct l_hashmap *hashmap;
+
+	hashmap = l_new(struct l_hashmap, 1);
+
+	hashmap->hash_func = direct_hash_func;
+	hashmap->compare_func = direct_compare_func;
+	hashmap->entries = 0;
+
+	return hashmap;
+}
+
+LIB_EXPORT unsigned int l_str_hash(const void *p)
+{
+	const char *s = p;
+	size_t len = strlen(s);
+
+	return hash_superfast((const uint8_t *)s, len);
+}
+
+/**
+ * l_hashmap_string_new:
+ *
+ * Create a new hash table. The keys are considered strings and are
+ * copied.
+ *
+ * No error handling is needed since. In case of real memory allocation
+ * problems abort() will be called.
+ *
+ * See also l_hashmap_new().
+ *
+ * Returns: a newly allocated #l_hashmap object
+ **/
+LIB_EXPORT struct l_hashmap *l_hashmap_string_new(void)
+{
+	struct l_hashmap *hashmap;
+
+	hashmap = l_new(struct l_hashmap, 1);
+
+	hashmap->hash_func = l_str_hash;
+	hashmap->compare_func = (l_hashmap_compare_func_t) strcmp;
+	hashmap->key_new_func = (l_hashmap_key_new_func_t) l_strdup;
+	hashmap->key_free_func = l_free;
+	hashmap->entries = 0;
+
+	return hashmap;
+}
+
+/**
+ * l_hashmap_set_hash_function:
+ * @hashmap: hash table object
+ * @func: Key hashing function
+ *
+ * Sets the hashing function to be used by this object.
+ *
+ * This function can only be called when the @hashmap is empty.
+ *
+ * Returns: #true when the hashing function could be updated successfully,
+ * and #false otherwise.
+ **/
+LIB_EXPORT bool l_hashmap_set_hash_function(struct l_hashmap *hashmap,
+						l_hashmap_hash_func_t func)
+{
+	if (unlikely(!hashmap))
+		return false;
+
+	if (hashmap->entries != 0)
+		return false;
+
+	hashmap->hash_func = func;
+
+	return true;
+}
+
+/**
+ * l_hashmap_set_compare_function:
+ * @hashmap: hash table object
+ * @func: Key compare function
+ *
+ * Sets the key comparison function to be used by this object.
+ *
+ * This function can only be called when the @hashmap is empty.
+ *
+ * Returns: #true when the comparison function could be updated successfully,
+ * and #false otherwise.
+ **/
+LIB_EXPORT bool l_hashmap_set_compare_function(struct l_hashmap *hashmap,
+						l_hashmap_compare_func_t func)
+{
+	if (unlikely(!hashmap))
+		return false;
+
+	if (hashmap->entries != 0)
+		return false;
+
+	hashmap->compare_func = func;
+
+	return true;
+}
+
+/**
+ * l_hashmap_set_key_copy_function:
+ * @hashmap: hash table object
+ * @func: Key duplication function
+ *
+ * Sets the key duplication function to be used by this object.  If the
+ * function is NULL, then the keys are assigned directly.
+ *
+ * This function can only be called when the @hashmap is empty.
+ *
+ * Returns: #true when the key copy function could be updated successfully,
+ * and #false otherwise.
+ **/
+LIB_EXPORT bool l_hashmap_set_key_copy_function(struct l_hashmap *hashmap,
+						l_hashmap_key_new_func_t func)
+{
+	if (unlikely(!hashmap))
+		return false;
+
+	if (hashmap->entries != 0)
+		return false;
+
+	hashmap->key_new_func = func;
+
+	return true;
+}
+
+/**
+ * l_hashmap_set_key_free_function:
+ * @hashmap: hash table object
+ * @func: Key destructor function
+ *
+ * Sets the key destructor function to be used by this object.  This function
+ * should undo the result of the function specified in
+ * l_hashmap_set_key_copy_function(). This function can be NULL, in which
+ * case no destructor is called.
+ *
+ * This function can only be called when the @hashmap is empty.
+ *
+ * Returns: #true when the key free function could be updated successfully,
+ * and #false otherwise.
+ **/
+LIB_EXPORT bool l_hashmap_set_key_free_function(struct l_hashmap *hashmap,
+						l_hashmap_key_free_func_t func)
+{
+	if (unlikely(!hashmap))
+		return false;
+
+	if (hashmap->entries != 0)
+		return false;
+
+	hashmap->key_free_func = func;
+
+	return true;
+}
+
+/**
+ * l_hashmap_destroy:
+ * @hashmap: hash table object
+ * @destroy: destroy function
+ *
+ * Free hash table and call @destroy on all remaining entries.
+ *
+ * NOTE: While the destroy is in progress, the hashmap is assumed to be
+ * invariant.  The behavior of adding or removing entries while a destroy
+ * operation is in progress is undefined.
+ **/
+LIB_EXPORT void l_hashmap_destroy(struct l_hashmap *hashmap,
+				l_hashmap_destroy_func_t destroy)
+{
+	unsigned int i;
+
+	if (unlikely(!hashmap))
+		return;
+
+	for (i = 0; i < NBUCKETS; i++) {
+		struct entry *entry, *next, *head = &hashmap->buckets[i];
+
+		if (!head->next)
+			continue;
+
+		for (entry = head;; entry = next) {
+			if (destroy)
+				destroy(entry->value);
+
+			free_key(hashmap, entry->key);
+
+			next = entry->next;
+
+			if (entry != head)
+				l_free(entry);
+
+			if (next == head)
+				break;
+		}
+	}
+
+	l_free(hashmap);
+}
+
+/**
+ * l_hashmap_insert:
+ * @hashmap: hash table object
+ * @key: key pointer
+ * @value: value pointer
+ *
+ * Insert new @value entry with @key.  Note that entries with a duplicate key
+ * are allowed.  If a duplicate entry in inserted, it will be added in order
+ * of insertion.  @l_hashmap_lookup and @l_hashmap_remove will remove the
+ * first matching entry.
+ *
+ * Returns: #true when value has been added and #false in case of failure
+ **/
+LIB_EXPORT bool l_hashmap_insert(struct l_hashmap *hashmap,
+				const void *key, void *value)
+{
+	struct entry *entry, *head;
+	unsigned int hash;
+	void *key_new;
+
+	if (unlikely(!hashmap))
+		return false;
+
+	key_new = get_key_new(hashmap, key);
+	hash = hashmap->hash_func(key_new);
+	head = &hashmap->buckets[hash % NBUCKETS];
+
+	if (!head->next) {
+		head->key = key_new;
+		head->value = value;
+		head->hash = hash;
+		head->next = head;
+		goto done;
+	}
+
+	entry = l_new(struct entry, 1);
+	entry->key = key_new;
+	entry->value = value;
+	entry->hash = hash;
+	entry->next = head;
+
+	while (head->next != entry->next)
+		head = head->next;
+
+	head->next = entry;
+
+done:
+	hashmap->entries++;
+
+	return true;
+}
+
+/**
+ * l_hashmap_replace:
+ * @hashmap: hash table object
+ * @key: key pointer
+ * @value: value pointer
+ * @old_value: old value that has been replaced.
+ *
+ * Replace the first entry with @key by @value or insert a new @value entry
+ * with @key.  If the entry was replaced, then the old value is returned
+ * in @old_value, otherwise @old_value is assigned a #NULL.
+ *
+ * Returns: #true when value has been added and #false in case of failure
+ **/
+LIB_EXPORT bool l_hashmap_replace(struct l_hashmap *hashmap,
+					const void *key, void *value,
+					void **old_value)
+{
+	struct entry *entry;
+	struct entry *head;
+	unsigned int hash;
+	void *key_new;
+
+	if (unlikely(!hashmap))
+		return false;
+
+	key_new = get_key_new(hashmap, key);
+	hash = hashmap->hash_func(key_new);
+	head = &hashmap->buckets[hash % NBUCKETS];
+
+	if (!head->next) {
+		head->key = key_new;
+		head->value = value;
+		head->hash = hash;
+		head->next = head;
+		goto done;
+	}
+
+	for (entry = head;; entry = entry->next) {
+		if (entry->hash != hash)
+			goto next;
+
+		if (hashmap->compare_func(key, entry->key))
+			goto next;
+
+		if (old_value)
+			*old_value = entry->value;
+
+		entry->value = value;
+		free_key(hashmap, key_new);
+
+		return true;
+
+next:
+		if (entry->next == head)
+			break;
+	}
+
+	entry = l_new(struct entry, 1);
+	entry->key = key_new;
+	entry->value = value;
+	entry->hash = hash;
+	entry->next = head;
+
+	while (head->next != entry->next)
+		head = head->next;
+
+	head->next = entry;
+
+done:
+	if (old_value)
+		*old_value = NULL;
+
+	hashmap->entries++;
+
+	return true;
+}
+
+/**
+ * l_hashmap_remove:
+ * @hashmap: hash table object
+ * @key: key pointer
+ *
+ * Remove entry for @key.
+ *
+ * Returns: value pointer of the removed entry or #NULL in case of failure
+ **/
+LIB_EXPORT void *l_hashmap_remove(struct l_hashmap *hashmap, const void *key)
+{
+	struct entry *entry, *head, *prev;
+	unsigned int hash;
+
+	if (unlikely(!hashmap))
+		return NULL;
+
+	hash = hashmap->hash_func(key);
+	head = &hashmap->buckets[hash % NBUCKETS];
+
+	if (!head->next)
+		return NULL;
+
+	for (entry = head, prev = NULL;; prev = entry, entry = entry->next) {
+		void *value;
+
+		if (entry->hash != hash)
+			goto next;
+
+		if (hashmap->compare_func(key, entry->key))
+			goto next;
+
+		value = entry->value;
+
+		if (entry == head) {
+			if (entry->next == head) {
+				free_key(hashmap, entry->key);
+				head->key = NULL;
+				head->value = NULL;
+				head->hash = 0;
+				head->next = NULL;
+			} else {
+				entry = entry->next;
+				free_key(hashmap, head->key);
+				head->key = entry->key;
+				head->value = entry->value;
+				head->hash = entry->hash;
+				head->next = entry->next;
+				l_free(entry);
+			}
+		} else {
+			prev->next = entry->next;
+			free_key(hashmap, entry->key);
+			l_free(entry);
+		}
+
+		hashmap->entries--;
+
+		return value;
+
+next:
+		if (entry->next == head)
+			break;
+	}
+
+	return NULL;
+}
+
+/**
+ * l_hashmap_lookup:
+ * @hashmap: hash table object
+ * @key: key pointer
+ *
+ * Lookup entry for @key.
+ *
+ * Returns: value pointer for @key or #NULL in case of failure
+ **/
+LIB_EXPORT void *l_hashmap_lookup(struct l_hashmap *hashmap, const void *key)
+{
+	struct entry *entry, *head;
+	unsigned int hash;
+
+	if (unlikely(!hashmap))
+		return NULL;
+
+	hash = hashmap->hash_func(key);
+	head = &hashmap->buckets[hash % NBUCKETS];
+
+	if (!head->next)
+		return NULL;
+
+	for (entry = head;; entry = entry->next) {
+		if (entry->hash == hash &&
+				!hashmap->compare_func(key, entry->key))
+			return entry->value;
+
+		if (entry->next == head)
+			break;
+	}
+
+	return NULL;
+}
+
+/**
+ * l_hashmap_foreach:
+ * @hashmap: hash table object
+ * @function: callback function
+ * @user_data: user data given to callback function
+ *
+ * Call @function for every entry in @hashmap.
+ *
+ * NOTE: While the foreach is in progress, the hashmap is assumed to be
+ * invariant.  The behavior of adding or removing entries while a foreach
+ * operation is in progress is undefined.
+ **/
+LIB_EXPORT void l_hashmap_foreach(struct l_hashmap *hashmap,
+			l_hashmap_foreach_func_t function, void *user_data)
+{
+	unsigned int i;
+
+	if (unlikely(!hashmap || !function))
+		return;
+
+	for (i = 0; i < NBUCKETS; i++) {
+		struct entry *entry, *head = &hashmap->buckets[i];
+
+		if (!head->next)
+			continue;
+
+		for (entry = head;; entry = entry->next) {
+			function(entry->key, entry->value, user_data);
+
+			if (entry->next == head)
+				break;
+		}
+	}
+}
+
+/**
+ * l_hashmap_foreach_remove:
+ * @hashmap: hash table object
+ * @function: callback function
+ * @user_data: user data given to callback function
+ *
+ * Call @function for every entry in @hashmap.  If the @function returns
+ * true, then the object will be removed from the hashmap.
+ *
+ * NOTE: While the foreach is in progress, the hashmap is assumed to be
+ * invariant.  The behavior of adding or removing entries while a foreach
+ * operation is in progress is undefined.
+ *
+ * Returns: Number of entries removed.
+ **/
+LIB_EXPORT unsigned int l_hashmap_foreach_remove(struct l_hashmap *hashmap,
+					l_hashmap_remove_func_t function,
+					void *user_data)
+{
+	unsigned int i;
+	unsigned int nremoved = 0;
+
+	if (unlikely(!hashmap || !function))
+		return 0;
+
+	for (i = 0; i < NBUCKETS; i++) {
+		struct entry *head = &hashmap->buckets[i];
+		struct entry *entry;
+		struct entry *prev;
+		bool remove;
+
+		if (head->next == NULL)
+			continue;
+
+		entry = head;
+		prev = NULL;
+
+		while (true) {
+			remove = function(entry->key, entry->value, user_data);
+
+			if (!remove)
+				goto next;
+
+			nremoved += 1;
+			hashmap->entries -= 1;
+
+			if (entry == head) {
+				if (entry->next == head) {
+					free_key(hashmap, entry->key);
+					head->key = NULL;
+					head->value = NULL;
+					head->hash = 0;
+					head->next = NULL;
+					break;
+				} else {
+					entry = entry->next;
+					free_key(hashmap, head->key);
+					head->key = entry->key;
+					head->value = entry->value;
+					head->hash = entry->hash;
+					head->next = entry->next;
+					l_free(entry);
+					entry = head;
+					continue;
+				}
+			} else {
+				prev->next = entry->next;
+				free_key(hashmap, entry->key);
+				l_free(entry);
+				entry = prev->next;
+				if (entry == head)
+					break;
+				continue;
+			}
+
+next:
+			if (entry->next == head)
+				break;
+
+			prev = entry;
+			entry = entry->next;
+		}
+	}
+
+	return nremoved;
+}
+
+/**
+ * l_hashmap_size:
+ * @hashmap: hash table object
+ *
+ * Returns: entries in the hash table
+ **/
+LIB_EXPORT unsigned int l_hashmap_size(struct l_hashmap *hashmap)
+{
+	if (unlikely(!hashmap))
+		return 0;
+
+	return hashmap->entries;
+}
+
+/**
+ * l_hashmap_isempty:
+ * @hashmap: hash table object
+ *
+ * Returns: #true if hash table is empty and #false if not
+ **/
+LIB_EXPORT bool l_hashmap_isempty(struct l_hashmap *hashmap)
+{
+	if (unlikely(!hashmap))
+		return true;
+
+	return hashmap->entries == 0;
+}
diff --git a/ell/hashmap.h b/ell/hashmap.h
new file mode 100644
index 0000000..cf61825
--- /dev/null
+++ b/ell/hashmap.h
@@ -0,0 +1,66 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_HASHMAP_H
+#define __ELL_HASHMAP_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*l_hashmap_foreach_func_t) (const void *key, void *value,
+							void *user_data);
+typedef void (*l_hashmap_destroy_func_t) (void *value);
+typedef unsigned int (*l_hashmap_hash_func_t) (const void *p);
+typedef int (*l_hashmap_compare_func_t) (const void *a, const void *b);
+typedef void *(*l_hashmap_key_new_func_t) (const void *p);
+typedef void (*l_hashmap_key_free_func_t) (void *p);
+typedef bool (*l_hashmap_remove_func_t)(const void *key, void *value,
+						void *user_data);
+
+struct l_hashmap;
+
+unsigned int l_str_hash(const void *p);
+
+struct l_hashmap *l_hashmap_new(void);
+struct l_hashmap *l_hashmap_string_new(void);
+
+bool l_hashmap_set_hash_function(struct l_hashmap *hashmap,
+						l_hashmap_hash_func_t func);
+bool l_hashmap_set_compare_function(struct l_hashmap *hashmap,
+						l_hashmap_compare_func_t func);
+bool l_hashmap_set_key_copy_function(struct l_hashmap *hashmap,
+						l_hashmap_key_new_func_t func);
+bool l_hashmap_set_key_free_function(struct l_hashmap *hashmap,
+					l_hashmap_key_free_func_t func);
+
+void l_hashmap_destroy(struct l_hashmap *hashmap,
+			l_hashmap_destroy_func_t destroy);
+
+bool l_hashmap_insert(struct l_hashmap *hashmap,
+			const void *key, void *value);
+bool l_hashmap_replace(struct l_hashmap *hashmap,
+					const void *key, void *value,
+					void **old_value);
+void *l_hashmap_remove(struct l_hashmap *hashmap, const void *key);
+void *l_hashmap_lookup(struct l_hashmap *hashmap, const void *key);
+
+void l_hashmap_foreach(struct l_hashmap *hashmap,
+			l_hashmap_foreach_func_t function, void *user_data);
+unsigned int l_hashmap_foreach_remove(struct l_hashmap *hashmap,
+			l_hashmap_remove_func_t function, void *user_data);
+
+unsigned int l_hashmap_size(struct l_hashmap *hashmap);
+bool l_hashmap_isempty(struct l_hashmap *hashmap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_HASHMAP_H */
diff --git a/ell/idle.c b/ell/idle.c
new file mode 100644
index 0000000..11daaf4
--- /dev/null
+++ b/ell/idle.c
@@ -0,0 +1,153 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "useful.h"
+#include "idle.h"
+#include "main-private.h"
+#include "private.h"
+
+/**
+ * SECTION:idle
+ * @short_description: Idle processing support
+ *
+ * Idle processing support
+ */
+
+/**
+ * l_idle:
+ *
+ * Opaque object representing the idle time event.
+ */
+struct l_idle {
+	union {
+		l_idle_notify_cb_t callback;
+		l_idle_oneshot_cb_t oneshot;
+	};
+
+	l_idle_destroy_cb_t destroy;
+	void *user_data;
+	int id;
+};
+
+static void idle_destroy(void *user_data)
+{
+	struct l_idle *idle = user_data;
+
+	if (idle->destroy)
+		idle->destroy(idle->user_data);
+
+	l_free(idle);
+}
+
+static void idle_callback(void *user_data)
+{
+	struct l_idle *idle = user_data;
+
+	if (idle->callback)
+		idle->callback(idle, idle->user_data);
+}
+
+static void oneshot_callback(void *user_data)
+{
+	struct l_idle *idle = user_data;
+
+	if (idle->oneshot)
+		idle->oneshot(idle->user_data);
+
+	idle_remove(idle->id);
+}
+
+/**
+ * l_idle_create:
+ * @callback: idle callback function
+ * @user_data: user data provided to idle callback function
+ * @destroy: destroy function for user data
+ *
+ * Create a new idle event processing object.
+ *
+ * The idle callback will be called until canceled using l_idle_remove().
+ *
+ * Returns: a newly allocated #l_idle object
+ **/
+LIB_EXPORT struct l_idle *l_idle_create(l_idle_notify_cb_t callback,
+			void *user_data, l_idle_destroy_cb_t destroy)
+{
+	struct l_idle *idle;
+
+	if (unlikely(!callback))
+		return NULL;
+
+	idle = l_new(struct l_idle, 1);
+
+	idle->callback = callback;
+	idle->destroy = destroy;
+	idle->user_data = user_data;
+
+	idle->id = idle_add(idle_callback, idle, 0, idle_destroy);
+	if (idle->id < 0) {
+		l_free(idle);
+		return NULL;
+	}
+
+	return idle;
+}
+
+/**
+ * l_idle_oneshot:
+ * @callback: idle callback function
+ * @user_data: user data provided to idle callback function
+ * @destroy: destroy function for user data
+ *
+ * Create a new idle event processing object.  The callback will be called
+ * only once at which point the object will be destroyed.
+ *
+ * Returns: true if the oneshot idle object could be created successfully.
+ **/
+LIB_EXPORT bool l_idle_oneshot(l_idle_oneshot_cb_t callback, void *user_data,
+				l_idle_destroy_cb_t destroy)
+{
+	struct l_idle *idle;
+
+	if (unlikely(!callback))
+		return NULL;
+
+	idle = l_new(struct l_idle, 1);
+
+	idle->oneshot = callback;
+	idle->destroy = destroy;
+	idle->user_data = user_data;
+
+	idle->id = idle_add(oneshot_callback, idle,
+				IDLE_FLAG_NO_WARN_DANGLING, idle_destroy);
+	if (idle->id < 0) {
+		l_free(idle);
+		return false;
+	}
+
+	return true;
+}
+/**
+ * l_idle_remove:
+ * @idle: idle object
+ *
+ * Remove idle event processing object.
+ **/
+LIB_EXPORT void l_idle_remove(struct l_idle *idle)
+{
+	if (unlikely(!idle))
+		return;
+
+	idle_remove(idle->id);
+}
diff --git a/ell/idle.h b/ell/idle.h
new file mode 100644
index 0000000..8856a98
--- /dev/null
+++ b/ell/idle.h
@@ -0,0 +1,34 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_IDLE_H
+#define __ELL_IDLE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_idle;
+
+typedef void (*l_idle_notify_cb_t) (struct l_idle *idle, void *user_data);
+typedef void (*l_idle_oneshot_cb_t) (void *user_data);
+typedef void (*l_idle_destroy_cb_t) (void *user_data);
+
+struct l_idle *l_idle_create(l_idle_notify_cb_t callback,
+			void *user_data, l_idle_destroy_cb_t destroy);
+void l_idle_remove(struct l_idle *idle);
+
+bool l_idle_oneshot(l_idle_oneshot_cb_t callback, void *user_data,
+			l_idle_destroy_cb_t destroy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_IDLE_H */
diff --git a/ell/internal b/ell/internal
new file mode 100644
index 0000000..e69de29
diff --git a/ell/io.c b/ell/io.c
new file mode 100644
index 0000000..64bbed1
--- /dev/null
+++ b/ell/io.c
@@ -0,0 +1,399 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/epoll.h>
+
+#include "useful.h"
+#include "main-private.h"
+#include "io.h"
+#include "private.h"
+
+/**
+ * SECTION:io
+ * @short_description: IO support
+ *
+ * IO support
+ */
+
+/**
+ * l_io:
+ *
+ * Opaque object representing the IO.
+ */
+struct l_io {
+	int fd;
+	uint32_t events;
+	bool close_on_destroy;
+	l_io_read_cb_t read_handler;
+	l_io_destroy_cb_t read_destroy;
+	void *read_data;
+	l_io_write_cb_t write_handler;
+	l_io_destroy_cb_t write_destroy;
+	void *write_data;
+	l_io_disconnect_cb_t disconnect_handler;
+	l_io_destroy_cb_t disconnect_destroy;
+	void *disconnect_data;
+	l_io_debug_cb_t debug_handler;
+	l_io_destroy_cb_t debug_destroy;
+	void *debug_data;
+};
+
+static void io_cleanup(void *user_data)
+{
+	struct l_io *io = user_data;
+
+	l_util_debug(io->debug_handler, io->debug_data, "cleanup <%p>", io);
+
+	if (io->write_destroy)
+		io->write_destroy(io->write_data);
+
+	io->write_handler = NULL;
+	io->write_data = NULL;
+
+	if (io->read_destroy)
+		io->read_destroy(io->read_data);
+
+	io->read_handler = NULL;
+	io->read_data = NULL;
+
+	if (io->close_on_destroy)
+		close(io->fd);
+
+	io->fd = -1;
+}
+
+static void io_closed(struct l_io *io)
+{
+	/*
+	 * Save off copies of disconnect_handler, disconnect_destroy
+	 * and disconnect_data in case the handler calls io_destroy
+	 */
+	l_io_disconnect_cb_t handler = io->disconnect_handler;
+	l_io_destroy_cb_t destroy = io->disconnect_destroy;
+	void *disconnect_data = io->disconnect_data;
+
+	io->disconnect_handler = NULL;
+	io->disconnect_destroy = NULL;
+	io->disconnect_data = NULL;
+
+	if (handler)
+		handler(io, disconnect_data);
+
+	if (destroy)
+		destroy(disconnect_data);
+}
+
+static void io_callback(int fd, uint32_t events, void *user_data)
+{
+	struct l_io *io = user_data;
+
+	if ((events & EPOLLIN) && io->read_handler) {
+		l_util_debug(io->debug_handler, io->debug_data,
+						"read event <%p>", io);
+
+		if (!io->read_handler(io, io->read_data)) {
+			if (io->read_destroy)
+				io->read_destroy(io->read_data);
+
+			io->read_handler = NULL;
+			io->read_destroy = NULL;
+			io->read_data = NULL;
+
+			io->events &= ~EPOLLIN;
+
+			if (watch_modify(io->fd, io->events, false) == -EBADF) {
+				io->close_on_destroy = false;
+				watch_clear(io->fd);
+				io_closed(io);
+				return;
+			}
+		}
+	}
+
+	if (unlikely(events & (EPOLLERR | EPOLLHUP))) {
+		bool close_on_destroy = io->close_on_destroy;
+		int fd = io->fd;
+
+		l_util_debug(io->debug_handler, io->debug_data,
+						"disconnect event <%p>", io);
+		io_closed(io);
+		watch_remove(fd, !close_on_destroy);
+		return;
+	}
+
+	if ((events & EPOLLOUT) && io->write_handler) {
+		l_util_debug(io->debug_handler, io->debug_data,
+						"write event <%p>", io);
+
+		if (!io->write_handler(io, io->write_data)) {
+			if (io->write_destroy)
+				io->write_destroy(io->write_data);
+
+			io->write_handler = NULL;
+			io->write_destroy = NULL;
+			io->write_data = NULL;
+
+			io->events &= ~EPOLLOUT;
+
+			if (watch_modify(io->fd, io->events, false) == -EBADF) {
+				io->close_on_destroy = false;
+				watch_clear(io->fd);
+				io_closed(io);
+				return;
+			}
+		}
+	}
+}
+
+/**
+ * l_io_new:
+ * @fd: file descriptor
+ *
+ * Create new IO handling for a given file descriptor.
+ *
+ * Returns: a newly allocated #l_io object
+ **/
+LIB_EXPORT struct l_io *l_io_new(int fd)
+{
+	struct l_io *io;
+	int err;
+
+	if (unlikely(fd < 0))
+		return NULL;
+
+	io = l_new(struct l_io, 1);
+
+	io->fd = fd;
+	io->events = EPOLLHUP | EPOLLERR;
+	io->close_on_destroy = false;
+
+	err = watch_add(io->fd, io->events, io_callback, io, io_cleanup);
+	if (err) {
+		l_free(io);
+		return NULL;
+	}
+
+	return io;
+}
+
+/**
+ * l_io_destroy:
+ * @io: IO object
+ *
+ * Free IO object and close file descriptor (if enabled).
+ **/
+LIB_EXPORT void l_io_destroy(struct l_io *io)
+{
+	if (unlikely(!io))
+		return;
+
+	if (io->fd != -1)
+		watch_remove(io->fd, !io->close_on_destroy);
+
+	io_closed(io);
+
+	if (io->debug_destroy)
+		io->debug_destroy(io->debug_data);
+
+	l_free(io);
+}
+
+/**
+ * l_io_get_fd:
+ * @io: IO object
+ *
+ * Returns: file descriptor associated with @io
+ **/
+LIB_EXPORT int l_io_get_fd(struct l_io *io)
+{
+	if (unlikely(!io))
+		return -1;
+
+	return io->fd;
+}
+
+/**
+ * l_io_set_close_on_destroy:
+ * @io: IO object
+ * @do_close: setting for destroy handling
+ *
+ * Set the automatic closing of the file descriptor when destroying @io.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_io_set_close_on_destroy(struct l_io *io, bool do_close)
+{
+	if (unlikely(!io))
+		return false;
+
+	io->close_on_destroy = do_close;
+
+	return true;
+}
+
+/**
+ * l_io_set_read_handler:
+ * @io: IO object
+ * @callback: read handler callback function
+ * @user_data: user data provided to read handler callback function
+ * @destroy: destroy function for user data
+ *
+ * Set read function.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_io_set_read_handler(struct l_io *io, l_io_read_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy)
+{
+	uint32_t events;
+	int err;
+
+	if (unlikely(!io || io->fd < 0))
+		return false;
+
+	l_util_debug(io->debug_handler, io->debug_data,
+					"set read handler <%p>", io);
+
+	if (io->read_destroy)
+		io->read_destroy(io->read_data);
+
+	if (callback)
+		events = io->events | EPOLLIN;
+	else
+		events = io->events & ~EPOLLIN;
+
+	io->read_handler = callback;
+	io->read_destroy = destroy;
+	io->read_data = user_data;
+
+	if (events == io->events)
+		return true;
+
+	err = watch_modify(io->fd, events, false);
+	if (err)
+		return false;
+
+	io->events = events;
+
+	return true;
+}
+
+/**
+ * l_io_set_write_handler:
+ * @io: IO object
+ * @callback: write handler callback function
+ * @user_data: user data provided to write handler callback function
+ * @destroy: destroy function for user data
+ *
+ * Set write function.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_io_set_write_handler(struct l_io *io, l_io_write_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy)
+{
+	uint32_t events;
+	int err;
+
+	if (unlikely(!io || io->fd < 0))
+		return false;
+
+	l_util_debug(io->debug_handler, io->debug_data,
+					"set write handler <%p>", io);
+
+	if (io->write_handler == callback && io->write_destroy == destroy &&
+						io->write_data == user_data)
+		return true;
+
+	if (io->write_destroy)
+		io->write_destroy(io->write_data);
+
+	if (callback)
+		events = io->events | EPOLLOUT;
+	else
+		events = io->events & ~EPOLLOUT;
+
+	io->write_handler = callback;
+	io->write_destroy = destroy;
+	io->write_data = user_data;
+
+	if (events == io->events)
+		return true;
+
+	err = watch_modify(io->fd, events, false);
+	if (err)
+		return false;
+
+	io->events = events;
+
+	return true;
+}
+
+/**
+ * l_io_set_disconnect_handler:
+ * @io: IO object
+ * @callback: disconnect handler callback function
+ * @user_data: user data provided to disconnect handler callback function
+ * @destroy: destroy function for user data
+ *
+ * Set disconnect function.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_io_set_disconnect_handler(struct l_io *io,
+				l_io_disconnect_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy)
+{
+	if (unlikely(!io || io->fd < 0))
+		return false;
+
+	l_util_debug(io->debug_handler, io->debug_data,
+					"set disconnect handler <%p>", io);
+
+	if (io->disconnect_destroy)
+		io->disconnect_destroy(io->disconnect_data);
+
+	io->disconnect_handler = callback;
+	io->disconnect_destroy = destroy;
+	io->disconnect_data = user_data;
+
+	return true;
+}
+
+/**
+ * l_io_set_debug:
+ * @io: IO object
+ * @callback: debug callback function
+ * @user_data: user data provided to debug callback function
+ * @destroy: destroy function for user data
+ *
+ * Set debug function.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_io_set_debug(struct l_io *io, l_io_debug_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy)
+{
+	if (unlikely(!io))
+		return false;
+
+	if (io->debug_destroy)
+		io->debug_destroy(io->debug_data);
+
+	io->debug_handler = callback;
+	io->debug_destroy = destroy;
+	io->debug_data = user_data;
+
+	return true;
+}
diff --git a/ell/io.h b/ell/io.h
new file mode 100644
index 0000000..a2a1dad
--- /dev/null
+++ b/ell/io.h
@@ -0,0 +1,47 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_IO_H
+#define __ELL_IO_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_io;
+
+typedef void (*l_io_debug_cb_t) (const char *str, void *user_data);
+
+typedef bool (*l_io_read_cb_t) (struct l_io *io, void *user_data);
+typedef bool (*l_io_write_cb_t) (struct l_io *io, void *user_data);
+typedef void (*l_io_disconnect_cb_t) (struct l_io *io, void *user_data);
+typedef void (*l_io_destroy_cb_t) (void *user_data);
+
+struct l_io *l_io_new(int fd);
+void l_io_destroy(struct l_io *io);
+
+int l_io_get_fd(struct l_io *io);
+bool l_io_set_close_on_destroy(struct l_io *io, bool do_close);
+
+bool l_io_set_read_handler(struct l_io *io, l_io_read_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy);
+bool l_io_set_write_handler(struct l_io *io, l_io_write_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy);
+bool l_io_set_disconnect_handler(struct l_io *io,
+				l_io_disconnect_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy);
+
+bool l_io_set_debug(struct l_io *io, l_io_debug_cb_t callback,
+				void *user_data, l_io_destroy_cb_t destroy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_IO_H */
diff --git a/ell/key.c b/ell/key.c
new file mode 100644
index 0000000..325fa09
--- /dev/null
+++ b/ell/key.c
@@ -0,0 +1,799 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2016  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/syscall.h>
+#include <linux/keyctl.h>
+#include <errno.h>
+
+#include "private.h"
+#include "useful.h"
+#include "key.h"
+#include "string.h"
+#include "random.h"
+#include "missing.h"
+
+#ifndef KEYCTL_DH_COMPUTE
+#define KEYCTL_DH_COMPUTE 23
+#endif
+
+#ifndef KEYCTL_PKEY_QUERY
+#define KEYCTL_PKEY_QUERY	24
+#define KEYCTL_PKEY_ENCRYPT	25
+#define KEYCTL_PKEY_DECRYPT	26
+#define KEYCTL_PKEY_SIGN	27
+#define KEYCTL_PKEY_VERIFY	28
+
+#define KEYCTL_SUPPORTS_ENCRYPT	0x01
+#define KEYCTL_SUPPORTS_DECRYPT	0x02
+#define KEYCTL_SUPPORTS_SIGN	0x04
+#define KEYCTL_SUPPORTS_VERIFY	0x08
+
+struct keyctl_pkey_query {
+	uint32_t supported_ops;
+	uint32_t key_size;
+	uint16_t max_data_size;
+	uint16_t max_sig_size;
+	uint16_t max_enc_size;
+	uint16_t max_dec_size;
+
+	uint32_t __spare[10];
+};
+
+struct keyctl_pkey_params {
+	int32_t key_id;
+	uint32_t in_len;
+	union {
+		uint32_t out_len;
+		uint32_t in2_len;
+	};
+	uint32_t __spare[7];
+};
+
+/* Work around the missing (pre-4.7) or broken (4.14.{70,71,72} and
+ * 4.18.{8,9,10}) kernel declaration of struct keyctl_dh_params
+ */
+struct dh_params {
+	int32_t private;
+	int32_t prime;
+	int32_t base;
+};
+#else
+/* When KEYCTL_PKEY_QUERY is defined by the kernel, the
+ * struct keyctl_dh_params declaration is valid.
+ */
+#define dh_params keyctl_dh_params
+#endif
+
+#ifndef KEYCTL_RESTRICT_KEYRING
+#define KEYCTL_RESTRICT_KEYRING 29
+#endif
+
+static int32_t internal_keyring;
+
+struct l_key {
+	int type;
+	int32_t serial;
+};
+
+struct l_keyring {
+	int32_t serial;
+};
+
+static const char * const key_type_names[] = {
+	[L_KEY_RAW] = "user",
+	[L_KEY_RSA] = "asymmetric",
+	[L_KEY_ECC] = "asymmetric",
+};
+
+static long kernel_add_key(const char *type, const char *description,
+				const void *payload, size_t len, int32_t keyring)
+{
+	long result;
+
+	result = syscall(__NR_add_key, type, description, payload, len,
+				keyring);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_read_key(int32_t serial, const void *payload, size_t len)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_READ, serial, payload, len);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_update_key(int32_t serial, const void *payload, size_t len)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_UPDATE, serial, payload, len);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_invalidate_key(int32_t serial)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_INVALIDATE, serial);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_link_key(int32_t key_serial, int32_t ring_serial)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_LINK, key_serial, ring_serial);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_unlink_key(int32_t key_serial, int32_t ring_serial)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_UNLINK, key_serial, ring_serial);
+
+	return result >= 0 ? result : -errno;
+}
+
+static char *format_key_info(const char *encoding, const char *hash)
+{
+	struct l_string *info;
+
+	if (!encoding && !hash)
+		return NULL;
+
+	info = l_string_new(0);
+
+	if (encoding)
+		l_string_append_printf(info, "enc=%s ", encoding);
+
+	if (hash)
+		l_string_append_printf(info, "hash=%s", hash);
+
+	return l_string_unwrap(info);
+}
+
+static long kernel_query_key(int32_t key_serial, const char *encoding,
+				const char *hash, size_t *size, bool *public)
+{
+	long result;
+	struct keyctl_pkey_query query;
+	char *info = format_key_info(encoding, hash);
+
+	memset(&query, 0, sizeof(query));
+
+	result = syscall(__NR_keyctl, KEYCTL_PKEY_QUERY, key_serial, 0,
+				info ?: "", &query);
+	if (result == 0) {
+		*size = query.key_size;
+		*public = ((query.supported_ops & KEYCTL_SUPPORTS_ENCRYPT) &&
+			!(query.supported_ops & KEYCTL_SUPPORTS_DECRYPT));
+	}
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
+			      void *payload, size_t len)
+{
+	long result;
+
+	struct dh_params params = { .private = private,
+				    .prime = prime,
+				    .base = base };
+
+	result = syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, &params, payload, len,
+			NULL);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_restrict_keyring(int32_t serial, const char *keytype,
+					const char *restriction)
+{
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_RESTRICT_KEYRING, serial, keytype,
+				restriction);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_key_eds(int op, int32_t serial, const char *encoding,
+				const char *hash, const void *in, void *out,
+				size_t len_in, size_t len_out)
+{
+	long result;
+	struct keyctl_pkey_params params = { .key_id = serial,
+					     .in_len = len_in,
+					     .out_len = len_out };
+	char *info = format_key_info(encoding, hash);
+
+	memset(out, 0, len_out);
+
+	result = syscall(__NR_keyctl, op, &params, info ?: "", in, out);
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_key_verify(int32_t serial,
+				const char *encoding, const char *hash,
+				const void *data, size_t data_len,
+				const void *sig, size_t sig_len)
+{
+	struct keyctl_pkey_params params = {
+		.key_id		= serial,
+		.in_len		= data_len,
+		.in2_len	= sig_len,
+	};
+	char *info = format_key_info(encoding, hash);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_PKEY_VERIFY, &params,
+				info ?: "", data, sig);
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
+static bool setup_internal_keyring(void)
+{
+	internal_keyring = kernel_add_key("keyring", "ell-internal", NULL, 0,
+						KEY_SPEC_THREAD_KEYRING);
+
+	if (internal_keyring <= 0) {
+		internal_keyring = 0;
+		return false;
+	}
+
+	return true;
+}
+
+LIB_EXPORT struct l_key *l_key_new(enum l_key_type type, const void *payload,
+					size_t payload_length)
+{
+	struct l_key *key;
+	char *description;
+	static unsigned long key_idx;
+
+	if (unlikely(!payload))
+		return NULL;
+
+	if (unlikely((size_t)type >= L_ARRAY_SIZE(key_type_names)))
+		return NULL;
+
+	if (!internal_keyring && !setup_internal_keyring())
+		return NULL;
+
+	key = l_new(struct l_key, 1);
+	key->type = type;
+	description = l_strdup_printf("ell-key-%lu", key_idx++);
+	key->serial = kernel_add_key(key_type_names[type], description, payload,
+					payload_length, internal_keyring);
+	l_free(description);
+
+	if (key->serial < 0) {
+		l_free(key);
+		key = NULL;
+	}
+
+	/*
+	 * TODO: Query asymmetric key algorithm from the kernel and
+	 * ensure that it matches the expected l_key_type. This can
+	 * currently be found by digging through /proc/keys, but a
+	 * keyctl() op makes more sense.
+	 */
+
+	return key;
+}
+
+LIB_EXPORT void l_key_free(struct l_key *key)
+{
+	if (unlikely(!key))
+		return;
+
+	/*
+	 * Use invalidate as, unlike revoke, this doesn't delay the
+	 * key garbage collection and causes the quota used by the
+	 * key to be released sooner and more predictably.
+	 */
+	kernel_invalidate_key(key->serial);
+
+	l_free(key);
+}
+
+LIB_EXPORT void l_key_free_norevoke(struct l_key *key)
+{
+	if (unlikely(!key))
+		return;
+
+	kernel_unlink_key(key->serial, internal_keyring);
+
+	l_free(key);
+}
+
+LIB_EXPORT bool l_key_update(struct l_key *key, const void *payload, size_t len)
+{
+	long error;
+
+	if (unlikely(!key))
+		return false;
+
+	error = kernel_update_key(key->serial, payload, len);
+
+	return error == 0;
+}
+
+LIB_EXPORT bool l_key_extract(struct l_key *key, void *payload, size_t *len)
+{
+	long keylen;
+
+	if (unlikely(!key))
+		return false;
+
+	keylen = kernel_read_key(key->serial, payload, *len);
+
+	if (keylen < 0 || (size_t)keylen > *len) {
+		explicit_bzero(payload, *len);
+		return false;
+	}
+
+	*len = keylen;
+	return true;
+}
+
+LIB_EXPORT ssize_t l_key_get_payload_size(struct l_key *key)
+{
+	return kernel_read_key(key->serial, NULL, 0);
+}
+
+static const char *lookup_cipher(enum l_key_cipher_type cipher)
+{
+	switch (cipher) {
+	case L_KEY_RSA_PKCS1_V1_5:
+		return "pkcs1";
+	case L_KEY_RSA_RAW:
+		return "raw";
+	case L_KEY_ECDSA_X962:
+		return "x962";
+	}
+
+	return NULL;
+}
+
+static const char *lookup_checksum(enum l_checksum_type checksum)
+{
+	const char* ret = NULL;
+
+	switch (checksum) {
+	case L_CHECKSUM_NONE:
+		break;
+	case L_CHECKSUM_MD4:
+		ret = "md4";
+		break;
+	case L_CHECKSUM_MD5:
+		ret = "md5";
+		break;
+	case L_CHECKSUM_SHA1:
+		ret = "sha1";
+		break;
+	case L_CHECKSUM_SHA224:
+		ret = "sha224";
+		break;
+	case L_CHECKSUM_SHA256:
+		ret = "sha256";
+		break;
+	case L_CHECKSUM_SHA384:
+		ret = "sha384";
+		break;
+	case L_CHECKSUM_SHA512:
+		ret = "sha512";
+		break;
+	}
+
+	return ret;
+}
+
+LIB_EXPORT bool l_key_get_info(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, size_t *bits,
+			bool *public)
+{
+	if (unlikely(!key))
+		return false;
+
+	return !kernel_query_key(key->serial, lookup_cipher(cipher),
+					lookup_checksum(checksum), bits,
+					public);
+}
+
+LIB_EXPORT struct l_key *l_key_generate_dh_private(const void *prime_buf,
+							size_t prime_len)
+{
+	uint8_t *buf;
+	const uint8_t *prime = prime_buf;
+	size_t prime_bits;
+	unsigned int i;
+	size_t private_bytes;
+	size_t random_bytes;
+	struct l_key *private;
+
+	/* Find the prime's bit length excluding leading 0s */
+
+	for (i = 0; i < prime_len && !prime[i]; i++);
+
+	if (i == prime_len || (i == prime_len - 1 && prime[i] < 5))
+		return NULL;
+
+	prime_bits = (prime_len - i) * 8 - __builtin_clz(prime[i]);
+
+	/*
+	 * Generate a random DH private value conforming to 1 < x < p - 1.
+	 * To do this covering all possible values in this range with the
+	 * same probability of generating each value generally requires
+	 * looping.  Instead we generate a value in the range
+	 * [2 ^ (prime_bits - 2), 2 ^ (prime_bits - 1) - 1] by forcing bit
+	 * prime_bits - 2 to 1, i.e. the range in PKCS #3 Section 7.1 for
+	 * l equal to prime_bits - 1.  This means we're using between
+	 * one half and one quarter of the full [2, p - 2] range, i.e.
+	 * between 1 and 2 bits fewer.  Note that since p is odd
+	 * p - 1 has the same bit length as p and so our maximum value
+	 * 2 ^ (prime_bits - 1) - 1 is still less than p - 1.
+	 */
+	private_bytes = ((prime_bits - 1) + 7) / 8;
+	random_bytes = ((prime_bits - 2) + 7) / 8;
+	buf = l_malloc(private_bytes);
+	l_getrandom(buf + private_bytes - random_bytes, random_bytes);
+
+	buf[0] &= (1 << ((prime_bits - 2) % 8)) - 1;
+	buf[0] |= 1 << ((prime_bits - 2) % 8);
+
+	private = l_key_new(L_KEY_RAW, buf, private_bytes);
+	explicit_bzero(buf, private_bytes);
+	l_free(buf);
+	return private;
+}
+
+static bool compute_common(struct l_key *base, struct l_key *private,
+				struct l_key *prime, void *payload, size_t *len)
+{
+	long result_len;
+	bool usable_payload = *len != 0;
+
+	result_len = kernel_dh_compute(private->serial, prime->serial,
+					base->serial, payload, *len);
+
+	if (result_len > 0) {
+		*len = result_len;
+		return usable_payload;
+	}
+	return false;
+}
+
+LIB_EXPORT bool l_key_compute_dh_public(struct l_key *generator,
+					struct l_key *private,
+					struct l_key *prime,
+					void *payload, size_t *len)
+{
+	return compute_common(generator, private, prime, payload, len);
+}
+
+LIB_EXPORT bool l_key_compute_dh_secret(struct l_key *other_public,
+					struct l_key *private,
+					struct l_key *prime,
+					void *payload, size_t *len)
+{
+	return compute_common(other_public, private, prime, payload, len);
+}
+
+static int be_bignum_compare(const uint8_t *a, size_t a_len,
+				const uint8_t *b, size_t b_len)
+{
+	unsigned int i;
+
+	if (a_len >= b_len) {
+		for (i = 0; i < a_len - b_len; i++)
+			if (a[i])
+				return 1;
+
+		return memcmp(a + i, b, b_len);
+	}
+
+	for (i = 0; i < b_len - a_len; i++)
+		if (b[i])
+			return -1;
+
+	return memcmp(a, b + i, a_len);
+}
+
+/*
+ * Validate that @payload is within range for a private and public key for
+ * a DH computation in the finite field group defined by modulus @prime_buf,
+ * both numbers stored as big-endian integers.  We require a key in the
+ * [2, prime - 2] (inclusive) interval.  PKCS #3 does not exclude 1 as a
+ * private key but other specs do.
+ */
+LIB_EXPORT bool l_key_validate_dh_payload(const void *payload, size_t len,
+				const void *prime_buf, size_t prime_len)
+{
+	static const uint8_t one[] = { 1 };
+	uint8_t prime_1[prime_len];
+
+	/*
+	 * Produce prime - 1 for the payload < prime - 1 check.
+	 * prime is odd so just zero the LSB.
+	 */
+	memcpy(prime_1, prime_buf, prime_len);
+
+	if (prime_len < 1 || !(prime_1[prime_len - 1] & 1))
+		return false;
+
+	prime_1[prime_len - 1] &= ~1;
+
+	if (be_bignum_compare(payload, len, one, 1) <= 0)
+		return false;
+
+	if (be_bignum_compare(payload, len, prime_1, prime_len) >= 0)
+		return false;
+
+	return true;
+}
+
+/* Common code for encrypt/decrypt/sign */
+static ssize_t eds_common(struct l_key *key,
+				enum l_key_cipher_type cipher,
+				enum l_checksum_type checksum, const void *in,
+				void *out, size_t len_in, size_t len_out,
+				int op)
+{
+	if (unlikely(!key))
+		return -EINVAL;
+
+	return kernel_key_eds(op, key->serial, lookup_cipher(cipher),
+				lookup_checksum(checksum), in, out, len_in,
+				len_out);
+}
+
+LIB_EXPORT ssize_t l_key_encrypt(struct l_key *key,
+					enum l_key_cipher_type cipher,
+					enum l_checksum_type checksum,
+					const void *in, void *out,
+					size_t len_in, size_t len_out)
+{
+	ssize_t ret_len;
+
+	ret_len = eds_common(key, cipher, checksum, in, out,
+				len_in, len_out,
+				KEYCTL_PKEY_ENCRYPT);
+
+	return ret_len;
+}
+
+LIB_EXPORT ssize_t l_key_decrypt(struct l_key *key,
+					enum l_key_cipher_type cipher,
+					enum l_checksum_type checksum,
+					const void *in, void *out,
+					size_t len_in, size_t len_out)
+{
+	ssize_t ret_len;
+
+	ret_len = eds_common(key, cipher, checksum, in, out, len_in,
+				len_out, KEYCTL_PKEY_DECRYPT);
+
+	if (ret_len < 0)
+		goto done;
+
+done:
+	return ret_len;
+}
+
+LIB_EXPORT ssize_t l_key_sign(struct l_key *key,
+				enum l_key_cipher_type cipher,
+				enum l_checksum_type checksum, const void *in,
+				void *out, size_t len_in, size_t len_out)
+{
+	ssize_t ret_len;
+
+	ret_len = eds_common(key, cipher, checksum, in, out,
+				len_in, len_out,
+				KEYCTL_PKEY_SIGN);
+
+	return ret_len;
+}
+
+LIB_EXPORT bool l_key_verify(struct l_key *key,
+				enum l_key_cipher_type cipher,
+				enum l_checksum_type checksum, const void *data,
+				const void *sig, size_t len_data,
+				size_t len_sig)
+{
+	long result;
+
+	if (unlikely(!key))
+		return false;
+
+	result = kernel_key_verify(key->serial, lookup_cipher(cipher),
+					lookup_checksum(checksum),
+					data, len_data,
+					sig, len_sig);
+
+	return result >= 0;
+}
+
+LIB_EXPORT struct l_keyring *l_keyring_new(void)
+{
+	struct l_keyring *keyring;
+	char *description;
+	static unsigned long keyring_idx;
+
+	if (!internal_keyring && !setup_internal_keyring())
+		return NULL;
+
+	keyring = l_new(struct l_keyring, 1);
+	description = l_strdup_printf("ell-keyring-%lu", keyring_idx++);
+	keyring->serial = kernel_add_key("keyring", description, NULL, 0,
+						internal_keyring);
+	l_free(description);
+
+	if (keyring->serial < 0) {
+		l_free(keyring);
+		return NULL;
+	}
+
+	return keyring;
+}
+
+LIB_EXPORT bool l_keyring_restrict(struct l_keyring *keyring,
+					enum l_keyring_restriction res,
+					const struct l_keyring *trusted)
+{
+	char *restriction = NULL;
+	long result;
+
+	switch (res) {
+	case L_KEYRING_RESTRICT_ASYM:
+	case L_KEYRING_RESTRICT_ASYM_CHAIN:
+	{
+		char *option = "";
+
+		if (res == L_KEYRING_RESTRICT_ASYM_CHAIN)
+			option = ":chain";
+
+		restriction = l_strdup_printf("key_or_keyring:%d%s",
+						trusted ? trusted->serial : 0,
+						option);
+
+		break;
+	}
+	default:
+		/* Unsupported type */
+		return NULL;
+	}
+
+	result = kernel_restrict_keyring(keyring->serial, "asymmetric",
+						restriction);
+
+	l_free(restriction);
+
+	return result == 0;
+}
+
+LIB_EXPORT void l_keyring_free(struct l_keyring *keyring)
+{
+	if (unlikely(!keyring))
+		return;
+
+	kernel_invalidate_key(keyring->serial);
+
+	l_free(keyring);
+}
+
+LIB_EXPORT void l_keyring_free_norevoke(struct l_keyring *keyring)
+{
+	if (unlikely(!keyring))
+		return;
+
+	kernel_unlink_key(keyring->serial, internal_keyring);
+
+	l_free(keyring);
+}
+
+LIB_EXPORT bool l_keyring_link(struct l_keyring *keyring,
+							const struct l_key *key)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!key))
+		return false;
+
+	error = kernel_link_key(key->serial, keyring->serial);
+
+	return error == 0;
+}
+
+LIB_EXPORT bool l_keyring_unlink(struct l_keyring *keyring,
+							const struct l_key *key)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!key))
+		return false;
+
+	error = kernel_unlink_key(key->serial, keyring->serial);
+
+	return error == 0;
+}
+
+LIB_EXPORT bool l_keyring_link_nested(struct l_keyring *keyring,
+						const struct l_keyring *nested)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!nested))
+		return false;
+
+	error = kernel_link_key(nested->serial, keyring->serial);
+
+	return error == 0;
+}
+
+LIB_EXPORT bool l_keyring_unlink_nested(struct l_keyring *keyring,
+						const struct l_keyring *nested)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!nested))
+		return false;
+
+	error = kernel_unlink_key(nested->serial, keyring->serial);
+
+	return error == 0;
+}
+
+LIB_EXPORT bool l_key_is_supported(uint32_t features)
+{
+	long result;
+
+	if (features & L_KEY_FEATURE_DH) {
+		result = syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, NULL, "x", 1,
+					NULL);
+
+		if (result == -1 && errno == EOPNOTSUPP)
+			return false;
+	}
+
+	if (features & L_KEY_FEATURE_RESTRICT) {
+		result = syscall(__NR_keyctl, KEYCTL_RESTRICT_KEYRING, 0,
+					"asymmetric", "");
+
+		if (result == -1 && errno == EOPNOTSUPP)
+			return false;
+	}
+
+	if (features & L_KEY_FEATURE_CRYPTO) {
+		result = syscall(__NR_keyctl, KEYCTL_PKEY_QUERY, 0, 0, "", 0);
+
+		if (result == -1 && errno == EOPNOTSUPP)
+			return false;
+	}
+
+	return true;
+}
diff --git a/ell/key.h b/ell/key.h
new file mode 100644
index 0000000..657b863
--- /dev/null
+++ b/ell/key.h
@@ -0,0 +1,118 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2016  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_KEY_H
+#define __ELL_KEY_H
+
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <ell/cleanup.h>
+#include <ell/checksum.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_key;
+struct l_keyring;
+
+enum l_key_feature {
+	L_KEY_FEATURE_DH	= 1 << 0,
+	L_KEY_FEATURE_RESTRICT	= 1 << 1,
+	L_KEY_FEATURE_CRYPTO	= 1 << 2,
+};
+
+enum l_key_type {
+	L_KEY_RAW = 0,
+	L_KEY_RSA,
+	L_KEY_ECC,
+};
+
+enum l_keyring_restriction {
+	L_KEYRING_RESTRICT_ASYM = 0,
+	L_KEYRING_RESTRICT_ASYM_CHAIN,
+};
+
+enum l_key_cipher_type {
+	L_KEY_RSA_PKCS1_V1_5,
+	L_KEY_RSA_RAW,
+	L_KEY_ECDSA_X962,
+};
+
+struct l_key *l_key_new(enum l_key_type type, const void *payload,
+			size_t payload_length);
+
+void l_key_free(struct l_key *key);
+void l_key_free_norevoke(struct l_key *key);
+
+bool l_key_update(struct l_key *key, const void *payload, size_t len);
+
+bool l_key_extract(struct l_key *key, void *payload, size_t *len);
+
+ssize_t l_key_get_payload_size(struct l_key *key);
+
+bool l_key_get_info(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, size_t *bits,
+			bool *out_public);
+
+struct l_key *l_key_generate_dh_private(const void *prime_buf,
+					size_t prime_len);
+
+bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private_key,
+				struct l_key *prime,
+				void *payload, size_t *len);
+
+bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private_key,
+				struct l_key *prime,
+				void *payload, size_t *len);
+
+bool l_key_validate_dh_payload(const void *payload, size_t len,
+				const void *prime_buf, size_t prime_len);
+
+ssize_t l_key_encrypt(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+ssize_t l_key_decrypt(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+ssize_t l_key_sign(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+bool l_key_verify(struct l_key *key, enum l_key_cipher_type cipher,
+			enum l_checksum_type checksum, const void *data,
+			const void *sig, size_t len_data, size_t len_sig);
+
+struct l_keyring *l_keyring_new(void);
+
+bool l_keyring_restrict(struct l_keyring *keyring, enum l_keyring_restriction res,
+			const struct l_keyring *trust);
+
+void l_keyring_free(struct l_keyring *keyring);
+DEFINE_CLEANUP_FUNC(l_keyring_free);
+void l_keyring_free_norevoke(struct l_keyring *keyring);
+DEFINE_CLEANUP_FUNC(l_keyring_free_norevoke);
+
+bool l_keyring_link(struct l_keyring *keyring, const struct l_key *key);
+
+bool l_keyring_unlink(struct l_keyring *keyring, const struct l_key *key);
+
+bool l_keyring_link_nested(struct l_keyring *keyring,
+				const struct l_keyring *nested);
+bool l_keyring_unlink_nested(struct l_keyring *keyring,
+				const struct l_keyring *nested);
+
+bool l_key_is_supported(uint32_t features);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_KEY_H */
diff --git a/ell/log.c b/ell/log.c
new file mode 100644
index 0000000..a8c2617
--- /dev/null
+++ b/ell/log.c
@@ -0,0 +1,442 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "queue.h"
+#include "log.h"
+#include "private.h"
+
+struct debug_section {
+	struct l_debug_desc *start;
+	struct l_debug_desc *end;
+};
+
+struct l_queue *debug_sections;
+
+/**
+ * SECTION:log
+ * @short_description: Logging framework
+ *
+ * Logging framework
+ */
+
+/**
+ * l_debug_desc:
+ *
+ * Debug descriptor.
+ */
+
+static void log_null(int priority, const char *file, const char *line,
+			const char *func, const char *format, va_list ap)
+{
+}
+
+static l_log_func_t log_func = log_null;
+static const char *log_ident = "";
+static int log_fd = -1;
+static unsigned long log_pid;
+
+static inline void close_log(void)
+{
+	if (log_fd > 0) {
+		close(log_fd);
+		log_fd = -1;
+	}
+}
+
+static int open_log(const char *path)
+{
+	struct sockaddr_un addr;
+
+	log_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+	if (log_fd < 0)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
+
+	if (connect(log_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		close_log();
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * l_log_set_ident:
+ * @ident: string identifier
+ *
+ * Sets the log identifier string.
+ **/
+LIB_EXPORT void l_log_set_ident(const char *ident)
+{
+	log_ident = ident;
+}
+
+/**
+ * l_log_set_handler:
+ * @function: log handler function
+ *
+ * Sets the log handler function.
+ **/
+LIB_EXPORT void l_log_set_handler(l_log_func_t function)
+{
+	L_DEBUG_SYMBOL(__debug_intern, "");
+
+	close_log();
+
+	if (!function) {
+		log_func = log_null;
+		return;
+	}
+
+	log_func = function;
+}
+
+/**
+ * l_log_set_null:
+ *
+ * Disable logging.
+ **/
+LIB_EXPORT void l_log_set_null(void)
+{
+	close_log();
+
+	log_func = log_null;
+}
+
+__attribute__((format(printf, 5, 0)))
+static void log_stderr(int priority, const char *file, const char *line,
+			const char *func, const char *format, va_list ap)
+{
+	vfprintf(stderr, format, ap);
+}
+
+/**
+ * l_log_set_stderr:
+ *
+ * Enable logging to stderr.
+ **/
+LIB_EXPORT void l_log_set_stderr(void)
+{
+	close_log();
+
+	log_func = log_stderr;
+}
+
+__attribute__((format(printf, 5, 0)))
+static void log_syslog(int priority, const char *file, const char *line,
+			const char *func, const char *format, va_list ap)
+{
+	struct msghdr msg;
+	struct iovec iov[2];
+	char hdr[64], *str;
+	int hdr_len, str_len;
+
+	str_len = vasprintf(&str, format, ap);
+	if (str_len < 0)
+		return;
+
+	hdr_len = snprintf(hdr, sizeof(hdr), "<%i>%s[%lu]: ", priority,
+					log_ident, (unsigned long) log_pid);
+
+	iov[0].iov_base = hdr;
+	iov[0].iov_len  = hdr_len;
+	iov[1].iov_base = str;
+	iov[1].iov_len  = str_len;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 2;
+
+	sendmsg(log_fd, &msg, 0);
+
+	free(str);
+}
+
+/**
+ * l_log_set_syslog:
+ *
+ * Enable logging to syslog.
+ **/
+LIB_EXPORT void l_log_set_syslog(void)
+{
+	close_log();
+
+	if (open_log("/dev/log") < 0) {
+		log_func = log_null;
+		return;
+	}
+
+	log_pid = getpid();
+
+	log_func = log_syslog;
+}
+
+__attribute__((format(printf, 5, 0)))
+static void log_journal(int priority, const char *file, const char *line,
+			const char *func, const char *format, va_list ap)
+{
+	struct msghdr msg;
+	struct iovec iov[12];
+	char prio[16], *str;
+	int prio_len, str_len;
+
+	str_len = vasprintf(&str, format, ap);
+	if (str_len < 0)
+		return;
+
+	prio_len = snprintf(prio, sizeof(prio), "PRIORITY=%u\n", priority);
+
+	iov[0].iov_base = "MESSAGE=";
+	iov[0].iov_len  = 8;
+	iov[1].iov_base = str;
+	iov[1].iov_len  = str_len;
+	iov[2].iov_base = prio;
+	iov[2].iov_len  = prio_len;
+	iov[3].iov_base = "CODE_FILE=";
+	iov[3].iov_len  = 10;
+	iov[4].iov_base = (char *) file;
+	iov[4].iov_len  = strlen(file);
+	iov[5].iov_base = "\n";
+	iov[5].iov_len  = 1;
+	iov[6].iov_base = "CODE_LINE=";
+	iov[6].iov_len  = 10;
+	iov[7].iov_base = (char *) line;
+	iov[7].iov_len  = strlen(line);
+	iov[8].iov_base = "\n";
+	iov[8].iov_len  = 1;
+	iov[9].iov_base = "CODE_FUNC=";
+	iov[9].iov_len  = 10;
+	iov[10].iov_base = (char *) func;
+	iov[10].iov_len  = strlen(func);
+	iov[11].iov_base = "\n";
+	iov[11].iov_len  = 1;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 12;
+
+	sendmsg(log_fd, &msg, 0);
+
+	free(str);
+}
+
+/**
+ * l_log_set_journal:
+ *
+ * Enable logging to journal.
+ **/
+LIB_EXPORT void l_log_set_journal(void)
+{
+	close_log();
+
+	if (open_log("/run/systemd/journal/socket") < 0) {
+		log_func = log_null;
+		return;
+	}
+
+	log_pid = getpid();
+
+	log_func = log_journal;
+}
+
+/**
+ * l_log_with_location:
+ * @priority: priority level
+ * @file: source file
+ * @line: source line
+ * @func: source function
+ * @format: format string
+ * @...: format arguments
+ *
+ * Log information.
+ **/
+LIB_EXPORT void l_log_with_location(int priority,
+				const char *file, const char *line,
+				const char *func, const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	log_func(priority, file, line, func, format, ap);
+	va_end(ap);
+}
+
+/**
+ * l_error:
+ * @format: format string
+ * @...: format arguments
+ *
+ **/
+
+/**
+ * l_warn:
+ * @format: format string
+ * @...: format arguments
+ *
+ **/
+
+/**
+ * l_info:
+ * @format: format string
+ * @...: format arguments
+ *
+ **/
+
+/**
+ * l_debug:
+ * @format: format string
+ * @...: format arguments
+ **/
+
+static const char *debug_pattern;
+
+static void debug_enable(struct l_debug_desc *start, struct l_debug_desc *stop)
+{
+	struct l_debug_desc *desc;
+	char *pattern_copy;
+
+	if (!debug_pattern)
+		return;
+
+	pattern_copy = strdupa(debug_pattern);
+
+	while (pattern_copy) {
+		char *str = strsep(&pattern_copy, ":,");
+		if (!str)
+			break;
+
+		for (desc = start; desc < stop; desc++) {
+			if (!fnmatch(str, desc->file, 0))
+				desc->flags |= L_DEBUG_FLAG_PRINT;
+			if (!fnmatch(str, desc->func, 0))
+				desc->flags |= L_DEBUG_FLAG_PRINT;
+		}
+	}
+}
+
+static void debug_disable(struct l_debug_desc *start, struct l_debug_desc *stop)
+{
+	struct l_debug_desc *desc;
+
+	for (desc = start; desc < stop; desc++)
+		desc->flags &= ~L_DEBUG_FLAG_PRINT;
+}
+
+/**
+ * l_debug_add_section:
+ * @start: start of the debug section
+ * @stop: stop of the debug section
+ *
+ * Add information about a debug section.  This is used by shared libraries
+ * to tell ell about their debug section start & stopping points.  This is used
+ * to make l_debug statements work across all shared libraries that might be
+ * linked into the executable
+ */
+LIB_EXPORT void l_debug_add_section(struct l_debug_desc *start,
+					struct l_debug_desc *end)
+{
+	const struct l_queue_entry *entry;
+	struct debug_section *new_section;
+
+	if (!debug_sections) {
+		debug_sections = l_queue_new();
+		goto add;
+	}
+
+	for (entry = l_queue_get_entries(debug_sections); entry;
+					entry = entry->next) {
+		const struct debug_section *section = entry->data;
+
+		if (section->start == start && section->end == end)
+			return;
+	}
+
+add:
+	new_section = l_new(struct debug_section, 1);
+	new_section->start = start;
+	new_section->end = end;
+
+	l_queue_push_head(debug_sections, new_section);
+}
+
+/**
+ * l_debug_enable_full:
+ * @pattern: debug pattern
+ * @start: start of the debug section
+ * @stop: end of the debug section
+ *
+ * Enable debug sections based on @pattern.
+ **/
+LIB_EXPORT void l_debug_enable_full(const char *pattern,
+					struct l_debug_desc *start,
+					struct l_debug_desc *end)
+{
+	const struct l_queue_entry *entry;
+
+	if (!pattern)
+		return;
+
+	debug_pattern = pattern;
+
+	l_debug_add_section(start, end);
+
+	for (entry = l_queue_get_entries(debug_sections); entry;
+					entry = entry->next) {
+		const struct debug_section *section = entry->data;
+
+		debug_enable(section->start, section->end);
+	}
+}
+
+/**
+ * l_debug_disable:
+ *
+ * Disable all debug sections.
+ **/
+LIB_EXPORT void l_debug_disable(void)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(debug_sections); entry;
+					entry = entry->next) {
+		const struct debug_section *section = entry->data;
+
+		debug_disable(section->start, section->end);
+	}
+
+	debug_pattern = NULL;
+}
+
+__attribute__((constructor)) static void register_debug_section()
+{
+	extern struct l_debug_desc __start___ell_debug[];
+	extern struct l_debug_desc __stop___ell_debug[];
+
+	l_debug_add_section(__start___ell_debug, __stop___ell_debug);
+}
+
+__attribute__((destructor(65535))) static void free_debug_sections()
+{
+	l_queue_destroy(debug_sections, l_free);
+}
diff --git a/ell/log.h b/ell/log.h
new file mode 100644
index 0000000..7ddf663
--- /dev/null
+++ b/ell/log.h
@@ -0,0 +1,96 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_LOG_H
+#define __ELL_LOG_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define L_LOG_ERR	3
+#define L_LOG_WARNING	4
+#define L_LOG_NOTICE	5
+#define L_LOG_INFO	6
+#define L_LOG_DEBUG	7
+
+typedef void (*l_log_func_t) (int priority, const char *file, const char *line,
+			const char *func, const char *format, va_list ap);
+
+void l_log_set_ident(const char *ident);
+void l_log_set_handler(l_log_func_t function);
+void l_log_set_null(void);
+void l_log_set_stderr(void);
+void l_log_set_syslog(void);
+void l_log_set_journal(void);
+
+void l_log_with_location(int priority, const char *file, const char *line,
+				const char *func, const char *format, ...)
+				__attribute__((format(printf, 5, 6)));
+
+#define l_log(priority, format, ...)  l_log_with_location(priority, \
+					__FILE__, L_STRINGIFY(__LINE__), \
+					__func__, format "\n", ##__VA_ARGS__)
+
+struct l_debug_desc {
+	const char *file;
+	const char *func;
+#define L_DEBUG_FLAG_DEFAULT (0)
+#define L_DEBUG_FLAG_PRINT   (1 << 0)
+	unsigned int flags;
+} __attribute__((aligned(8)));
+
+/*
+ * Set the retain attribute so that the section cannot be discarded by ld
+ * --gc-sections -z start-stop-gc. Older compilers would warn for the unknown
+ *  attribute, so just disable -Wattributes.
+ */
+#define L_DEBUG_SYMBOL(symbol, format, ...) do { \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wattributes\"") \
+	static struct l_debug_desc symbol \
+	__attribute__((used, retain, section("__ell_debug"), aligned(8))) = { \
+		.file = __FILE__, .func = __func__, \
+		.flags = L_DEBUG_FLAG_DEFAULT, \
+	}; \
+_Pragma("GCC diagnostic pop") \
+	if (symbol.flags & L_DEBUG_FLAG_PRINT) \
+		l_log(L_LOG_DEBUG, "%s:%s() " format, __FILE__, \
+					__func__ , ##__VA_ARGS__); \
+} while (0)
+
+void l_debug_enable_full(const char *pattern,
+				struct l_debug_desc *start,
+				struct l_debug_desc *end);
+void l_debug_add_section(struct l_debug_desc *start,
+					struct l_debug_desc *end);
+
+#define l_debug_enable(pattern) do { \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wredundant-decls\"") \
+	extern struct l_debug_desc __start___ell_debug[]; \
+	extern struct l_debug_desc __stop___ell_debug[]; \
+	l_debug_enable_full(pattern, __start___ell_debug, __stop___ell_debug); \
+_Pragma("GCC diagnostic pop") \
+} while (0)
+
+void l_debug_disable(void);
+
+#define l_error(format, ...)  l_log(L_LOG_ERR, format, ##__VA_ARGS__)
+#define l_warn(format, ...)   l_log(L_LOG_WARNING, format, ##__VA_ARGS__)
+#define l_notice(format, ...) l_log(L_LOG_NOTICE, format, ##__VA_ARGS__)
+#define l_info(format, ...)   l_log(L_LOG_INFO, format, ##__VA_ARGS__)
+#define l_debug(format, ...)  L_DEBUG_SYMBOL(__debug_desc, format, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_LOG_H */
diff --git a/ell/main-private.h b/ell/main-private.h
new file mode 100644
index 0000000..d8afcef
--- /dev/null
+++ b/ell/main-private.h
@@ -0,0 +1,23 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2021  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+typedef void (*watch_event_cb_t) (int fd, uint32_t events, void *user_data);
+typedef void (*watch_destroy_cb_t) (void *user_data);
+
+typedef void (*idle_event_cb_t) (void *user_data);
+typedef void (*idle_destroy_cb_t) (void *user_data);
+
+int watch_add(int fd, uint32_t events, watch_event_cb_t callback,
+				void *user_data, watch_destroy_cb_t destroy);
+int watch_modify(int fd, uint32_t events, bool force);
+int watch_remove(int fd, bool epoll_del);
+int watch_clear(int fd);
+
+#define IDLE_FLAG_NO_WARN_DANGLING 0x10000000
+int idle_add(idle_event_cb_t callback, void *user_data, uint32_t flags,
+		idle_destroy_cb_t destroy);
+void idle_remove(int id);
diff --git a/ell/main.c b/ell/main.c
new file mode 100644
index 0000000..1d59181
--- /dev/null
+++ b/ell/main.c
@@ -0,0 +1,651 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "signal.h"
+#include "queue.h"
+#include "log.h"
+#include "useful.h"
+#include "main.h"
+#include "main-private.h"
+#include "private.h"
+#include "timeout.h"
+
+/**
+ * SECTION:main
+ * @short_description: Main loop handling
+ *
+ * Main loop handling
+ */
+
+#define MAX_EPOLL_EVENTS 10
+
+#define IDLE_FLAG_DISPATCHING	1
+#define IDLE_FLAG_DESTROYED	2
+
+#define WATCH_FLAG_DISPATCHING	1
+#define WATCH_FLAG_DESTROYED	2
+
+#define WATCHDOG_TRIGGER_FREQ	2
+
+static int epoll_fd = -1;
+static bool epoll_running;
+static bool epoll_terminate;
+static int idle_id;
+
+static int notify_fd;
+
+static struct l_timeout *watchdog;
+
+static struct l_queue *idle_list;
+
+struct watch_data {
+	int fd;
+	uint32_t events;
+	uint32_t flags;
+	watch_event_cb_t callback;
+	watch_destroy_cb_t destroy;
+	void *user_data;
+};
+
+#define DEFAULT_WATCH_ENTRIES 128
+
+static unsigned int watch_entries;
+static struct watch_data **watch_list;
+
+struct idle_data {
+	idle_event_cb_t callback;
+	idle_destroy_cb_t destroy;
+	void *user_data;
+	uint32_t flags;
+	int id;
+};
+
+static inline bool __attribute__ ((always_inline)) create_epoll(void)
+{
+	unsigned int i;
+
+	epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+	if (epoll_fd < 0)
+		return false;
+
+	watch_list = malloc(DEFAULT_WATCH_ENTRIES * sizeof(void *));
+	if (!watch_list)
+		goto close_epoll;
+
+	idle_list = l_queue_new();
+
+	idle_id = 0;
+
+	watch_entries = DEFAULT_WATCH_ENTRIES;
+
+	for (i = 0; i < watch_entries; i++)
+		watch_list[i] = NULL;
+
+	return true;
+
+close_epoll:
+	close(epoll_fd);
+	epoll_fd = -1;
+
+	return false;
+}
+
+int watch_add(int fd, uint32_t events, watch_event_cb_t callback,
+				void *user_data, watch_destroy_cb_t destroy)
+{
+	struct watch_data *data;
+	struct epoll_event ev;
+	int err;
+
+	if (unlikely(fd < 0 || !callback))
+		return -EINVAL;
+
+	if (epoll_fd < 0)
+		return -EIO;
+
+	if (L_WARN_ON((unsigned int) fd > watch_entries - 1))
+		return -ERANGE;
+
+	data = l_new(struct watch_data, 1);
+
+	data->fd = fd;
+	data->events = events;
+	data->flags = 0;
+	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) {
+		l_free(data);
+		return -errno;
+	}
+
+	watch_list[fd] = data;
+
+	return 0;
+}
+
+int watch_modify(int fd, uint32_t events, bool force)
+{
+	struct watch_data *data;
+	struct epoll_event ev;
+	int err;
+
+	if (unlikely(fd < 0))
+		return -EINVAL;
+
+	if ((unsigned int) fd > watch_entries - 1)
+		return -ERANGE;
+
+	data = watch_list[fd];
+	if (!data)
+		return -ENXIO;
+
+	if (data->events == events && !force)
+		return 0;
+
+	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 -errno;
+
+	data->events = events;
+
+	return 0;
+}
+
+int watch_clear(int fd)
+{
+	struct watch_data *data;
+
+	if (unlikely(fd < 0))
+		return -EINVAL;
+
+	if ((unsigned int) fd > watch_entries - 1)
+		return -ERANGE;
+
+	data = watch_list[fd];
+	if (!data)
+		return -ENXIO;
+
+	watch_list[fd] = NULL;
+
+	if (data->destroy)
+		data->destroy(data->user_data);
+
+	if (data->flags & WATCH_FLAG_DISPATCHING)
+		data->flags |= WATCH_FLAG_DESTROYED;
+	else
+		l_free(data);
+
+	return 0;
+}
+
+int watch_remove(int fd, bool epoll_del)
+{
+	int err = watch_clear(fd);
+
+	if (err < 0)
+		return err;
+
+	if (!epoll_del)
+		goto done;
+
+	err = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
+	if (err < 0)
+		return -errno;
+
+done:
+	return err;
+}
+
+static bool idle_remove_by_id(void *data, void *user_data)
+{
+	struct idle_data *idle = data;
+	int id = L_PTR_TO_INT(user_data);
+
+	if (idle->id != id)
+		return false;
+
+	if (idle->destroy)
+		idle->destroy(idle->user_data);
+
+	if (idle->flags & IDLE_FLAG_DISPATCHING) {
+		idle->flags |= IDLE_FLAG_DESTROYED;
+		return false;
+	}
+
+	l_free(idle);
+
+	return true;
+}
+
+static bool idle_prune(void *data, void *user_data)
+{
+	struct idle_data *idle = data;
+
+	if ((idle->flags & IDLE_FLAG_DESTROYED) == 0)
+		return false;
+
+	l_free(idle);
+
+	return true;
+}
+
+int idle_add(idle_event_cb_t callback, void *user_data, uint32_t flags,
+		idle_destroy_cb_t destroy)
+{
+	struct idle_data *data;
+
+	if (unlikely(!callback))
+		return -EINVAL;
+
+	if (epoll_fd < 0)
+		return -EIO;
+
+	data = l_new(struct idle_data, 1);
+
+	data->callback = callback;
+	data->destroy = destroy;
+	data->user_data = user_data;
+	data->flags = flags;
+
+	if (!l_queue_push_tail(idle_list, data)) {
+		l_free(data);
+		return -ENOMEM;
+	}
+
+	data->id = idle_id++;
+
+	if (idle_id == INT_MAX)
+		idle_id = 0;
+
+	return data->id;
+}
+
+void idle_remove(int id)
+{
+	l_queue_foreach_remove(idle_list, idle_remove_by_id,
+					L_INT_TO_PTR(id));
+}
+
+static void idle_destroy(void *data)
+{
+	struct idle_data *idle = data;
+
+	if (!(idle->flags & IDLE_FLAG_NO_WARN_DANGLING))
+		l_error("Dangling idle descriptor %p, %d found",
+							data, idle->id);
+
+	if (idle->destroy)
+		idle->destroy(idle->user_data);
+
+	l_free(idle);
+}
+
+static void idle_dispatch(void *data, void *user_data)
+{
+	struct idle_data *idle = data;
+
+	if (!idle->callback)
+		return;
+
+	idle->flags |= IDLE_FLAG_DISPATCHING;
+	idle->callback(idle->user_data);
+	idle->flags &= ~IDLE_FLAG_DISPATCHING;
+}
+
+static int sd_notify(const char *state)
+{
+	int err;
+
+	if (notify_fd <= 0)
+		return -ENOTCONN;
+
+	err = send(notify_fd, state, strlen(state), MSG_NOSIGNAL);
+	if (err < 0)
+		return -errno;
+
+	return 0;
+}
+
+static void watchdog_callback(struct l_timeout *timeout, void *user_data)
+{
+	int msec = L_PTR_TO_INT(user_data);
+
+	sd_notify("WATCHDOG=1");
+
+	l_timeout_modify_ms(timeout, msec);
+}
+
+static void create_sd_notify_socket(void)
+{
+	const char *sock;
+	struct sockaddr_un addr;
+	const char *watchdog_usec;
+	int msec;
+
+	/* check if NOTIFY_SOCKET has been set */
+	sock = getenv("NOTIFY_SOCKET");
+	if (!sock)
+		return;
+
+	/* check for abstract socket or absolute path */
+	if (sock[0] != '@' && sock[0] != '/')
+		return;
+
+	notify_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+	if (notify_fd < 0) {
+		notify_fd = 0;
+		return;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, sock, sizeof(addr.sun_path) - 1);
+
+	if (addr.sun_path[0] == '@')
+		addr.sun_path[0] = '\0';
+
+	if (bind(notify_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		close(notify_fd);
+		notify_fd = 0;
+		return;
+	}
+
+	watchdog_usec = getenv("WATCHDOG_USEC");
+	if (!watchdog_usec)
+		return;
+
+	msec = atoi(watchdog_usec) / 1000;
+	if (msec < WATCHDOG_TRIGGER_FREQ)
+		return;
+
+	msec /= WATCHDOG_TRIGGER_FREQ;
+
+	watchdog = l_timeout_create_ms(msec, watchdog_callback,
+					L_INT_TO_PTR(msec), NULL);
+}
+
+/**
+ * l_main_init:
+ *
+ * Initialize the main loop. This must be called before l_main_run()
+ * and any other function that directly or indirectly sets up an idle
+ * or watch. A safe rule-of-thumb is to call it before any function
+ * prefixed with "l_".
+ *
+ * Returns: true if initialization was successful, false otherwise.
+ **/
+LIB_EXPORT bool l_main_init(void)
+{
+	if (unlikely(epoll_running))
+		return false;
+
+	if (!create_epoll())
+		return false;
+
+	create_sd_notify_socket();
+
+	epoll_terminate = false;
+
+	return true;
+}
+
+/**
+ * l_main_prepare:
+ *
+ * Prepare the iteration of the main loop
+ *
+ * Returns: The timeout to use.  This will be 0 if idle-event processing is
+ * currently pending, or -1 otherwise.  This value can be used to pass to
+ * l_main_iterate.
+ */
+LIB_EXPORT int l_main_prepare(void)
+{
+	return l_queue_isempty(idle_list) ? -1 : 0;
+}
+
+/**
+ * l_main_iterate:
+ *
+ * Run one iteration of the main event loop
+ */
+LIB_EXPORT void l_main_iterate(int timeout)
+{
+	struct epoll_event events[MAX_EPOLL_EVENTS];
+	struct watch_data *data;
+	int n, nfds;
+
+	nfds = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, timeout);
+
+	for (n = 0; n < nfds; n++) {
+		data = events[n].data.ptr;
+
+		data->flags |= WATCH_FLAG_DISPATCHING;
+	}
+
+	for (n = 0; n < nfds; n++) {
+		data = events[n].data.ptr;
+
+		if (data->flags & WATCH_FLAG_DESTROYED)
+			continue;
+
+		data->callback(data->fd, events[n].events,
+							data->user_data);
+	}
+
+	for (n = 0; n < nfds; n++) {
+		data = events[n].data.ptr;
+
+		if (data->flags & WATCH_FLAG_DESTROYED)
+			l_free(data);
+		else
+			data->flags = 0;
+	}
+
+	l_queue_foreach(idle_list, idle_dispatch, NULL);
+	l_queue_foreach_remove(idle_list, idle_prune, NULL);
+}
+
+/**
+ * l_main_run:
+ *
+ * Run the main loop
+ *
+ * The loop may be restarted by invoking this function after a
+ * previous invocation returns, provided that l_main_exit() has not
+ * been called first.
+ *
+ * Returns: #EXIT_SUCCESS after successful execution or #EXIT_FAILURE in
+ *          case of failure
+ **/
+LIB_EXPORT int l_main_run(void)
+{
+	int timeout;
+
+	/* Has l_main_init() been called? */
+	if (unlikely(epoll_fd < 0))
+		return EXIT_FAILURE;
+
+	if (unlikely(epoll_running))
+		return EXIT_FAILURE;
+
+	epoll_running = true;
+
+	for (;;) {
+		if (epoll_terminate)
+			break;
+
+		timeout = l_main_prepare();
+		l_main_iterate(timeout);
+	}
+
+	epoll_running = false;
+
+	if (notify_fd) {
+		close(notify_fd);
+		notify_fd = 0;
+		l_timeout_remove(watchdog);
+		watchdog = NULL;
+	}
+
+	return EXIT_SUCCESS;
+}
+
+/**
+ * l_main_exit:
+ *
+ * Clean up after main loop completes.
+ *
+ **/
+LIB_EXPORT bool l_main_exit(void)
+{
+	unsigned int i;
+
+	if (epoll_running) {
+		l_error("Cleanup attempted on running main loop");
+		return false;
+	}
+
+	for (i = 0; i < watch_entries; i++) {
+		struct watch_data *data = watch_list[i];
+
+		if (!data)
+			continue;
+
+		epoll_ctl(epoll_fd, EPOLL_CTL_DEL, data->fd, NULL);
+
+		if (data->destroy)
+			data->destroy(data->user_data);
+		else
+			l_error("Dangling file descriptor %d found", data->fd);
+
+		l_free(data);
+	}
+
+	watch_entries = 0;
+
+	free(watch_list);
+	watch_list = NULL;
+
+	l_queue_destroy(idle_list, idle_destroy);
+	idle_list = NULL;
+
+	close(epoll_fd);
+	epoll_fd = -1;
+
+	return true;
+}
+
+/**
+ * l_main_quit:
+ *
+ * Terminate the running main loop
+ *
+ * Returns: #true when terminating the main loop or #false in case of failure
+ **/
+LIB_EXPORT bool l_main_quit(void)
+{
+	if (unlikely(!epoll_running))
+		return false;
+
+	epoll_terminate = true;
+
+	return true;
+}
+
+struct signal_data {
+	l_main_signal_cb_t callback;
+	void *user_data;
+};
+
+static void sigint_handler(void *user_data)
+{
+	struct signal_data *data = user_data;
+
+	if (data->callback)
+		data->callback(SIGINT, data->user_data);
+}
+
+static void sigterm_handler(void *user_data)
+{
+	struct signal_data *data = user_data;
+
+	if (data->callback)
+		data->callback(SIGTERM, data->user_data);
+}
+
+/**
+ * l_main_run_with_signal:
+ *
+ * Run the main loop with signal handling for SIGINT and SIGTERM
+ *
+ * Returns: #EXIT_SUCCESS after successful execution or #EXIT_FAILURE in
+ *          case of failure
+ **/
+LIB_EXPORT int l_main_run_with_signal(l_main_signal_cb_t callback,
+							void *user_data)
+{
+	struct signal_data *data;
+	struct l_signal *sigint;
+	struct l_signal *sigterm;
+	int result;
+
+	data = l_new(struct signal_data, 1);
+
+	data->callback = callback;
+	data->user_data = user_data;
+
+	sigint = l_signal_create(SIGINT, sigint_handler, data, NULL);
+	sigterm = l_signal_create(SIGTERM, sigterm_handler, data, NULL);
+
+	result = l_main_run();
+
+	l_signal_remove(sigint);
+	l_signal_remove(sigterm);
+
+	l_free(data);
+
+	return result;
+}
+
+/**
+ * l_main_get_epoll_fd:
+ *
+ * Can be used to obtain the epoll file descriptor in order to integrate
+ * the ell main event loop with other event loops.
+ *
+ * Returns: epoll file descriptor
+ **/
+LIB_EXPORT int l_main_get_epoll_fd(void)
+{
+	return epoll_fd;
+}
diff --git a/ell/main.h b/ell/main.h
new file mode 100644
index 0000000..e4826e5
--- /dev/null
+++ b/ell/main.h
@@ -0,0 +1,36 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_MAIN_H
+#define __ELL_MAIN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool l_main_init(void);
+int l_main_prepare(void);
+void l_main_iterate(int timeout);
+int l_main_run(void);
+bool l_main_exit(void);
+
+bool l_main_quit(void);
+
+typedef void (*l_main_signal_cb_t) (uint32_t signo, void *user_data);
+
+int l_main_run_with_signal(l_main_signal_cb_t callback, void *user_data);
+
+int l_main_get_epoll_fd(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_MAIN_H */
diff --git a/ell/missing.h b/ell/missing.h
new file mode 100644
index 0000000..b1ee0f1
--- /dev/null
+++ b/ell/missing.h
@@ -0,0 +1,64 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <sys/syscall.h>
+#include <sys/socket.h>
+
+#ifndef __NR_getrandom
+#  if defined __x86_64__
+#    define __NR_getrandom 318
+#  elif defined(__i386__)
+#    define __NR_getrandom 355
+#  elif defined(__arm__)
+#    define __NR_getrandom 384
+# elif defined(__aarch64__)
+#    define __NR_getrandom 278
+#  elif defined(__ia64__)
+#    define __NR_getrandom 1339
+#  elif defined(__m68k__)
+#    define __NR_getrandom 352
+#  elif defined(__s390x__)
+#    define __NR_getrandom 349
+#  elif defined(__powerpc__)
+#    define __NR_getrandom 359
+#  elif defined _MIPS_SIM
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define __NR_getrandom 4353
+#    endif
+#    if _MIPS_SIM == _MIPS_SIM_NABI32
+#      define __NR_getrandom 6317
+#    endif
+#    if _MIPS_SIM == _MIPS_SIM_ABI64
+#      define __NR_getrandom 5313
+#    endif
+#  else
+#    warning "__NR_getrandom unknown for your architecture"
+#    define __NR_getrandom 0xffffffff
+#  endif
+#endif
+
+#ifndef HAVE_EXPLICIT_BZERO
+static inline void explicit_bzero(void *s, size_t n)
+{
+	memset(s, 0, n);
+	__asm__ __volatile__ ("" : : "r"(s) : "memory");
+}
+#endif
+
+#ifndef SO_BINDTOIFINDEX
+#define SO_BINDTOIFINDEX 62
+#endif
+
+#ifndef HAVE_RAWMEMCHR
+static inline void *rawmemchr(const void *s, int c)
+{
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wstringop-overflow=\"")
+	return memchr(s, c, PTRDIFF_MAX);
+_Pragma("GCC diagnostic pop")
+}
+#endif
diff --git a/ell/pem-private.h b/ell/pem-private.h
new file mode 100644
index 0000000..78f7c8e
--- /dev/null
+++ b/ell/pem-private.h
@@ -0,0 +1,36 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2019  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+
+struct l_certchain;
+
+struct pem_file_info {
+	int fd;
+	struct stat st;
+	uint8_t *data;
+};
+
+int pem_file_open(struct pem_file_info *info, const char *filename);
+void pem_file_close(struct pem_file_info *info);
+
+const char *pem_next(const void *buf, size_t buf_len, char **type_label,
+				size_t *base64_len,
+				const char **endp, bool strict);
+
+uint8_t *pem_load_buffer(const void *buf, size_t buf_len,
+				char **out_type_label, size_t *out_len,
+				char **out_headers, const char **out_endp);
+
+struct l_key *pem_load_private_key(uint8_t *content, size_t len, char *label,
+					const char *passphrase, char *headers,
+					bool *encrypted);
+
+int pem_write_certificate_chain(const struct l_certchain *cert,
+				const char *filename);
diff --git a/ell/pem.c b/ell/pem.c
new file mode 100644
index 0000000..24e8372
--- /dev/null
+++ b/ell/pem.c
@@ -0,0 +1,819 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <strings.h>
+#include <errno.h>
+
+#include "useful.h"
+#include "private.h"
+#include "key.h"
+#include "cert.h"
+#include "queue.h"
+#include "pem.h"
+#include "base64.h"
+#include "utf8.h"
+#include "asn1-private.h"
+#include "cipher.h"
+#include "cert-private.h"
+#include "missing.h"
+#include "pem-private.h"
+
+#define PEM_START_BOUNDARY	"-----BEGIN "
+#define PEM_END_BOUNDARY	"-----END "
+
+static const char *is_start_boundary(const void *buf, size_t buf_len,
+					size_t *label_len)
+{
+	const char *start, *end, *ptr;
+	int prev_special, special;
+	const char *buf_ptr = buf;
+
+	if (buf_len < strlen(PEM_START_BOUNDARY))
+		return NULL;
+
+	/* Check we have a "-----BEGIN " (RFC7468 section 2) */
+	if (memcmp(buf, PEM_START_BOUNDARY, strlen(PEM_START_BOUNDARY)))
+		return NULL;
+
+	/*
+	 * Check we have a string of printable characters in which no
+	 * two consecutive characters are "special" nor is the first or the
+	 * final character "special".  These special characters are space
+	 * and hyphen.  (RFC7468 section 3)
+	 * The loop will end on the second hyphen of the final "-----" if
+	 * no error found earlier.
+	 */
+	start = buf + strlen(PEM_START_BOUNDARY);
+	end = start;
+	prev_special = 1;
+
+	while (end < buf_ptr + buf_len && l_ascii_isprint(*end)) {
+		special = *end == ' ' || *end == '-';
+
+		if (prev_special && special)
+			break;
+
+		end++;
+		prev_special = special;
+	}
+
+	/* Rewind to the first '-', but handle empty labels */
+	if (end != start)
+		end--;
+
+	/* Check we have a "-----" (RFC7468 section 2) */
+	if (end + 5 > buf_ptr + buf_len || memcmp(end, "-----", 5))
+		return NULL;
+
+	/* Check all remaining characters are horizontal whitespace (WSP) */
+	for (ptr = end + 5; ptr < buf_ptr + buf_len; ptr++)
+		if (*ptr != ' ' && *ptr != '\t')
+			return NULL;
+
+	*label_len = end - start;
+
+	return start;
+}
+
+static bool is_end_boundary(const void *buf, size_t buf_len,
+				const char *label, size_t label_len)
+{
+	const char *buf_ptr = buf;
+	size_t len = strlen(PEM_END_BOUNDARY) + label_len + 5;
+
+	if (buf_len < len)
+		return false;
+
+	if (memcmp(buf_ptr, PEM_END_BOUNDARY, strlen(PEM_END_BOUNDARY)) ||
+			memcmp(buf_ptr + strlen(PEM_END_BOUNDARY),
+				label, label_len) ||
+			memcmp(buf_ptr + (len - 5), "-----", 5))
+		return false;
+
+	/* Check all remaining characters are horizontal whitespace (WSP) */
+	for (; len < buf_len; len++)
+		if (buf_ptr[len] != ' ' && buf_ptr[len] != '\t')
+			return false;
+
+	return true;
+}
+
+const char *pem_next(const void *buf, size_t buf_len, char **type_label,
+				size_t *base64_len,
+				const char **endp, bool strict)
+{
+	const char *buf_ptr = buf;
+	const char *base64_data = NULL, *eol;
+	const char *label = NULL;
+	size_t label_len = 0;
+	const char *start = NULL;
+
+	/*
+	 * The base64 parser uses the RFC7468 laxbase64text grammar but we
+	 * do full checks on the encapsulation boundary lines, i.e. no
+	 * leading spaces allowed, making sure quoted text and similar
+	 * are not confused for actual PEM "textual encoding".
+	 */
+	while (buf_len) {
+		for (eol = buf_ptr; eol < buf_ptr + buf_len; eol++)
+			if (*eol == '\r' || *eol == '\n')
+				break;
+
+		if (!base64_data) {
+			label = is_start_boundary(buf_ptr, eol - buf_ptr,
+							&label_len);
+			if (label) {
+				start = label - strlen("-----BEGIN ");
+				base64_data = eol;
+			} else if (strict)
+				break;
+		} else if (start && is_end_boundary(buf_ptr, eol - buf_ptr,
+							label, label_len)) {
+			if (type_label)
+				*type_label = l_strndup(label, label_len);
+
+			if (base64_len)
+				*base64_len = buf_ptr - base64_data;
+
+			if (endp) {
+				if (eol == buf_ptr + buf_len)
+					*endp = eol;
+				else
+					*endp = eol + 1;
+			}
+
+			return base64_data;
+		}
+
+		if (eol == buf_ptr + buf_len)
+			break;
+
+		buf_len -= eol + 1 - buf_ptr;
+		buf_ptr = eol + 1;
+
+		if (buf_len && *eol == '\r' && *buf_ptr == '\n') {
+			buf_ptr++;
+			buf_len--;
+		}
+	}
+
+	/* If we found no label signal EOF rather than parse error */
+	if (!base64_data && endp)
+		*endp = NULL;
+
+	return NULL;
+}
+
+uint8_t *pem_load_buffer(const void *buf, size_t buf_len,
+				char **out_type_label, size_t *out_len,
+				char **out_headers, const char **out_endp)
+{
+	size_t base64_len;
+	const char *base64;
+	char *label;
+	const char *headers = NULL;
+	size_t headers_len;
+	uint8_t *ret;
+
+	base64 = pem_next(buf, buf_len, &label, &base64_len,
+				out_endp, false);
+	if (!base64)
+		return NULL;
+
+	if (memchr(base64, ':', base64_len)) {
+		const char *start;
+		const char *end;
+
+		while (base64_len && l_ascii_isspace(*base64)) {
+			base64++;
+			base64_len--;
+		}
+
+		start = base64;
+
+		if (!(end = memmem(start, base64_len, "\n\n", 2)) &&
+				!(end = memmem(start, base64_len, "\n\r\n", 3)))
+			goto err;
+
+		/* Check that each header line has a key and a colon */
+		while (start < end) {
+			const char *lf = rawmemchr(start, '\n');
+			const char *colon = memchr(start, ':', lf - start);
+
+			if (!colon)
+				goto err;
+
+			for (; start < colon; start++)
+				if (l_ascii_isalnum(*start))
+					break;
+
+			if (start == colon)
+				goto err;
+
+			start = lf + 1;
+		}
+
+		headers = base64;
+		headers_len = end - base64;
+
+		base64_len -= headers_len + 2;
+		base64 = end + 2;
+	}
+
+	ret = l_base64_decode(base64, base64_len, out_len);
+	if (ret) {
+		*out_type_label = label;
+
+		if (out_headers) {
+			if (headers)
+				*out_headers = l_strndup(headers, headers_len);
+			else
+				*out_headers = NULL;
+		}
+
+		return ret;
+	}
+
+err:
+	l_free(label);
+
+	return NULL;
+}
+
+LIB_EXPORT uint8_t *l_pem_load_buffer(const void *buf, size_t buf_len,
+					char **type_label, size_t *out_len)
+{
+	return pem_load_buffer(buf, buf_len, type_label, out_len, NULL, NULL);
+}
+
+int pem_file_open(struct pem_file_info *info, const char *filename)
+{
+	info->fd = open(filename, O_RDONLY);
+	if (info->fd < 0)
+		return -errno;
+
+	if (fstat(info->fd, &info->st) < 0) {
+		int r = -errno;
+
+		close(info->fd);
+		return r;
+	}
+
+	info->data = mmap(NULL, info->st.st_size,
+				PROT_READ, MAP_SHARED, info->fd, 0);
+	if (info->data == MAP_FAILED) {
+		int r = -errno;
+
+		close(info->fd);
+		return r;
+	}
+
+	return 0;
+}
+
+void pem_file_close(struct pem_file_info *info)
+{
+	munmap(info->data, info->st.st_size);
+	close(info->fd);
+}
+
+static uint8_t *pem_load_file(const char *filename, char **out_type_label,
+				size_t *out_len, char **out_headers)
+{
+	struct pem_file_info file;
+	uint8_t *result;
+
+	if (unlikely(!filename))
+		return NULL;
+
+	if (pem_file_open(&file, filename) < 0)
+		return NULL;
+
+	result = pem_load_buffer(file.data, file.st.st_size,
+					out_type_label, out_len, out_headers,
+					NULL);
+	pem_file_close(&file);
+	return result;
+}
+
+LIB_EXPORT uint8_t *l_pem_load_file(const char *filename,
+					char **out_type_label, size_t *out_len)
+{
+	return pem_load_file(filename, out_type_label, out_len, NULL);
+}
+
+static struct l_certchain *pem_list_to_chain(struct l_queue *list)
+{
+	struct l_certchain *chain;
+
+	if (!list)
+		return NULL;
+
+	chain = certchain_new_from_leaf(l_queue_pop_head(list));
+
+	while (!l_queue_isempty(list))
+		certchain_link_issuer(chain, l_queue_pop_head(list));
+
+	l_queue_destroy(list, NULL);
+	return chain;
+}
+
+LIB_EXPORT struct l_certchain *l_pem_load_certificate_chain_from_data(
+						const void *buf, size_t len)
+{
+	struct l_queue *list = l_pem_load_certificate_list_from_data(buf, len);
+
+	if (!list)
+		return NULL;
+
+	return pem_list_to_chain(list);
+}
+
+LIB_EXPORT struct l_certchain *l_pem_load_certificate_chain(
+							const char *filename)
+{
+	struct l_queue *list = l_pem_load_certificate_list(filename);
+
+	if (!list)
+		return NULL;
+
+	return pem_list_to_chain(list);
+}
+
+static bool pem_write_one_cert(struct l_cert *cert, void *user_data)
+{
+	int *fd = user_data;
+	const uint8_t *der;
+	size_t der_len;
+	struct iovec iov[3];
+	ssize_t r;
+
+	der = l_cert_get_der_data(cert, &der_len);
+
+	iov[0].iov_base = "-----BEGIN CERTIFICATE-----\n";
+	iov[0].iov_len = strlen(iov[0].iov_base);
+	iov[1].iov_base = l_base64_encode(der, der_len, 64);
+	iov[1].iov_len = strlen(iov[1].iov_base);
+	iov[2].iov_base = "\n-----END CERTIFICATE-----\n";
+	iov[2].iov_len = strlen(iov[2].iov_base);
+	r = L_TFR(writev(*fd, iov, 3));
+	l_free(iov[1].iov_base);
+
+	if (r == (ssize_t) (iov[0].iov_len + iov[1].iov_len + iov[2].iov_len))
+		return false;
+
+	if (r < 0)
+		*fd = -errno;
+	else
+		*fd = -EIO;
+
+	return true;
+}
+
+int pem_write_certificate_chain(const struct l_certchain *chain,
+				const char *filename)
+{
+	int fd = L_TFR(open(filename, O_CREAT | O_WRONLY | O_CLOEXEC, 0600));
+	int err = fd;
+
+	if (err < 0)
+		return -errno;
+
+	l_certchain_walk_from_leaf((struct l_certchain *) chain,
+					pem_write_one_cert, &err);
+	close(fd);
+
+	return err < 0 ? err : 0;
+}
+
+LIB_EXPORT struct l_queue *l_pem_load_certificate_list_from_data(
+						const void *buf, size_t len)
+{
+	const char *ptr, *end;
+	struct l_queue *list = NULL;
+
+	ptr = buf;
+	end = buf + len;
+
+	while (ptr && ptr < end) {
+		uint8_t *der;
+		size_t der_len;
+		char *label = NULL;
+		struct l_cert *cert;
+		const char *base64;
+		size_t base64_len;
+		bool is_certificate;
+
+		base64 = pem_next(ptr, end - ptr, &label,
+					&base64_len, &ptr, false);
+		if (!base64) {
+			if (!ptr)
+				break;
+
+			/* if ptr was not reset to NULL; parse error */
+			goto error;
+		}
+
+		is_certificate = !strcmp(label, "CERTIFICATE");
+		l_free(label);
+
+		if (!is_certificate)
+			goto error;
+
+		der = l_base64_decode(base64, base64_len, &der_len);
+		if (!der)
+			goto error;
+
+		cert = l_cert_new_from_der(der, der_len);
+		l_free(der);
+
+		if (!cert)
+			goto error;
+
+		if (!list)
+			list = l_queue_new();
+
+		l_queue_push_tail(list, cert);
+	}
+
+	return list;
+
+error:
+	l_queue_destroy(list, (l_queue_destroy_func_t) l_cert_free);
+	return NULL;
+}
+
+LIB_EXPORT struct l_queue *l_pem_load_certificate_list(const char *filename)
+{
+	struct pem_file_info file;
+	struct l_queue *list = NULL;
+
+	if (unlikely(!filename))
+		return NULL;
+
+	if (pem_file_open(&file, filename) < 0)
+		return NULL;
+
+	list = l_pem_load_certificate_list_from_data(file.data,
+							file.st.st_size);
+	pem_file_close(&file);
+
+	return list;
+}
+
+#define SKIP_WHITESPACE(str)		\
+	while (l_ascii_isspace(*(str)))	\
+		(str)++;
+
+static const char *parse_rfc1421_dek_info(char *headers,
+						const char **out_params)
+{
+	const char *proc_type = NULL;
+	char *dek_info = NULL;
+	char *comma;
+
+	while (headers) {
+		char *lf = strchrnul(headers, '\n');
+		char *key;
+
+		key = headers;
+		SKIP_WHITESPACE(key);
+		headers = (*lf == '\n') ? lf + 1 : NULL;
+
+		if (!memcmp(key, "X-", 2))
+			key += 2;
+
+		if (!memcmp(key, "Proc-Type:", 10)) {
+			if (proc_type)
+				return NULL;
+
+			proc_type = key + 10;
+			SKIP_WHITESPACE(proc_type);
+		} else if (!memcmp(key, "DEK-Info:", 9)) {
+			if (dek_info)
+				return NULL;
+
+			dek_info = key + 9;
+			SKIP_WHITESPACE(dek_info);
+		} else
+			continue;
+
+		while (l_ascii_isspace(lf[-1]))
+			lf--;
+
+		*lf = '\0';
+	}
+
+	if (!proc_type || !dek_info)
+		return NULL;
+
+	/* Skip the version field (should be 3 or 4) */
+	proc_type = strchr(proc_type, ',');
+	if (!proc_type)
+		return NULL;
+
+	proc_type++;
+	SKIP_WHITESPACE(proc_type);
+
+	/* Section 4.6.1.1 */
+	if (strcmp(proc_type, "ENCRYPTED"))
+		return NULL;
+
+	comma = strchr(dek_info, ',');
+	if (comma) {
+		*out_params = comma + 1;
+		SKIP_WHITESPACE(*out_params);
+
+		while (comma > dek_info && l_ascii_isspace(comma[-1]))
+			comma--;
+
+		*comma = '\0';
+	} else
+		*out_params = NULL;
+
+	return dek_info;
+}
+
+static struct l_cipher *cipher_from_dek_info(const char *algid, const char *params,
+						const char *passphrase,
+						size_t *block_len)
+{
+	enum l_cipher_type type;
+	struct l_cipher *cipher;
+	struct l_checksum *md5;
+	uint8_t key[32];
+	size_t key_len;
+	bool ok;
+	L_AUTO_FREE_VAR(uint8_t *, iv) = NULL;
+	size_t iv_len;
+
+	if (!strcmp(algid, "DES-CBC")) {
+		type = L_CIPHER_DES_CBC;
+		key_len = 8;
+		iv_len = 8;
+	} else if (!strcmp(algid, "DES-EDE3-CBC")) {
+		type = L_CIPHER_DES3_EDE_CBC;
+		key_len = 24;
+		iv_len = 8;
+	} else if (!strcmp(algid, "AES-128-CBC")) {
+		type = L_CIPHER_AES_CBC;
+		key_len = 16;
+		iv_len = 16;
+	} else if (!strcmp(algid, "AES-192-CBC")) {
+		type = L_CIPHER_AES_CBC;
+		key_len = 24;
+		iv_len = 16;
+	} else if (!strcmp(algid, "AES-256-CBC")) {
+		type = L_CIPHER_AES_CBC;
+		key_len = 32;
+		iv_len = 16;
+	} else
+		return NULL;
+
+	if (!params || strlen(params) != 2 * iv_len)
+		return NULL;
+
+	*block_len = iv_len;
+
+	iv = l_util_from_hexstring(params, &iv_len);
+	if (!iv)
+		return NULL;
+
+	/*
+	 * The encryption key is the MD5(password | IV[:8]), this comes from
+	 * opessl's crypto/evp/evp_key.c:EVP_BytesToKey() and doesn't seem to
+	 * be backed by any standard:
+	 * https://web.archive.org/web/20190528100132/https://latacora.singles/2018/08/03/the-default-openssh.html
+	 */
+	md5 = l_checksum_new(L_CHECKSUM_MD5);
+	if (!md5)
+		return NULL;
+
+	ok = l_checksum_update(md5, passphrase, strlen(passphrase)) &&
+		l_checksum_update(md5, iv, 8) &&
+		l_checksum_get_digest(md5, key, 16) == 16;
+
+	if (ok && key_len > 16) {
+		l_checksum_reset(md5);
+		ok = l_checksum_update(md5, key, 16) &&
+			l_checksum_update(md5, passphrase, strlen(passphrase)) &&
+			l_checksum_update(md5, iv, 8) &&
+			l_checksum_get_digest(md5, key + 16, 16) == 16;
+	}
+
+	l_checksum_free(md5);
+
+	if (!ok) {
+		cipher = NULL;
+		goto cleanup;
+	}
+
+	cipher  = l_cipher_new(type, key, key_len);
+	if (!cipher)
+		goto cleanup;
+
+	if (l_cipher_set_iv(cipher, iv, iv_len))
+		goto cleanup;
+
+	l_cipher_free(cipher);
+	cipher = NULL;
+
+cleanup:
+	explicit_bzero(key, sizeof(key));
+	return cipher;
+}
+
+struct l_key *pem_load_private_key(uint8_t *content, size_t len, char *label,
+					const char *passphrase, char *headers,
+					bool *encrypted)
+{
+	struct l_key *pkey;
+
+	/*
+	 * RFC7468 Section 10-compatible unencrypted private key label
+	 * (also mentioned in PKCS#8/RFC5958 Section 5), encodes
+	 * the PKCS#8/RFC5958 PrivateKeyInfo structure -- supported
+	 * directly by the pkcs8-key-parser kernel module.
+	 */
+	if (!strcmp(label, "PRIVATE KEY")) {
+		/* RFC822 Headers explicitly disallowed in RFC7468 */
+		if (headers)
+			goto err;
+
+		pkey = cert_key_from_pkcs8_private_key_info(content, len);
+		goto done;
+	}
+
+	/*
+	 * RFC7468 Section 11-compatible encrypted private key label
+	 * (also mentioned in PKCS#8/RFC5958 Section 5), encodes
+	 * the PKCS#8/RFC5958 EncryptedPrivateKeyInfo structure.  We
+	 * decrypt it into a plain PrivateKeyInfo for the
+	 * pkcs8-key-parser module.
+	 */
+	if (!strcmp(label, "ENCRYPTED PRIVATE KEY")) {
+		if (encrypted)
+			*encrypted = true;
+
+		if (!passphrase)
+			goto err;
+
+		/* RFC822 Headers explicitly disallowed in RFC7468 */
+		if (headers)
+			goto err;
+
+		pkey = cert_key_from_pkcs8_encrypted_private_key_info(content,
+								len,
+								passphrase);
+		goto done;
+	}
+
+	/*
+	 * Legacy RSA private key label aka. SSLeay format, understood by
+	 * most software but not documented in an RFC.  Encodes the
+	 * PKCS#1/RFC8017 RSAPrivateKey structure.  We wrap it in a PKCS#8
+	 * PrivateKeyInfo for the pkcs8-key-parser module.
+	 */
+	if (!strcmp(label, "RSA PRIVATE KEY")) {
+		const char *dekalgid;
+		const char *dekparameters;
+
+		/*
+		 * "openssl rsa ..." can produce encrypted PKCS#1-formatted
+		 * keys.  These are incompatible with RFC7468 parsing because
+		 * of the RFC822 headers present but the format is the same
+		 * as documented in RFC1421.  The encryption algorithms are
+		 * supposed to be the ones defined in RFC1423 but that would
+		 * be only DES-CBC while openssl allows other algorithms.
+		 * When decrypted we get the RSAPrivateKey struct and proceed
+		 * like with the unencrypted format.
+		 */
+		dekalgid = parse_rfc1421_dek_info(headers, &dekparameters);
+		if (dekalgid) {
+			struct l_cipher *alg;
+			bool r;
+			size_t block_len;
+			uint8_t pad;
+
+			if (encrypted)
+				*encrypted = true;
+
+			if (!passphrase)
+				goto err;
+
+			alg = cipher_from_dek_info(dekalgid, dekparameters,
+							passphrase, &block_len);
+			if (!alg)
+				goto err;
+
+			if (len % block_len || !len) {
+				l_cipher_free(alg);
+				goto err;
+			}
+
+			r = l_cipher_decrypt(alg, content, content, len);
+			l_cipher_free(alg);
+
+			if (!r)
+				goto err;
+
+			/* Remove padding like in RFC1423 Section 1.1 */
+			pad = content[len - 1];
+			if (pad > block_len || pad == 0)
+				goto err;
+
+			if (!l_secure_memeq(content + len - pad, pad - 1U, pad))
+				goto err;
+
+			len -= pad;
+		}
+
+		pkey = cert_key_from_pkcs1_rsa_private_key(content, len);
+		goto done;
+	}
+
+	/* Label not known */
+err:
+	pkey = NULL;
+done:
+	explicit_bzero(content, len);
+	l_free(content);
+	l_free(label);
+	l_free(headers);
+	return pkey;
+}
+
+LIB_EXPORT struct l_key *l_pem_load_private_key_from_data(const void *buf,
+							size_t buf_len,
+							const char *passphrase,
+							bool *encrypted)
+{
+	uint8_t *content;
+	char *label;
+	size_t len;
+	char *headers;
+
+	if (encrypted)
+		*encrypted = false;
+
+	content = pem_load_buffer(buf, buf_len, &label, &len, &headers, NULL);
+
+	if (!content)
+		return NULL;
+
+	return pem_load_private_key(content, len, label, passphrase, headers,
+					encrypted);
+}
+
+/**
+ * l_pem_load_private_key
+ * @filename: path string to the PEM file to load
+ * @passphrase: private key encryption passphrase or NULL for unencrypted
+ * @encrypted: receives indication whether the file was encrypted if non-NULL
+ *
+ * Load the PEM encoded RSA Private Key file at @filename.  If it is an
+ * encrypted private key and @passphrase was non-NULL, the file is
+ * decrypted.  If it's unencrypted @passphrase is ignored.  @encrypted
+ * stores information of whether the file was encrypted, both in a
+ * success case and on error when NULL is returned.  This can be used to
+ * check if a passphrase is required without prior information.
+ *
+ * The passphrase, if given, must have been validated as UTF-8 unless the
+ * caller knows that PKCS#12 encryption algorithms are not used.
+ * Use l_utf8_validate.
+ *
+ * Returns: An l_key object to be freed with an l_key_free* function,
+ * or NULL.
+ **/
+LIB_EXPORT struct l_key *l_pem_load_private_key(const char *filename,
+						const char *passphrase,
+						bool *encrypted)
+{
+	uint8_t *content;
+	char *label;
+	size_t len;
+	char *headers;
+
+	if (encrypted)
+		*encrypted = false;
+
+	content = pem_load_file(filename, &label, &len, &headers);
+
+	if (!content)
+		return NULL;
+
+	return pem_load_private_key(content, len, label, passphrase, headers,
+					encrypted);
+}
diff --git a/ell/pem.h b/ell/pem.h
new file mode 100644
index 0000000..26aac84
--- /dev/null
+++ b/ell/pem.h
@@ -0,0 +1,42 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_PEM_H
+#define __ELL_PEM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_queue;
+struct l_key;
+struct l_cert;
+struct l_certchain;
+
+uint8_t *l_pem_load_buffer(const void *buf, size_t buf_len, char **type_label,
+				size_t *out_len);
+uint8_t *l_pem_load_file(const char *filename, char **type_label, size_t *len);
+
+struct l_certchain *l_pem_load_certificate_chain(const char *filename);
+struct l_certchain *l_pem_load_certificate_chain_from_data(const void *buf,
+								size_t len);
+struct l_queue *l_pem_load_certificate_list(const char *filename);
+struct l_queue *l_pem_load_certificate_list_from_data(const void *buf,
+							size_t len);
+
+struct l_key *l_pem_load_private_key(const char *filename,
+					const char *passphrase,
+					bool *encrypted);
+struct l_key *l_pem_load_private_key_from_data(const void *buf, size_t len,
+						const char *passphrase,
+						bool *encrypted);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_PEM_H */
diff --git a/ell/private.h b/ell/private.h
new file mode 100644
index 0000000..e4cbce9
--- /dev/null
+++ b/ell/private.h
@@ -0,0 +1,10 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <ell/util.h>
+
+#define LIB_EXPORT __attribute__ ((visibility("default")))
diff --git a/ell/queue.c b/ell/queue.c
new file mode 100644
index 0000000..9018402
--- /dev/null
+++ b/ell/queue.c
@@ -0,0 +1,573 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "queue.h"
+#include "private.h"
+#include "useful.h"
+
+/**
+ * SECTION:queue
+ * @short_description: Queue support
+ *
+ * Queue support
+ */
+
+/**
+ * l_queue:
+ *
+ * Opaque object representing the queue.
+ */
+struct l_queue {
+	struct l_queue_entry *head;
+	struct l_queue_entry *tail;
+	unsigned int entries;
+};
+
+/**
+ * l_queue_new:
+ *
+ * Create a new queue.
+ *
+ * No error handling is needed since. In case of real memory allocation
+ * problems abort() will be called.
+ *
+ * Returns: a newly allocated #l_queue object
+ **/
+LIB_EXPORT struct l_queue *l_queue_new(void)
+{
+	struct l_queue *queue;
+
+	queue = l_new(struct l_queue, 1);
+
+	queue->head = NULL;
+	queue->tail = NULL;
+	queue->entries = 0;
+
+	return queue;
+}
+
+/**
+ * l_queue_destroy:
+ * @queue: queue object
+ * @destroy: destroy function
+ *
+ * Free queue and call @destroy on all remaining entries.
+ **/
+LIB_EXPORT void l_queue_destroy(struct l_queue *queue,
+				l_queue_destroy_func_t destroy)
+{
+	l_queue_clear(queue, destroy);
+	l_free(queue);
+}
+
+/**
+ * l_queue_clear:
+ * @queue: queue object
+ * @destroy: destroy function
+ *
+ * Clear queue and call @destroy on all remaining entries.
+ **/
+LIB_EXPORT void l_queue_clear(struct l_queue *queue,
+				l_queue_destroy_func_t destroy)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue))
+		return;
+
+	entry = queue->head;
+
+	while (entry) {
+		struct l_queue_entry *tmp = entry;
+
+		if (destroy)
+			destroy(entry->data);
+
+		entry = entry->next;
+
+		l_free(tmp);
+	}
+
+	queue->head = NULL;
+	queue->tail = NULL;
+	queue->entries = 0;
+}
+
+/**
+ * l_queue_push_tail:
+ * @queue: queue object
+ * @data: pointer to data
+ *
+ * Adds @data pointer at the end of the queue.
+ *
+ * Returns: #true when data has been added and #false in case an invalid
+ *          @queue object has been provided
+ **/
+LIB_EXPORT bool l_queue_push_tail(struct l_queue *queue, void *data)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue))
+		return false;
+
+	entry = l_new(struct l_queue_entry, 1);
+
+	entry->data = data;
+	entry->next = NULL;
+
+	if (queue->tail)
+		queue->tail->next = entry;
+
+	queue->tail = entry;
+
+	if (!queue->head)
+		queue->head = entry;
+
+	queue->entries++;
+
+	return true;
+}
+
+/**
+ * l_queue_push_head:
+ * @queue: queue object
+ * @data: pointer to data
+ *
+ * Adds @data pointer at the start of the queue.
+ *
+ * Returns: #true when data has been added and #false in case an invalid
+ *          @queue object has been provided
+ **/
+LIB_EXPORT bool l_queue_push_head(struct l_queue *queue, void *data)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue))
+		return false;
+
+	entry = l_new(struct l_queue_entry, 1);
+
+	entry->data = data;
+	entry->next = queue->head;
+
+	queue->head = entry;
+
+	if (!queue->tail)
+		queue->tail = entry;
+
+	queue->entries++;
+
+	return true;
+}
+
+/**
+ * l_queue_pop_head:
+ * @queue: queue object
+ *
+ * Removes the first element of the queue an returns it.
+ *
+ * Returns: data pointer to first element or #NULL in case an empty queue
+ **/
+LIB_EXPORT void *l_queue_pop_head(struct l_queue *queue)
+{
+	struct l_queue_entry *entry;
+	void *data;
+
+	if (unlikely(!queue))
+		return NULL;
+
+	if (!queue->head)
+		return NULL;
+
+	entry = queue->head;
+
+	if (!queue->head->next) {
+		queue->head = NULL;
+		queue->tail = NULL;
+	} else
+		queue->head = queue->head->next;
+
+	data = entry->data;
+
+	l_free(entry);
+
+	queue->entries--;
+
+	return data;
+}
+
+/**
+ * l_queue_peek_head:
+ * @queue: queue object
+ *
+ * Peeks at the first element of the queue an returns it.
+ *
+ * Returns: data pointer to first element or #NULL in case an empty queue
+ **/
+LIB_EXPORT void *l_queue_peek_head(struct l_queue *queue)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue))
+		return NULL;
+
+	if (!queue->head)
+		return NULL;
+
+	entry = queue->head;
+	return entry->data;
+}
+
+/**
+ * l_queue_peek_tail:
+ * @queue: queue object
+ *
+ * Peeks at the last element of the queue an returns it.
+ *
+ * Returns: data pointer to first element or #NULL in case an empty queue
+ **/
+LIB_EXPORT void *l_queue_peek_tail(struct l_queue *queue)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue))
+		return NULL;
+
+	if (!queue->tail)
+		return NULL;
+
+	entry = queue->tail;
+	return entry->data;
+}
+
+/**
+ * l_queue_insert:
+ * @queue: queue object
+ * @data: pointer to data
+ * @function: compare function
+ * @user_data: user data given to compare function
+ *
+ * Inserts @data pointer at a position in the queue determined by the
+ * compare @function.  @function should return >= 0 if the @data (first
+ * parameter) should be inserted after the current entry (second parameter)
+ * and should return < 0 if before it.
+ *
+ * Returns: #true when data has been added and #false in case of failure
+ **/
+LIB_EXPORT bool l_queue_insert(struct l_queue *queue, void *data,
+                        l_queue_compare_func_t function, void *user_data)
+{
+	struct l_queue_entry *entry, *prev, *cur;
+	int cmp;
+
+	if (unlikely(!queue || !function))
+		return false;
+
+	entry = l_new(struct l_queue_entry, 1);
+
+	entry->data = data;
+	entry->next = NULL;
+
+	if (!queue->head) {
+		queue->head = entry;
+		queue->tail = entry;
+		goto done;
+	}
+
+	for (prev = NULL, cur = queue->head; cur; prev = cur, cur = cur->next) {
+		cmp = function(entry->data, cur->data, user_data);
+
+		if (cmp >= 0)
+			continue;
+
+		if (prev == NULL) {
+			entry->next = queue->head;
+			queue->head = entry;
+			goto done;
+		}
+
+		entry->next = cur;
+		prev->next = entry;
+
+		goto done;
+	}
+
+	queue->tail->next = entry;
+	queue->tail = entry;
+
+done:
+	queue->entries++;
+
+	return true;
+}
+
+/**
+ * l_queue_find:
+ * @queue: queue object
+ * @function: match function
+ * @user_data: user data given to compare function
+ *
+ * Finds an entry in the queue by running the match @function
+ *
+ * Returns: Matching entry or NULL if no entry can be found
+ **/
+LIB_EXPORT void *l_queue_find(struct l_queue *queue,
+				l_queue_match_func_t function,
+				const void *user_data)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue || !function))
+		return NULL;
+
+	for (entry = queue->head; entry; entry = entry->next)
+		if (function(entry->data, user_data))
+			return entry->data;
+
+	return NULL;
+}
+
+/**
+ * l_queue_remove:
+ * @queue: queue object
+ * @data: pointer to data
+ *
+ * Remove given @data from the queue.
+ *
+ * Returns: #true when data has been removed and #false when data could not
+ *          be found or an invalid @queue object has been provided
+ **/
+LIB_EXPORT bool l_queue_remove(struct l_queue *queue, void *data)
+{
+	struct l_queue_entry *entry, *prev;
+
+	if (unlikely(!queue))
+		return false;
+
+	for (entry = queue->head, prev = NULL; entry;
+					prev = entry, entry = entry->next) {
+		if (entry->data != data)
+			continue;
+
+		if (prev)
+			prev->next = entry->next;
+		else
+			queue->head = entry->next;
+
+		if (!entry->next)
+			queue->tail = prev;
+
+		l_free(entry);
+
+		queue->entries--;
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * l_queue_reverse:
+ * @queue: queue object
+ *
+ * Reverse entries in the queue.
+ *
+ * Returns: #true on success and #false on failure
+ **/
+LIB_EXPORT bool l_queue_reverse(struct l_queue *queue)
+{
+	struct l_queue_entry *entry, *prev = NULL;
+
+	if (unlikely(!queue))
+		return false;
+
+	entry = queue->head;
+
+	while (entry) {
+		struct l_queue_entry *next = entry->next;
+
+		entry->next = prev;
+
+		prev = entry;
+		entry = next;
+	}
+
+	queue->tail = queue->head;
+	queue->head = prev;
+
+	return true;
+}
+
+/**
+ * l_queue_foreach:
+ * @queue: queue object
+ * @function: callback function
+ * @user_data: user data given to callback function
+ *
+ * Call @function for every given data in @queue.
+ **/
+LIB_EXPORT void l_queue_foreach(struct l_queue *queue,
+			l_queue_foreach_func_t function, void *user_data)
+{
+	struct l_queue_entry *entry;
+
+	if (unlikely(!queue || !function))
+		return;
+
+	for (entry = queue->head; entry; entry = entry->next)
+		function(entry->data, user_data);
+}
+
+/**
+ * l_queue_foreach_remove:
+ * @queue: queue object
+ * @function: callback function
+ * @user_data: user data given to callback function
+ *
+ * Remove all entries in the @queue where @function returns #true.
+ *
+ * Returns: number of removed entries
+ **/
+LIB_EXPORT unsigned int l_queue_foreach_remove(struct l_queue *queue,
+                        l_queue_remove_func_t function, void *user_data)
+{
+	struct l_queue_entry *entry, *prev = NULL;
+	unsigned int count = 0;
+
+	if (unlikely(!queue || !function))
+		return 0;
+
+	entry = queue->head;
+
+	while (entry) {
+		if (function(entry->data, user_data)) {
+			struct l_queue_entry *tmp = entry;
+
+			if (prev)
+				prev->next = entry->next;
+			else
+				queue->head = entry->next;
+
+			if (!entry->next)
+				queue->tail = prev;
+
+			entry = entry->next;
+
+			l_free(tmp);
+
+			count++;
+		} else {
+			prev = entry;
+			entry = entry->next;
+		}
+	}
+
+	queue->entries -= count;
+
+	return count;
+}
+
+/**
+ * l_queue_remove_if
+ * @queue: queue object
+ * @function: callback function
+ * @user_data: user data given to callback function
+ *
+ * Remove the first entry in the @queue where the function returns #true.
+ *
+ * Returns: NULL if no entry was found, or the entry data if removal was
+ * successful.
+ **/
+LIB_EXPORT void *l_queue_remove_if(struct l_queue *queue,
+				l_queue_match_func_t function,
+				const void *user_data)
+{
+	struct l_queue_entry *entry, *prev = NULL;
+
+	if (unlikely(!queue || !function))
+		return NULL;
+
+	entry = queue->head;
+
+	while (entry) {
+		if (function(entry->data, user_data)) {
+			struct l_queue_entry *tmp = entry;
+			void *data;
+
+			if (prev)
+				prev->next = entry->next;
+			else
+				queue->head = entry->next;
+
+			if (!entry->next)
+				queue->tail = prev;
+
+			data = tmp->data;
+
+			l_free(tmp);
+			queue->entries--;
+
+			return data;
+		}
+
+		prev = entry;
+		entry = entry->next;
+	}
+
+	return NULL;
+}
+
+/**
+ * l_queue_length:
+ * @queue: queue object
+ *
+ * Returns: entries of the queue
+ **/
+LIB_EXPORT unsigned int l_queue_length(struct l_queue *queue)
+{
+	if (unlikely(!queue))
+		return 0;
+
+	return queue->entries;
+}
+
+/**
+ * l_queue_isempty:
+ * @queue: queue object
+ *
+ * Returns: #true if @queue is empty and #false is not
+ **/
+LIB_EXPORT bool l_queue_isempty(struct l_queue *queue)
+{
+	if (unlikely(!queue))
+		return true;
+
+	return queue->entries == 0;
+}
+
+/**
+ * l_queue_get_entries:
+ * @queue: queue object
+ *
+ * This function gives direct, read-only access to the internal list structure
+ * of the queue.  This can be used to efficiently traverse the elements.
+ *
+ * Returns: A pointer to the head of the queue.
+ **/
+LIB_EXPORT const struct l_queue_entry *l_queue_get_entries(
+						const struct l_queue *queue)
+{
+	if (unlikely(!queue))
+		return NULL;
+
+	return queue->head;
+}
diff --git a/ell/queue.h b/ell/queue.h
new file mode 100644
index 0000000..517298c
--- /dev/null
+++ b/ell/queue.h
@@ -0,0 +1,67 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_QUEUE_H
+#define __ELL_QUEUE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*l_queue_foreach_func_t) (void *data, void *user_data);
+typedef void (*l_queue_destroy_func_t) (void *data);
+typedef int (*l_queue_compare_func_t) (const void *a, const void *b,
+							void *user_data);
+typedef bool (*l_queue_match_func_t) (const void *data, const void *user_data);
+typedef bool (*l_queue_remove_func_t) (void *data, void *user_data);
+
+struct l_queue;
+
+struct l_queue_entry {
+	void *data;
+	struct l_queue_entry *next;
+};
+
+struct l_queue *l_queue_new(void);
+void l_queue_destroy(struct l_queue *queue,
+			l_queue_destroy_func_t destroy);
+void l_queue_clear(struct l_queue *queue,
+			l_queue_destroy_func_t destroy);
+
+bool l_queue_push_tail(struct l_queue *queue, void *data);
+bool l_queue_push_head(struct l_queue *queue, void *data);
+void *l_queue_pop_head(struct l_queue *queue);
+void *l_queue_peek_head(struct l_queue *queue);
+void *l_queue_peek_tail(struct l_queue *queue);
+
+bool l_queue_insert(struct l_queue *queue, void *data,
+			l_queue_compare_func_t function, void *user_data);
+void *l_queue_find(struct l_queue *queue,
+			l_queue_match_func_t function, const void *user_data);
+bool l_queue_remove(struct l_queue *queue, void *data);
+void *l_queue_remove_if(struct l_queue *queue,
+			l_queue_match_func_t function, const void *user_data);
+
+bool l_queue_reverse(struct l_queue *queue);
+
+void l_queue_foreach(struct l_queue *queue,
+			l_queue_foreach_func_t function, void *user_data);
+unsigned int l_queue_foreach_remove(struct l_queue *queue,
+			l_queue_remove_func_t function, void *user_data);
+
+unsigned int l_queue_length(struct l_queue *queue);
+bool l_queue_isempty(struct l_queue *queue);
+
+const struct l_queue_entry *l_queue_get_entries(const struct l_queue *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_QUEUE_H */
diff --git a/ell/random.c b/ell/random.c
new file mode 100644
index 0000000..6e0adfe
--- /dev/null
+++ b/ell/random.c
@@ -0,0 +1,90 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+
+#include "random.h"
+#include "private.h"
+#include "missing.h"
+
+#ifndef GRND_NONBLOCK
+#define GRND_NONBLOCK	0x0001
+#endif
+
+#ifndef GRND_RANDOM
+#define GRND_RANDOM	0x0002
+#endif
+
+static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+        return syscall(__NR_getrandom, buffer, count, flags);
+}
+
+/**
+ * l_getrandom:
+ * @buf: buffer to fill with random data
+ * @len: length of random data requested
+ *
+ * Request a number of randomly generated bytes given by @len and put them
+ * into buffer @buf.
+ *
+ * Returns: true if the random data could be generated, false otherwise.
+ **/
+LIB_EXPORT bool l_getrandom(void *buf, size_t len)
+{
+	while (len) {
+		int ret;
+
+		ret = L_TFR(getrandom(buf, len, 0));
+		if (ret < 0)
+			return false;
+
+		buf += ret;
+		len -= ret;
+	}
+
+	return true;
+}
+
+LIB_EXPORT bool l_getrandom_is_supported()
+{
+	static bool initialized = false;
+	static bool supported = true;
+	uint8_t buf[4];
+	int ret;
+
+	if (initialized)
+		return supported;
+
+	ret = getrandom(buf, sizeof(buf), GRND_NONBLOCK);
+
+	if (ret < 0 && errno == ENOSYS)
+		supported = false;
+
+	initialized = true;
+	return supported;
+}
+
+LIB_EXPORT uint32_t l_getrandom_uint32(void)
+{
+	int ret;
+	uint32_t u;
+
+	ret = getrandom(&u, sizeof(u), GRND_NONBLOCK);
+
+	if (ret == sizeof(u))
+		return u;
+
+        return random() * RAND_MAX + random();
+}
diff --git a/ell/random.h b/ell/random.h
new file mode 100644
index 0000000..9c50192
--- /dev/null
+++ b/ell/random.h
@@ -0,0 +1,28 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_RANDOM_H
+#define __ELL_RANDOM_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool l_getrandom(void *buf, size_t len);
+bool l_getrandom_is_supported(void);
+
+uint32_t l_getrandom_uint32(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_RANDOM_H */
diff --git a/ell/settings.c b/ell/settings.c
new file mode 100644
index 0000000..a5f17d1
--- /dev/null
+++ b/ell/settings.c
@@ -0,0 +1,1542 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if __STDC_VERSION__ <= 199409L
+#define _DEFAULT_SOURCE  /* for strto{u}ll() */
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "useful.h"
+#include "strv.h"
+#include "utf8.h"
+#include "string.h"
+#include "queue.h"
+#include "settings.h"
+#include "private.h"
+#include "missing.h"
+#include "pem-private.h"
+
+struct setting_data {
+	char *key;
+	char *value;
+};
+
+struct embedded_group_data {
+	char *name;
+	char type[32];
+	size_t len;
+	char data[];
+};
+
+struct group_data {
+	char *name;
+	struct l_queue *settings;
+};
+
+struct l_settings {
+	l_settings_debug_cb_t debug_handler;
+	l_settings_destroy_cb_t debug_destroy;
+	void *debug_data;
+	struct l_queue *groups;
+	struct l_queue *embedded_groups;
+};
+
+static void setting_destroy(void *data)
+{
+	struct setting_data *pair = data;
+
+	l_free(pair->key);
+	explicit_bzero(pair->value, strlen(pair->value));
+	l_free(pair->value);
+	l_free(pair);
+}
+
+static void group_destroy(void *data)
+{
+	struct group_data *group = data;
+
+	l_free(group->name);
+	l_queue_destroy(group->settings, setting_destroy);
+
+	l_free(group);
+}
+
+static void embedded_group_destroy(void *data)
+{
+	struct embedded_group_data *group = data;
+
+	l_free(group->name);
+	l_free(group);
+}
+
+LIB_EXPORT struct l_settings *l_settings_new(void)
+{
+	struct l_settings *settings;
+
+	settings = l_new(struct l_settings, 1);
+	settings->groups = l_queue_new();
+	settings->embedded_groups = l_queue_new();
+
+	return settings;
+}
+
+static void copy_key_value_foreach(void *data, void *user_data)
+{
+	struct setting_data *s = data;
+	struct l_queue *settings = user_data;
+	struct setting_data *copy = l_new(struct setting_data, 1);
+
+	copy->key = l_strdup(s->key);
+	copy->value = l_strdup(s->value);
+
+	l_queue_push_head(settings, copy);
+}
+
+static void copy_group_foreach(void *data, void *user_data)
+{
+	struct group_data *group = data;
+	struct l_queue *groups = user_data;
+	struct group_data *copy = l_new(struct group_data, 1);
+
+	copy->name = l_strdup(group->name);
+	copy->settings = l_queue_new();
+
+	l_queue_push_head(groups, copy);
+
+	l_queue_foreach(group->settings, copy_key_value_foreach,
+				copy->settings);
+}
+
+static void copy_embedded_foreach(void *data, void *user_data)
+{
+	struct embedded_group_data *embedded = data;
+	struct l_queue *groups = user_data;
+	struct embedded_group_data *copy;
+
+	copy = l_memdup(embedded, sizeof(struct embedded_group_data) +
+			embedded->len + 1);
+	copy->name = l_strdup(embedded->name);
+
+	l_queue_push_tail(groups, copy);
+}
+
+LIB_EXPORT struct l_settings *l_settings_clone(
+					const struct l_settings *settings)
+{
+	struct l_settings *copy;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	copy = l_settings_new();
+
+	l_queue_foreach(settings->groups, copy_group_foreach, copy->groups);
+	l_queue_foreach(settings->embedded_groups, copy_embedded_foreach,
+				copy->embedded_groups);
+
+	return copy;
+}
+
+LIB_EXPORT void l_settings_free(struct l_settings *settings)
+{
+	if (unlikely(!settings))
+		return;
+
+	if (settings->debug_destroy)
+		settings->debug_destroy(settings->debug_data);
+
+	l_queue_destroy(settings->groups, group_destroy);
+	l_queue_destroy(settings->embedded_groups, embedded_group_destroy);
+
+	l_free(settings);
+}
+
+static char *unescape_value(const char *value)
+{
+	char *ret;
+	char *n;
+	const char *o;
+
+	ret = l_new(char, strlen(value) + 1);
+
+	for (n = ret, o = value; *o; o++, n++) {
+		if (*o != '\\') {
+			*n = *o;
+			continue;
+		}
+
+		o += 1;
+
+		switch (*o) {
+		case 's':
+			*n = ' ';
+			break;
+		case 'n':
+			*n = '\n';
+			break;
+		case 't':
+			*n = '\t';
+			break;
+		case 'r':
+			*n = '\r';
+			break;
+		case '\\':
+			*n = '\\';
+			break;
+		default:
+			explicit_bzero(ret, n - ret);
+			l_free(ret);
+			return NULL;
+		}
+	}
+
+	return ret;
+}
+
+static char *escape_value(const char *value)
+{
+	size_t i;
+	size_t j;
+	char *ret;
+	bool lead_whitespace;
+
+	for (i = 0, j = 0, lead_whitespace = true; value[i]; i++) {
+		switch (value[i]) {
+		case ' ':
+		case '\t':
+			if (lead_whitespace)
+				j += 1;
+
+			break;
+		case '\n':
+		case '\r':
+		case '\\':
+			j += 1;
+			/* fall through */
+		default:
+			lead_whitespace = false;
+		}
+	}
+
+	ret = l_malloc(i + j + 1);
+
+	for (i = 0, j = 0, lead_whitespace = true; value[i]; i++) {
+		switch (value[i]) {
+		case ' ':
+			if (lead_whitespace) {
+				ret[j++] = '\\';
+				ret[j++] = 's';
+			} else
+				ret[j++] = value[i];
+
+			break;
+		case '\t':
+			if (lead_whitespace) {
+				ret[j++] = '\\';
+				ret[j++] = 't';
+			} else
+				ret[j++] = value[i];
+
+			break;
+		case '\n':
+			ret[j++] = '\\';
+			ret[j++] = 'n';
+			lead_whitespace = false;
+			break;
+		case '\r':
+			ret[j++] = '\\';
+			ret[j++] = 'r';
+			lead_whitespace = false;
+			break;
+		case '\\':
+			ret[j++] = '\\';
+			ret[j++] = '\\';
+			lead_whitespace = false;
+			break;
+		default:
+			ret[j++] = value[i];
+			lead_whitespace = false;
+		}
+	}
+
+	ret[j] = '\0';
+
+	return ret;
+}
+
+static ssize_t parse_pem(const char *data, size_t len)
+{
+	const char *ptr;
+	const char *end;
+	size_t count = 0;
+
+	ptr = data;
+	end = data + len;
+
+	while (ptr && ptr < end) {
+		const char *pem_start = ptr;
+
+		if (!pem_next(ptr, len, NULL, NULL, &ptr, true)) {
+			if (ptr)
+				return -EINVAL;
+
+			break;
+		}
+
+		len -= ptr - pem_start;
+		count += ptr - pem_start;
+	}
+
+	return count;
+}
+
+struct group_extension {
+	char *name;
+	ssize_t (*parse)(const char *data, size_t len);
+};
+
+static const struct group_extension pem_extension = {
+	.name = "pem",
+	.parse = parse_pem,
+};
+
+static const struct group_extension *extensions[] = {
+	&pem_extension,
+	NULL
+};
+
+static const struct group_extension *find_group_extension(const char *type,
+								size_t len)
+{
+	unsigned int i;
+
+	for (i = 0; extensions[i]; i++) {
+		if (!strncmp(type, extensions[i]->name, len))
+			return extensions[i];
+	}
+
+	return NULL;
+}
+
+static ssize_t parse_embedded_group(struct l_settings *setting,
+					const char *data,
+					size_t line_len, size_t len,
+					size_t line)
+{
+	struct embedded_group_data *group;
+	const struct group_extension *ext;
+	const char *ptr;
+	const char *type;
+	size_t type_len;
+	const char *name;
+	size_t name_len;
+	ssize_t bytes;
+
+	/* Must be at least [@a@b] */
+	if (line_len < 6)
+		goto invalid_group;
+
+	/* caller checked data[1] == '@', next char is type */
+	type = data + 2;
+
+	ptr = memchr(type, '@', line_len - 2);
+
+	type_len = ptr - type;
+
+	if (!ptr || type_len > 31 || type_len < 1)
+		goto invalid_group;
+
+	if (ptr + 1 > data + line_len)
+		goto invalid_group;
+
+	name = ptr + 1;
+
+	/* subtract [@@ + type */
+	ptr = memchr(name, ']', line_len - 3 - type_len);
+
+	name_len = ptr - name;
+
+	if (!ptr || name_len < 1)
+		goto invalid_group;
+
+	ext = find_group_extension(type, type_len);
+	if (!ext)
+		goto invalid_group;
+
+	if (ptr + 2 > data + len) {
+		l_util_debug(setting->debug_handler, setting->debug_data,
+				"Embedded group had no payload");
+		return -EINVAL;
+	}
+
+	bytes = ext->parse(ptr + 2, len - line_len);
+	if (bytes < 0) {
+		l_util_debug(setting->debug_handler, setting->debug_data,
+				"Failed to parse embedded group data");
+		return -EINVAL;
+	}
+
+	group = l_malloc(sizeof(struct embedded_group_data) + bytes + 1);
+
+	group->name = l_strndup(name, name_len);
+
+	memcpy(group->type, type, type_len);
+	group->type[type_len] = '\0';
+
+	group->len = bytes;
+	memcpy(group->data, ptr + 2, bytes);
+	group->data[bytes] = '\0';
+
+	l_queue_push_tail(setting->embedded_groups, group);
+
+	return bytes;
+
+invalid_group:
+	l_util_debug(setting->debug_handler, setting->debug_data,
+			"Invalid embedded group at line %zd", line);
+
+	return -EINVAL;
+}
+
+static bool parse_group(struct l_settings *settings, const char *data,
+			size_t len, size_t line)
+{
+	size_t i = 1;
+	size_t end;
+	struct group_data *group;
+
+	while (i < len && data[i] != ']') {
+		if (l_ascii_isprint(data[i]) == false || data[i] == '[') {
+			l_util_debug(settings->debug_handler,
+					settings->debug_data,
+					"Invalid group name at line %zd", line);
+			return false;
+		}
+
+		i += 1;
+	}
+
+	if (i >= len) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Unterminated group name at line %zd", line);
+		return false;
+	}
+
+	end = i;
+	i += 1;
+
+	while (i < len && l_ascii_isblank(data[i]))
+		i += 1;
+
+	if (i != len) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Junk characters at the end of line %zd", line);
+		return false;
+	}
+
+	group = l_new(struct group_data, 1);
+	group->name = l_strndup(data + 1, end - 1);
+	group->settings = l_queue_new();
+
+	l_queue_push_tail(settings->groups, group);
+
+	return true;
+}
+
+static bool validate_key_character(char c)
+{
+	if (l_ascii_isalnum(c))
+		return true;
+
+	if (c == '_' || c == '-' || c == '.')
+		return true;
+
+	return false;
+}
+
+static unsigned int parse_key(struct l_settings *settings, const char *data,
+				size_t len, size_t line)
+{
+	unsigned int i;
+	unsigned int end;
+	struct group_data *group;
+	struct setting_data *pair;
+
+	for (i = 0; i < len; i++) {
+		if (validate_key_character(data[i]))
+			continue;
+
+		if (l_ascii_isblank(data[i]))
+			break;
+
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Invalid character in Key on line %zd", line);
+
+		return 0;
+	}
+
+	end = i;
+
+	/* Make sure the rest of the characters are blanks */
+	while (i < len) {
+		if (l_ascii_isblank(data[i++]))
+			continue;
+
+		l_util_debug(settings->debug_handler, settings->debug_data,
+					"Garbage after Key on line %zd", line);
+
+		return 0;
+	}
+
+	group = l_queue_peek_tail(settings->groups);
+	pair = l_new(struct setting_data, 1);
+	pair->key = l_strndup(data, end);
+	l_queue_push_head(group->settings, pair);
+
+	return end;
+}
+
+static bool parse_value(struct l_settings *settings, const char *data,
+			size_t len, size_t line)
+{
+	unsigned int end = len;
+	struct group_data *group;
+	struct setting_data *pair;
+
+	group = l_queue_peek_tail(settings->groups);
+	pair = l_queue_pop_head(group->settings);
+
+	if (!l_utf8_validate(data, len, NULL)) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Invalid UTF8 in value on line: %zd", line);
+
+		l_free(pair->key);
+		l_free(pair);
+
+		return false;
+	}
+
+	pair->value = l_strndup(data, end);
+	l_queue_push_tail(group->settings, pair);
+
+	return true;
+}
+
+static bool parse_keyvalue(struct l_settings *settings, const char *data,
+				size_t len, size_t line)
+{
+	const char *equal = memchr(data, '=', len);
+
+	if (!equal) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Delimiter '=' not found on line: %zd", line);
+		return false;
+	}
+
+	if (equal == data) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+					"Empty key on line: %zd", line);
+		return false;
+	}
+
+	if (!parse_key(settings, data, equal - data, line))
+		return false;
+
+	equal += 1;
+	while (equal < data + len && l_ascii_isblank(*equal))
+		equal += 1;
+
+	return parse_value(settings, equal, len - (equal - data), line);
+}
+
+LIB_EXPORT bool l_settings_load_from_data(struct l_settings *settings,
+						const char *data, size_t len)
+{
+	size_t pos = 0;
+	bool r = true;
+	bool has_group = false;
+	const char *eol;
+	size_t line = 1;
+	size_t line_len;
+
+	if (unlikely(!settings || !data || !len))
+		return false;
+
+	while (pos < len && r) {
+		if (l_ascii_isblank(data[pos])) {
+			pos += 1;
+			continue;
+		}
+
+		if (data[pos] == '\n') {
+			line += 1;
+			pos += 1;
+			continue;
+		}
+
+		eol = memchr(data + pos, '\n', len - pos);
+		if (!eol)
+			eol = data + len;
+
+		line_len = eol - data - pos;
+
+		if (line_len > 1 && data[pos] == '[' && data[pos + 1] == '@') {
+			ssize_t ret;
+
+			ret = parse_embedded_group(settings, data + pos,
+							line_len, len - pos,
+							line);
+			if (ret < 0)
+				return false;
+
+			/*
+			 * This is the offset for the actual raw data, the
+			 * group line will be offset below
+			 */
+			pos += ret;
+		} else if (data[pos] == '[') {
+			r = parse_group(settings, data + pos, line_len, line);
+			if (r)
+				has_group = true;
+		} else if (data[pos] != '#') {
+			if (!has_group)
+				return false;
+
+			r = parse_keyvalue(settings, data + pos, line_len,
+						line);
+		}
+
+		pos += line_len;
+	}
+
+	return r;
+}
+
+LIB_EXPORT char *l_settings_to_data(const struct l_settings *settings,
+								size_t *len)
+{
+	struct l_string *buf;
+	char *ret;
+	const struct l_queue_entry *group_entry;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	buf = l_string_new(255);
+
+	group_entry = l_queue_get_entries(settings->groups);
+	while (group_entry) {
+		struct group_data *group = group_entry->data;
+		const struct l_queue_entry *setting_entry;
+
+		l_string_append_printf(buf, "[%s]\n", group->name);
+
+		setting_entry = l_queue_get_entries(group->settings);
+
+		while (setting_entry) {
+			struct setting_data *setting = setting_entry->data;
+
+			l_string_append_printf(buf, "%s=%s\n",
+						setting->key, setting->value);
+			setting_entry = setting_entry->next;
+		}
+
+		if (group_entry->next)
+			l_string_append_c(buf, '\n');
+
+		group_entry = group_entry->next;
+	}
+
+	group_entry = l_queue_get_entries(settings->embedded_groups);
+
+	if (group_entry && l_queue_length(settings->groups) > 0)
+		l_string_append_c(buf, '\n');
+
+	while (group_entry) {
+		struct embedded_group_data *group = group_entry->data;
+
+		l_string_append_printf(buf, "[@%s@%s]\n%s",
+					group->type,
+					group->name,
+					group->data);
+		if (group_entry->next)
+			l_string_append_c(buf, '\n');
+
+		group_entry = group_entry->next;
+	}
+
+	ret = l_string_unwrap(buf);
+
+	if (len)
+		*len = strlen(ret);
+
+	return ret;
+}
+
+LIB_EXPORT bool l_settings_load_from_file(struct l_settings *settings,
+						const char *filename)
+{
+	int fd;
+	struct stat st;
+	char *data;
+	bool r;
+
+	if (unlikely(!settings || !filename))
+		return false;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Could not open %s (%s)", filename,
+				strerror(errno));
+		return false;
+	}
+
+	if (fstat(fd, &st) < 0) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Could not stat %s (%s)", filename,
+				strerror(errno));
+		close(fd);
+
+		return false;
+	}
+
+	/* Nothing to do, assume success */
+	if (st.st_size == 0) {
+		close(fd);
+		return true;
+	}
+
+	data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (data == MAP_FAILED) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Could not mmap %s (%s)", filename,
+				strerror(errno));
+		close(fd);
+
+		return false;
+	}
+
+	r = l_settings_load_from_data(settings, data, st.st_size);
+
+	munmap(data, st.st_size);
+	close(fd);
+
+	return r;
+}
+
+LIB_EXPORT bool l_settings_set_debug(struct l_settings *settings,
+					l_settings_debug_cb_t callback,
+					void *user_data,
+					l_settings_destroy_cb_t destroy)
+{
+	if (unlikely(!settings))
+		return false;
+
+	if (settings->debug_destroy)
+		settings->debug_destroy(settings->debug_data);
+
+	settings->debug_handler = callback;
+	settings->debug_destroy = destroy;
+	settings->debug_data = user_data;
+
+	return true;
+}
+
+static bool group_match(const void *a, const void *b)
+{
+	const struct group_data *group = a;
+	const char *name = b;
+
+	return !strcmp(group->name, name);
+}
+
+struct gather_data {
+	int cur;
+	char **v;
+};
+
+static void gather_groups(void *data, void *user_data)
+{
+	struct group_data *group_data = data;
+	struct gather_data *gather = user_data;
+
+	gather->v[gather->cur++] = l_strdup(group_data->name);
+}
+
+LIB_EXPORT char **l_settings_get_groups(const struct l_settings *settings)
+{
+	char **ret;
+	struct gather_data gather;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	ret = l_new(char *, l_queue_length(settings->groups) + 1);
+	gather.v = ret;
+	gather.cur = 0;
+
+	l_queue_foreach(settings->groups, gather_groups, &gather);
+
+	return ret;
+}
+
+LIB_EXPORT bool l_settings_has_group(const struct l_settings *settings,
+					const char *group_name)
+{
+	struct group_data *group;
+
+	if (unlikely(!settings))
+		return false;
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+
+	return !!group;
+}
+
+static bool key_match(const void *a, const void *b)
+{
+	const struct setting_data *setting = a;
+	const char *key = b;
+
+	return !strcmp(setting->key, key);
+}
+
+static void gather_keys(void *data, void *user_data)
+{
+	struct setting_data *setting_data = data;
+	struct gather_data *gather = user_data;
+
+	gather->v[gather->cur++] = l_strdup(setting_data->key);
+}
+
+LIB_EXPORT char **l_settings_get_keys(const struct l_settings *settings,
+					const char *group_name)
+{
+	char **ret;
+	struct group_data *group_data;
+	struct gather_data gather;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	group_data = l_queue_find(settings->groups, group_match, group_name);
+	if (!group_data)
+		return NULL;
+
+	ret = l_new(char *, l_queue_length(group_data->settings) + 1);
+	gather.v = ret;
+	gather.cur = 0;
+
+	l_queue_foreach(group_data->settings, gather_keys, &gather);
+
+	return ret;
+}
+
+LIB_EXPORT bool l_settings_has_key(const struct l_settings *settings,
+					const char *group_name, const char *key)
+{
+	struct group_data *group;
+	struct setting_data *setting;
+
+	if (unlikely(!settings))
+		return false;
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+	if (!group)
+		return false;
+
+	setting = l_queue_find(group->settings, key_match, key);
+
+	return !!setting;
+}
+
+LIB_EXPORT const char *l_settings_get_value(const struct l_settings *settings,
+						const char *group_name,
+						const char *key)
+{
+	struct group_data *group;
+	struct setting_data *setting;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+	if (!group)
+		return NULL;
+
+	setting = l_queue_find(group->settings, key_match, key);
+	if (!setting)
+		return NULL;
+
+	return setting->value;
+}
+
+static bool validate_group_name(const char *group_name)
+{
+	int i;
+
+	for (i = 0; group_name[i]; i++) {
+		if (!l_ascii_isprint(group_name[i]))
+			return false;
+
+		if (group_name[i] == ']' || group_name[i] == '[')
+			return false;
+	}
+
+	return true;
+}
+
+LIB_EXPORT bool l_settings_add_group(struct l_settings *settings,
+					const char *group_name)
+{
+	struct group_data *group;
+
+	if (unlikely(!settings || !group_name))
+		return false;
+
+	if (!validate_group_name(group_name)) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Invalid group name %s", group_name);
+		return false;
+	}
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+	if (group) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Group %s exists", group_name);
+		return true;
+	}
+
+	group = l_new(struct group_data, 1);
+	group->name = l_strdup(group_name);
+	group->settings = l_queue_new();
+	l_queue_push_tail(settings->groups, group);
+	return true;
+}
+
+static bool validate_key(const char *key)
+{
+	int i;
+
+	for (i = 0; key[i]; i++) {
+		if (!validate_key_character(key[i]))
+			return false;
+	}
+
+	return true;
+}
+
+static bool set_value(struct l_settings *settings, const char *group_name,
+			const char *key, char *value)
+{
+	struct group_data *group;
+	struct setting_data *pair;
+
+	if (!validate_group_name(group_name)) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Invalid group name %s", group_name);
+		goto error;
+	}
+
+	if (!validate_key(key)) {
+		l_util_debug(settings->debug_handler, settings->debug_data,
+				"Invalid key %s", key);
+		goto error;
+	}
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+	if (!group) {
+		group = l_new(struct group_data, 1);
+		group->name = l_strdup(group_name);
+		group->settings = l_queue_new();
+
+		l_queue_push_tail(settings->groups, group);
+		goto add_pair;
+	}
+
+	pair = l_queue_find(group->settings, key_match, key);
+	if (!pair) {
+add_pair:
+		pair = l_new(struct setting_data, 1);
+		pair->key = l_strdup(key);
+		pair->value = value;
+		l_queue_push_tail(group->settings, pair);
+
+		return true;
+	}
+
+	explicit_bzero(pair->value, strlen(pair->value));
+	l_free(pair->value);
+	pair->value = value;
+
+	return true;
+
+error:
+	explicit_bzero(value, strlen(value));
+	l_free(value);
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_value(struct l_settings *settings,
+					const char *group_name, const char *key,
+					const char *value)
+{
+	if (unlikely(!settings || !value))
+		return false;
+
+	return set_value(settings, group_name, key, l_strdup(value));
+}
+
+LIB_EXPORT bool l_settings_get_bool(const struct l_settings *settings,
+					const char *group_name, const char *key,
+					bool *out)
+{
+	const char *value;
+
+	value = l_settings_get_value(settings, group_name, key);
+	if (!value)
+		return false;
+
+	if (!strcasecmp(value, "true") || !strcmp(value, "1")) {
+		if (out)
+			*out = true;
+
+		return true;
+	}
+
+	if (!strcasecmp(value, "false") || !strcmp(value, "0")) {
+		if (out)
+			*out = false;
+
+		return true;
+	}
+
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as a bool", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_bool(struct l_settings *settings,
+					const char *group_name, const char *key,
+					bool in)
+{
+	static const char *true_str = "true";
+	static const char *false_str = "false";
+	const char *v;
+
+	if (in == false)
+		v = false_str;
+	else
+		v = true_str;
+
+	return l_settings_set_value(settings, group_name, key, v);
+}
+
+LIB_EXPORT bool l_settings_get_int(const struct l_settings *settings,
+					const char *group_name,
+					const char *key, int *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	long int r;
+	int t;
+	char *endp;
+
+	if (!value)
+		return false;
+
+	if (*value == '\0')
+		goto error;
+
+	errno = 0;
+
+	t = r = strtol(value, &endp, 0);
+	if (*endp != '\0')
+		goto error;
+
+	if (unlikely(errno == ERANGE || r != t))
+		goto error;
+
+	if (out)
+		*out = r;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as an int", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_int(struct l_settings *settings,
+					const char *group_name, const char *key,
+					int in)
+{
+	char buf[64];
+
+	snprintf(buf, sizeof(buf), "%d", in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_get_uint(const struct l_settings *settings,
+					const char *group_name,
+					const char *key,
+					unsigned int *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+
+	if (!value)
+		return false;
+
+	if (l_safe_atou32(value, out) < 0)
+		goto error;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as a uint", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_uint(struct l_settings *settings,
+					const char *group_name, const char *key,
+					unsigned int in)
+{
+	char buf[64];
+
+	snprintf(buf, sizeof(buf), "%u", in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_get_int64(const struct l_settings *settings,
+					const char *group_name, const char *key,
+					int64_t *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	int64_t r;
+	char *endp;
+
+	if (!value)
+		return false;
+
+	if (*value == '\0')
+		goto error;
+
+	errno = 0;
+
+	r = strtoll(value, &endp, 0);
+	if (*endp != '\0')
+		goto error;
+
+	if (unlikely(errno == ERANGE))
+		goto error;
+
+	if (out)
+		*out = r;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as an int64", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_int64(struct l_settings *settings,
+					const char *group_name, const char *key,
+					int64_t in)
+{
+	char buf[64];
+
+	snprintf(buf, sizeof(buf), "%" PRId64, in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_get_uint64(const struct l_settings *settings,
+					const char *group_name,
+					const char *key,
+					uint64_t *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	uint64_t r;
+	char *endp;
+
+	if (!value)
+		return false;
+
+	/* Do not allow '+' or '-' or empty string */
+	if (!l_ascii_isdigit(*value))
+		goto error;
+
+	errno = 0;
+
+	r = strtoull(value, &endp, 0);
+	if (*endp != '\0')
+		goto error;
+
+	if (unlikely(errno == ERANGE))
+		goto error;
+
+	if (out)
+		*out = r;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as a uint64", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_uint64(struct l_settings *settings,
+					const char *group_name, const char *key,
+					uint64_t in)
+{
+	char buf[64];
+
+	snprintf(buf, sizeof(buf), "%" PRIu64, in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT char *l_settings_get_string(const struct l_settings *settings,
+					const char *group_name, const char *key)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+
+	if (!value)
+		return NULL;
+
+	return unescape_value(value);
+}
+
+LIB_EXPORT bool l_settings_set_string(struct l_settings *settings,
+					const char *group_name, const char *key,
+					const char *value)
+{
+	char *buf;
+
+	if (unlikely(!settings || !value))
+		return false;
+
+	buf = escape_value(value);
+
+	return set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT char **l_settings_get_string_list(const struct l_settings *settings,
+						const char *group_name,
+						const char *key,
+						const char delimiter)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	char *str;
+	char **ret;
+
+	if (!value)
+		return NULL;
+
+	str = unescape_value(value);
+	if (str == NULL)
+		return NULL;
+
+	ret = l_strsplit(str, delimiter);
+	l_free(str);
+
+	return ret;
+}
+
+LIB_EXPORT bool l_settings_set_string_list(struct l_settings *settings,
+					const char *group_name, const char *key,
+					char **value, char delimiter)
+{
+	char *buf;
+	char *tmp;
+
+	if (unlikely(!settings || !value))
+		return false;
+
+	tmp = l_strjoinv(value, delimiter);
+	buf = escape_value(tmp);
+	l_free(tmp);
+
+	return set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_get_double(const struct l_settings *settings,
+					const char *group_name, const char *key,
+					double *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	char *endp;
+	double r;
+
+	if (!value)
+		return NULL;
+
+	if (*value == '\0')
+		goto error;
+
+	errno = 0;
+
+	r = strtod(value, &endp);
+	if (*endp != '\0')
+		goto error;
+
+	if (unlikely(errno == ERANGE))
+		goto error;
+
+	if (out)
+		*out = r;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as a double", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_double(struct l_settings *settings,
+					const char *group_name, const char *key,
+					double in)
+{
+	L_AUTO_FREE_VAR(char *, buf);
+
+	buf = l_strdup_printf("%f", in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_get_float(const struct l_settings *settings,
+					const char *group_name, const char *key,
+					float *out)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+	char *endp;
+	float r;
+
+	if (!value)
+		return NULL;
+
+	if (*value == '\0')
+		goto error;
+
+	errno = 0;
+
+	r = strtof(value, &endp);
+	if (*endp != '\0')
+		goto error;
+
+	if (unlikely(errno == ERANGE))
+		goto error;
+
+	if (out)
+		*out = r;
+
+	return true;
+
+error:
+	l_util_debug(settings->debug_handler, settings->debug_data,
+			"Could not interpret %s as a float", value);
+
+	return false;
+}
+
+LIB_EXPORT bool l_settings_set_float(struct l_settings *settings,
+					const char *group_name, const char *key,
+					float in)
+{
+	L_AUTO_FREE_VAR(char *, buf);
+
+	buf = l_strdup_printf("%f", (double)in);
+
+	return l_settings_set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT uint8_t *l_settings_get_bytes(const struct l_settings *settings,
+						const char *group_name,
+						const char *key,
+						size_t *out_len)
+{
+	const char *value = l_settings_get_value(settings, group_name, key);
+
+	if (!value)
+		return NULL;
+
+	if (value[0] == '\0') {
+		*out_len = 0;
+
+		/* Return something that can be l_freed but is not a NULL */
+		return l_memdup("", 1);
+	}
+
+	return l_util_from_hexstring(value, out_len);
+}
+
+LIB_EXPORT bool l_settings_set_bytes(struct l_settings *settings,
+					const char *group_name, const char *key,
+					const uint8_t *value, size_t value_len)
+{
+	char *buf;
+
+	if (unlikely(!settings || !value))
+		return false;
+
+	if (value_len)
+		buf = l_util_hexstring(value, value_len);
+	else
+		buf = l_strdup("");
+
+	return set_value(settings, group_name, key, buf);
+}
+
+LIB_EXPORT bool l_settings_remove_group(struct l_settings *settings,
+					const char *group_name)
+{
+	struct group_data *group;
+
+	if (unlikely(!settings))
+		return false;
+
+	group = l_queue_remove_if(settings->groups, group_match, group_name);
+	if (!group)
+		return false;
+
+	group_destroy(group);
+
+	return true;
+}
+
+LIB_EXPORT bool l_settings_remove_key(struct l_settings *settings,
+					const char *group_name,
+					const char *key)
+{
+	struct group_data *group;
+	struct setting_data *setting;
+
+	if (unlikely(!settings))
+		return false;
+
+	group = l_queue_find(settings->groups, group_match, group_name);
+	if (!group)
+		return false;
+
+	setting = l_queue_remove_if(group->settings, key_match, key);
+	if (!setting)
+		return false;
+
+	setting_destroy(setting);
+
+	return true;
+}
+
+static void gather_embedded_groups(void *data, void *user_data)
+{
+	struct embedded_group_data *group_data = data;
+	struct gather_data *gather = user_data;
+
+	gather->v[gather->cur++] = l_strdup(group_data->name);
+}
+
+LIB_EXPORT char **l_settings_get_embedded_groups(struct l_settings *settings)
+{
+	char **ret;
+	struct gather_data gather;
+
+	if (unlikely(!settings))
+		return NULL;
+
+	ret = l_new(char *, l_queue_length(settings->groups) + 1);
+	gather.v = ret;
+	gather.cur = 0;
+
+	l_queue_foreach(settings->embedded_groups, gather_embedded_groups,
+				&gather);
+
+	return ret;
+}
+
+static bool embedded_group_match(const void *a, const void *b)
+{
+	const struct embedded_group_data *group = a;
+	const char *name = b;
+
+	return !strcmp(group->name, name);
+}
+
+LIB_EXPORT bool l_settings_has_embedded_group(struct l_settings *settings,
+						const char *group)
+{
+	struct embedded_group_data *group_data;
+
+	if (unlikely(!settings))
+		return false;
+
+	group_data = l_queue_find(settings->embedded_groups,
+					embedded_group_match, group);
+
+	return group_data != NULL;
+}
+
+LIB_EXPORT const char *l_settings_get_embedded_value(
+						struct l_settings *settings,
+						const char *group_name,
+						const char **out_type)
+{
+	struct embedded_group_data *group;
+
+	if (unlikely(!settings))
+		return false;
+
+	group = l_queue_find(settings->embedded_groups,
+					embedded_group_match, group_name);
+	if (!group)
+		return NULL;
+
+	if (out_type)
+		*out_type = group->type;
+
+	return group->data;
+}
+
+LIB_EXPORT bool l_settings_remove_embedded_groups(struct l_settings *settings)
+{
+	if (unlikely(!settings))
+		return false;
+
+	l_queue_clear(settings->embedded_groups, embedded_group_destroy);
+
+	return true;
+}
diff --git a/ell/settings.h b/ell/settings.h
new file mode 100644
index 0000000..b3e73d8
--- /dev/null
+++ b/ell/settings.h
@@ -0,0 +1,136 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_SETTINGS_H
+#define __ELL_SETTINGS_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_settings;
+
+typedef void (*l_settings_debug_cb_t) (const char *str, void *user_data);
+typedef void (*l_settings_destroy_cb_t) (void *user_data);
+
+struct l_settings *l_settings_new(void);
+struct l_settings *l_settings_clone(const struct l_settings *settings);
+
+void l_settings_free(struct l_settings *settings);
+DEFINE_CLEANUP_FUNC(l_settings_free);
+
+bool l_settings_load_from_data(struct l_settings *settings,
+						const char *data, size_t len);
+char *l_settings_to_data(const struct l_settings *settings, size_t *len);
+
+bool l_settings_load_from_file(struct l_settings *settings,
+					const char *filename);
+
+bool l_settings_set_debug(struct l_settings *settings,
+				l_settings_debug_cb_t callback,
+				void *user_data,
+				l_settings_destroy_cb_t destroy);
+
+char **l_settings_get_groups(const struct l_settings *settings);
+char **l_settings_get_keys(const struct l_settings *settings,
+							const char *group_name);
+
+bool l_settings_add_group(struct l_settings *settings, const char *group_name);
+
+bool l_settings_has_group(const struct l_settings *settings,
+							const char *group_name);
+bool l_settings_has_key(const struct l_settings *settings,
+				const char *group_name, const char *key);
+
+const char *l_settings_get_value(const struct l_settings *settings,
+					const char *group_name,
+					const char *key);
+bool l_settings_set_value(struct l_settings *settings, const char *group_name,
+				const char *key, const char *value);
+
+bool l_settings_get_bool(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, bool *out);
+bool l_settings_set_bool(struct l_settings *settings, const char *group_name,
+				const char *key, bool in);
+
+bool l_settings_get_int(const struct l_settings *settings,
+			const char *group_name, const char *key, int *out);
+bool l_settings_set_int(struct l_settings *settings, const char *group_name,
+				const char *key, int in);
+
+bool l_settings_get_uint(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, unsigned int *out);
+bool l_settings_set_uint(struct l_settings *settings, const char *group_name,
+				const char *key, unsigned int in);
+
+bool l_settings_get_int64(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, int64_t *out);
+bool l_settings_set_int64(struct l_settings *settings, const char *group_name,
+				const char *key, int64_t in);
+
+bool l_settings_get_uint64(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, uint64_t *out);
+bool l_settings_set_uint64(struct l_settings *settings, const char *group_name,
+				const char *key, uint64_t in);
+
+char *l_settings_get_string(const struct l_settings *settings,
+				const char *group_name, const char *key);
+bool l_settings_set_string(struct l_settings *settings, const char *group_name,
+				const char *key, const char *value);
+
+char **l_settings_get_string_list(const struct l_settings *settings,
+					const char *group_name,
+					const char *key, char delimiter);
+bool l_settings_set_string_list(struct l_settings *settings,
+					const char *group_name,
+					const char *key, char **list,
+					char delimiter);
+
+bool l_settings_get_double(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, double *out);
+bool l_settings_set_double(struct l_settings *settings, const char *group_name,
+				const char *key, double in);
+
+bool l_settings_get_float(const struct l_settings *settings,
+				const char *group_name,
+				const char *key, float *out);
+bool l_settings_set_float(struct l_settings *settings, const char *group_name,
+				const char *key, float in);
+
+uint8_t *l_settings_get_bytes(const struct l_settings *settings,
+				const char *group_name, const char *key,
+				size_t *out_len);
+bool l_settings_set_bytes(struct l_settings *settings, const char *group_name,
+				const char *key,
+				const uint8_t *value, size_t value_len);
+
+bool l_settings_remove_key(struct l_settings *settings, const char *group_name,
+				const char *key);
+bool l_settings_remove_group(struct l_settings *settings,
+				const char *group_name);
+
+bool l_settings_remove_embedded_groups(struct l_settings *settings);
+char **l_settings_get_embedded_groups(struct l_settings *settings);
+bool l_settings_has_embedded_group(struct l_settings *settings,
+					const char *group);
+const char *l_settings_get_embedded_value(struct l_settings *settings,
+						const char *group_name,
+						const char **out_type);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_SETTINGS_H */
diff --git a/ell/signal.c b/ell/signal.c
new file mode 100644
index 0000000..c1c3512
--- /dev/null
+++ b/ell/signal.c
@@ -0,0 +1,253 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
+
+#include "util.h"
+#include "io.h"
+#include "queue.h"
+#include "signal.h"
+#include "private.h"
+
+/**
+ * SECTION:signal
+ * @short_description: Unix signal support
+ *
+ * Unix signal support
+ */
+
+/**
+ * l_signal:
+ *
+ * Opaque object representing the signal.
+ */
+struct l_signal {
+	struct signal_desc *desc;
+	l_signal_notify_cb_t callback;
+	void *user_data;
+	l_signal_destroy_cb_t destroy;
+};
+
+struct signal_desc {
+	uint32_t signo;
+	struct l_queue *callbacks;
+};
+
+static struct l_io *signalfd_io = NULL;
+static struct l_queue *signal_list = NULL;
+static sigset_t signal_mask;
+
+static void handle_callback(struct signal_desc *desc)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(desc->callbacks); entry;
+							entry = entry->next) {
+		struct l_signal *signal = entry->data;
+
+		if (signal->callback)
+			signal->callback(signal->user_data);
+	}
+}
+
+static bool desc_match_signo(const void *a, const void *b)
+{
+	const struct signal_desc *desc = a;
+	uint32_t signo = L_PTR_TO_UINT(b);
+
+	return (desc->signo == signo);
+}
+
+static bool signalfd_read_cb(struct l_io *io, void *user_data)
+{
+	int fd = l_io_get_fd(io);
+	struct signal_desc *desc;
+	struct signalfd_siginfo si;
+	ssize_t result;
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return true;
+
+	desc = l_queue_find(signal_list, desc_match_signo,
+						L_UINT_TO_PTR(si.ssi_signo));
+	if (desc)
+		handle_callback(desc);
+
+	return true;
+}
+
+static bool signalfd_add(int signo)
+{
+	int fd;
+
+	if (!signalfd_io) {
+		fd = -1;
+		sigemptyset(&signal_mask);
+	} else
+		fd = l_io_get_fd(signalfd_io);
+
+	sigaddset(&signal_mask, signo);
+
+	fd = signalfd(fd, &signal_mask, SFD_CLOEXEC);
+	if (fd < 0)
+		return false;
+
+	if (signalfd_io)
+		return true;
+
+	signalfd_io = l_io_new(fd);
+	if (!signalfd_io) {
+		close(fd);
+		return false;
+	}
+
+	l_io_set_close_on_destroy(signalfd_io, true);
+
+	if (!l_io_set_read_handler(signalfd_io, signalfd_read_cb, NULL, NULL)) {
+		l_io_destroy(signalfd_io);
+		return false;
+	}
+
+	signal_list = l_queue_new();
+
+	return true;
+}
+
+static void signalfd_remove(int signo)
+{
+	if (!signalfd_io)
+		return;
+
+	sigdelset(&signal_mask, signo);
+
+	if (!sigisemptyset(&signal_mask)) {
+		signalfd(l_io_get_fd(signalfd_io), &signal_mask, SFD_CLOEXEC);
+		return;
+	}
+
+	l_io_destroy(signalfd_io);
+	signalfd_io = NULL;
+
+	l_queue_destroy(signal_list, NULL);
+	signal_list = NULL;
+}
+
+/**
+ * l_signal_create:
+ * @callback: signal callback function
+ * @user_data: user data provided to signal callback function
+ * @destroy: destroy function for user data
+ *
+ * Create new signal callback handling for a given set of signals.
+ *
+ * Returns: a newly allocated #l_signal object
+ **/
+LIB_EXPORT struct l_signal *l_signal_create(uint32_t signo,
+				l_signal_notify_cb_t callback,
+				void *user_data, l_signal_destroy_cb_t destroy)
+{
+	struct l_signal *signal;
+	struct signal_desc *desc;
+	sigset_t mask, oldmask;
+
+	if (signo <= 1 || signo >= _NSIG)
+		return NULL;
+
+	signal = l_new(struct l_signal, 1);
+	signal->callback = callback;
+	signal->destroy = destroy;
+	signal->user_data = user_data;
+
+	desc = l_queue_find(signal_list, desc_match_signo,
+						L_UINT_TO_PTR(signo));
+	if (desc)
+		goto done;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, signo);
+
+	if (sigprocmask(SIG_BLOCK, &mask, &oldmask) < 0) {
+		l_free(signal);
+		return NULL;
+	}
+
+	if (!signalfd_add(signo)) {
+		sigprocmask(SIG_SETMASK, &oldmask, NULL);
+		l_free(signal);
+		return NULL;
+	}
+
+	desc = l_new(struct signal_desc, 1);
+	desc->signo = signo;
+	desc->callbacks = l_queue_new();
+
+	l_queue_push_tail(signal_list, desc);
+
+done:
+	l_queue_push_tail(desc->callbacks, signal);
+	signal->desc = desc;
+	return signal;
+}
+
+/**
+ * l_signal_remove:
+ * @signal: signal object
+ *
+ * Remove signal handling.
+ **/
+LIB_EXPORT void l_signal_remove(struct l_signal *signal)
+{
+	struct signal_desc *desc;
+	sigset_t mask;
+
+	if (!signal)
+		return;
+
+	desc = signal->desc;
+	l_queue_remove(desc->callbacks, signal);
+
+	/*
+	 * As long as the signal descriptor has callbacks registered, it is
+	 * still needed to be active.
+	 */
+	if (!l_queue_isempty(desc->callbacks))
+		goto done;
+
+	if (!l_queue_remove(signal_list, desc))
+		goto done;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, desc->signo);
+
+	/*
+	 * When the number of signals goes to zero, then this will close
+	 * the signalfd file descriptor, otherwise it will only adjust the
+	 * signal mask to account for the removed signal.
+	 *
+	 */
+	signalfd_remove(desc->signo);
+	sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	l_queue_destroy(desc->callbacks, NULL);
+	l_free(desc);
+
+done:
+	if (signal->destroy)
+		signal->destroy(signal->user_data);
+
+	l_free(signal);
+}
diff --git a/ell/signal.h b/ell/signal.h
new file mode 100644
index 0000000..f9a90f8
--- /dev/null
+++ b/ell/signal.h
@@ -0,0 +1,30 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_SIGNAL_H
+#define __ELL_SIGNAL_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_signal;
+
+typedef void (*l_signal_notify_cb_t) (void *user_data);
+typedef void (*l_signal_destroy_cb_t) (void *user_data);
+
+struct l_signal *l_signal_create(uint32_t signo, l_signal_notify_cb_t callback,
+				void *user_data, l_signal_destroy_cb_t destroy);
+void l_signal_remove(struct l_signal *signal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_SIGNAL_H */
diff --git a/ell/siphash-private.h b/ell/siphash-private.h
new file mode 100644
index 0000000..97b2525
--- /dev/null
+++ b/ell/siphash-private.h
@@ -0,0 +1,12 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void _siphash24(uint8_t out[8], const uint8_t *in, size_t inlen,
+						const uint8_t k[16]);
diff --git a/ell/siphash.c b/ell/siphash.c
new file mode 100644
index 0000000..70daaad
--- /dev/null
+++ b/ell/siphash.c
@@ -0,0 +1,123 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "siphash-private.h"
+
+/*
+ * Based on public domain SipHash reference C implementation
+ *
+ * Written in 2012 by
+ * Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
+ * Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ */
+
+#define ROTL(x,b) (uint64_t) (((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v)			\
+	(p)[0] = (uint8_t) ((v));	\
+	(p)[1] = (uint8_t) ((v) >>  8);	\
+	(p)[2] = (uint8_t) ((v) >> 16);	\
+	(p)[3] = (uint8_t) ((v) >> 24);
+
+#define U64TO8_LE(p, v)					\
+	U32TO8_LE((p), (uint32_t) ((v)));		\
+	U32TO8_LE((p) + 4, (uint32_t) ((v) >> 32));
+
+#define U8TO64_LE(p)			\
+	(((uint64_t) ((p)[0])) |	\
+	((uint64_t) ((p)[1]) <<  8) |	\
+	((uint64_t) ((p)[2]) << 16) |	\
+	((uint64_t) ((p)[3]) << 24) |	\
+	((uint64_t) ((p)[4]) << 32) |	\
+	((uint64_t) ((p)[5]) << 40) |	\
+	((uint64_t) ((p)[6]) << 48) |	\
+	((uint64_t) ((p)[7]) << 56))
+
+#define SIPROUND				\
+	do {					\
+		v0 += v1; v1=ROTL(v1, 13);	\
+		v1 ^= v0; v0=ROTL(v0, 32);	\
+		v2 += v3; v3=ROTL(v3, 16);	\
+		v3 ^= v2;			\
+		v0 += v3; v3=ROTL(v3, 21);	\
+		v3 ^= v0;			\
+		v2 += v1; v1=ROTL(v1, 17);	\
+		v1 ^= v2; v2=ROTL(v2, 32);	\
+	} while(0)
+
+void _siphash24(uint8_t out[8], const uint8_t *in, size_t inlen,
+						const uint8_t k[16])
+{
+	/* "somepseudorandomlygeneratedbytes" */
+	uint64_t v0 = 0x736f6d6570736575ULL;
+	uint64_t v1 = 0x646f72616e646f6dULL;
+	uint64_t v2 = 0x6c7967656e657261ULL;
+	uint64_t v3 = 0x7465646279746573ULL;
+	uint64_t b;
+	uint64_t k0 = U8TO64_LE(k);
+	uint64_t k1 = U8TO64_LE(k + 8);
+	uint64_t m;
+	const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+	const int left = inlen & 7;
+
+	b = ((uint64_t) inlen) << 56;
+	v3 ^= k1;
+	v2 ^= k0;
+	v1 ^= k1;
+	v0 ^= k0;
+
+	for (; in != end; in += 8) {
+		m = U8TO64_LE(in);
+		v3 ^= m;
+		SIPROUND;
+		SIPROUND;
+		v0 ^= m;
+	}
+
+	switch (left) {
+	case 7:
+		b |= ((uint64_t) in[6]) << 48;
+		/* fall through */
+	case 6:
+		b |= ((uint64_t) in[5]) << 40;
+		/* fall through */
+	case 5:
+		b |= ((uint64_t) in[4]) << 32;
+		/* fall through */
+	case 4:
+		b |= ((uint64_t) in[3]) << 24;
+		/* fall through */
+	case 3:
+		b |= ((uint64_t) in[2]) << 16;
+		/* fall through */
+	case 2:
+		b |= ((uint64_t) in[1]) << 8;
+		/* fall through */
+	case 1:
+		b |= ((uint64_t) in[0]);
+		break;
+	case 0:
+		break;
+	}
+
+	v3 ^= b;
+	SIPROUND;
+	SIPROUND;
+	v0 ^= b;
+	v2 ^= 0xff;
+	SIPROUND;
+	SIPROUND;
+	SIPROUND;
+	SIPROUND;
+	b = v0 ^ v1 ^ v2  ^ v3;
+	U64TO8_LE(out, b)
+}
diff --git a/ell/string.c b/ell/string.c
new file mode 100644
index 0000000..e8e45be
--- /dev/null
+++ b/ell/string.c
@@ -0,0 +1,496 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "strv.h"
+#include "string.h"
+#include "private.h"
+#include "useful.h"
+
+/**
+ * SECTION:string
+ * @short_description: Growable string buffer
+ *
+ * Growable string buffer support
+ */
+
+/**
+ * l_string:
+ *
+ * Opaque object representing the string buffer.
+ */
+struct l_string {
+	size_t max;
+	size_t len;
+	char *str;
+};
+
+static void grow_string(struct l_string *str, size_t extra)
+{
+	if (str->len + extra < str->max)
+		return;
+
+	str->max = str->len + extra + 1;
+
+	if (str->max < l_util_pagesize())
+		str->max = roundup_pow_of_two(str->max);
+	else
+		str->max = align_len(str->max, l_util_pagesize());
+
+	str->str = l_realloc(str->str, str->max);
+}
+
+/**
+ * l_string_new:
+ * @initial_length: Initial length of the groable string
+ *
+ * Create new growable string.  If the @initial_length is 0, then a safe
+ * default is chosen.
+ *
+ * Returns: a newly allocated #l_string object.
+ **/
+LIB_EXPORT struct l_string *l_string_new(size_t initial_length)
+{
+	static const size_t DEFAULT_INITIAL_LENGTH = 127;
+	struct l_string *ret;
+
+	ret = l_new(struct l_string, 1);
+
+	if (initial_length == 0)
+		initial_length = DEFAULT_INITIAL_LENGTH;
+
+	grow_string(ret, initial_length);
+	ret->str[0] = '\0';
+
+	return ret;
+}
+
+/**
+ * l_string_free:
+ * @string: growable string object
+ *
+ * Free the growable string object and all associated data
+ **/
+LIB_EXPORT void l_string_free(struct l_string *string)
+{
+	if (unlikely(!string))
+		return;
+
+	l_free(string->str);
+	l_free(string);
+}
+
+/**
+ * l_string_unwrap:
+ * @string: growable string object
+ *
+ * Free the growable string object and return the internal string data.
+ * The caller is responsible for freeing the string data using l_free(),
+ * and the string object is no longer usable.
+ *
+ * Returns: @string's internal buffer
+ **/
+LIB_EXPORT char *l_string_unwrap(struct l_string *string)
+{
+	char *result;
+
+	if (unlikely(!string))
+		return NULL;
+
+	result = string->str;
+
+	l_free(string);
+
+	return result;
+}
+
+/**
+ * l_string_append:
+ * @dest: growable string object
+ * @src: C-style string to copy
+ *
+ * Appends the contents of @src to @dest.  The internal buffer of @dest is
+ * grown if necessary.
+ *
+ * Returns: @dest
+ **/
+LIB_EXPORT struct l_string *l_string_append(struct l_string *dest,
+						const char *src)
+{
+	size_t size;
+
+	if (unlikely(!dest || !src))
+		return NULL;
+
+	size = strlen(src);
+
+	grow_string(dest, size);
+
+	memcpy(dest->str + dest->len, src, size);
+	dest->len += size;
+	dest->str[dest->len] = '\0';
+
+	return dest;
+}
+
+/**
+ * l_string_append_c:
+ * @dest: growable string object
+ * @c: Character
+ *
+ * Appends character given by @c to @dest.  The internal buffer of @dest is
+ * grown if necessary.
+ *
+ * Returns: @dest
+ **/
+LIB_EXPORT struct l_string *l_string_append_c(struct l_string *dest,
+						const char c)
+{
+	if (unlikely(!dest))
+		return NULL;
+
+	grow_string(dest, 1);
+	dest->str[dest->len++] = c;
+	dest->str[dest->len] = '\0';
+
+	return dest;
+}
+
+/**
+ * l_string_append_fixed:
+ * @dest: growable string object
+ * @src: Character array to copy from
+ * @max: Maximum number of characters to copy
+ *
+ * Appends the contents of a fixed size string array @src to @dest.
+ * The internal buffer of @dest is grown if necessary.  Up to a maximum of
+ * @max characters are copied.  If a null is encountered in the first @max
+ * characters, the string is copied only up to the NULL character.
+ *
+ * Returns: @dest
+ **/
+LIB_EXPORT struct l_string *l_string_append_fixed(struct l_string *dest,
+							const char *src,
+							size_t max)
+{
+	const char *nul;
+
+	if (unlikely(!dest || !src || !max))
+		return NULL;
+
+	nul = memchr(src, 0, max);
+	if (nul)
+		max = nul - src;
+
+	grow_string(dest, max);
+
+	memcpy(dest->str + dest->len, src, max);
+	dest->len += max;
+	dest->str[dest->len] = '\0';
+
+	return dest;
+}
+
+/**
+ * l_string_append_vprintf:
+ * @dest: growable string object
+ * @format: the string format.  See the sprintf() documentation
+ * @args: the parameters to insert
+ *
+ * Appends a formatted string to the growable string buffer.  This function
+ * is equivalent to l_string_append_printf except that the arguments are
+ * passed as a va_list.
+ **/
+LIB_EXPORT void l_string_append_vprintf(struct l_string *dest,
+					const char *format, va_list args)
+{
+	size_t len;
+	size_t have_space;
+	va_list args_copy;
+
+	if (unlikely(!dest))
+		return;
+
+#if __STDC_VERSION__ > 199409L
+	va_copy(args_copy, args);
+#else
+	__va_copy(args_copy, args);
+#endif
+
+	have_space = dest->max - dest->len;
+	len = vsnprintf(dest->str + dest->len, have_space, format, args);
+
+	if (len >= have_space) {
+		grow_string(dest, len);
+		len = vsprintf(dest->str + dest->len, format, args_copy);
+	}
+
+	dest->len += len;
+
+	va_end(args_copy);
+}
+
+/**
+ * l_string_append_printf:
+ * @dest: growable string object
+ * @format: the string format.  See the sprintf() documentation
+ * @...: the parameters to insert
+ *
+ * Appends a formatted string to the growable string buffer, growing it as
+ * necessary.
+ **/
+LIB_EXPORT void l_string_append_printf(struct l_string *dest,
+					const char *format, ...)
+{
+	va_list args;
+
+	if (unlikely(!dest))
+		return;
+
+	va_start(args, format);
+	l_string_append_vprintf(dest, format, args);
+	va_end(args);
+}
+
+/**
+ * l_string_length:
+ * @string: growable string object
+ *
+ * Returns: bytes used in the string.
+ **/
+LIB_EXPORT unsigned int l_string_length(struct l_string *string)
+{
+	if (unlikely(!string))
+		return 0;
+
+	return string->len;
+}
+
+LIB_EXPORT struct l_string *l_string_truncate(struct l_string *string,
+							size_t new_size)
+{
+	if (unlikely(!string))
+		return NULL;
+
+	if (new_size >= string->len)
+		return string;
+
+	string->len = new_size;
+	string->str[new_size] = '\0';
+
+	return string;
+}
+
+struct arg {
+	size_t max_len;
+	size_t cur_len;
+	char *chars;
+};
+
+static inline void arg_init(struct arg *arg)
+{
+	arg->max_len = 0;
+	arg->cur_len = 0;
+	arg->chars = NULL;
+}
+
+static void arg_putchar(struct arg *arg, char ch)
+{
+	if (arg->cur_len == arg->max_len) {
+		arg->max_len += 32; /* Grow by at least 32 bytes */
+		arg->chars = l_realloc(arg->chars, 1 + arg->max_len);
+	}
+
+	arg->chars[arg->cur_len++] = ch;
+	arg->chars[arg->cur_len] = '\0';
+}
+
+static void arg_putmem(struct arg *arg, const void *mem, size_t len)
+{
+	if (len == 0)
+		return;
+
+	if (arg->cur_len + len > arg->max_len) {
+		size_t growby = len * 2;
+
+		if (growby < 32)
+			growby = 32;
+
+		arg->max_len += growby;
+		arg->chars = l_realloc(arg->chars, 1 + arg->max_len);
+	}
+
+	memcpy(arg->chars + arg->cur_len, mem, len);
+	arg->cur_len += len;
+	arg->chars[arg->cur_len] = '\0';
+}
+
+static bool parse_backslash(struct arg *arg, const char *args, size_t *pos)
+{
+	/* We're at the backslash, not within double quotes */
+	char c = args[*pos + 1];
+
+	switch (c) {
+	case 0:
+		return false;
+	case '\n':
+		break;
+	default:
+		arg_putchar(arg, c);
+		break;
+	}
+
+	*pos += 1;
+	return true;
+}
+
+static bool parse_quoted_backslash(struct arg *arg,
+						const char *args, size_t *pos)
+{
+	/* We're at the backslash, within double quotes */
+	char c = args[*pos + 1];
+
+	switch (c) {
+	case 0:
+		return false;
+	case '\n':
+		break;
+	case '"':
+	case '\\':
+		arg_putchar(arg, c);
+		break;
+	default:
+		arg_putchar(arg, '\\');
+		arg_putchar(arg, c);
+		break;
+	}
+
+	*pos += 1;
+	return true;
+}
+
+static bool parse_single_quote(struct arg *arg, const char *args, size_t *pos)
+{
+	/* We're just past the single quote */
+	size_t start = *pos;
+
+	for (; args[*pos]; *pos += 1) {
+		if (args[*pos] != '\'')
+			continue;
+
+		arg_putmem(arg, args + start, *pos - start);
+		return true;
+	}
+
+	/* Unterminated ' */
+	return false;
+}
+
+static bool parse_double_quote(struct arg *arg, const char *args, size_t *pos)
+{
+	/* We're just past the double quote */
+	for (; args[*pos]; *pos += 1) {
+		char c = args[*pos];
+
+		switch (c) {
+		case '"':
+			return true;
+		case '\\':
+			if (!parse_quoted_backslash(arg, args, pos))
+				return false;
+
+			break;
+		default:
+			arg_putchar(arg, c);
+			break;
+		}
+	}
+
+	/* Unterminated */
+	return false;
+}
+
+static void add_arg(char ***args, char *arg, int *n_args)
+{
+	*args = l_realloc(*args, sizeof(char *) * (2 + *n_args));
+	(*args)[*n_args] = arg;
+	(*args)[*n_args + 1] = NULL;
+
+	*n_args += 1;
+}
+
+LIB_EXPORT char **l_parse_args(const char *args, int *out_n_args)
+{
+	size_t i;
+	struct arg arg;
+	char **ret = l_realloc(NULL, sizeof(char *));
+	int n_args = 0;
+
+	ret[0] = NULL;
+	arg_init(&arg);
+
+	for (i = 0; args[i]; i++) {
+		switch (args[i]) {
+		case '\\':
+			if (!parse_backslash(&arg, args, &i))
+				goto error;
+			break;
+		case '"':
+			i += 1;
+			if (!parse_double_quote(&arg, args, &i))
+				goto error;
+
+			/* Add an empty string */
+			if (!arg.cur_len)
+				add_arg(&ret, l_strdup(""), &n_args);
+
+			break;
+		case '\'':
+			i += 1;
+			if (!parse_single_quote(&arg, args, &i))
+				goto error;
+
+			/* Add an empty string */
+			if (!arg.cur_len)
+				add_arg(&ret, l_strdup(""), &n_args);
+
+			break;
+		default:
+			if (!strchr(" \t", args[i])) {
+				if (args[i] == '\n')
+					goto error;
+
+				arg_putchar(&arg, args[i]);
+				continue;
+			}
+
+			if (arg.cur_len)
+				add_arg(&ret, arg.chars, &n_args);
+
+			arg_init(&arg);
+			break;
+		}
+	}
+
+	if (arg.cur_len)
+		add_arg(&ret, arg.chars, &n_args);
+
+	if (out_n_args)
+		*out_n_args = n_args;
+
+	return ret;
+
+error:
+	l_free(arg.chars);
+	l_strfreev(ret);
+	return NULL;
+}
diff --git a/ell/string.h b/ell/string.h
new file mode 100644
index 0000000..471648f
--- /dev/null
+++ b/ell/string.h
@@ -0,0 +1,46 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_STRING_H
+#define __ELL_STRING_H
+
+#include <stdarg.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_string;
+
+struct l_string *l_string_new(size_t initial_length);
+void l_string_free(struct l_string *string);
+DEFINE_CLEANUP_FUNC(l_string_free);
+char *l_string_unwrap(struct l_string *string);
+
+struct l_string *l_string_append(struct l_string *dest, const char *src);
+struct l_string *l_string_append_c(struct l_string *dest, const char c);
+struct l_string *l_string_append_fixed(struct l_string *dest, const char *src,
+					size_t max);
+
+void l_string_append_vprintf(struct l_string *dest,
+					const char *format, va_list args)
+					__attribute__((format(printf, 2, 0)));
+void l_string_append_printf(struct l_string *dest, const char *format, ...)
+					__attribute__((format(printf, 2, 3)));
+
+struct l_string *l_string_truncate(struct l_string *string, size_t new_size);
+
+unsigned int l_string_length(struct l_string *string);
+
+char **l_parse_args(const char *args, int *out_n_args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_STRING_H */
diff --git a/ell/strv.c b/ell/strv.c
new file mode 100644
index 0000000..b7bf23c
--- /dev/null
+++ b/ell/strv.c
@@ -0,0 +1,366 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include "strv.h"
+#include "private.h"
+#include "useful.h"
+
+/**
+ * SECTION:strv
+ * @short_description: String array functions
+ *
+ * String array functions
+ */
+
+/**
+ * l_strfreev:
+ * @strlist: String list to free
+ *
+ * Frees a list of strings
+ **/
+LIB_EXPORT void l_strfreev(char **strlist)
+{
+	l_strv_free(strlist);
+}
+
+/**
+ * l_strsplit:
+ * @str: String to split
+ * @sep: The delimiter character
+ *
+ * Splits a string into pieces which do not contain the delimiter character.
+ * As a special case, an empty string is returned as an empty array, e.g.
+ * an array with just the NULL element.
+ *
+ * Note that this function only works with ASCII delimiters.
+ *
+ * Returns: A newly allocated %NULL terminated string array.  This array
+ * should be freed using l_strfreev().
+ **/
+LIB_EXPORT char **l_strsplit(const char *str, const char sep)
+{
+	int len;
+	int i;
+	const char *p;
+	char **ret;
+
+	if (unlikely(!str))
+		return NULL;
+
+	if (str[0] == '\0')
+		return l_new(char *, 1);
+
+	for (p = str, len = 1; *p; p++)
+		if (*p == sep)
+			len += 1;
+
+	ret = l_new(char *, len + 1);
+
+	i = 0;
+	p = str;
+	len = 0;
+
+	while (p[len]) {
+		if (p[len] != sep) {
+			len += 1;
+			continue;
+		}
+
+		ret[i++] = l_strndup(p, len);
+		p += len + 1;
+		len = 0;
+	}
+
+	ret[i++] = l_strndup(p, len);
+
+	return ret;
+}
+
+/**
+ * l_strsplit_set:
+ * @str: String to split
+ * @separators: A set of delimiters
+ *
+ * Splits a string into pieces which do not contain the delimiter characters
+ * that can be found in @separators.
+ * As a special case, an empty string is returned as an empty array, e.g.
+ * an array with just the NULL element.
+ *
+ * Note that this function only works with ASCII delimiters.
+ *
+ * Returns: A newly allocated %NULL terminated string array.  This array
+ * should be freed using l_strfreev().
+ **/
+LIB_EXPORT char **l_strsplit_set(const char *str, const char *separators)
+{
+	int len;
+	int i;
+	const char *p;
+	char **ret;
+	bool sep_table[256];
+
+	if (unlikely(!str))
+		return NULL;
+
+	if (str[0] == '\0')
+		return l_new(char *, 1);
+
+	memset(sep_table, 0, sizeof(sep_table));
+
+	for (p = separators; *p; p++)
+		sep_table[(unsigned char) *p] = true;
+
+	for (p = str, len = 1; *p; p++)
+		if (sep_table[(unsigned char) *p] == true)
+			len += 1;
+
+	ret = l_new(char *, len + 1);
+
+	i = 0;
+	p = str;
+	len = 0;
+
+	while (p[len]) {
+		if (sep_table[(unsigned char) p[len]] != true) {
+			len += 1;
+			continue;
+		}
+
+		ret[i++] = l_strndup(p, len);
+		p += len + 1;
+		len = 0;
+	}
+
+	ret[i++] = l_strndup(p, len);
+
+	return ret;
+}
+
+/**
+ * l_strjoinv:
+ * @str_array: a %NULL terminated array of strings to join
+ * @delim: Delimiting character
+ *
+ * Joins strings contanied in the @str_array into one long string delimited
+ * by @delim.
+ *
+ * Returns: A newly allocated string that should be freed using l_free()
+ */
+LIB_EXPORT char *l_strjoinv(char **str_array, const char delim)
+{
+	size_t len = 0;
+	unsigned int i;
+	char *ret;
+	char *p;
+
+	if (unlikely(!str_array))
+		return NULL;
+
+	if (!str_array[0])
+		return l_strdup("");
+
+	for (i = 0; str_array[i]; i++)
+		len += strlen(str_array[i]);
+
+	len += 1 + i - 1;
+
+	ret = l_malloc(len);
+
+	p = stpcpy(ret, str_array[0]);
+
+	for (i = 1; str_array[i]; i++) {
+		*p++ = delim;
+		p = stpcpy(p, str_array[i]);
+	}
+
+	return ret;
+}
+
+/**
+ * l_strv_new:
+ *
+ * Returns: new empty string array
+ **/
+LIB_EXPORT char **l_strv_new(void)
+{
+	return l_new(char *, 1);
+}
+
+/**
+ * l_strv_free:
+ * @str_array: a %NULL terminated array of strings
+ *
+ * Frees strings in @str_array and @str_array itself
+ **/
+LIB_EXPORT void l_strv_free(char **str_array)
+{
+	if (likely(str_array)) {
+		int i;
+
+		for (i = 0; str_array[i]; i++)
+			l_free(str_array[i]);
+
+		l_free(str_array);
+	}
+}
+
+/**
+ * l_strv_length:
+ * @str_array: a %NULL terminated array of strings
+ *
+ * Returns: the number of strings in @str_array
+ */
+LIB_EXPORT unsigned int l_strv_length(char **str_array)
+{
+	unsigned int i = 0;
+
+	if (unlikely(!str_array))
+		return 0;
+
+	while (str_array[i])
+		i += 1;
+
+	return i;
+}
+
+/**
+ * l_strv_contains:
+ * @str_array: a %NULL terminated array of strings
+ * @item: An item to search for, must be not %NULL
+ *
+ * Returns: #true if @str_array contains item
+ */
+LIB_EXPORT bool l_strv_contains(char **str_array, const char *item)
+{
+	unsigned int i = 0;
+
+	if (unlikely(!str_array || !item))
+		return false;
+
+	while (str_array[i]) {
+		if (!strcmp(str_array[i], item))
+			return true;
+
+		i += 1;
+	}
+
+	return false;
+}
+
+/**
+ * l_strv_append:
+ * @str_array: a %NULL terminated array of strings or %NULL
+ * @str: A string to be appened at the end of @str_array
+ *
+ * Returns: New %NULL terminated array of strings with @str added
+ */
+LIB_EXPORT char **l_strv_append(char **str_array, const char *str)
+{
+	char **ret;
+	unsigned int i, len;
+
+	if (unlikely(!str))
+		return str_array;
+
+	len = l_strv_length(str_array);
+	ret = l_new(char *, len + 2);
+
+	for (i = 0; i < len; i++)
+		ret[i] = str_array[i];
+
+	ret[i] = l_strdup(str);
+
+	l_free(str_array);
+
+	return ret;
+}
+
+LIB_EXPORT char **l_strv_append_printf(char **str_array,
+						const char *format, ...)
+{
+	va_list args;
+	char **ret;
+
+	va_start(args, format);
+	ret = l_strv_append_vprintf(str_array, format, args);
+	va_end(args);
+
+	return ret;
+}
+
+LIB_EXPORT char **l_strv_append_vprintf(char **str_array,
+					const char *format, va_list args)
+{
+	char **ret;
+	unsigned int i, len;
+
+	if (unlikely(!format))
+		return str_array;
+
+	len = l_strv_length(str_array);
+	ret = l_new(char *, len + 2);
+
+	for (i = 0; i < len; i++)
+		ret[i] = str_array[i];
+
+	ret[i] = l_strdup_vprintf(format, args);
+
+	l_free(str_array);
+
+	return ret;
+}
+
+/**
+ * l_strv_copy:
+ * @str_array: a %NULL terminated array of strings or %NULL
+ *
+ * Returns: An independent copy of @str_array.
+ */
+LIB_EXPORT char **l_strv_copy(char **str_array)
+{
+	int i, len;
+	char **copy;
+
+	if (unlikely(!str_array))
+		return NULL;
+
+	for (len = 0; str_array[len]; len++);
+
+	copy = l_malloc(sizeof(char *) * (len + 1));
+
+	for (i = len; i >= 0; i--)
+		copy[i] = l_strdup(str_array[i]);
+
+	return copy;
+}
+
+/**
+ * l_strv_eq:
+ * @a: a %NULL terminated array of strings or %NULL
+ * @b: another %NULL terminated array of strings or %NULL
+ *
+ * Returns: Whether @a and @b's contents are identical, including the
+ * order, or @a and @b are both %NULL.
+ */
+LIB_EXPORT bool l_strv_eq(char **a, char **b)
+{
+	if (!a || !b)
+		return a == b;
+
+	for (; *a; a++, b++)
+		if (!*b || strcmp(*a, *b))
+			return false;
+
+	return !*b;
+}
diff --git a/ell/strv.h b/ell/strv.h
new file mode 100644
index 0000000..f6f5c78
--- /dev/null
+++ b/ell/strv.h
@@ -0,0 +1,42 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_STRV_H
+#define __ELL_STRV_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void l_strfreev(char **strlist);
+char **l_strsplit(const char *str, const char sep);
+char **l_strsplit_set(const char *str, const char *separators);
+char *l_strjoinv(char **str_array, const char delim);
+
+char **l_strv_new(void);
+void l_strv_free(char **str_array);
+DEFINE_CLEANUP_FUNC(l_strv_free);
+unsigned int l_strv_length(char **str_array);
+bool l_strv_contains(char **str_array, const char *item);
+char **l_strv_append(char **str_array, const char *str);
+char **l_strv_append_printf(char **str_array, const char *format, ...)
+					__attribute__((format(printf, 2, 3)));
+char **l_strv_append_vprintf(char **str_array, const char *format,
+							va_list args)
+					__attribute__((format(printf, 2, 0)));
+char **l_strv_copy(char **str_array);
+bool l_strv_eq(char **a, char **b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_STRV_H */
diff --git a/ell/tester.c b/ell/tester.c
new file mode 100644
index 0000000..552ffb7
--- /dev/null
+++ b/ell/tester.c
@@ -0,0 +1,765 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2021  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sys/time.h>
+
+#include "idle.h"
+#include "log.h"
+#include "private.h"
+#include "queue.h"
+#include "time.h"
+#include "timeout.h"
+#include "useful.h"
+#include "tester.h"
+
+/**
+ * SECTION:tester
+ * @short_description: Non-interactive test framework
+ *
+ * Non-interactive test framework
+ */
+
+#define COLOR_OFF	"\x1B[0m"
+#define COLOR_BLACK	"\x1B[0;30m"
+#define COLOR_RED	"\x1B[0;31m"
+#define COLOR_GREEN	"\x1B[0;32m"
+#define COLOR_YELLOW	"\x1B[0;33m"
+#define COLOR_BLUE	"\x1B[0;34m"
+#define COLOR_MAGENTA	"\x1B[0;35m"
+#define COLOR_HIGHLIGHT	"\x1B[1;39m"
+
+#define print_text(color, fmt, args...) \
+		l_info(color fmt COLOR_OFF, ## args)
+
+#define print_summary(label, color, value, fmt, args...) \
+		l_info("%-52s " color "%-10s" COLOR_OFF fmt, \
+							label, value, ## args)
+
+#define print_progress(name, color, fmt, args...) \
+		l_info(COLOR_HIGHLIGHT "%s" COLOR_OFF " - " \
+				color fmt COLOR_OFF, name, ## args)
+
+enum test_result {
+	TEST_RESULT_NOT_RUN,
+	TEST_RESULT_PASSED,
+	TEST_RESULT_FAILED,
+	TEST_RESULT_TIMED_OUT,
+};
+
+struct l_tester {
+	uint64_t start_time;
+	struct l_queue *tests;
+	const struct l_queue_entry *test_entry;
+	bool list_cases;
+	const char *prefix;
+	const char *substring;
+	l_tester_finish_func_t finish_callback;
+};
+
+struct test_case {
+	uint64_t start_time;
+	uint64_t end_time;
+	char *name;
+	enum test_result result;
+	enum l_tester_stage stage;
+	const void *test_data;
+	l_tester_data_func_t pre_setup_func;
+	l_tester_data_func_t setup_func;
+	l_tester_data_func_t test_func;
+	l_tester_data_func_t teardown_func;
+	l_tester_data_func_t post_teardown_func;
+	unsigned int timeout;
+	struct l_timeout *run_timer;
+	l_tester_destroy_func_t destroy;
+	void *user_data;
+	bool teardown;
+};
+
+static void destroy_test(void *data)
+{
+	struct test_case *test = data;
+
+	l_timeout_remove(test->run_timer);
+
+	if (test->destroy)
+		test->destroy(test->user_data);
+
+	l_free(test->name);
+	l_free(test);
+}
+
+static uint64_t get_elapsed_time(uint64_t base)
+{
+	uint64_t now;
+
+	now = l_time_now();
+
+	return l_time_diff(base, now);
+}
+
+static void teardown_callback(void *user_data)
+{
+	struct l_tester *tester = user_data;
+	struct test_case *test;
+
+	test = tester->test_entry->data;
+	test->stage = L_TESTER_STAGE_TEARDOWN;
+	test->teardown = false;
+
+	print_progress(test->name, COLOR_MAGENTA, "teardown");
+
+	if (test->teardown_func)
+		test->teardown_func(test->test_data);
+	else
+		l_tester_teardown_complete(tester);
+}
+
+static void test_timeout(struct l_timeout *timer, void *user_data)
+{
+	struct l_tester *tester = user_data;
+	struct test_case *test;
+
+	test = tester->test_entry->data;
+
+	l_timeout_remove(timer);
+	test->run_timer = NULL;
+
+	test->result = TEST_RESULT_TIMED_OUT;
+	print_progress(test->name, COLOR_RED, "test timed out");
+
+	l_idle_oneshot(teardown_callback, tester, NULL);
+}
+
+static void next_test_case(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (tester->test_entry)
+		tester->test_entry = tester->test_entry->next;
+	else
+		tester->test_entry = l_queue_get_entries(tester->tests);
+
+	if (!tester->test_entry) {
+		if (tester->finish_callback)
+			tester->finish_callback(tester);
+		return;
+	}
+
+	test = tester->test_entry->data;
+
+	print_progress(test->name, COLOR_BLACK, "init");
+
+	test->start_time = get_elapsed_time(tester->start_time);
+
+	if (test->timeout > 0)
+		test->run_timer = l_timeout_create(test->timeout, test_timeout,
+								tester, NULL);
+
+	test->stage = L_TESTER_STAGE_PRE_SETUP;
+
+	if (test->pre_setup_func)
+		test->pre_setup_func(test->test_data);
+	else
+		l_tester_pre_setup_complete(tester);
+}
+
+static void setup_callback(void *user_data)
+{
+	struct l_tester *tester = user_data;
+	struct test_case *test = tester->test_entry->data;
+
+	test->stage = L_TESTER_STAGE_SETUP;
+
+	print_progress(test->name, COLOR_BLUE, "setup");
+
+	if (test->setup_func)
+		test->setup_func(test->test_data);
+	else
+		l_tester_setup_complete(tester);
+}
+
+static void run_callback(void *user_data)
+{
+	struct l_tester *tester = user_data;
+	struct test_case *test = tester->test_entry->data;
+
+	test->stage = L_TESTER_STAGE_RUN;
+
+	print_progress(test->name, COLOR_BLACK, "run");
+	test->test_func(test->test_data);
+}
+
+static void done_callback(void *user_data)
+{
+	struct l_tester *tester = user_data;
+	struct test_case *test = tester->test_entry->data;
+
+	test->end_time = get_elapsed_time(tester->start_time);
+
+	print_progress(test->name, COLOR_BLACK, "done");
+	next_test_case(tester);
+}
+
+LIB_EXPORT void *l_tester_get_data(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return NULL;
+
+	if (!tester->test_entry)
+		return NULL;
+
+	test = tester->test_entry->data;
+
+	return test->user_data;
+}
+
+LIB_EXPORT void l_tester_pre_setup_complete(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_PRE_SETUP)
+		return;
+
+	l_idle_oneshot(setup_callback, tester, NULL);
+}
+
+LIB_EXPORT void l_tester_pre_setup_failed(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_PRE_SETUP)
+		return;
+
+	print_progress(test->name, COLOR_RED, "pre setup failed");
+
+	l_timeout_remove(test->run_timer);
+	test->run_timer = NULL;
+
+	l_idle_oneshot(done_callback, tester, NULL);
+}
+
+LIB_EXPORT void l_tester_setup_complete(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_SETUP)
+		return;
+
+	print_progress(test->name, COLOR_BLUE, "setup complete");
+
+	l_idle_oneshot(run_callback, tester, NULL);
+}
+
+LIB_EXPORT void l_tester_setup_failed(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_SETUP)
+		return;
+
+	test->stage = L_TESTER_STAGE_POST_TEARDOWN;
+
+	l_timeout_remove(test->run_timer);
+	test->run_timer = NULL;
+
+	print_progress(test->name, COLOR_RED, "setup failed");
+	print_progress(test->name, COLOR_MAGENTA, "teardown");
+
+	test->post_teardown_func(test->test_data);
+}
+
+static void test_result(struct l_tester *tester, enum test_result result)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_RUN)
+		return;
+
+	l_timeout_remove(test->run_timer);
+	test->run_timer = NULL;
+
+	test->result = result;
+	switch (result) {
+	case TEST_RESULT_PASSED:
+		print_progress(test->name, COLOR_GREEN, "test passed");
+		break;
+	case TEST_RESULT_FAILED:
+		print_progress(test->name, COLOR_RED, "test failed");
+		break;
+	case TEST_RESULT_NOT_RUN:
+		print_progress(test->name, COLOR_YELLOW, "test not run");
+		break;
+	case TEST_RESULT_TIMED_OUT:
+		print_progress(test->name, COLOR_RED, "test timed out");
+		break;
+	}
+
+	if (test->teardown)
+		return;
+
+	test->teardown = true;
+
+	l_idle_oneshot(teardown_callback, tester, NULL);
+}
+
+LIB_EXPORT void l_tester_test_passed(struct l_tester *tester)
+{
+	if (unlikely(!tester))
+		return;
+
+	test_result(tester, TEST_RESULT_PASSED);
+}
+
+LIB_EXPORT void l_tester_test_failed(struct l_tester *tester)
+{
+	if (unlikely(!tester))
+		return;
+
+	test_result(tester, TEST_RESULT_FAILED);
+}
+
+LIB_EXPORT void l_tester_test_abort(struct l_tester *tester)
+{
+	if (unlikely(!tester))
+		return;
+
+	test_result(tester, TEST_RESULT_NOT_RUN);
+}
+
+LIB_EXPORT void l_tester_teardown_complete(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_TEARDOWN)
+		return;
+
+	test->stage = L_TESTER_STAGE_POST_TEARDOWN;
+
+	if (test->post_teardown_func)
+		test->post_teardown_func(test->test_data);
+	else
+		l_tester_post_teardown_complete(tester);
+}
+
+LIB_EXPORT void l_tester_teardown_failed(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_TEARDOWN)
+		return;
+
+	test->stage = L_TESTER_STAGE_POST_TEARDOWN;
+
+	l_tester_post_teardown_failed(tester);
+}
+
+LIB_EXPORT void l_tester_post_teardown_complete(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_POST_TEARDOWN)
+		return;
+
+	print_progress(test->name, COLOR_MAGENTA, "teardown complete");
+
+	l_idle_oneshot(done_callback, tester, NULL);
+}
+
+LIB_EXPORT void l_tester_post_teardown_failed(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	if (test->stage != L_TESTER_STAGE_POST_TEARDOWN)
+		return;
+
+	print_progress(test->name, COLOR_RED, "teardown failed");
+
+	l_idle_oneshot(done_callback, tester, NULL);
+}
+
+struct wait_data {
+	unsigned int seconds;
+	struct test_case *test;
+	l_tester_wait_func_t func;
+	void *user_data;
+};
+
+static void wait_callback(struct l_timeout *timer, void *user_data)
+{
+	struct wait_data *wait = user_data;
+	struct test_case *test = wait->test;
+
+	wait->seconds--;
+
+	if (wait->seconds > 0) {
+		print_progress(test->name, COLOR_BLACK, "%u seconds left",
+								wait->seconds);
+		return;
+	}
+
+	print_progress(test->name, COLOR_BLACK, "waiting done");
+
+	wait->func(wait->user_data);
+
+	l_free(wait);
+
+	l_timeout_remove(timer);
+}
+
+LIB_EXPORT void l_tester_wait(struct l_tester *tester, unsigned int seconds,
+				l_tester_wait_func_t func, void *user_data)
+{
+	struct test_case *test;
+	struct wait_data *wait;
+
+	if (unlikely(!tester))
+		return;
+
+	if (!func || seconds < 1)
+		return;
+
+	if (!tester->test_entry)
+		return;
+
+	test = tester->test_entry->data;
+
+	wait = l_new(struct wait_data, 1);
+	wait->seconds = seconds;
+	wait->test = test;
+	wait->func = func;
+	wait->user_data = user_data;
+
+	l_timeout_create(seconds, wait_callback, wait, NULL);
+
+	print_progress(test->name, COLOR_BLACK, "waiting %u seconds", seconds);
+}
+
+/**
+ * l_tester_add_full:
+ * @tester: tester instance
+ * @name: test case name
+ * @test_data: test data
+ * @pre_setup_func: test pre-setup function
+ * @setup_func: test setup function
+ * @test_func: test function
+ * @teardown_func: test teardown function
+ * @teardown_func: test post-teardown function
+ * @timeout: test teardown function
+ * @user_data: user data
+ * @destroy: user data destroy function
+ *
+ * Add a new test case.
+ **/
+LIB_EXPORT void l_tester_add_full(struct l_tester *tester, const char *name,
+							const void *test_data,
+					l_tester_data_func_t pre_setup_func,
+					l_tester_data_func_t setup_func,
+					l_tester_data_func_t test_func,
+					l_tester_data_func_t teardown_func,
+					l_tester_data_func_t post_teardown_func,
+					unsigned int timeout,
+					void *user_data,
+					l_tester_destroy_func_t destroy)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester || !test_func))
+		return;
+
+	if (tester->prefix && !l_str_has_prefix(name, tester->prefix)) {
+		if (destroy)
+			destroy(user_data);
+		return;
+	}
+
+	if (tester->substring && !strstr(name, tester->substring)) {
+		if (destroy)
+			destroy(user_data);
+		return;
+	}
+
+	if (tester->list_cases) {
+		l_info("%s", name);
+
+		if (destroy)
+			destroy(user_data);
+		return;
+	}
+
+	test = l_new(struct test_case, 1);
+	test->name = l_strdup(name);
+	test->result = TEST_RESULT_NOT_RUN;
+	test->stage = L_TESTER_STAGE_INVALID;
+
+	test->test_data = test_data;
+	test->pre_setup_func = pre_setup_func;
+	test->setup_func = setup_func;
+	test->test_func = test_func;
+	test->teardown_func = teardown_func;
+	test->post_teardown_func = post_teardown_func;
+	test->timeout = timeout;
+	test->destroy = destroy;
+	test->user_data = user_data;
+
+	l_queue_push_tail(tester->tests, test);
+}
+
+/**
+ * l_tester_add:
+ * @tester: tester instance
+ * @name: test case name
+ * @test_data: test data
+ * @setup_func: test setup function
+ * @test_func: test function
+ * @teardown_func: test teardown function
+ *
+ * Add a new test with default settings for timeout and no pre-setup procedure.
+ **/
+LIB_EXPORT void l_tester_add(struct l_tester *tester, const char *name,
+					const void *test_data,
+					l_tester_data_func_t setup_func,
+					l_tester_data_func_t test_func,
+					l_tester_data_func_t teardown_func)
+{
+	l_tester_add_full(tester, name, test_data, NULL, setup_func, test_func,
+					teardown_func, NULL, 0, NULL, NULL);
+}
+
+/**
+ * l_tester_new:
+ *
+ * Initialize tester framework.
+ *
+ * Returns: new tester instance
+ **/
+LIB_EXPORT struct l_tester *l_tester_new(const char *prefix,
+					const char *substring, bool list_cases)
+{
+	struct l_tester *tester = l_new(struct l_tester, 1);
+
+	tester->prefix = prefix;
+	tester->substring = substring;
+	tester->list_cases = list_cases;
+	tester->tests = l_queue_new();
+	return tester;
+}
+
+/**
+ * l_tester_start:
+ * @tester: tester instance
+ *
+ * Kick off execution of the test queue
+ *
+ **/
+LIB_EXPORT void l_tester_start(struct l_tester *tester,
+					l_tester_finish_func_t finish_func)
+{
+	if (unlikely(!tester))
+		return;
+
+	if (!tester->tests)
+		return;
+
+	tester->finish_callback = finish_func;
+
+	tester->start_time = l_time_now();
+	next_test_case(tester);
+}
+
+/**
+ * l_tester_summarize:
+ * @tester: tester instance
+ *
+ * Print summary of all added test cases.
+ *
+ * Returns: true, if all the tests passed
+ *          false, if any of the tests failed
+ **/
+LIB_EXPORT bool l_tester_summarize(struct l_tester *tester)
+{
+	unsigned int not_run = 0, passed = 0, failed = 0;
+	double execution_time;
+	const struct l_queue_entry *entry;
+
+	if (unlikely(!tester))
+		return false;
+
+	l_info(COLOR_HIGHLIGHT "%s" COLOR_OFF,
+					"\n\nTest Summary\n------------");
+
+	entry = l_queue_get_entries(tester->tests);
+
+	for (; entry; entry = entry->next) {
+		struct test_case *test = entry->data;
+		double exec_time;
+
+		exec_time = (test->end_time - test->start_time) /
+							(double)L_USEC_PER_SEC;
+
+		switch (test->result) {
+		case TEST_RESULT_NOT_RUN:
+			print_summary(test->name, COLOR_YELLOW, "Not Run", "");
+			not_run++;
+			break;
+		case TEST_RESULT_PASSED:
+			print_summary(test->name, COLOR_GREEN, "Passed",
+					"%8.3f seconds", exec_time);
+			passed++;
+			break;
+		case TEST_RESULT_FAILED:
+			print_summary(test->name, COLOR_RED, "Failed",
+						"%8.3f seconds", exec_time);
+			failed++;
+			break;
+		case TEST_RESULT_TIMED_OUT:
+			print_summary(test->name, COLOR_RED, "Timed out",
+						"%8.3f seconds", exec_time);
+			failed++;
+			break;
+		}
+	}
+
+	l_info("Total: %d, "
+		COLOR_GREEN "Passed: %d (%.1f%%)" COLOR_OFF ", "
+		COLOR_RED "Failed: %d" COLOR_OFF ", "
+		COLOR_YELLOW "Not Run: %d" COLOR_OFF,
+			not_run + passed + failed, passed,
+			(not_run + passed + failed) ?
+			(float) passed * 100 / (not_run + passed + failed) : 0,
+			failed, not_run);
+
+	execution_time = get_elapsed_time(tester->start_time);
+
+	l_info("Overall execution time: %8.3f seconds",
+				execution_time / (double)L_USEC_PER_SEC);
+
+	return failed;
+}
+
+/**
+ * l_tester_destroy:
+ * @tester: tester instance
+ *
+ * Free up the teter framework resources
+ *
+ **/
+LIB_EXPORT void l_tester_destroy(struct l_tester *tester)
+{
+	if (unlikely(!tester))
+		return;
+
+	l_queue_destroy(tester->tests, destroy_test);
+	l_free(tester);
+}
+
+/**
+ * l_tester_get_stage:
+ * @tester: tester instance
+ *
+ * Get the current test stage
+ *
+ * Returns: the stage of the current test that is being processing.
+ *
+ **/
+LIB_EXPORT enum l_tester_stage l_tester_get_stage(struct l_tester *tester)
+{
+	struct test_case *test;
+
+	if (unlikely(!tester))
+		return L_TESTER_STAGE_INVALID;
+
+	if (!tester->test_entry)
+		return L_TESTER_STAGE_INVALID;
+
+	test = tester->test_entry->data;
+
+	return test->stage;
+}
diff --git a/ell/tester.h b/ell/tester.h
new file mode 100644
index 0000000..370aecc
--- /dev/null
+++ b/ell/tester.h
@@ -0,0 +1,82 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2021  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_TESTER_H
+#define __ELL_TESTER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_tester;
+
+enum l_tester_stage {
+	L_TESTER_STAGE_INVALID,
+	L_TESTER_STAGE_PRE_SETUP,
+	L_TESTER_STAGE_SETUP,
+	L_TESTER_STAGE_RUN,
+	L_TESTER_STAGE_TEARDOWN,
+	L_TESTER_STAGE_POST_TEARDOWN,
+};
+
+typedef void (*l_tester_destroy_func_t)(void *user_data);
+typedef void (*l_tester_data_func_t)(const void *test_data);
+typedef void (*l_tester_finish_func_t)(struct l_tester *tester);
+typedef void (*l_tester_wait_func_t)(void *user_data);
+
+struct l_tester *l_tester_new(const char *prefix, const char *substring,
+							bool list_cases);
+void l_tester_destroy(struct l_tester *tester);
+void l_tester_start(struct l_tester *tester,
+					l_tester_finish_func_t finish_func);
+
+bool l_tester_summarize(struct l_tester *tester);
+
+void l_tester_add_full(struct l_tester *tester, const char *name,
+				const void *test_data,
+				l_tester_data_func_t pre_setup_func,
+				l_tester_data_func_t setup_func,
+				l_tester_data_func_t test_func,
+				l_tester_data_func_t teardown_func,
+				l_tester_data_func_t post_teardown_func,
+				unsigned int timeout,
+				void *user_data,
+				l_tester_destroy_func_t destroy);
+
+void l_tester_add(struct l_tester *tester, const char *name,
+					const void *test_data,
+					l_tester_data_func_t setup_func,
+					l_tester_data_func_t test_func,
+					l_tester_data_func_t teardown_func);
+
+void l_tester_pre_setup_complete(struct l_tester *tester);
+void l_tester_pre_setup_failed(struct l_tester *tester);
+void l_tester_setup_complete(struct l_tester *tester);
+void l_tester_setup_failed(struct l_tester *tester);
+void l_tester_test_passed(struct l_tester *tester);
+void l_tester_test_failed(struct l_tester *tester);
+void l_tester_test_abort(struct l_tester *tester);
+void l_tester_teardown_complete(struct l_tester *tester);
+void l_tester_teardown_failed(struct l_tester *tester);
+void l_tester_post_teardown_complete(struct l_tester *tester);
+void l_tester_post_teardown_failed(struct l_tester *tester);
+
+enum l_tester_stage l_tester_get_stage(struct l_tester *tester);
+void *l_tester_get_data(struct l_tester *tester);
+
+void l_tester_wait(struct l_tester *tester, unsigned int seconds,
+				l_tester_wait_func_t func, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TESTER_H */
diff --git a/ell/time-private.h b/ell/time-private.h
new file mode 100644
index 0000000..2860943
--- /dev/null
+++ b/ell/time-private.h
@@ -0,0 +1,15 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2020  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+struct timeval;
+
+uint64_t _time_pick_interval_secs(uint32_t min_secs, uint32_t max_secs);
+uint64_t _time_fuzz_msecs(uint64_t ms);
+uint64_t _time_fuzz_secs(uint32_t secs, uint32_t max_offset);
+uint64_t _time_realtime_to_boottime(const struct timeval *ts);
+uint64_t time_realtime_now(void);
+uint64_t _time_from_timespec(const struct timespec *ts);
diff --git a/ell/time.c b/ell/time.c
new file mode 100644
index 0000000..e124a91
--- /dev/null
+++ b/ell/time.c
@@ -0,0 +1,141 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2019  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <time.h>
+#include <sys/time.h>
+
+#include "time.h"
+#include "time-private.h"
+#include "random.h"
+#include "private.h"
+
+uint64_t _time_from_timespec(const struct timespec *ts)
+{
+	return ts->tv_sec * L_USEC_PER_SEC + ts->tv_nsec / L_NSEC_PER_USEC;
+}
+
+static uint64_t _time_from_timeval(const struct timeval *tv)
+{
+	return tv->tv_sec * L_USEC_PER_SEC + tv->tv_usec;
+}
+
+/**
+ * l_time_now:
+ *
+ * Get the running clocktime in microseconds
+ *
+ * Returns: Current clock time in microseconds
+ **/
+LIB_EXPORT uint64_t l_time_now(void)
+{
+	struct timespec now;
+
+	clock_gettime(CLOCK_BOOTTIME, &now);
+	return _time_from_timespec(&now);
+}
+
+uint64_t time_realtime_now(void)
+{
+	struct timespec now;
+
+	clock_gettime(CLOCK_REALTIME, &now);
+	return _time_from_timespec(&now);
+}
+
+/**
+ * l_time_after
+ *
+ * Returns: True if time a is after time b
+ **/
+
+/**
+ * l_time_before
+ *
+ * Returns: True if time a is before time b
+ **/
+
+/**
+ * l_time_offset
+ *
+ * @time: Start time to calculate offset
+ * @offset: Amount of time to add to 'time'
+ *
+ * Adds an offset to a time value. This checks for overflow, and if detected
+ * returns UINT64_MAX.
+ *
+ * Returns: A time value 'time' + 'offset'. Or UINT64_MAX if time + offset
+ * exceeds UINT64_MAX.
+ **/
+
+/* Compute ms + RAND*ms where RAND is in range -0.1 .. 0.1 */
+uint64_t _time_fuzz_msecs(uint64_t ms)
+{
+	/* We do this by subtracting 0.1ms and adding 0.1ms * rand[0 .. 2] */
+	return ms - ms / 10 +
+			(l_getrandom_uint32() % (2 * L_MSEC_PER_SEC)) *
+						ms / 10 / L_MSEC_PER_SEC;
+}
+
+uint64_t _time_pick_interval_secs(uint32_t min_secs, uint32_t max_secs)
+{
+	uint64_t min_ms = min_secs * L_MSEC_PER_SEC;
+	uint64_t max_ms = max_secs * L_MSEC_PER_SEC;
+
+	return l_getrandom_uint32() % (max_ms + 1 - min_ms) + min_ms;
+}
+
+/* Compute a time in ms based on seconds + max_offset * [-1.0 .. 1.0] */
+uint64_t _time_fuzz_secs(uint32_t secs, uint32_t max_offset)
+{
+	uint64_t ms = secs * L_MSEC_PER_SEC;
+	uint64_t r = l_getrandom_uint32();
+
+	max_offset *= L_MSEC_PER_SEC;
+
+	if (r & 0x80000000)
+		ms += (r & 0x7fffffff) % max_offset;
+	else
+		ms -= (r & 0x7fffffff) % max_offset;
+
+	return ms;
+}
+
+/*
+ * Convert a *recent* CLOCK_REALTIME-based timestamp to a
+ * CLOCK_BOOTTIME-based usec count consistent with l_time functions.
+ * The longer the time since the input timestamp the higher the
+ * probability of the two clocks having diverged and the higher the
+ * expected error magnitude.
+ */
+uint64_t _time_realtime_to_boottime(const struct timeval *ts)
+{
+	uint64_t now_realtime;
+	uint64_t now_boottime = l_time_now();
+	struct timespec timespec;
+	uint64_t ts_realtime;
+	uint64_t offset;
+
+	clock_gettime(CLOCK_REALTIME, &timespec);
+	now_realtime = _time_from_timespec(&timespec);
+	ts_realtime = _time_from_timeval(ts);
+	offset = l_time_diff(ts_realtime, now_realtime);
+
+	/* Most likely case, timestamp in the past */
+	if (l_time_before(ts_realtime, now_realtime)) {
+		if (offset > now_boottime)
+			return 0;
+
+		return now_boottime - offset;
+	}
+
+	return l_time_offset(now_boottime, offset);
+}
diff --git a/ell/time.h b/ell/time.h
new file mode 100644
index 0000000..7be41a2
--- /dev/null
+++ b/ell/time.h
@@ -0,0 +1,66 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2019  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_TIME_H
+#define __ELL_TIME_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define L_USEC_PER_SEC 1000000ULL
+#define L_MSEC_PER_SEC 1000ULL
+#define L_USEC_PER_MSEC 1000ULL
+#define L_NSEC_PER_SEC  1000000000ULL
+#define L_NSEC_PER_MSEC 1000000ULL
+#define L_NSEC_PER_USEC 1000ULL
+#define L_TIME_INVALID ((uint64_t) -1)
+
+uint64_t l_time_now(void);
+
+static inline bool l_time_after(uint64_t a, uint64_t b)
+{
+	return a > b;
+}
+
+static inline bool l_time_before(uint64_t a, uint64_t b)
+{
+	return l_time_after(b, a);
+}
+
+static inline uint64_t l_time_offset(uint64_t time, uint64_t offset)
+{
+	/* check overflow */
+	if (offset > UINT64_MAX - time)
+		return UINT64_MAX;
+
+	return time + offset;
+}
+
+static inline uint64_t l_time_diff(uint64_t a, uint64_t b)
+{
+	return (a < b) ? b - a : a - b;
+}
+
+static inline uint64_t l_time_to_secs(uint64_t time)
+{
+	return time / L_USEC_PER_SEC;
+}
+
+static inline uint64_t l_time_to_msecs(uint64_t time)
+{
+	return time / L_USEC_PER_MSEC;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TIME_H */
diff --git a/ell/timeout.c b/ell/timeout.c
new file mode 100644
index 0000000..541692e
--- /dev/null
+++ b/ell/timeout.c
@@ -0,0 +1,329 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/timerfd.h>
+#include <time.h>
+#include <limits.h>
+
+#include "useful.h"
+#include "timeout.h"
+#include "main-private.h"
+#include "private.h"
+#include "time-private.h"
+
+/**
+ * SECTION:timeout
+ * @short_description: Timeout support
+ *
+ * Timeout support
+ */
+
+/**
+ * l_timeout:
+ *
+ * Opaque object representing the timeout.
+ */
+struct l_timeout {
+	int fd;
+	l_timeout_notify_cb_t callback;
+	l_timeout_destroy_cb_t destroy;
+	void *user_data;
+};
+
+static void timeout_destroy(void *user_data)
+{
+	struct l_timeout *timeout = user_data;
+
+	close(timeout->fd);
+	timeout->fd = -1;
+
+	if (timeout->destroy)
+		timeout->destroy(timeout->user_data);
+}
+
+static void timeout_callback(int fd, uint32_t events, void *user_data)
+{
+	struct l_timeout *timeout = user_data;
+	uint64_t expired;
+	ssize_t result;
+
+	result = read(timeout->fd, &expired, sizeof(expired));
+	if (result != sizeof(expired))
+		return;
+
+	if (timeout->callback)
+		timeout->callback(timeout, timeout->user_data);
+}
+
+static inline int timeout_set(int fd, unsigned int seconds, long nanoseconds)
+{
+	struct itimerspec itimer;
+
+	memset(&itimer, 0, sizeof(itimer));
+	itimer.it_interval.tv_sec = 0;
+	itimer.it_interval.tv_nsec = 0;
+	itimer.it_value.tv_sec = seconds;
+	itimer.it_value.tv_nsec = nanoseconds;
+
+	return timerfd_settime(fd, 0, &itimer, NULL);
+}
+
+static bool convert_ms(uint64_t milliseconds, unsigned int *seconds,
+			long *nanoseconds)
+{
+	uint64_t big_seconds = milliseconds / 1000;
+
+	if (big_seconds > UINT_MAX)
+		return false;
+
+	*seconds = big_seconds;
+	*nanoseconds = (milliseconds % 1000) * 1000000L;
+
+	return true;
+}
+
+/**
+ * timeout_create_with_nanoseconds:
+ * @seconds: number of seconds
+ * @nanoseconds: number of nanoseconds
+ * @callback: timeout callback function
+ * @user_data: user data provided to timeout callback function
+ * @destroy: destroy function for user data
+ *
+ * Create new timeout callback handling.
+ *
+ * The timeout will only fire once. The timeout handling needs to be rearmed
+ * with one of the l_timeout_modify functions to trigger again.
+ *
+ * Returns: a newly allocated #l_timeout object. On failure, the function
+ * returns NULL.
+ **/
+static struct l_timeout *timeout_create_with_nanoseconds(unsigned int seconds,
+			long nanoseconds, l_timeout_notify_cb_t callback,
+			void *user_data, l_timeout_destroy_cb_t destroy)
+{
+	struct l_timeout *timeout;
+	int err;
+
+	if (unlikely(!callback))
+		return NULL;
+
+	timeout = l_new(struct l_timeout, 1);
+
+	timeout->callback = callback;
+	timeout->destroy = destroy;
+	timeout->user_data = user_data;
+
+	timeout->fd = timerfd_create(CLOCK_MONOTONIC,
+					TFD_NONBLOCK | TFD_CLOEXEC);
+	if (timeout->fd < 0) {
+		l_free(timeout);
+		return NULL;
+	}
+
+	if (seconds > 0 || nanoseconds > 0) {
+		if (timeout_set(timeout->fd, seconds, nanoseconds) < 0) {
+			close(timeout->fd);
+			l_free(timeout);
+			return NULL;
+		}
+	}
+
+	err = watch_add(timeout->fd, EPOLLIN | EPOLLONESHOT, timeout_callback,
+			timeout, timeout_destroy);
+
+	if (err < 0) {
+		l_free(timeout);
+		return NULL;
+	}
+
+	return timeout;
+}
+
+/**
+ * l_timeout_create:
+ * @seconds: timeout in seconds
+ * @callback: timeout callback function
+ * @user_data: user data provided to timeout callback function
+ * @destroy: destroy function for user data
+ *
+ * Create new timeout callback handling.
+ *
+ * The timeout will only fire once. The timeout handling needs to be rearmed
+ * with one of the l_timeout_modify functions to trigger again.
+ *
+ * Returns: a newly allocated #l_timeout object. On failure, the function
+ * returns NULL.
+ **/
+LIB_EXPORT struct l_timeout *l_timeout_create(unsigned int seconds,
+			l_timeout_notify_cb_t callback,
+			void *user_data, l_timeout_destroy_cb_t destroy)
+{
+	return timeout_create_with_nanoseconds(seconds, 0, callback,
+							user_data, destroy);
+}
+
+/**
+ * l_timeout_create_ms:
+ * @milliseconds: timeout in milliseconds
+ * @callback: timeout callback function
+ * @user_data: user data provided to timeout callback function
+ * @destroy: destroy function for user data
+ *
+ * Create new timeout callback handling.
+ *
+ * The timeout will only fire once. The timeout handling needs to be rearmed
+ * with one of the l_timeout_modify functions to trigger again.
+ *
+ * Returns: a newly allocated #l_timeout object. On failure, the function
+ * returns NULL.
+ **/
+LIB_EXPORT struct l_timeout *l_timeout_create_ms(uint64_t milliseconds,
+			l_timeout_notify_cb_t callback,
+			void *user_data, l_timeout_destroy_cb_t destroy)
+{
+	unsigned int seconds;
+	long nanoseconds;
+
+	if (!convert_ms(milliseconds, &seconds, &nanoseconds))
+		return NULL;
+
+	return timeout_create_with_nanoseconds(seconds, nanoseconds, callback,
+						user_data, destroy);
+}
+
+/**
+ * l_timeout_modify:
+ * @timeout: timeout object
+ * @seconds: timeout in seconds
+ *
+ * Modify an existing @timeout and rearm it.
+ **/
+LIB_EXPORT void l_timeout_modify(struct l_timeout *timeout,
+					unsigned int seconds)
+{
+	if (unlikely(!timeout))
+		return;
+
+	if (unlikely(timeout->fd < 0))
+		return;
+
+	if (seconds > 0) {
+		if (timeout_set(timeout->fd, seconds, 0) < 0)
+			return;
+	}
+
+	watch_modify(timeout->fd, EPOLLIN | EPOLLONESHOT, true);
+}
+
+/**
+ * l_timeout_modify_ms:
+ * @timeout: timeout object
+ * @milliseconds: number of milliseconds
+ *
+ * Modify an existing @timeout and rearm it.
+ **/
+LIB_EXPORT void l_timeout_modify_ms(struct l_timeout *timeout,
+					uint64_t milliseconds)
+{
+	if (unlikely(!timeout))
+		return;
+
+	if (unlikely(timeout->fd < 0))
+		return;
+
+	if (milliseconds > 0) {
+		unsigned int sec;
+		long nanosec;
+
+		if (!convert_ms(milliseconds, &sec, &nanosec) ||
+			timeout_set(timeout->fd, sec, nanosec) < 0)
+			return;
+	}
+
+	watch_modify(timeout->fd, EPOLLIN | EPOLLONESHOT, true);
+}
+
+/**
+ * l_timeout_remove:
+ * @timeout: timeout object
+ *
+ * Remove timeout handling.
+ **/
+LIB_EXPORT void l_timeout_remove(struct l_timeout *timeout)
+{
+	if (unlikely(!timeout))
+		return;
+
+	watch_remove(timeout->fd, false);
+
+	l_free(timeout);
+}
+
+/**
+ * l_timeout_set_callback:
+ * @timeout: timeout object
+ * @callback: The new callback
+ * @user_data: The new user_data
+ * @destroy: The new destroy function
+ *
+ * Sets the new notify callback for @timeout.  If the old user_data object had
+ * a destroy function set, then that function will be called.
+ */
+LIB_EXPORT void l_timeout_set_callback(struct l_timeout *timeout,
+					l_timeout_notify_cb_t callback,
+					void *user_data,
+					l_timeout_destroy_cb_t destroy)
+{
+	if (unlikely(!timeout))
+		return;
+
+	if (timeout->destroy)
+		timeout->destroy(timeout->user_data);
+
+	timeout->callback = callback;
+	timeout->user_data = user_data;
+	timeout->destroy = destroy;
+}
+
+/**
+ * l_timeout_get_remaining:
+ *
+ * Get the remaining time for a timeout in microseconds
+ *
+ * @timeout: timeout object
+ * @remaining: microseconds remaining on timer
+ *
+ * Returns: True if successfully got remaining time
+ *          False if failure to get remaining time
+ **/
+LIB_EXPORT bool l_timeout_remaining(struct l_timeout *timeout,
+						uint64_t *remaining)
+{
+	struct itimerspec current;
+
+	if (unlikely(!timeout))
+		return false;
+
+	if (timerfd_gettime(timeout->fd, &current) < 0)
+		return false;
+
+	if (remaining)
+		*remaining = _time_from_timespec(&current.it_value);
+
+	return true;
+}
diff --git a/ell/timeout.h b/ell/timeout.h
new file mode 100644
index 0000000..c0d463c
--- /dev/null
+++ b/ell/timeout.h
@@ -0,0 +1,43 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_TIMEOUT_H
+#define __ELL_TIMEOUT_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_timeout;
+
+typedef void (*l_timeout_notify_cb_t) (struct l_timeout *timeout,
+						void *user_data);
+typedef void (*l_timeout_destroy_cb_t) (void *user_data);
+
+struct l_timeout *l_timeout_create(unsigned int seconds,
+			l_timeout_notify_cb_t callback,
+			void *user_data, l_timeout_destroy_cb_t destroy);
+struct l_timeout *l_timeout_create_ms(uint64_t milliseconds,
+			l_timeout_notify_cb_t callback,
+			void *user_data, l_timeout_destroy_cb_t destroy);
+void l_timeout_modify(struct l_timeout *timeout,
+				unsigned int seconds);
+void l_timeout_modify_ms(struct l_timeout *timeout,
+				uint64_t milliseconds);
+void l_timeout_remove(struct l_timeout *timeout);
+void l_timeout_set_callback(struct l_timeout *timeout,
+				l_timeout_notify_cb_t callback, void *user_data,
+				l_timeout_destroy_cb_t destroy);
+bool l_timeout_remaining(struct l_timeout *timeout,
+				uint64_t *remaining);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TIMEOUT_H */
diff --git a/ell/tls-extensions.c b/ell/tls-extensions.c
new file mode 100644
index 0000000..eaa8912
--- /dev/null
+++ b/ell/tls-extensions.c
@@ -0,0 +1,1037 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include "util.h"
+#include "tls.h"
+#include "cipher.h"
+#include "checksum.h"
+#include "cert.h"
+#include "tls-private.h"
+
+/* Most extensions are not used when resuming a cached session */
+#define SKIP_ON_RESUMPTION()	\
+	do {	\
+		if (tls->session_id_size && !tls->session_id_new)	\
+			return -ENOMSG;	\
+	} while (0);
+
+/* RFC 7919, Section A.1 */
+static const uint8_t tls_ffdhe2048_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x28, 0x5c, 0x97, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.2 */
+static const uint8_t tls_ffdhe3072_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0xc6, 0x2e, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.3 */
+static const uint8_t tls_ffdhe4096_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x65, 0x5f, 0x6a,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.4 */
+static const uint8_t tls_ffdhe6144_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02,
+	0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03, 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c,
+	0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca, 0xf5, 0x3e, 0xa6,
+	0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
+	0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a,
+	0xcd, 0xad, 0x06, 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e,
+	0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81, 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77,
+	0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8, 0x55, 0x32, 0x2e,
+	0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
+	0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c,
+	0x18, 0x30, 0x23, 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4,
+	0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2, 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e,
+	0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a, 0x28, 0x1b, 0xf6,
+	0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
+	0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c,
+	0xd7, 0x2b, 0x03, 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31,
+	0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d, 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a,
+	0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c, 0xcf, 0x2d, 0xd5,
+	0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
+	0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e,
+	0x9a, 0xdb, 0x1e, 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1,
+	0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38, 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c,
+	0xd0, 0xe4, 0x0e, 0x65, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.5 */
+static const uint8_t tls_ffdhe8192_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02,
+	0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03, 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c,
+	0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca, 0xf5, 0x3e, 0xa6,
+	0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
+	0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a,
+	0xcd, 0xad, 0x06, 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e,
+	0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81, 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77,
+	0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8, 0x55, 0x32, 0x2e,
+	0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
+	0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c,
+	0x18, 0x30, 0x23, 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4,
+	0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2, 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e,
+	0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a, 0x28, 0x1b, 0xf6,
+	0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
+	0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c,
+	0xd7, 0x2b, 0x03, 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31,
+	0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d, 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a,
+	0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c, 0xcf, 0x2d, 0xd5,
+	0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
+	0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e,
+	0x9a, 0xdb, 0x1e, 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1,
+	0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38, 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c,
+	0xcf, 0xf4, 0x6a, 0xaa, 0x36, 0xad, 0x00, 0x4c, 0xf6, 0x00, 0xc8, 0x38,
+	0x1e, 0x42, 0x5a, 0x31, 0xd9, 0x51, 0xae, 0x64, 0xfd, 0xb2, 0x3f, 0xce,
+	0xc9, 0x50, 0x9d, 0x43, 0x68, 0x7f, 0xeb, 0x69, 0xed, 0xd1, 0xcc, 0x5e,
+	0x0b, 0x8c, 0xc3, 0xbd, 0xf6, 0x4b, 0x10, 0xef, 0x86, 0xb6, 0x31, 0x42,
+	0xa3, 0xab, 0x88, 0x29, 0x55, 0x5b, 0x2f, 0x74, 0x7c, 0x93, 0x26, 0x65,
+	0xcb, 0x2c, 0x0f, 0x1c, 0xc0, 0x1b, 0xd7, 0x02, 0x29, 0x38, 0x88, 0x39,
+	0xd2, 0xaf, 0x05, 0xe4, 0x54, 0x50, 0x4a, 0xc7, 0x8b, 0x75, 0x82, 0x82,
+	0x28, 0x46, 0xc0, 0xba, 0x35, 0xc3, 0x5f, 0x5c, 0x59, 0x16, 0x0c, 0xc0,
+	0x46, 0xfd, 0x82, 0x51, 0x54, 0x1f, 0xc6, 0x8c, 0x9c, 0x86, 0xb0, 0x22,
+	0xbb, 0x70, 0x99, 0x87, 0x6a, 0x46, 0x0e, 0x74, 0x51, 0xa8, 0xa9, 0x31,
+	0x09, 0x70, 0x3f, 0xee, 0x1c, 0x21, 0x7e, 0x6c, 0x38, 0x26, 0xe5, 0x2c,
+	0x51, 0xaa, 0x69, 0x1e, 0x0e, 0x42, 0x3c, 0xfc, 0x99, 0xe9, 0xe3, 0x16,
+	0x50, 0xc1, 0x21, 0x7b, 0x62, 0x48, 0x16, 0xcd, 0xad, 0x9a, 0x95, 0xf9,
+	0xd5, 0xb8, 0x01, 0x94, 0x88, 0xd9, 0xc0, 0xa0, 0xa1, 0xfe, 0x30, 0x75,
+	0xa5, 0x77, 0xe2, 0x31, 0x83, 0xf8, 0x1d, 0x4a, 0x3f, 0x2f, 0xa4, 0x57,
+	0x1e, 0xfc, 0x8c, 0xe0, 0xba, 0x8a, 0x4f, 0xe8, 0xb6, 0x85, 0x5d, 0xfe,
+	0x72, 0xb0, 0xa6, 0x6e, 0xde, 0xd2, 0xfb, 0xab, 0xfb, 0xe5, 0x8a, 0x30,
+	0xfa, 0xfa, 0xbe, 0x1c, 0x5d, 0x71, 0xa8, 0x7e, 0x2f, 0x74, 0x1e, 0xf8,
+	0xc1, 0xfe, 0x86, 0xfe, 0xa6, 0xbb, 0xfd, 0xe5, 0x30, 0x67, 0x7f, 0x0d,
+	0x97, 0xd1, 0x1d, 0x49, 0xf7, 0xa8, 0x44, 0x3d, 0x08, 0x22, 0xe5, 0x06,
+	0xa9, 0xf4, 0x61, 0x4e, 0x01, 0x1e, 0x2a, 0x94, 0x83, 0x8f, 0xf8, 0x8c,
+	0xd6, 0x8c, 0x8b, 0xb7, 0xc5, 0xc6, 0x42, 0x4c, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 3526, Section 3 */
+static const uint8_t tls_dh14_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
+	0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
+	0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
+	0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+	0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
+	0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
+	0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
+	0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+	0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
+	0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
+	0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
+	0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
+	0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
+	0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
+	0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
+	0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
+	0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2,
+	0xec, 0x07, 0xa2, 0x8f, 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9,
+	0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7c,
+	0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
+	0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xac, 0xaa, 0x68, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+};
+
+static const struct tls_named_group tls_group_pref[] = {
+	{ "secp256r1", 23, TLS_GROUP_TYPE_EC },
+	{ "secp384r1", 24, TLS_GROUP_TYPE_EC },
+	{
+		"ffdhe2048", 256, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe2048_prime,
+			.prime_len = sizeof(tls_ffdhe2048_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe3072", 257, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe3072_prime,
+			.prime_len = sizeof(tls_ffdhe3072_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe4096", 258, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe4096_prime,
+			.prime_len = sizeof(tls_ffdhe4096_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe6144", 259, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe6144_prime,
+			.prime_len = sizeof(tls_ffdhe6144_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe8192", 260, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe8192_prime,
+			.prime_len = sizeof(tls_ffdhe8192_prime),
+			.generator = 2,
+		},
+	},
+};
+
+/*
+ * For now hardcode a default group for non-RFC7919 clients - same group
+ * as some other TLS servers use, which is actually a downside because the
+ * more common the group parameters are the less secure they are assumed
+ * to be, but it is also a test that the group is sufficiently good.
+ *
+ * Eventually we need to make this configurable so that a unique
+ * likely-prime number generated by either 'openssl dhparam' or
+ * 'ssh-keygen -G' can be set, or parse /etc/ssh/moduli to select
+ * a random pre-generated FFDH group each time.
+ */
+static const struct tls_named_group tls_default_ffdh_group = {
+	"RFC3526/Oakley Group 14", 0, TLS_GROUP_TYPE_FF,
+	.ff = {
+		.prime = tls_dh14_prime,
+		.prime_len = sizeof(tls_dh14_prime),
+		.generator = 2,
+	},
+};
+
+/* RFC 8422, Section 5.1 + RFC 7919 */
+static ssize_t tls_elliptic_curves_client_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	uint8_t *ptr = buf;
+	unsigned int i;
+
+	if (len < 2 + L_ARRAY_SIZE(tls_group_pref) * 2)
+		return -ENOMEM;
+
+	l_put_be16(L_ARRAY_SIZE(tls_group_pref) * 2, ptr);
+	ptr += 2;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++) {
+		l_put_be16(tls_group_pref[i].id, ptr);
+		ptr += 2;
+	}
+
+	return ptr - buf;
+}
+
+static bool tls_elliptic_curves_client_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	bool ffdh_offered = false;
+
+	if (len < 2)
+		return false;
+
+	if (l_get_be16(buf) != len - 2 || (len & 1))
+		return false;
+
+	buf += 2;
+	len -= 2;
+
+	/*
+	 * We select one group for DH and one group for ECDH and we'll
+	 * let the cipher suite selection logic decide which one is actually
+	 * used.  It will take into account the client's cipher suite
+	 * preference but it could just as well look at the strengths of
+	 * the groups chosen.  This is not done for simplicity but RFC 7919
+	 * suggests the Supported Groups should actually overrule the
+	 * cipher suite preference list in case of a conflict:
+	 * "A server that encounters such a contradiction when selecting
+	 * between an ECDHE or FFDHE key exchange mechanism while trying
+	 * to respect client preferences SHOULD give priority to the
+	 * Supported Groups extension (...) but MAY resolve the
+	 * contradiction any way it sees fit."
+	 *
+	 * Not implemented: "If a non-anonymous FFDHE cipher suite is
+	 * selected and the TLS client has used this extension to offer
+	 * an FFDHE group of comparable or greater strength than the server's
+	 * public key, the server SHOULD select an FFDHE group at least
+	 * as strong as the server's public key."
+	 */
+
+	while (len) {
+		unsigned int i;
+		uint16_t id;
+		const struct tls_named_group *group = NULL;
+
+		id = l_get_be16(buf);
+		buf += 2;
+		len -= 2;
+
+		if (id >> 8 == 1)	/* RFC 7919 ids */
+			ffdh_offered = true;
+
+		for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+			if (tls_group_pref[i].id == id) {
+				group = &tls_group_pref[i];
+				break;
+			}
+
+		if (!group)
+			continue;
+
+		switch (group->type) {
+		case TLS_GROUP_TYPE_EC:
+			if (!tls->negotiated_curve)
+				tls->negotiated_curve = group;
+
+			break;
+		case TLS_GROUP_TYPE_FF:
+			if (!tls->negotiated_ff_group)
+				tls->negotiated_ff_group = group;
+
+			break;
+		}
+	}
+
+	/*
+	 * Note we need to treat DH slightly differently from ECDH groups
+	 * here because the extension is defined in RFC 8422 and if the
+	 * client offers no elliptic curves we can't use ECDH at all:
+	 * "If a server (...) is unable to complete the ECC handshake while
+	 * restricting itself to the enumerated curves (...), it MUST NOT
+	 * negotiate the use of an ECC cipher suite.  Depending on what
+	 * other cipher suites are proposed by the client and supported by
+	 * the server, this may result in a fatal handshake failure alert
+	 * due to the lack of common cipher suites."
+	 *
+	 * On the other hand if the client offers no FFDH groups we can
+	 * only assume the client is okay with us picking a group.  Note
+	 * the "includes any FFDHE group" part in RFC 7919 Section 4:
+	 * "If a compatible TLS server receives a Supported Groups
+	 * extension from a client that includes any FFDHE group (i.e.,
+	 * any codepoint between 256 and 511, inclusive, even if unknown
+	 * to the server), and if none of the client-proposed FFDHE groups
+	 * are known and acceptable to the server, then the server MUST
+	 * NOT select an FFDHE cipher suite."
+	 */
+
+	if (tls->negotiated_curve)
+		TLS_DEBUG("Negotiated %s", tls->negotiated_curve->name);
+	else
+		TLS_DEBUG("non-fatal: No common supported elliptic curves "
+				"for ECDHE");
+
+	if (tls->negotiated_ff_group)
+		TLS_DEBUG("Negotiated %s", tls->negotiated_ff_group->name);
+	else if (ffdh_offered)
+		TLS_DEBUG("non-fatal: No common supported finite-field groups "
+				"for DHE");
+	else
+		tls->negotiated_ff_group = &tls_default_ffdh_group;
+
+	return true;
+}
+
+static bool tls_elliptic_curves_client_absent(struct l_tls *tls)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+		if (tls_group_pref[i].type == TLS_GROUP_TYPE_EC) {
+			tls->negotiated_curve = &tls_group_pref[i];
+			break;
+		}
+
+	tls->negotiated_ff_group = &tls_default_ffdh_group;
+
+	return true;
+}
+
+static bool tls_ec_point_formats_client_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	if (len < 2)
+		return false;
+
+	if (buf[0] != len - 1)
+		return false;
+
+	if (!memchr(buf + 1, 0, len - 1)) {
+		TLS_DEBUG("Uncompressed point format missing");
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * For compatibility with clients respond to a valid Client Hello Supported
+ * Point Formats extension with the hardcoded confirmation that we do
+ * support the single valid point format.  As a client we never send this
+ * extension so we never have to handle a server response to it either.
+ */
+static ssize_t tls_ec_point_formats_server_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	SKIP_ON_RESUMPTION(); /* RFC 4492 Section 4 */
+
+	if (len < 2)
+		return -ENOMEM;
+
+	buf[0] = 0x01;	/* ec_point_format_list length */
+	buf[1] = 0x00;	/* uncompressed */
+	return 2;
+}
+
+/*
+ * This is used to append the list of signature algorithm and hash type
+ * combinations we support to the Signature Algorithms client hello
+ * extension (on the client) and the Certificate Request message (on the
+ * server).  In both cases we need to list the algorithms we support for
+ * two use cases: certificate chain verification and signing/verifying
+ * Server Key Exchange params (server->client) or Certificate Verify
+ * data (client->server).
+ *
+ * For the server side RFC 5462, Section 7.4.1.4.1 says:
+ * "If the client [...] is willing to use them for verifying
+ * messages sent by the server, i.e., server certificates and
+ * server key exchange [...] it MUST send the
+ * signature_algorithms extension, listing the algorithms it
+ * is willing to accept."
+ *
+ * As for the certificate chains we mostly rely on the kernel to do
+ * this so when we receive the list we do not currently verify the
+ * that the whole chain uses only algorithms from the list on either
+ * side (TODO). But we know that the chain verification in the kernel
+ * can use a superset of the hash algorithms l_checksum supports.
+ * For the Server Key Exchange and Certificate Verify signatures we
+ * use l_checksum but we need to map the TLS-specific hash IDs to
+ * enum l_checksum_type using the tls_handshake_hash_data list in
+ * signature->sign() and signature->verify(), so we use
+ * tls_handshake_hash_data as the definitive list of allowed hash
+ * algorithms.
+ *
+ * Our supported signature algorithms can work with any hash type so we
+ * basically have to send all possible combinations of the signature
+ * algorithm IDs from the supported cipher suites (except anonymous)
+ * with the hash algorithms we can use for signature verification,
+ * i.e. those in the tls_handshake_hash_data table.
+ */
+ssize_t tls_write_signature_algorithms(struct l_tls *tls,
+					uint8_t *buf, size_t len)
+{
+	uint8_t *ptr = buf;
+	unsigned int i, j;
+	struct tls_cipher_suite **suite;
+	uint8_t sig_alg_ids[16];
+	uint8_t hash_ids[16];
+	unsigned int sig_alg_cnt = 0;
+	unsigned int hash_cnt = 0;
+
+	for (suite = tls->cipher_suite_pref_list; *suite; suite++) {
+		uint8_t id;
+
+		if (!(*suite)->signature)
+			continue;
+
+		id = (*suite)->signature->id;
+
+		if (memchr(sig_alg_ids, id, sig_alg_cnt))
+			continue;
+
+		if (!tls_cipher_suite_is_compatible(tls, *suite, NULL))
+			continue;
+
+		if (sig_alg_cnt >= sizeof(sig_alg_ids))
+			return -ENOMEM;
+
+		sig_alg_ids[sig_alg_cnt++] = id;
+	}
+
+	for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++) {
+		const struct tls_hash_algorithm *hash =
+			&tls_handshake_hash_data[i];
+		bool supported;
+
+		/*
+		 * The hash types in the Signature Algorithms extension are
+		 * all supported hashes but the ones in the Certificate
+		 * Request (server->client) must be in the set for which we
+		 * maintain handshake message hashes because that is going
+		 * to be used in Certificate Verify.
+		 */
+		if (tls->server)
+			supported = !!tls->handshake_hash[i];
+		else
+			supported = l_checksum_is_supported(hash->l_id, false);
+
+		if (supported)
+			hash_ids[hash_cnt++] = hash->tls_id;
+	}
+
+	if (len < 2 + sig_alg_cnt * hash_cnt * 2)
+		return -ENOMEM;
+
+	l_put_be16(sig_alg_cnt * hash_cnt * 2, ptr);
+	ptr += 2;
+
+	for (i = 0; i < sig_alg_cnt; i++)
+		for (j = 0; j < hash_cnt; j++) {
+			*ptr++ = hash_ids[j];
+			*ptr++ = sig_alg_ids[i];
+		}
+
+	return ptr - buf;
+}
+
+ssize_t tls_parse_signature_algorithms(struct l_tls *tls,
+					const uint8_t *buf, size_t len)
+{
+	const uint8_t *ptr = buf;
+	enum handshake_hash_type first_supported, hash;
+	const struct tls_hash_algorithm *preferred;
+	struct tls_cipher_suite **suite;
+	uint8_t sig_alg_ids[16];
+	unsigned int sig_alg_cnt = 0;
+
+	/*
+	 * This only makes sense as a variable-length field, assume
+	 * there's a typo in RFC5246 7.4.4 here.
+	 */
+	if (len < 4)
+		return -EINVAL;
+
+	if (l_get_be16(ptr) > len - 2)
+		return -EINVAL;
+
+	len = l_get_be16(ptr);
+	ptr += 2;
+
+	if (len & 1)
+		return -EINVAL;
+
+	for (suite = tls->cipher_suite_pref_list; *suite; suite++) {
+		uint8_t id;
+
+		if (!(*suite)->signature)
+			continue;
+
+		id = (*suite)->signature->id;
+
+		if (memchr(sig_alg_ids, id, sig_alg_cnt))
+			continue;
+
+		if (!tls_cipher_suite_is_compatible(tls, *suite, NULL))
+			continue;
+
+		if (sig_alg_cnt >= sizeof(sig_alg_ids))
+			return -ENOMEM;
+
+		sig_alg_ids[sig_alg_cnt++] = id;
+	}
+
+	/*
+	 * In 1.2 we force our preference for SHA256/SHA384 (depending on
+	 * cipher suite's PRF hmac) if it is supported by the peer because
+	 * that must be supported anyway for the PRF and the Finished hash
+	 * meaning that we only need to keep one hash instead of two.
+	 * If not available fall back to the first common hash algorithm.
+	 */
+	first_supported = -1;
+
+	if (tls->prf_hmac)
+		preferred = tls->prf_hmac;
+	else
+		preferred = &tls_handshake_hash_data[HANDSHAKE_HASH_SHA256];
+
+	while (len) {
+		uint8_t hash_id = *ptr++;
+		uint8_t sig_alg_id = *ptr++;
+		bool supported;
+
+		len -= 2;
+
+		/* Ignore hash types for signatures other than ours */
+		if (tls->pending.cipher_suite &&
+				(!tls->pending.cipher_suite->signature ||
+				 tls->pending.cipher_suite->signature->id !=
+				 sig_alg_id))
+			continue;
+
+		if (!tls->pending.cipher_suite &&
+				!memchr(sig_alg_ids, sig_alg_id, sig_alg_cnt))
+			continue;
+
+		if (hash_id == preferred->tls_id) {
+			for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+				if (&tls_handshake_hash_data[hash] == preferred)
+					break;
+			break;
+		}
+
+		if ((int) first_supported != -1)
+			continue;
+
+		for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+			if (hash_id == tls_handshake_hash_data[hash].tls_id)
+				break;
+
+		if (hash == __HANDSHAKE_HASH_COUNT)
+			continue;
+
+		if (tls->server)
+			supported = l_checksum_is_supported(
+					tls_handshake_hash_data[hash].l_id,
+					false);
+		else
+			supported = !!tls->handshake_hash[hash];
+
+		if (supported)
+			first_supported = hash;
+	}
+
+	if (len)
+		tls->signature_hash = hash;
+	else if ((int) first_supported != -1)
+		tls->signature_hash = first_supported;
+	else
+		return -ENOTSUP;
+
+	return ptr + len - buf;
+}
+
+/* RFC 5246, Section 7.4.1.4.1 */
+static ssize_t tls_signature_algorithms_client_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	/*
+	 * "Note: this extension is not meaningful for TLS versions
+	 * prior to 1.2.  Clients MUST NOT offer it if they are offering
+	 * prior versions."
+	 */
+	if (tls->max_version < L_TLS_V12)
+		return -ENOMSG;
+
+	return tls_write_signature_algorithms(tls, buf, len);
+}
+
+static bool tls_signature_algorithms_client_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	ssize_t ret;
+
+	/*
+	 * "However, even if clients do offer it, the rules specified in
+	 * [TLSEXT] require servers to ignore extensions they do not
+	 * understand."
+	 */
+	if (tls->max_version < L_TLS_V12)
+		return true;
+
+	ret = tls_parse_signature_algorithms(tls, buf, len);
+
+	if (ret == -ENOTSUP)
+		TLS_DEBUG("No common signature algorithms");
+
+	/*
+	 * TODO: also check our certificate chain against the parsed
+	 * signature algorithms.
+	 */
+
+	return ret == (ssize_t) len;
+}
+
+static bool tls_signature_algorithms_client_absent(struct l_tls *tls)
+{
+	/*
+	 * "If the client does not send the signature_algorithms extension,
+	 * the server MUST do the following:
+	 *    - [...] behave as if client had sent the value {sha1,rsa}.
+	 *    - [...] behave as if client had sent the value {sha1,dsa}.
+	 *    - [...] behave as if client had sent the value {sha1,ecdsa}.
+	 */
+	if (tls->max_version >= L_TLS_V12)
+		tls->signature_hash = HANDSHAKE_HASH_SHA1;
+
+	return true;
+}
+
+/* RFC 5746, Section 3.2 */
+static ssize_t tls_renegotiation_info_client_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	/*
+	 * Section 4.2 implies we should send the client_verify_data on
+	 * renegotiation even if .secure_renegotiation is false, if we want
+	 * to go through with the renegotiation in the first place.
+	 */
+	if (tls->ready) {
+		size_t vdl = tls_verify_data_length(tls, 1);
+
+		if (len < vdl + 1)
+			return -ENOMEM;
+
+		buf[0] = vdl;
+		memcpy(buf + 1, tls->renegotiation_info.client_verify_data,
+			vdl);
+		return 1 + vdl;
+	} else {
+		if (len < 1)
+			return -ENOMEM;
+
+		buf[0] = 0x00;	/* Empty "renegotiated_connection" */
+		return 1;
+	}
+}
+
+static ssize_t tls_renegotiation_info_server_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	if (tls->ready) {
+		size_t rx_vdl = tls_verify_data_length(tls, 0);
+		size_t tx_vdl = tls_verify_data_length(tls, 1);
+
+		if (len < rx_vdl + tx_vdl + 1)
+			return -ENOMEM;
+
+		buf[0] = rx_vdl + tx_vdl;
+		memcpy(buf + 1,
+			tls->renegotiation_info.client_verify_data, rx_vdl);
+		memcpy(buf + 1 + rx_vdl,
+			tls->renegotiation_info.server_verify_data, tx_vdl);
+		return 1 + rx_vdl + tx_vdl;
+	} else {
+		if (len < 1)
+			return -ENOMEM;
+
+		buf[0] = 0x00;	/* Empty "renegotiated_connection" */
+		return 1;
+	}
+}
+
+static bool tls_renegotiation_info_client_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	if (tls->ready) {
+		size_t vdl = tls_verify_data_length(tls, 0);
+
+		return len >= 1 + vdl &&
+			tls->renegotiation_info.secure_renegotiation &&
+			!memcmp(tls->renegotiation_info.client_verify_data,
+				buf + 1, vdl);
+	}
+
+	/*
+	 * RFC 5746 Section 3.6: "The server MUST then verify that the length
+	 * of the "renegotiated_connection" field is zero, ..."
+	 */
+	if (len < 1 || buf[0] != 0x00)
+		return false;
+
+	tls->renegotiation_info.secure_renegotiation = true;
+	return true;
+}
+
+static bool tls_renegotiation_info_server_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	if (tls->ready) {
+		size_t rx_vdl = tls_verify_data_length(tls, 0);
+		size_t tx_vdl = tls_verify_data_length(tls, 1);
+
+		return len >= 1 + rx_vdl + tx_vdl &&
+			tls->renegotiation_info.secure_renegotiation &&
+			!memcmp(tls->renegotiation_info.client_verify_data,
+				buf + 1, tx_vdl) &&
+			!memcmp(tls->renegotiation_info.server_verify_data,
+				buf + 1 + tx_vdl, rx_vdl);
+	}
+
+	/*
+	 * RFC 5746 Section 3.4: "The client MUST then verify that the length
+	 * of the "renegotiated_connection" field is zero, ..."
+	 */
+	if (len < 1 || buf[0] != 0x00)
+		return false;
+
+	tls->renegotiation_info.secure_renegotiation = true;
+	return true;
+}
+
+static bool tls_renegotiation_info_absent(struct l_tls *tls)
+{
+	/*
+	 * RFC 5746 Section 4.2: "It is possible that un-upgraded servers
+	 * will request that the client renegotiate.  It is RECOMMENDED
+	 * that clients refuse this renegotiation request." and Section 4.4:
+	 * "It is RECOMMENDED that servers not permit legacy renegotiation."
+	 *
+	 * This may need to be made configurable, for now follow the
+	 * recommendation and don't renegotiate.
+	 */
+	if (tls->ready)
+		return false;
+
+	/*
+	 * The normal policy otherwise is that the extension must be
+	 * present in renegotiation if the previous Client or Server Hello
+	 * did include this extension, or the SCSV in the Client Hello case.
+	 */
+	return !tls->ready || !tls->renegotiation_info.secure_renegotiation;
+}
+
+const struct tls_hello_extension tls_extensions[] = {
+	{
+		"Supported Groups", "elliptic_curves", 10,
+		tls_elliptic_curves_client_write,
+		tls_elliptic_curves_client_handle,
+		tls_elliptic_curves_client_absent,
+		NULL, NULL, NULL,
+	},
+	{
+		"Supported Point Formats", "ec_point_formats", 11,
+		NULL,
+		tls_ec_point_formats_client_handle,
+		NULL,
+		tls_ec_point_formats_server_write,
+		NULL, NULL,
+	},
+	{
+		"Signature Algorithms", "signature_algoritms", 13,
+		tls_signature_algorithms_client_write,
+		tls_signature_algorithms_client_handle,
+		tls_signature_algorithms_client_absent,
+		NULL, NULL, NULL,
+	},
+	{
+		"Secure Renegotiation", "renegotiation_info", 0xff01,
+		tls_renegotiation_info_client_write,
+		tls_renegotiation_info_client_handle,
+		tls_renegotiation_info_absent,
+		tls_renegotiation_info_server_write,
+		tls_renegotiation_info_server_handle,
+		tls_renegotiation_info_absent,
+	},
+	{}
+};
+
+const struct tls_named_group *tls_find_group(uint16_t id)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+		if (tls_group_pref[i].id == id)
+			return &tls_group_pref[i];
+
+	return NULL;
+}
+
+const struct tls_named_group *tls_find_ff_group(const uint8_t *prime,
+						size_t prime_len,
+						const uint8_t *generator,
+						size_t generator_len)
+{
+	unsigned int i;
+
+	if (generator_len != 1)
+		return NULL;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++) {
+		const struct tls_named_group *g = &tls_group_pref[i];
+
+		if (g->type != TLS_GROUP_TYPE_FF)
+			continue;
+
+		if (g->ff.prime_len != prime_len ||
+				memcmp(prime, g->ff.prime, prime_len))
+			continue;
+
+		if (g->ff.generator != *generator)
+			continue;
+
+		return g;
+	}
+
+	return NULL;
+}
diff --git a/ell/tls-private.h b/ell/tls-private.h
new file mode 100644
index 0000000..c493f7f
--- /dev/null
+++ b/ell/tls-private.h
@@ -0,0 +1,373 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#define TLS_MAX_VERSION	L_TLS_V12
+#define TLS_MIN_VERSION	L_TLS_V10
+
+enum tls_cipher_type {
+	TLS_CIPHER_STREAM,
+	TLS_CIPHER_BLOCK,
+	TLS_CIPHER_AEAD,
+};
+
+struct tls_bulk_encryption_algorithm {
+	enum tls_cipher_type cipher_type;
+	union {
+		enum l_cipher_type l_id;
+		enum l_aead_cipher_type l_aead_id;
+	};
+	size_t key_length;
+	size_t iv_length;
+	size_t fixed_iv_length;
+	size_t block_length;
+	size_t auth_tag_length;
+};
+
+/*
+ * Support the minimum required set of handshake hash types for the
+ * Certificate Verify digital signature and the Finished PRF seed so we
+ * don't have to accumulate all of messages full contents until the
+ * Finished message.  If we're sent a hash of a different type (in TLS 1.2+)
+ * and need to verify we'll give up.
+ * SHA1 and MD5 are explicitly required by versions < 1.2 and 1.2 requires
+ * that the Finished hash is the same as used for the PRF so we need to
+ * keep at least the hashes our supported cipher suites specify for the PRF.
+ */
+enum handshake_hash_type {
+	HANDSHAKE_HASH_SHA384,
+	HANDSHAKE_HASH_SHA256,
+	HANDSHAKE_HASH_MD5,
+	HANDSHAKE_HASH_SHA1,
+	__HANDSHAKE_HASH_COUNT,
+};
+#define HANDSHAKE_HASH_MAX_SIZE	48
+
+struct tls_hash_algorithm {
+	uint8_t tls_id;
+	enum handshake_hash_type type;
+	enum l_checksum_type l_id;
+	const char *name;
+};
+
+extern const struct tls_hash_algorithm tls_handshake_hash_data[];
+
+typedef bool (*tls_get_hash_t)(struct l_tls *tls,
+				enum handshake_hash_type type,
+				const uint8_t *data, size_t data_len,
+				uint8_t *out, size_t *out_len);
+
+struct tls_signature_algorithm {
+	uint8_t id;
+
+	bool (*validate_cert_key_type)(struct l_cert *cert);
+
+	ssize_t (*sign)(struct l_tls *tls, uint8_t *out, size_t out_len,
+			tls_get_hash_t get_hash,
+			const uint8_t *data, size_t data_len);
+	bool (*verify)(struct l_tls *tls, const uint8_t *in, size_t in_len,
+			tls_get_hash_t get_hash,
+			const uint8_t *data, size_t data_len);
+};
+
+struct tls_key_exchange_algorithm {
+	bool need_ecc;
+	bool need_ffdh;
+
+	bool (*send_server_key_exchange)(struct l_tls *tls);
+	void (*handle_server_key_exchange)(struct l_tls *tls,
+						const uint8_t *buf, size_t len);
+
+	bool (*send_client_key_exchange)(struct l_tls *tls);
+	void (*handle_client_key_exchange)(struct l_tls *tls,
+						const uint8_t *buf, size_t len);
+
+	void (*free_params)(struct l_tls *tls);
+};
+
+struct tls_mac_algorithm {
+	uint8_t id;
+	enum l_checksum_type hmac_type;
+	size_t mac_length;
+};
+
+struct tls_cipher_suite {
+	uint8_t id[2];
+	const char *name;
+	size_t verify_data_length;
+
+	struct tls_bulk_encryption_algorithm *encryption;
+	struct tls_signature_algorithm *signature;
+	struct tls_key_exchange_algorithm *key_xchg;
+	struct tls_mac_algorithm *mac;
+	enum l_checksum_type prf_hmac;
+};
+
+extern struct tls_cipher_suite *tls_cipher_suite_pref[];
+
+struct tls_compression_method {
+	int id;
+	const char *name;
+};
+
+struct tls_hello_extension {
+	const char *name;
+	const char *short_name;
+	uint16_t id;
+	ssize_t (*client_write)(struct l_tls *tls, uint8_t *buf, size_t len);
+	/* Handle a Client Hello extension (on server), can't be NULL */
+	bool (*client_handle)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+	/* Handle a Client Hello extension's absence (on server) */
+	bool (*client_handle_absent)(struct l_tls *tls);
+	ssize_t (*server_write)(struct l_tls *tls, uint8_t *buf, size_t len);
+	/* Handle a Server Hello extension (on client) */
+	bool (*server_handle)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+	/* Handle a Server Hello extension's absence (on client) */
+	bool (*server_handle_absent)(struct l_tls *tls);
+};
+
+extern const struct tls_hello_extension tls_extensions[];
+
+struct tls_named_group {
+	const char *name;
+	uint16_t id;
+	enum {
+		TLS_GROUP_TYPE_EC,
+		TLS_GROUP_TYPE_FF,
+	} type;
+	union {
+		struct {
+			const uint8_t *prime;
+			size_t prime_len;
+			unsigned int generator;
+		} ff;
+	};
+};
+
+enum tls_handshake_state {
+	TLS_HANDSHAKE_WAIT_START,
+	TLS_HANDSHAKE_WAIT_HELLO,
+	TLS_HANDSHAKE_WAIT_CERTIFICATE,
+	TLS_HANDSHAKE_WAIT_KEY_EXCHANGE,
+	TLS_HANDSHAKE_WAIT_HELLO_DONE,
+	TLS_HANDSHAKE_WAIT_CERTIFICATE_VERIFY,
+	TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC,
+	TLS_HANDSHAKE_WAIT_FINISHED,
+	TLS_HANDSHAKE_DONE,
+};
+
+enum tls_content_type {
+	TLS_CT_CHANGE_CIPHER_SPEC	= 20,
+	TLS_CT_ALERT			= 21,
+	TLS_CT_HANDSHAKE		= 22,
+	TLS_CT_APPLICATION_DATA		= 23,
+};
+
+enum tls_handshake_type {
+	TLS_HELLO_REQUEST	= 0,
+	TLS_CLIENT_HELLO	= 1,
+	TLS_SERVER_HELLO	= 2,
+	TLS_CERTIFICATE		= 11,
+	TLS_SERVER_KEY_EXCHANGE	= 12,
+	TLS_CERTIFICATE_REQUEST	= 13,
+	TLS_SERVER_HELLO_DONE	= 14,
+	TLS_CERTIFICATE_VERIFY	= 15,
+	TLS_CLIENT_KEY_EXCHANGE	= 16,
+	TLS_FINISHED		= 20,
+};
+
+struct l_tls {
+	bool server;
+
+	l_tls_write_cb_t tx, rx;
+	l_tls_ready_cb_t ready_handle;
+	l_tls_disconnect_cb_t disconnected;
+	void *user_data;
+	l_tls_debug_cb_t debug_handler;
+	l_tls_destroy_cb_t debug_destroy;
+	void *debug_data;
+	char *cert_dump_path;
+	enum l_tls_version min_version;
+	enum l_tls_version max_version;
+
+	struct l_queue *ca_certs;
+	struct l_certchain *cert;
+	struct l_key *priv_key;
+	size_t priv_key_size;
+	char **subject_mask;
+
+	struct tls_cipher_suite **cipher_suite_pref_list;
+
+	struct l_settings *session_settings;
+	char *session_prefix;
+	uint64_t session_lifetime;
+	unsigned int session_count_max;
+	l_tls_session_update_cb_t session_update_cb;
+	void *session_update_user_data;
+
+	bool in_callback;
+	bool pending_destroy;
+
+	/* Record layer */
+
+	uint8_t *record_buf;
+	int record_buf_len;
+	int record_buf_max_len;
+	bool record_flush;
+
+	uint8_t *message_buf;
+	int message_buf_len;
+	int message_buf_max_len;
+	enum tls_content_type message_content_type;
+
+	/* Handshake protocol layer */
+
+	enum tls_handshake_state state;
+	struct l_checksum *handshake_hash[__HANDSHAKE_HASH_COUNT];
+	uint8_t prev_digest[__HANDSHAKE_HASH_COUNT][HANDSHAKE_HASH_MAX_SIZE];
+
+	enum l_tls_version client_version;
+	enum l_tls_version negotiated_version;
+	bool cert_requested, cert_sent;
+	bool peer_authenticated;
+	struct l_cert *peer_cert;
+	struct l_key *peer_pubkey;
+	size_t peer_pubkey_size;
+	enum handshake_hash_type signature_hash;
+	const struct tls_hash_algorithm *prf_hmac;
+	const struct tls_named_group *negotiated_curve;
+	const struct tls_named_group *negotiated_ff_group;
+
+	uint8_t session_id[32];
+	size_t session_id_size;
+	uint8_t session_id_replaced[32];
+	size_t session_id_size_replaced;
+	bool session_id_new;
+	uint8_t session_cipher_suite_id[2];
+	uint8_t session_compression_method_id;
+	char *session_peer_identity;
+	bool session_resumed;
+
+	struct {
+		bool secure_renegotiation;
+		/* Max .verify_data_length over supported cipher suites */
+		uint8_t client_verify_data[12];
+		uint8_t server_verify_data[12];
+	} renegotiation_info;
+
+	/* SecurityParameters current and pending */
+
+	struct {
+		struct tls_cipher_suite *cipher_suite;
+		struct tls_compression_method *compression_method;
+		uint8_t master_secret[48];
+		uint8_t client_random[32];
+		uint8_t server_random[32];
+		/*
+		 * Max key block size per 6.3 v1.1 is 136 bytes but if we
+		 * allow AES_256_CBC_SHA256 with v1.0 we get 128 per section
+		 * 6.3 v1.2 + two IVs of 32 bytes.
+		 */
+		uint8_t key_block[192];
+		void *key_xchg_params;
+	} pending;
+
+	enum tls_cipher_type cipher_type[2];
+	struct tls_cipher_suite *cipher_suite[2];
+	union {
+		struct l_cipher *cipher[2];
+		struct l_aead_cipher *aead_cipher[2];
+	};
+	struct l_checksum *mac[2];
+	size_t mac_length[2];
+	size_t block_length[2];
+	size_t record_iv_length[2];
+	size_t fixed_iv_length[2];
+	uint8_t fixed_iv[2][32];
+	size_t auth_tag_length[2];
+	uint64_t seq_num[2];
+	/*
+	 * Some of the key and IV parts of the "current" state are kept
+	 * inside the cipher and mac states in the kernel so we don't
+	 * duplicate them here.
+	 */
+
+	bool ready;
+};
+
+bool tls10_prf(const void *secret, size_t secret_len,
+		const char *label,
+		const void *seed, size_t seed_len,
+		uint8_t *out, size_t out_len);
+
+bool tls12_prf(enum l_checksum_type type,
+		const void *secret, size_t secret_len,
+		const char *label,
+		const void *seed, size_t seed_len,
+		uint8_t *out, size_t out_len);
+
+void tls_disconnect(struct l_tls *tls, enum l_tls_alert_desc desc,
+			enum l_tls_alert_desc local_desc);
+
+void tls_tx_record(struct l_tls *tls, enum tls_content_type type,
+			const uint8_t *data, size_t len);
+bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
+			int len, enum tls_content_type type, uint16_t version);
+
+#define TLS_HANDSHAKE_HEADER_SIZE	4
+
+void tls_tx_handshake(struct l_tls *tls, int type, uint8_t *buf, size_t length);
+
+bool tls_cipher_suite_is_compatible(struct l_tls *tls,
+					const struct tls_cipher_suite *suite,
+					const char **error);
+
+/* Optionally limit allowed cipher suites to a custom set */
+bool tls_set_cipher_suites(struct l_tls *tls, const char **suite_list);
+
+void tls_generate_master_secret(struct l_tls *tls,
+				const uint8_t *pre_master_secret,
+				int pre_master_secret_len);
+
+size_t tls_verify_data_length(struct l_tls *tls, unsigned int index);
+
+const struct tls_named_group *tls_find_group(uint16_t id);
+const struct tls_named_group *tls_find_ff_group(const uint8_t *prime,
+						size_t prime_len,
+						const uint8_t *generator,
+						size_t generator_len);
+
+ssize_t tls_write_signature_algorithms(struct l_tls *tls,
+					uint8_t *buf, size_t len);
+ssize_t tls_parse_signature_algorithms(struct l_tls *tls,
+					const uint8_t *buf, size_t len);
+
+int tls_parse_certificate_list(const void *data, size_t len,
+				struct l_certchain **out_certchain);
+
+#define TLS_DEBUG(fmt, args...)	\
+	l_util_debug(tls->debug_handler, tls->debug_data, "%s:%i " fmt,	\
+			__func__, __LINE__, ## args)
+#define TLS_SET_STATE(new_state)	\
+	do {	\
+		TLS_DEBUG("New state %s",	\
+				tls_handshake_state_to_str(new_state));	\
+		tls->state = new_state;	\
+	} while (0)
+#define TLS_DISCONNECT(desc, local_desc, fmt, args...)	\
+	do {	\
+		TLS_DEBUG("Disconnect desc=%s local-desc=%s reason=" fmt,\
+				l_tls_alert_to_str(desc),	\
+				l_tls_alert_to_str(local_desc), ## args);\
+		tls_disconnect(tls, desc, local_desc);	\
+	} while (0)
+
+#define TLS_VER_FMT		"1.%i"
+#define TLS_VER_ARGS(version)	(((version) & 0xff) - 1)
+
+const char *tls_handshake_state_to_str(enum tls_handshake_state state);
diff --git a/ell/tls-record.c b/ell/tls-record.c
new file mode 100644
index 0000000..b0471f8
--- /dev/null
+++ b/ell/tls-record.c
@@ -0,0 +1,629 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <alloca.h>
+
+#include "private.h"
+#include "tls.h"
+#include "checksum.h"
+#include "cipher.h"
+#include "cert.h"
+#include "tls-private.h"
+#include "random.h"
+
+/* Implementation-specific max Record Layer fragment size (must be < 16kB) */
+#define TX_RECORD_MAX_LEN	4096
+
+/* TLSPlaintext + TLSCompressed + TLSCiphertext headers + seq_num sizes */
+#define TX_RECORD_MAX_HEADERS	(5 + 5 + 8 + 5)
+#define TX_RECORD_MAX_MAC	64
+
+/* Head room and tail room for the buffer passed to the cipher */
+#define TX_RECORD_HEADROOM	TX_RECORD_MAX_HEADERS
+#define TX_RECORD_TAILROOM	TX_RECORD_MAX_MAC
+
+static void tls_write_mac(struct l_tls *tls, uint8_t *compressed,
+				uint16_t compressed_len, uint8_t *out_buf,
+				bool txrx)
+{
+	uint8_t *in_buf;
+
+	/* Prepend the sequence number to the TLSCompressed buffer */
+	in_buf = compressed - 8;
+	l_put_be64(tls->seq_num[txrx]++, in_buf);
+
+	if (tls->mac[txrx]) {
+		l_checksum_reset(tls->mac[txrx]);
+		l_checksum_update(tls->mac[txrx], in_buf, compressed_len + 8);
+		l_checksum_get_digest(tls->mac[txrx], out_buf,
+					tls->mac_length[txrx]);
+	}
+}
+
+static void tls_tx_record_plaintext(struct l_tls *tls,
+					uint8_t *plaintext,
+					uint16_t plaintext_len)
+{
+	uint8_t *compressed;
+	uint16_t compressed_len;
+	uint8_t *cipher_input;
+	uint16_t cipher_input_len;
+	uint8_t *ciphertext;
+	uint16_t ciphertext_len;
+	uint8_t padding_length;
+	uint8_t buf[TX_RECORD_HEADROOM + TX_RECORD_MAX_LEN +
+				TX_RECORD_TAILROOM];
+	uint8_t iv[32];
+	uint8_t *assocdata;
+	int offset;
+
+	/*
+	 * TODO: if DEFLATE is selected in current state, use a new buffer
+	 * on stack to write a TLSCompressed structure there, otherwise use
+	 * the provided buffer.  Since only null compression is supported
+	 * today we always use the provided buffer.
+	 */
+	compressed_len = plaintext_len - 5;
+	compressed = plaintext;
+
+	/* Build a TLSCompressed struct */
+	compressed[0] = plaintext[0]; /* Copy type and version fields */
+	compressed[1] = plaintext[1];
+	compressed[2] = plaintext[2];
+	compressed[3] = compressed_len >> 8;
+	compressed[4] = compressed_len >> 0;
+
+	switch (tls->cipher_type[1]) {
+	case TLS_CIPHER_STREAM:
+		/* Append the MAC after TLSCompressed.fragment, if needed */
+		tls_write_mac(tls, compressed, compressed_len + 5,
+				compressed + compressed_len + 5, true);
+
+		cipher_input = compressed + 5;
+		cipher_input_len = compressed_len + tls->mac_length[1];
+
+		if (!tls->cipher[1]) {
+			ciphertext = cipher_input;
+			ciphertext_len = cipher_input_len;
+		} else {
+			ciphertext = buf + TX_RECORD_HEADROOM;
+			ciphertext_len = cipher_input_len;
+			l_cipher_encrypt(tls->cipher[1], cipher_input,
+						ciphertext, cipher_input_len);
+		}
+
+		break;
+
+	case TLS_CIPHER_BLOCK:
+		/* Append the MAC after TLSCompressed.fragment, if needed */
+		cipher_input = compressed + 5;
+		tls_write_mac(tls, compressed, compressed_len + 5,
+				cipher_input + compressed_len, true);
+		cipher_input_len = compressed_len + tls->mac_length[1];
+
+		/* Add minimum padding */
+		padding_length = (~cipher_input_len) &
+			(tls->block_length[1] - 1);
+		memset(cipher_input + cipher_input_len, padding_length,
+				padding_length + 1);
+		cipher_input_len += padding_length + 1;
+
+		/* Generate an IV */
+		ciphertext = buf + TX_RECORD_HEADROOM;
+
+		offset = 0;
+
+		if (tls->negotiated_version >= L_TLS_V12) {
+			l_getrandom(ciphertext, tls->record_iv_length[1]);
+
+			l_cipher_set_iv(tls->cipher[1], ciphertext,
+					tls->record_iv_length[1]);
+
+			offset = tls->record_iv_length[1];
+		} else if (tls->negotiated_version >= L_TLS_V11) {
+			l_getrandom(iv, tls->record_iv_length[1]);
+
+			l_cipher_encrypt(tls->cipher[1], iv, ciphertext,
+						tls->record_iv_length[1]);
+
+			offset = tls->record_iv_length[1];
+		}
+
+		l_cipher_encrypt(tls->cipher[1], cipher_input,
+					ciphertext + offset, cipher_input_len);
+		ciphertext_len = offset + cipher_input_len;
+
+		break;
+
+	case TLS_CIPHER_AEAD:
+		/* Prepend seq_num to TLSCompressed.type + .version + .length */
+		assocdata = compressed - 8;
+		l_put_be64(tls->seq_num[1]++, assocdata);
+
+		cipher_input = compressed + 5;
+		cipher_input_len = compressed_len;
+
+		/*
+		 * Build the IV.  The explicit part generation method is
+		 * actually cipher suite-specific but our only AEAD cipher
+		 * suites only require this part to be unique for each
+		 * record.  For future suites there may need to be a callback
+		 * that generates the per-record IV or an enum for the suite
+		 * to select one of a few IV types.
+		 *
+		 * Note kernel's rfc4106(gcm(...)) algorithm could potentially
+		 * be used to build the IV.
+		 */
+		memcpy(iv, tls->fixed_iv[1], tls->fixed_iv_length[1]);
+		l_put_le64(tls->seq_num[1], iv + tls->fixed_iv_length[1]);
+
+		if (tls->record_iv_length[1] > 8)
+			memset(iv + tls->fixed_iv_length[1] + 8, 42,
+				tls->record_iv_length[1] - 8);
+
+		/* Build the GenericAEADCipher struct */
+		ciphertext = buf + TX_RECORD_HEADROOM;
+		memcpy(ciphertext, iv + tls->fixed_iv_length[1],
+			tls->record_iv_length[1]);
+		l_aead_cipher_encrypt(tls->aead_cipher[1],
+					cipher_input, cipher_input_len,
+					assocdata, 13,
+					iv, tls->fixed_iv_length[1] +
+					tls->record_iv_length[1],
+					ciphertext + tls->record_iv_length[1],
+					cipher_input_len +
+					tls->auth_tag_length[1]);
+
+		ciphertext_len = tls->record_iv_length[1] +
+			cipher_input_len + tls->auth_tag_length[1];
+
+		break;
+
+	default:
+		return;
+	}
+
+	/* Build a TLSCiphertext struct */
+	ciphertext -= 5;
+	ciphertext[0] = plaintext[0]; /* Copy type and version fields */
+	ciphertext[1] = plaintext[1];
+	ciphertext[2] = plaintext[2];
+	ciphertext[3] = ciphertext_len >> 8;
+	ciphertext[4] = ciphertext_len >> 0;
+
+	tls->tx(ciphertext, ciphertext_len + 5, tls->user_data);
+}
+
+void tls_tx_record(struct l_tls *tls, enum tls_content_type type,
+			const uint8_t *data, size_t len)
+{
+	uint8_t buf[TX_RECORD_HEADROOM + TX_RECORD_MAX_LEN +
+				TX_RECORD_TAILROOM];
+	uint8_t *fragment, *plaintext;
+	uint16_t fragment_len;
+	uint16_t version = tls->negotiated_version ?: tls->min_version;
+
+	if (type == TLS_CT_ALERT)
+		tls->record_flush = true;
+
+	while (len) {
+		fragment = buf + TX_RECORD_HEADROOM;
+		fragment_len = len < TX_RECORD_MAX_LEN ?
+			len : TX_RECORD_MAX_LEN;
+
+		/* Build a TLSPlaintext struct */
+		plaintext = fragment - 5;
+		plaintext[0] = type;
+		plaintext[1] = (uint8_t) (version >> 8);
+		plaintext[2] = (uint8_t) (version >> 0);
+		plaintext[3] = fragment_len >> 8;
+		plaintext[4] = fragment_len >> 0;
+		memcpy(plaintext + 5, data, fragment_len);
+
+		tls_tx_record_plaintext(tls, plaintext, fragment_len + 5);
+
+		data += fragment_len;
+		len -= fragment_len;
+	}
+}
+
+static bool tls_handle_plaintext(struct l_tls *tls, const uint8_t *plaintext,
+					int len, uint8_t type, uint16_t version)
+{
+	if (len > (1 << 14)) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Plaintext message too long: %i", len);
+		return false;
+	}
+
+	switch (type) {
+	case TLS_CT_CHANGE_CIPHER_SPEC:
+	case TLS_CT_APPLICATION_DATA:
+		return tls_handle_message(tls, plaintext, len, type, version);
+
+	/*
+	 * We need to perform input reassembly twice at different levels:
+	 * once to make sure we're handling complete TLSCiphertext messages,
+	 * in l_tls_handle_rx(), and again here so that the Alert and
+	 * Handshake message type handlers deal with complete messages.
+	 * This does not affect ChangeCipherSpec messages because they're
+	 * just a single byte and there are never more than one such message
+	 * in a row.  Similarly it doesn't affect application data because
+	 * the application is not guaranteed that message boundaries are
+	 * preserved in any way and we don't know its message lengths anyway.
+	 * It does affect Alert because these messages are 2 byte long and
+	 * could potentially be split over two TLSPlaintext messages but
+	 * there are never more than one Alert in a TLSPlaintext for the same
+	 * reason as with ChangeCipherSpec.  Handshake messages are the
+	 * most affected although the need to do the reassembly twice still
+	 * seems wasteful considering most of these messages are sent in
+	 * plaintext and TLSCiphertext maps to TLSPlaintext records.
+	 */
+	case TLS_CT_ALERT:
+	case TLS_CT_HANDSHAKE:
+		break;
+
+	default:
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Unknown content type %i", type);
+		return false;
+	}
+
+	if (tls->message_buf_len && type != tls->message_content_type) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Message fragment type %i doesn't match "
+				"previous type %i", type,
+				tls->message_content_type);
+		return false;
+	}
+
+	tls->message_content_type = type;
+
+	while (1) {
+		int header_len, need_len;
+		int chunk_len;
+
+		/* Do we have a full header in tls->message_buf? */
+		header_len = (type == TLS_CT_ALERT) ? 2 : 4;
+		need_len = header_len;
+
+		if (tls->message_buf_len >= header_len) {
+			if (type == TLS_CT_HANDSHAKE) {
+				uint32_t hs_len = (tls->message_buf[1] << 16) |
+					(tls->message_buf[2] << 8) |
+					(tls->message_buf[3] << 0);
+				if (hs_len > (1 << 14)) {
+					TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR,
+							0, "Handshake message "
+							"too long: %i",
+							(int) hs_len);
+					return false;
+				}
+
+				need_len += hs_len;
+			}
+
+			/* Do we have a full structure? */
+			if (tls->message_buf_len == need_len) {
+				if (!tls_handle_message(tls, tls->message_buf,
+							need_len, type,
+							version))
+					return false;
+
+				tls->message_buf_len = 0;
+
+				if (tls->record_flush)
+					break;
+
+				continue;
+			}
+
+			if (!len)
+				break;
+		}
+
+		/* Try to fill up tls->message_buf up to need_len */
+		if (tls->message_buf_max_len < need_len) {
+			tls->message_buf_max_len = need_len;
+			tls->message_buf =
+				l_realloc(tls->message_buf, need_len);
+		}
+
+		need_len -= tls->message_buf_len;
+		chunk_len = need_len;
+		if (len < chunk_len)
+			chunk_len = len;
+
+		memcpy(tls->message_buf + tls->message_buf_len, plaintext,
+				chunk_len);
+		tls->message_buf_len += chunk_len;
+		plaintext += chunk_len;
+		len -= chunk_len;
+
+		if (chunk_len < need_len)
+			break;
+	}
+
+	return true;
+}
+
+static bool tls_handle_ciphertext(struct l_tls *tls)
+{
+	uint8_t type;
+	uint16_t version;
+	uint16_t fragment_len;
+	uint8_t mac_buf[TX_RECORD_MAX_MAC], i, padding_len;
+	int cipher_output_len, error;
+	uint8_t *compressed;
+	int compressed_len;
+	uint8_t iv[32];
+	uint8_t *assocdata;
+
+	type = tls->record_buf[0];
+	version = l_get_be16(tls->record_buf + 1);
+	fragment_len = l_get_be16(tls->record_buf + 3);
+
+	if (fragment_len > (1 << 14) + 2048) {
+		TLS_DISCONNECT(TLS_ALERT_RECORD_OVERFLOW, 0,
+				"Record fragment too long: %u", fragment_len);
+		return false;
+	}
+
+	if ((tls->negotiated_version && tls->negotiated_version != version) ||
+			(!tls->negotiated_version &&
+			 tls->record_buf[1] != 0x03 /* Appending E.1 */)) {
+		TLS_DISCONNECT(TLS_ALERT_PROTOCOL_VERSION, 0,
+				"Record version mismatch: %02x", version);
+		return false;
+	}
+
+	if (fragment_len < tls->mac_length[0]) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Record fragment too short: %u", fragment_len);
+		return false;
+	}
+
+	compressed = alloca(8 + 5 + fragment_len);
+	/* Copy the type and version fields */
+	compressed[8] = type;
+	l_put_be16(version, compressed + 9);
+
+	switch (tls->cipher_type[0]) {
+	case TLS_CIPHER_STREAM:
+		cipher_output_len = fragment_len;
+		compressed_len = cipher_output_len - tls->mac_length[0];
+		l_put_be16(compressed_len, compressed + 11);
+
+		if (!tls->cipher[0])
+			memcpy(compressed + 13, tls->record_buf + 5,
+					cipher_output_len);
+		else if (!l_cipher_decrypt(tls->cipher[0], tls->record_buf + 5,
+						compressed + 13,
+						cipher_output_len)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"Decrypting record fragment failed");
+			return false;
+		}
+
+		/* Calculate the MAC if needed */
+		tls_write_mac(tls, compressed + 8, 5 + compressed_len,
+				mac_buf, false);
+
+		if (memcmp(mac_buf, compressed + 13 + compressed_len,
+							tls->mac_length[0])) {
+			TLS_DISCONNECT(TLS_ALERT_BAD_RECORD_MAC, 0,
+					"Record fragment MAC mismatch");
+			return false;
+		}
+
+		compressed += 13;
+
+		break;
+
+	case TLS_CIPHER_BLOCK:
+		i = 0;
+		if (tls->negotiated_version >= L_TLS_V11)
+			i = tls->record_iv_length[0];
+
+		if (fragment_len <= tls->mac_length[0] + i) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Record fragment too short: %u",
+					fragment_len);
+			return false;
+		}
+
+		cipher_output_len = fragment_len - i;
+
+		if (cipher_output_len % tls->block_length[0] != 0) {
+			/*
+			 * In strict TLS 1.0 TLS_ALERT_DECRYPT_FAIL_RESERVED
+			 * should be returned here but that was declared
+			 * unsafe in the TLS 1.1 spec.
+			 */
+			TLS_DISCONNECT(TLS_ALERT_BAD_RECORD_MAC, 0,
+					"Fragment data len %i not a multiple "
+					"of block length %zi",
+					cipher_output_len,
+					tls->block_length[0]);
+			return false;
+		}
+
+		if (tls->negotiated_version >= L_TLS_V12) {
+			if (!l_cipher_set_iv(tls->cipher[0],
+						tls->record_buf + 5,
+						tls->record_iv_length[0])) {
+				TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+						"Setting fragment IV failed");
+				return false;
+			}
+		} else if (tls->negotiated_version >= L_TLS_V11)
+			if (!l_cipher_decrypt(tls->cipher[0],
+						tls->record_buf + 5, iv,
+						tls->record_iv_length[0])) {
+				TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+						"Setting fragment IV failed");
+				return false;
+			}
+
+		if (!l_cipher_decrypt(tls->cipher[0], tls->record_buf + 5 + i,
+					compressed + 13, cipher_output_len)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"Fragment decryption failed");
+			return false;
+		}
+
+		/*
+		 * RFC 5246, page 24:
+		 * In order to defend against this attack, implementations
+		 * MUST ensure that record processing time is essentially the
+		 * same whether or not the padding is correct.  In general,
+		 * the best way to do this is to compute the MAC even if the
+		 * padding is incorrect, and only then reject the packet.  For
+		 * instance, if the pad appears to be incorrect, the
+		 * implementation might assume a zero-length pad and then
+		 * compute the MAC.
+		 */
+		padding_len = compressed[13 + cipher_output_len - 1];
+		error = 0;
+		if (padding_len + tls->mac_length[0] + 1 >
+				(size_t) cipher_output_len) {
+			/*
+			 * In strict TLS 1.0 TLS_ALERT_DECRYPT_FAIL_RESERVED
+			 * should be returned here but that was declared
+			 * unsafe in the TLS 1.1 spec.
+			 */
+			padding_len = 0;
+			error = 1;
+		}
+
+		compressed_len = cipher_output_len - 1 - padding_len -
+			tls->mac_length[0];
+		l_put_be16(compressed_len, compressed + 11);
+
+		error |= !l_secure_memeq(compressed + 13 + cipher_output_len -
+						1 - padding_len, padding_len,
+						padding_len);
+
+		/* Calculate the MAC if needed */
+		tls_write_mac(tls, compressed + 8, 5 + compressed_len,
+				mac_buf, false);
+
+		if ((tls->mac_length[0] && memcmp(mac_buf, compressed + 13 +
+					compressed_len, tls->mac_length[0])) ||
+				error) {
+			TLS_DISCONNECT(TLS_ALERT_BAD_RECORD_MAC, 0,
+					"Record fragment MAC mismatch");
+			return false;
+		}
+
+		compressed += 13;
+
+		break;
+
+	case TLS_CIPHER_AEAD:
+		if (fragment_len <= tls->record_iv_length[0] +
+				tls->auth_tag_length[0]) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Record fragment too short: %u",
+					fragment_len);
+			return false;
+		}
+
+		compressed_len = fragment_len - tls->record_iv_length[0] -
+			tls->auth_tag_length[0];
+		l_put_be16(compressed_len, compressed + 11);
+
+		/* Prepend seq_num to TLSCompressed.type + .version + .length */
+		assocdata = compressed;
+		l_put_be64(tls->seq_num[0]++, assocdata);
+		compressed += 13;
+
+		/* Build the IV */
+		memcpy(iv, tls->fixed_iv[0], tls->fixed_iv_length[0]);
+		memcpy(iv + tls->fixed_iv_length[0], tls->record_buf + 5,
+			tls->record_iv_length[0]);
+
+		if (!l_aead_cipher_decrypt(tls->aead_cipher[0],
+				tls->record_buf + 5 + tls->record_iv_length[0],
+				fragment_len - tls->record_iv_length[0],
+				assocdata, 13, iv, tls->fixed_iv_length[0] +
+				tls->record_iv_length[0],
+				compressed, compressed_len)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"Decrypting record fragment failed");
+			return false;
+		}
+
+		break;
+
+	default:
+		return false;
+	}
+
+	/* DEFLATE not supported so just pass on compressed / compressed_len */
+
+	return tls_handle_plaintext(tls, compressed, compressed_len,
+					type, version);
+}
+
+LIB_EXPORT void l_tls_handle_rx(struct l_tls *tls, const uint8_t *data,
+				size_t len)
+{
+	int need_len;
+	int chunk_len;
+
+	tls->record_flush = false;
+
+	/* Reassemble TLSCiphertext structures from the received chunks */
+
+	while (1) {
+		/* Do we have a full header in tls->record_buf? */
+		if (tls->record_buf_len >= 5) {
+			need_len = 5 + l_get_be16(tls->record_buf + 3);
+
+			/* Do we have a full structure? */
+			if (tls->record_buf_len == need_len) {
+				if (!tls_handle_ciphertext(tls))
+					return;
+
+				tls->record_buf_len = 0;
+				need_len = 5;
+
+				if (tls->record_flush)
+					break;
+			}
+
+			if (!len)
+				break;
+		} else
+			need_len = 5;
+
+		/* Try to fill up tls->record_buf up to need_len */
+		if (tls->record_buf_max_len < need_len) {
+			tls->record_buf_max_len = need_len;
+			tls->record_buf = l_realloc(tls->record_buf, need_len);
+		}
+
+		need_len -= tls->record_buf_len;
+		chunk_len = need_len;
+		if (len < (size_t) chunk_len)
+			chunk_len = len;
+
+		memcpy(tls->record_buf + tls->record_buf_len, data, chunk_len);
+		tls->record_buf_len += chunk_len;
+		data += chunk_len;
+		len -= chunk_len;
+
+		if (chunk_len < need_len)
+			break;
+	}
+}
diff --git a/ell/tls-suites.c b/ell/tls-suites.c
new file mode 100644
index 0000000..eb023a6
--- /dev/null
+++ b/ell/tls-suites.c
@@ -0,0 +1,1458 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2018  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "util.h"
+#include "tls.h"
+#include "cipher.h"
+#include "checksum.h"
+#include "cert.h"
+#include "tls-private.h"
+#include "key.h"
+#include "random.h"
+#include "ecc.h"
+#include "ecdh.h"
+#include "missing.h"
+
+enum signature_algorithm {
+	SIGNATURE_ALGORITHM_ANONYMOUS = 0,
+	SIGNATURE_ALGORITHM_RSA = 1,
+	SIGNATURE_ALGORITHM_DSA = 2,
+	SIGNATURE_ALGORITHM_ECDSA = 3,
+};
+
+static enum handshake_hash_type find_hash_by_id(uint8_t id)
+{
+	enum handshake_hash_type hash;
+
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+		if (tls_handshake_hash_data[hash].tls_id == id)
+			break;
+
+	return hash;
+}
+
+/*
+ * Sanitize DigitallySigned struct input, making sure the lengths
+ * are valid and correspond to what we expect.
+ *
+ * Returns: start of the opaque portion
+ */
+static const uint8_t *validate_digitally_signed(struct l_tls *tls,
+					const uint8_t *in, size_t in_len,
+					enum signature_algorithm expected_alg,
+					uint16_t *opaque_len)
+{
+	size_t offset = 2;
+	uint16_t len;
+
+	if (tls->negotiated_version < L_TLS_V12)
+		offset = 0;
+
+	if (in_len < offset + 2)
+		goto size_error;
+
+	len = l_get_be16(in + offset);
+	if (len != in_len - offset - 2)
+		goto size_error;
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		if (in[1] != expected_alg) {
+			TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+					"Unknown signature algorithm %i",
+					in[1]);
+
+			return NULL;
+		}
+	}
+
+	*opaque_len = len;
+	return in + offset + 2;
+
+size_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, "Signature msg too "
+			"short (%zi) or signature length doesn't match",
+			in_len);
+	return NULL;
+}
+
+static bool tls_rsa_validate_cert_key(struct l_cert *cert)
+{
+	return l_cert_get_pubkey_type(cert) == L_CERT_KEY_RSA;
+}
+
+static ssize_t tls_rsa_sign(struct l_tls *tls, uint8_t *out, size_t out_len,
+				tls_get_hash_t get_hash,
+				const uint8_t *data, size_t data_len)
+{
+	ssize_t result = -EMSGSIZE;
+	enum l_checksum_type sign_checksum_type;
+	uint8_t sign_input[HANDSHAKE_HASH_MAX_SIZE + 36];
+	size_t sign_input_len;
+	uint8_t *ptr = out;
+
+	if (!tls->priv_key || !tls->priv_key_size) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, TLS_ALERT_BAD_CERT,
+				"No private key loaded");
+
+		return -ENOKEY;
+	}
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		const struct tls_hash_algorithm *hash_type =
+			&tls_handshake_hash_data[tls->signature_hash];
+
+		/* Build the DigitallySigned struct */
+		if (out_len < 2) /* Is there space for the algorithm IDs */
+			goto error;
+
+		get_hash(tls, tls->signature_hash, data, data_len,
+				sign_input, &sign_input_len);
+		sign_checksum_type = hash_type->l_id;
+
+		*ptr++ = hash_type->tls_id;
+		*ptr++ = 1;	/* RSA_sign */
+		out_len -= 2;
+	} else {
+		get_hash(tls, HANDSHAKE_HASH_MD5, data, data_len,
+				sign_input + 0, NULL);
+		get_hash(tls, HANDSHAKE_HASH_SHA1, data, data_len,
+				sign_input + 16, NULL);
+		sign_checksum_type = L_CHECKSUM_NONE;
+		sign_input_len = 36;
+	}
+
+	if (out_len < tls->priv_key_size + 2)
+		goto error;
+
+	l_put_be16(tls->priv_key_size, ptr);
+	result = l_key_sign(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
+				sign_checksum_type, sign_input, ptr + 2,
+				sign_input_len, tls->priv_key_size);
+	ptr += tls->priv_key_size + 2;
+
+	if (result == (ssize_t) tls->priv_key_size)
+		return ptr - out; /* Success */
+
+error:
+	TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+			"Signing the hash failed: %s",
+			strerror(-result));
+	return result;
+}
+
+static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len,
+				tls_get_hash_t get_hash,
+				const uint8_t *data, size_t data_len)
+{
+	enum l_checksum_type sign_checksum_type;
+	uint8_t expected[HANDSHAKE_HASH_MAX_SIZE + 36];
+	size_t expected_len;
+	const uint8_t *opaque;
+	uint16_t opaque_len;
+	bool success;
+
+	opaque = validate_digitally_signed(tls, in, in_len,
+				SIGNATURE_ALGORITHM_RSA, &opaque_len);
+	if (!opaque)
+		return false;
+
+	/* Only the default hash type supported */
+	if (opaque_len != tls->peer_pubkey_size) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Signature length %hu not equal %zi",
+				opaque_len, tls->peer_pubkey_size);
+
+		return false;
+	}
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		enum handshake_hash_type hash = find_hash_by_id(in[0]);
+
+		if (hash == __HANDSHAKE_HASH_COUNT) {
+			TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+					"Unknown hash type %i", in[0]);
+			return false;
+		}
+
+		get_hash(tls, hash, data, data_len, expected, &expected_len);
+		sign_checksum_type = tls_handshake_hash_data[hash].l_id;
+
+		/*
+		 * Note: Next we let the l_key_verify's underlying kernel
+		 * operation prepend the OID to the hash to build the
+		 * DigestInfo struct.  However according to 4.7 we need to
+		 * support at least two forms of the signed content in the
+		 * verification:
+		 *  - DigestInfo with NULL AlgorithmIdentifier.parameters,
+		 *  - DigestInfo with empty AlgorithmIdentifier.parameters,
+		 *
+		 * while the kernel only understands the former encoding.
+		 * Note PKCS#1 versions 2.0 and later section A.2.4 do
+		 * mandate NULL AlgorithmIdentifier.parameters.
+		 *
+		 * Additionally PKCS#1 v1.5 said BER is used in place of DER
+		 * for DigestInfo encoding which adds more ambiguity in the
+		 * encoding.
+		 */
+	} else {
+		get_hash(tls, HANDSHAKE_HASH_MD5, data, data_len,
+				expected + 0, NULL);
+		get_hash(tls, HANDSHAKE_HASH_SHA1, data, data_len,
+				expected + 16, NULL);
+		expected_len = 36;
+		sign_checksum_type = L_CHECKSUM_NONE;
+
+		/*
+		 * Note: Within the RSA padding for signatures PKCS#1 1.5
+		 * allows the block format to be either 0 or 1, while PKCS#1
+		 * v2.0+ mandates block type 1 making the signatures
+		 * unambiguous.  TLS 1.0 doesn't additionally specify which
+		 * block type is to be used (TLS 1.2 does) meaning that both
+		 * PKCS#1 v1.5 types are allowed.  The l_key_verify's
+		 * underlying kernel implementation only accepts block type
+		 * 1.  If this ever becomes an issue we'd need to go back to
+		 * using L_KEY_RSA_RAW and our own PKCS#1 v1.5 verify logic.
+		 */
+	}
+
+	success = l_key_verify(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5,
+				sign_checksum_type, expected, opaque,
+				expected_len, tls->peer_pubkey_size);
+
+	if (!success)
+		TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+				"Peer signature verification failed");
+	else
+		TLS_DEBUG("Peer signature verified");
+
+	return success;
+}
+
+static struct tls_signature_algorithm tls_rsa_signature = {
+	.id = 1, /* SignatureAlgorithm.rsa */
+	.validate_cert_key_type = tls_rsa_validate_cert_key,
+	.sign = tls_rsa_sign,
+	.verify = tls_rsa_verify,
+};
+
+static bool tls_ecdsa_validate_cert_key(struct l_cert *cert)
+{
+	return l_cert_get_pubkey_type(cert) == L_CERT_KEY_ECC;
+}
+
+static bool tls_ecdsa_verify(struct l_tls *tls,
+				const uint8_t *in, size_t in_len,
+				tls_get_hash_t get_hash,
+				const uint8_t *data, size_t data_len)
+{
+	/* RFC 8422, Section 5.10: "SHA-1 is used in TLS 1.1 and earlier" */
+	enum handshake_hash_type hash = HANDSHAKE_HASH_SHA1;
+	enum l_checksum_type sign_checksum_type;
+	const uint8_t *opaque;
+	uint16_t opaque_len;
+	uint8_t expected[HANDSHAKE_HASH_MAX_SIZE];
+	size_t expected_len;
+	bool success;
+
+	opaque = validate_digitally_signed(tls, in, in_len,
+				SIGNATURE_ALGORITHM_ECDSA, &opaque_len);
+	if (!opaque)
+		return false;
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		hash = find_hash_by_id(in[0]);
+		if (hash == __HANDSHAKE_HASH_COUNT) {
+			TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+					"Unknown hash type %i", in[0]);
+			return false;
+		}
+
+		/* Hash should match the curve, refer to RFC 5480, Section 4 */
+		switch (tls->peer_pubkey_size) {
+		case 32:
+			if (hash != HANDSHAKE_HASH_SHA256 &&
+					hash != HANDSHAKE_HASH_SHA384)
+				goto bad_hash;
+
+			break;
+		case 48:
+			if (hash != HANDSHAKE_HASH_SHA384)
+				goto bad_hash;
+
+			break;
+		bad_hash:
+		default:
+			TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+					"Invalid hash %i",
+					in[0]);
+		}
+	}
+
+	get_hash(tls, hash, data, data_len, expected, &expected_len);
+	sign_checksum_type = tls_handshake_hash_data[hash].l_id;
+
+	success = l_key_verify(tls->peer_pubkey, L_KEY_ECDSA_X962,
+				sign_checksum_type, expected, opaque,
+				expected_len, opaque_len);
+
+	if (!success)
+		TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+				"Peer signature verification failed");
+	else
+		TLS_DEBUG("Peer signature verified");
+
+	return success;
+}
+
+static struct tls_signature_algorithm tls_ecdsa_signature = {
+	.id = 3, /* SignatureAlgorithm.ecdsa */
+	.validate_cert_key_type = tls_ecdsa_validate_cert_key,
+	.verify = tls_ecdsa_verify,
+};
+
+static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
+{
+	uint8_t buf[1024 + 32];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	uint8_t pre_master_secret[48];
+	ssize_t bytes_encrypted;
+
+	if (!tls->peer_pubkey) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Peer public key not received");
+
+		return false;
+	}
+
+	/* Must match the version in tls_send_client_hello */
+	pre_master_secret[0] = (uint8_t) (tls->client_version >> 8);
+	pre_master_secret[1] = (uint8_t) (tls->client_version >> 0);
+
+	l_getrandom(pre_master_secret + 2, 46);
+
+	if (tls->peer_pubkey_size + 32 > (int) sizeof(buf)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Peer public key too big: %zi",
+				tls->peer_pubkey_size);
+
+		return false;
+	}
+
+	l_put_be16(tls->peer_pubkey_size, ptr);
+	bytes_encrypted = l_key_encrypt(tls->peer_pubkey,
+					L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
+					pre_master_secret, ptr + 2, 48,
+					tls->peer_pubkey_size);
+	ptr += tls->peer_pubkey_size + 2;
+
+	if (bytes_encrypted != (ssize_t) tls->peer_pubkey_size) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Encrypting PreMasterSecret failed: %s",
+				strerror(-bytes_encrypted));
+
+		return false;
+	}
+
+	tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
+
+	tls_generate_master_secret(tls, pre_master_secret, 48);
+	explicit_bzero(pre_master_secret, 48);
+
+	return true;
+}
+
+static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	uint8_t pre_master_secret[48], random_secret[46];
+	ssize_t bytes_decrypted;
+
+	if (!tls->priv_key || !tls->priv_key_size) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, TLS_ALERT_BAD_CERT,
+				"No private key");
+
+		return;
+	}
+
+	if (len != tls->priv_key_size + 2) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"ClientKeyExchange len %zi not %zi", len,
+				tls->priv_key_size + 2);
+
+		return;
+	}
+
+	len = l_get_be16(buf);
+
+	if (len != tls->priv_key_size) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"EncryptedPreMasterSecret len %zi not %zi",
+				len, tls->priv_key_size);
+
+		return;
+	}
+
+	bytes_decrypted = l_key_decrypt(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
+					L_CHECKSUM_NONE, buf + 2,
+					pre_master_secret, tls->priv_key_size,
+					48);
+
+	/*
+	 * Assume correct premaster secret client version which according
+	 * to the TLS1.2 spec is unlikely in client implementations SSLv3
+	 * and prior.  Spec suggests either not supporting them or adding
+	 * a configurable override for <= SSLv3 clients.  For now we have
+	 * no need to support them.
+	 *
+	 * On any decode error randomise the Pre Master Secret as per the
+	 * countermeasures in 7.4.7.1 and don't generate any alerts.
+	 */
+	l_getrandom(random_secret, 46);
+
+	pre_master_secret[0] = tls->client_version >> 8;
+	pre_master_secret[1] = tls->client_version >> 0;
+
+	if (bytes_decrypted != 48) {
+		memcpy(pre_master_secret + 2, random_secret, 46);
+
+		TLS_DEBUG("Error decrypting PreMasterSecret: %s",
+				strerror(-bytes_decrypted));
+	}
+
+	tls_generate_master_secret(tls, pre_master_secret, 48);
+	explicit_bzero(pre_master_secret, 48);
+	explicit_bzero(random_secret, 46);
+}
+
+static struct tls_key_exchange_algorithm tls_rsa_key_xchg = {
+	.send_client_key_exchange = tls_send_rsa_client_key_xchg,
+	.handle_client_key_exchange = tls_handle_rsa_client_key_xchg,
+};
+
+/* Used by both DHE and ECDHE */
+static bool tls_get_dh_params_hash(struct l_tls *tls,
+					enum handshake_hash_type type,
+					const uint8_t *data, size_t data_len,
+					uint8_t *out, size_t *out_len)
+{
+	struct l_checksum *checksum;
+	ssize_t ret;
+
+	/*
+	 * The ServerKeyExchange signature hash input format for RSA_sign is
+	 * not really specified in either RFC 8422 or RFC 5246 explicitly
+	 * but we use this format by analogy to DHE_RSA which uses RSA_sign
+	 * as well.  Also matches ecdsa, ed25519 and ed448 formats.
+	 */
+	struct iovec iov[] = {
+		{ .iov_base = tls->pending.client_random, .iov_len = 32 },
+		{ .iov_base = tls->pending.server_random, .iov_len = 32 },
+		{ .iov_base = (void *) data, .iov_len = data_len },
+	};
+
+	checksum = l_checksum_new(tls_handshake_hash_data[type].l_id);
+	if (!checksum)
+		return false;
+
+	l_checksum_updatev(checksum, iov, L_ARRAY_SIZE(iov));
+	ret = l_checksum_get_digest(checksum, out, HANDSHAKE_HASH_MAX_SIZE);
+	l_checksum_free(checksum);
+
+	if (ret < 0)
+		return false;
+
+	if (out_len)
+		*out_len = ret;
+
+	return true;
+}
+
+struct tls_ecdhe_params {
+	const struct l_ecc_curve *curve;
+	struct l_ecc_scalar *private;
+	struct l_ecc_point *public;
+};
+
+static void tls_free_ecdhe_params(struct l_tls *tls)
+{
+	struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
+
+	if (!params)
+		return;
+
+	tls->pending.key_xchg_params = NULL;
+
+	l_ecc_scalar_free(params->private);
+	l_ecc_point_free(params->public);
+	l_free(params);
+}
+
+static size_t tls_write_ecpoint(uint8_t *buf, size_t len,
+				const struct tls_named_group *curve,
+				const struct l_ecc_point *point)
+{
+	size_t point_bytes;
+
+	/* RFC 8422, Section 5.4.1 */
+	point_bytes = l_ecc_point_get_data(point, buf + 2, len - 2);
+	buf[0] = 1 + point_bytes;		/* length */
+	buf[1] = 4;				/* form: uncompressed */
+	return 2 + point_bytes;
+}
+
+static size_t tls_write_server_ecdh_params(struct l_tls *tls, uint8_t *buf, size_t len)
+{
+	struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
+
+	/* RFC 8422, Section 5.4 */
+	buf[0] = 3;				/* curve_type: named_curve */
+	l_put_be16(tls->negotiated_curve->id, buf + 1);
+	return 3 + tls_write_ecpoint(buf + 3, len - 3, tls->negotiated_curve,
+					params->public);
+}
+
+static bool tls_send_ecdhe_server_key_xchg(struct l_tls *tls)
+{
+	uint8_t buf[1024];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	struct tls_ecdhe_params *params;
+	ssize_t sign_len;
+	const uint8_t *server_ecdh_params_ptr;
+
+	/*
+	 * RFC 8422, Section 5.4
+	 *
+	 * If we're getting here we can assume that tls->pending.key_xchg_params
+	 * is NULL, tls->priv_key is our signing key and tls->negotiated_curve
+	 * is non-NULL.
+	 */
+
+	params = l_new(struct tls_ecdhe_params, 1);
+	params->curve = l_ecc_curve_from_tls_group(tls->negotiated_curve->id);
+	tls->pending.key_xchg_params = params;
+
+	if (!l_ecdh_generate_key_pair(params->curve,
+					&params->private, &params->public)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating ECDH key pair failed");
+		return false;
+	}
+
+	server_ecdh_params_ptr = ptr;
+	ptr += tls_write_server_ecdh_params(tls, ptr, buf + sizeof(buf) - ptr);
+
+	if (tls->pending.cipher_suite->signature) {
+		sign_len = tls->pending.cipher_suite->signature->sign(tls, ptr,
+						buf + sizeof(buf) - ptr,
+						tls_get_dh_params_hash,
+						server_ecdh_params_ptr,
+						ptr - server_ecdh_params_ptr);
+		if (sign_len < 0)
+			return false;
+
+		ptr += sign_len;
+	}
+
+	tls_tx_handshake(tls, TLS_SERVER_KEY_EXCHANGE, buf, ptr - buf);
+
+	return true;
+}
+
+static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	struct tls_ecdhe_params *params;
+	uint16_t namedcurve;
+	const uint8_t *server_ecdh_params_ptr = buf;
+	size_t point_bytes;
+
+	/* RFC 8422, Section 5.4 */
+
+	if (len < 5)
+		goto decode_error;
+
+	if (*buf != 3) {
+		TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
+				"Unsupported (deprecated?) ECCurveType %u",
+				*buf);
+		return;
+	}
+
+	namedcurve = l_get_be16(buf + 1);
+	buf += 3;
+	len -= 3;
+
+	tls->negotiated_curve = tls_find_group(namedcurve);
+
+	if (!tls->negotiated_curve ||
+			tls->negotiated_curve->type != TLS_GROUP_TYPE_EC) {
+		TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
+				"Unsupported NamedCurve %u", namedcurve);
+		return;
+	}
+
+	TLS_DEBUG("Negotiated %s", tls->negotiated_curve->name);
+
+	if (*buf < 1)
+		goto decode_error;
+
+	point_bytes = *buf++ - 1;
+
+	if (*buf != 4) {	/* uncompressed */
+		TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
+				"Unsupported (deprecated?) PointConversionForm "
+				"%u", *buf);
+		return;
+	}
+
+	buf++;
+	len -= 2;
+
+	if (len < point_bytes)
+		goto decode_error;
+
+	/*
+	 * RFC 8422, Section 5.11: "A receiving party MUST check that the
+	 * x and y parameters from the peer's public value satisfy the
+	 * curve equation, y^2 = x^3 + ax + b mod p."
+	 * This happens in l_ecc_point_from_data when the L_ECC_POINT_TYPE_FULL
+	 * format is used.
+	 */
+	params = l_new(struct tls_ecdhe_params, 1);
+	params->curve = l_ecc_curve_from_tls_group(tls->negotiated_curve->id);
+	params->public = l_ecc_point_from_data(params->curve,
+						L_ECC_POINT_TYPE_FULL,
+						buf, point_bytes);
+	tls->pending.key_xchg_params = params;
+	buf += point_bytes;
+	len -= point_bytes;
+
+	if (!params->public || point_bytes !=
+			2 * l_ecc_curve_get_scalar_bytes(params->curve)) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"ServerKeyExchange.params.public decode error");
+		return;
+	}
+
+	if (tls->pending.cipher_suite->signature) {
+		if (!tls->pending.cipher_suite->signature->verify(tls, buf, len,
+						tls_get_dh_params_hash,
+						server_ecdh_params_ptr,
+						buf - server_ecdh_params_ptr))
+			return;
+	} else {
+		if (len)
+			goto decode_error;
+	}
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
+
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ServerKeyExchange decode error");
+}
+
+static bool tls_send_ecdhe_client_key_xchg(struct l_tls *tls)
+{
+	uint8_t buf[1024];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	uint8_t pre_master_secret[128];
+	ssize_t pre_master_secret_len;
+	struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
+	struct l_ecc_point *our_public;
+	struct l_ecc_scalar *secret;
+
+	/* RFC 8422, Section 5.7 */
+
+	if (!l_ecdh_generate_key_pair(params->curve,
+					&params->private, &our_public)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating ECDH key pair failed");
+		return false;
+	}
+
+	ptr += tls_write_ecpoint(ptr, buf + sizeof(buf) - ptr,
+					tls->negotiated_curve, our_public);
+	l_ecc_point_free(our_public);
+
+	/*
+	 * Neither 5.4 or 5.7 "Actions" paragraphs say when the ECDH shared
+	 * secret is calculated but we can either do this in
+	 * tls_handle_ecdhe_server_key_xchg or here.  In both cases we only
+	 * need to store the public key in the client's key_xchg_params and
+	 * can free all of the params after sending the ClientKeyExchange.
+	 * By doing this calculation here we're aligned with RSA and also
+	 * with the server mode where the shared secret can only be
+	 * calculated after the ClientKeyExchange is received.
+	 */
+	if (!l_ecdh_generate_shared_secret(params->private, params->public,
+						&secret)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating ECDH shared-secret failed");
+		return false;
+	}
+
+	tls_free_ecdhe_params(tls);
+	pre_master_secret_len = l_ecc_scalar_get_data(secret,
+						pre_master_secret,
+						sizeof(pre_master_secret));
+	l_ecc_scalar_free(secret);
+
+	if (pre_master_secret_len < 0) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_ecc_scalar_get_data(secret) failed");
+		return false;
+	}
+
+	tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
+
+	tls_generate_master_secret(tls, pre_master_secret,
+					pre_master_secret_len);
+	explicit_bzero(pre_master_secret, pre_master_secret_len);
+
+	return true;
+}
+
+static void tls_handle_ecdhe_client_key_xchg(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
+	uint8_t pre_master_secret[128];
+	ssize_t pre_master_secret_len;
+	struct l_ecc_point *other_public;
+	struct l_ecc_scalar *secret;
+	size_t point_bytes = 2 * l_ecc_curve_get_scalar_bytes(params->curve);
+
+	/* RFC 8422, Section 5.7 */
+
+	if (len < 2)
+		goto decode_error;
+
+	if (*buf++ != 1 + point_bytes)
+		goto decode_error;
+
+	if (*buf != 4) {	/* uncompressed */
+		TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
+				"Unsupported (deprecated?) PointConversionForm "
+				"%u", *buf);
+		return;
+	}
+
+	buf++;
+	len -= 2;
+
+	if (len != point_bytes)
+		goto decode_error;
+
+	/*
+	 * RFC 8422, Section 5.11: "A receiving party MUST check that the
+	 * x and y parameters from the peer's public value satisfy the
+	 * curve equation, y^2 = x^3 + ax + b mod p."
+	 * This happens in l_ecc_point_from_data when the L_ECC_POINT_TYPE_FULL
+	 * format is used.
+	 */
+	other_public = l_ecc_point_from_data(params->curve,
+						L_ECC_POINT_TYPE_FULL,
+						buf, len);
+	if (!other_public) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"ClientKeyExchange.exchange_keys.ecdh_Yc "
+				"decode error");
+		return;
+	}
+
+	if (!l_ecdh_generate_shared_secret(params->private, other_public,
+						&secret)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating ECDH shared-secret failed");
+		return;
+	}
+
+	tls_free_ecdhe_params(tls);
+	l_ecc_point_free(other_public);
+	pre_master_secret_len = l_ecc_scalar_get_data(secret,
+						pre_master_secret,
+						sizeof(pre_master_secret));
+	l_ecc_scalar_free(secret);
+
+	if (pre_master_secret_len < 0) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_ecc_scalar_get_data(secret) failed");
+		return;
+	}
+
+	tls_generate_master_secret(tls, pre_master_secret,
+					pre_master_secret_len);
+	explicit_bzero(pre_master_secret, pre_master_secret_len);
+
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ClientKeyExchange decode error");
+}
+
+static struct tls_key_exchange_algorithm tls_ecdhe = {
+	.need_ecc = true,
+	.send_server_key_exchange = tls_send_ecdhe_server_key_xchg,
+	.handle_server_key_exchange = tls_handle_ecdhe_server_key_xchg,
+	.send_client_key_exchange = tls_send_ecdhe_client_key_xchg,
+	.handle_client_key_exchange = tls_handle_ecdhe_client_key_xchg,
+	.free_params = tls_free_ecdhe_params,
+};
+
+/* Maximum FF DH prime modulus size in bytes */
+#define TLS_DHE_MAX_SIZE 1024
+
+struct tls_dhe_params {
+	size_t prime_len;
+	struct l_key *prime;
+	struct l_key *generator;
+	struct l_key *private;
+	struct l_key *public;
+};
+
+static void tls_free_dhe_params(struct l_tls *tls)
+{
+	struct tls_dhe_params *params = tls->pending.key_xchg_params;
+
+	if (!params)
+		return;
+
+	tls->pending.key_xchg_params = NULL;
+
+	l_key_free(params->prime);
+	l_key_free(params->generator);
+	l_key_free(params->private);
+	l_key_free(params->public);
+	l_free(params);
+}
+
+static bool tls_send_dhe_server_key_xchg(struct l_tls *tls)
+{
+	uint8_t buf[1024 + TLS_DHE_MAX_SIZE * 3];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	struct tls_dhe_params *params;
+	const uint8_t *prime_buf;
+	uint8_t generator_buf = tls->negotiated_ff_group->ff.generator;
+	uint8_t public_buf[TLS_DHE_MAX_SIZE];
+	size_t public_len;
+	unsigned int zeros = 0;
+	ssize_t sign_len;
+	const uint8_t *server_dh_params_ptr;
+
+	params = l_new(struct tls_dhe_params, 1);
+	prime_buf = tls->negotiated_ff_group->ff.prime;
+	params->prime_len = tls->negotiated_ff_group->ff.prime_len;
+
+	params->prime = l_key_new(L_KEY_RAW, prime_buf, params->prime_len);
+	params->generator = l_key_new(L_KEY_RAW, &generator_buf, 1);
+
+	if (!params->prime || !params->generator) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
+		goto free_params;
+	}
+
+	params->private = l_key_generate_dh_private(prime_buf, params->prime_len);
+	if (!params->private) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_key_generate_dh_private failed");
+		goto free_params;
+	}
+
+	memset(public_buf, 0, sizeof(public_buf));
+	public_len = params->prime_len;
+
+	if (!l_key_compute_dh_public(params->generator, params->private,
+					params->prime, public_buf,
+					&public_len)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_key_compute_dh_public failed");
+		goto free_params;
+	}
+
+	while (zeros < public_len && public_buf[zeros] == 0x00)
+		zeros++;
+
+	server_dh_params_ptr = ptr;
+
+	/* RFC 5246, Section 7.4.3 */
+
+	l_put_be16(params->prime_len, ptr);
+	memcpy(ptr + 2, prime_buf, params->prime_len);
+	ptr += 2 + params->prime_len;
+
+	l_put_be16(1, ptr);
+	memcpy(ptr + 2, &generator_buf, 1);
+	ptr += 2 + 1;
+
+	l_put_be16(public_len - zeros, ptr);
+	memcpy(ptr + 2, public_buf + zeros, public_len - zeros);
+	ptr += 2 + public_len - zeros;
+
+	if (tls->pending.cipher_suite->signature) {
+		sign_len = tls->pending.cipher_suite->signature->sign(tls, ptr,
+						buf + sizeof(buf) - ptr,
+						tls_get_dh_params_hash,
+						server_dh_params_ptr,
+						ptr - server_dh_params_ptr);
+		if (sign_len < 0)
+			goto free_params;
+
+		ptr += sign_len;
+	}
+
+	tls->pending.key_xchg_params = params;
+
+	tls_tx_handshake(tls, TLS_SERVER_KEY_EXCHANGE, buf, ptr - buf);
+	return true;
+
+free_params:
+	l_key_free(params->prime);
+	l_key_free(params->generator);
+	l_key_free(params->private);
+	l_free(params);
+	return false;
+}
+
+static void tls_handle_dhe_server_key_xchg(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	struct tls_dhe_params *params = NULL;
+	const uint8_t *prime_buf;
+	const uint8_t *generator_buf;
+	size_t generator_len;
+	const uint8_t *public_buf;
+	size_t public_len;
+	const uint8_t *server_dh_params_ptr = buf;
+
+	if (len < 2)
+		goto decode_error;
+
+	params = l_new(struct tls_dhe_params, 1);
+	params->prime_len = l_get_be16(buf);
+	if (len < 2 + params->prime_len + 2)
+		goto decode_error;
+
+	prime_buf = buf + 2;
+	buf += 2 + params->prime_len;
+	len -= 2 + params->prime_len;
+
+	/* Strip leading zeros for the length checks later */
+	while (params->prime_len && prime_buf[0] == 0x00) {
+		prime_buf++;
+		params->prime_len--;
+	}
+
+	generator_len = l_get_be16(buf);
+	if (len < 2 + generator_len + 2)
+		goto decode_error;
+
+	generator_buf = buf + 2;
+	buf += 2 + generator_len;
+	len -= 2 + generator_len;
+
+	public_len = l_get_be16(buf);
+	if (len < 2 + public_len)
+		goto decode_error;
+
+	public_buf = buf + 2;
+	buf += 2 + public_len;
+	len -= 2 + public_len;
+
+	/*
+	 * Validate the values received.  Without requiring RFC 7919 from
+	 * the server, and there are many servers that don't implement it
+	 * yet, we basically have to blindly accept the provided prime value.
+	 * We have no way to confirm that it's actually prime or that it's a
+	 * "safe prime" or that it forms a group without small sub-groups.
+	 * There's also no way to whitelist all valid values.  But we do a
+	 * basic sanity check and require it to be 1536-bit or longer, the
+	 * minimum length required by the Linux kernel for keyctl_dh_compute().
+	 * The generator must also be at least within the min & max interval
+	 * for the private/public values.
+	 */
+
+	if (params->prime_len > TLS_DHE_MAX_SIZE || params->prime_len < 192 ||
+			!(prime_buf[params->prime_len - 1] & 1)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Server DH prime modulus invalid");
+		goto free_params;
+	}
+
+	if (!l_key_validate_dh_payload(generator_buf, generator_len,
+					prime_buf, params->prime_len)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Server DH generator value invalid");
+		goto free_params;
+	}
+
+	/*
+	 * Just output a warning if the server sent group parameters not
+	 * offered in our RFC 7919 Supported Groups extension.
+	 */
+	if (!tls_find_ff_group(prime_buf, params->prime_len,
+				generator_buf, generator_len))
+		TLS_DEBUG("Warning: using server's custom %i-bit FF DH group",
+				(int) (params->prime_len * 8));
+
+	/*
+	 * RFC 7919 Section 3.0:
+	 * "the client MUST verify that dh_Ys is in the range
+	 * 1 < dh_Ys < dh_p - 1.  If dh_Ys is not in this range, the client
+	 * MUST terminate the connection with a fatal handshake_failure(40)
+	 * alert."
+	 */
+	if (!l_key_validate_dh_payload(public_buf, public_len,
+					prime_buf, params->prime_len)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Server DH public value invalid");
+		goto free_params;
+	}
+
+	params->prime = l_key_new(L_KEY_RAW, prime_buf, params->prime_len);
+	params->generator = l_key_new(L_KEY_RAW, generator_buf, generator_len);
+	params->public = l_key_new(L_KEY_RAW, public_buf, public_len);
+
+	if (!params->prime || !params->generator || !params->public) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
+		goto free_params;
+	}
+
+	/* Do this now so we don't need prime_buf in send_client_key_xchg */
+	params->private = l_key_generate_dh_private(prime_buf, params->prime_len);
+	if (!params->private) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_key_generate_dh_private failed");
+		goto free_params;
+	}
+
+	tls->pending.key_xchg_params = params;
+
+	if (tls->pending.cipher_suite->signature) {
+		if (!tls->pending.cipher_suite->signature->verify(tls, buf, len,
+						tls_get_dh_params_hash,
+						server_dh_params_ptr,
+						buf - server_dh_params_ptr))
+			return;
+	} else {
+		if (len)
+			goto decode_error;
+	}
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ServerKeyExchange decode error");
+
+free_params:
+	if (params) {
+		l_key_free(params->prime);
+		l_key_free(params->generator);
+		l_key_free(params->public);
+		l_free(params);
+	}
+}
+
+static bool tls_send_dhe_client_key_xchg(struct l_tls *tls)
+{
+	struct tls_dhe_params *params = tls->pending.key_xchg_params;
+	uint8_t buf[128 + params->prime_len];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	uint8_t public_buf[params->prime_len];
+	size_t public_len;
+	unsigned int zeros = 0;
+	uint8_t pre_master_secret[params->prime_len];
+	size_t pre_master_secret_len;
+
+	public_len = params->prime_len;
+	memset(public_buf, 0, sizeof(public_buf));
+
+	if (!l_key_compute_dh_public(params->generator, params->private,
+					params->prime, public_buf,
+					&public_len)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"l_key_compute_dh_public failed");
+		return false;
+	}
+
+	while (zeros < public_len && public_buf[zeros] == 0x00)
+		zeros++;
+
+	l_put_be16(public_len - zeros, ptr);
+	memcpy(ptr + 2, public_buf + zeros, public_len - zeros);
+	ptr += 2 + public_len - zeros;
+
+	pre_master_secret_len = params->prime_len;
+	zeros = 0;
+
+	if (!l_key_compute_dh_secret(params->public, params->private,
+					params->prime, pre_master_secret,
+					&pre_master_secret_len)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating DH shared-secret failed");
+		return false;
+	}
+
+	while (zeros < pre_master_secret_len &&
+			pre_master_secret[zeros] == 0x00)
+		zeros++;
+
+	tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
+
+	tls_free_dhe_params(tls);
+	tls_generate_master_secret(tls, pre_master_secret + zeros,
+					pre_master_secret_len - zeros);
+	explicit_bzero(pre_master_secret, pre_master_secret_len);
+	return true;
+}
+
+static void tls_handle_dhe_client_key_xchg(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	struct tls_dhe_params *params = tls->pending.key_xchg_params;
+	uint8_t pre_master_secret[params->prime_len];
+	size_t pre_master_secret_len;
+	size_t public_len;
+	unsigned int zeros = 0;
+
+	if (len < 2)
+		goto decode_error;
+
+	public_len = l_get_be16(buf);
+	buf += 2;
+	len -= 2;
+
+	if (public_len != len)
+		goto decode_error;
+
+	/*
+	 * RFC 7919 Section 4:
+	 * "the server MUST verify that 1 < dh_Yc < dh_p - 1.  If dh_Yc is
+	 * out of range, the server MUST terminate the connection with
+	 * a fatal handshake_failure(40) alert."
+	 */
+	if (!l_key_validate_dh_payload(buf, public_len,
+					tls->negotiated_ff_group->ff.prime,
+					params->prime_len)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Client DH public value invalid");
+		return;
+	}
+
+	params->public = l_key_new(L_KEY_RAW, buf, public_len);
+	if (!params->public) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
+		return;
+	}
+
+	pre_master_secret_len = params->prime_len;
+
+	if (!l_key_compute_dh_secret(params->public, params->private,
+					params->prime, pre_master_secret,
+					&pre_master_secret_len)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Generating DH shared-secret failed");
+		return;
+	}
+
+	while (zeros < pre_master_secret_len &&
+			pre_master_secret[zeros] == 0x00)
+		zeros++;
+
+	tls_free_dhe_params(tls);
+	tls_generate_master_secret(tls, pre_master_secret + zeros,
+					pre_master_secret_len - zeros);
+	explicit_bzero(pre_master_secret, pre_master_secret_len);
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ClientKeyExchange decode error");
+}
+
+static struct tls_key_exchange_algorithm tls_dhe = {
+	.need_ecc = true,
+	.send_server_key_exchange = tls_send_dhe_server_key_xchg,
+	.handle_server_key_exchange = tls_handle_dhe_server_key_xchg,
+	.send_client_key_exchange = tls_send_dhe_client_key_xchg,
+	.handle_client_key_exchange = tls_handle_dhe_client_key_xchg,
+	.free_params = tls_free_dhe_params,
+};
+
+static struct tls_bulk_encryption_algorithm tls_aes128 = {
+	.cipher_type = TLS_CIPHER_BLOCK,
+	.l_id = L_CIPHER_AES_CBC,
+	.key_length = 16,
+	.iv_length = 16,
+	.block_length = 16,
+}, tls_aes256 = {
+	.cipher_type = TLS_CIPHER_BLOCK,
+	.l_id = L_CIPHER_AES_CBC,
+	.key_length = 32,
+	.iv_length = 16,
+	.block_length = 16,
+}, tls_3des_ede = {
+	.cipher_type = TLS_CIPHER_BLOCK,
+	.l_id = L_CIPHER_DES3_EDE_CBC,
+	.key_length = 24,
+	.iv_length = 8,
+	.block_length = 8,
+}, tls_aes128_gcm = {
+	.cipher_type = TLS_CIPHER_AEAD,
+	.l_aead_id = L_AEAD_CIPHER_AES_GCM,
+	.key_length = 16,
+	.iv_length = 12,
+	.fixed_iv_length = 4,
+	.auth_tag_length = 16,
+}, tls_aes256_gcm = {
+	.cipher_type = TLS_CIPHER_AEAD,
+	.l_aead_id = L_AEAD_CIPHER_AES_GCM,
+	.key_length = 32,
+	.iv_length = 12,
+	.fixed_iv_length = 4,
+	.auth_tag_length = 16,
+};
+
+static struct tls_mac_algorithm tls_sha = {
+	.id = 2,
+	.hmac_type = L_CHECKSUM_SHA1,
+	.mac_length = 20,
+}, tls_sha256 = {
+	.id = 4,
+	.hmac_type = L_CHECKSUM_SHA256,
+	.mac_length = 32,
+}, tls_sha384 = {
+	.id = 5,
+	.hmac_type = L_CHECKSUM_SHA384,
+	.mac_length = 48,
+};
+
+static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = {
+	.id = { 0x00, 0x0a },
+	.name = "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+	.encryption = &tls_3des_ede,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_dhe_rsa_with_3des_ede_cbc_sha = {
+	.id = { 0x00, 0x16 },
+	.name = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+	.encryption = &tls_3des_ede,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_rsa_with_aes_128_cbc_sha = {
+	.id = { 0x00, 0x2f },
+	.name = "TLS_RSA_WITH_AES_128_CBC_SHA",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_dhe_rsa_with_aes_128_cbc_sha = {
+	.id = { 0x00, 0x33 },
+	.name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_rsa_with_aes_256_cbc_sha = {
+	.id = { 0x00, 0x35 },
+	.name = "TLS_RSA_WITH_AES_256_CBC_SHA",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_dhe_rsa_with_aes_256_cbc_sha = {
+	.id = { 0x00, 0x39 },
+	.name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_rsa_with_aes_128_cbc_sha256 = {
+	.id = { 0x00, 0x3c },
+	.name = "TLS_RSA_WITH_AES_128_CBC_SHA256",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha256,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_rsa_with_aes_256_cbc_sha256 = {
+	.id = { 0x00, 0x3d },
+	.name = "TLS_RSA_WITH_AES_256_CBC_SHA256",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha256,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_dhe_rsa_with_aes_128_cbc_sha256 = {
+	.id = { 0x00, 0x67 },
+	.name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha256,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_dhe_rsa_with_aes_256_cbc_sha256 = {
+	.id = { 0x00, 0x6b },
+	.name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha256,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_rsa_with_aes_128_gcm_sha256 = {
+	.id = { 0x00, 0x9c },
+	.name = "TLS_RSA_WITH_AES_128_GCM_SHA256",
+	.encryption = &tls_aes128_gcm,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_rsa_with_aes_256_gcm_sha384 = {
+	.id = { 0x00, 0x9d },
+	.name = "TLS_RSA_WITH_AES_256_GCM_SHA384",
+	.encryption = &tls_aes256_gcm,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_rsa_key_xchg,
+}, tls_dhe_rsa_with_aes_128_gcm_sha256 = {
+	.id = { 0x00, 0x9e },
+	.name = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+	.encryption = &tls_aes128_gcm,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_dhe_rsa_with_aes_256_gcm_sha384 = {
+	.id = { 0x00, 0x9f },
+	.name = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+	.encryption = &tls_aes256_gcm,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_dhe,
+}, tls_ecdhe_rsa_with_3des_ede_cbc_sha = {
+	.id = { 0xc0, 0x12 },
+	.name = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+	.encryption = &tls_3des_ede,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_128_cbc_sha = {
+	.id = { 0xc0, 0x13 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_256_cbc_sha = {
+	.id = { 0xc0, 0x14 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_128_cbc_sha256 = {
+	.id = { 0xc0, 0x27 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha256,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_256_cbc_sha384 = {
+	.id = { 0xc0, 0x28 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha384,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_128_gcm_sha256 = {
+	.id = { 0xc0, 0x2f },
+	.name = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+	.encryption = &tls_aes128_gcm,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_rsa_with_aes_256_gcm_sha384 = {
+	.id = { 0xc0, 0x30 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+	.encryption = &tls_aes256_gcm,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.signature = &tls_rsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_ecdsa_with_3des_ede_cbc_sha = {
+	.id = { 0xc0, 0x08 },
+	.name = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+	.encryption = &tls_3des_ede,
+	.mac = &tls_sha,
+	.signature = &tls_ecdsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_ecdsa_with_aes_128_cbc_sha = {
+	.id = { 0xc0, 0x09 },
+	.name = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+	.encryption = &tls_aes128,
+	.mac = &tls_sha,
+	.signature = &tls_ecdsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_ecdsa_with_aes_256_cbc_sha = {
+	.id = { 0xc0, 0x0a },
+	.name = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+	.encryption = &tls_aes256,
+	.mac = &tls_sha,
+	.signature = &tls_ecdsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 = {
+	.id = { 0xc0, 0x2b },
+	.name = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+	.encryption = &tls_aes128_gcm,
+	.signature = &tls_ecdsa_signature,
+	.key_xchg = &tls_ecdhe,
+}, tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 = {
+	.id = { 0xc0, 0x2c },
+	.name = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+	.encryption = &tls_aes256_gcm,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.signature = &tls_ecdsa_signature,
+	.key_xchg = &tls_ecdhe,
+};
+
+struct tls_cipher_suite *tls_cipher_suite_pref[] = {
+	&tls_ecdhe_rsa_with_aes_256_cbc_sha,
+	&tls_ecdhe_ecdsa_with_aes_256_cbc_sha,
+	&tls_ecdhe_rsa_with_aes_128_cbc_sha,
+	&tls_ecdhe_ecdsa_with_aes_128_cbc_sha,
+	&tls_dhe_rsa_with_aes_256_cbc_sha,
+	&tls_dhe_rsa_with_aes_128_cbc_sha,
+	&tls_rsa_with_aes_256_cbc_sha,
+	&tls_rsa_with_aes_128_cbc_sha,
+	&tls_ecdhe_rsa_with_aes_256_cbc_sha384,
+	&tls_ecdhe_rsa_with_aes_128_cbc_sha256,
+	&tls_dhe_rsa_with_aes_256_cbc_sha256,
+	&tls_dhe_rsa_with_aes_128_cbc_sha256,
+	&tls_rsa_with_aes_256_cbc_sha256,
+	&tls_rsa_with_aes_128_cbc_sha256,
+	&tls_ecdhe_rsa_with_aes_256_gcm_sha384,
+	&tls_ecdhe_rsa_with_aes_128_gcm_sha256,
+	&tls_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+	&tls_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+	&tls_dhe_rsa_with_aes_256_gcm_sha384,
+	&tls_dhe_rsa_with_aes_128_gcm_sha256,
+	&tls_rsa_with_aes_256_gcm_sha384,
+	&tls_rsa_with_aes_128_gcm_sha256,
+	&tls_ecdhe_rsa_with_3des_ede_cbc_sha,
+	&tls_ecdhe_ecdsa_with_3des_ede_cbc_sha,
+	&tls_dhe_rsa_with_3des_ede_cbc_sha,
+	&tls_rsa_with_3des_ede_cbc_sha,
+	NULL,
+};
diff --git a/ell/tls.c b/ell/tls.c
new file mode 100644
index 0000000..5246650
--- /dev/null
+++ b/ell/tls.c
@@ -0,0 +1,3987 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <time.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include "useful.h"
+#include "private.h"
+#include "tls.h"
+#include "checksum.h"
+#include "cipher.h"
+#include "random.h"
+#include "queue.h"
+#include "pem.h"
+#include "pem-private.h"
+#include "asn1-private.h"
+#include "cert.h"
+#include "cert-private.h"
+#include "tls-private.h"
+#include "key.h"
+#include "strv.h"
+#include "missing.h"
+#include "string.h"
+#include "settings.h"
+#include "time.h"
+#include "time-private.h"
+
+bool tls10_prf(const void *secret, size_t secret_len,
+		const char *label,
+		const void *seed, size_t seed_len,
+		uint8_t *out, size_t out_len)
+{
+	uint8_t p_hash2[out_len];
+	uint8_t l_s1 = (secret_len + 1) / 2;
+	unsigned int i;
+
+	/*
+	 * RFC2246 section 5:
+	 * S1 and S2 are the two halves of the secret, and each is the same
+	 * length.  S1 is taken from the first half of the secret, S2 from the
+	 * second half.  Their length is created by rounding up the length of
+	 * the overall secret, divided by two; thus, if the original secret is
+	 * an odd number of bytes long, the last byte of S1 will be the same as
+	 * the first byte of S2.
+	 */
+
+	if (!tls12_prf(L_CHECKSUM_MD5, secret, l_s1,
+			label, seed, seed_len,
+			out, out_len))
+		return false;
+
+	if (secret_len > 0)
+		secret += secret_len - l_s1;
+
+	if (!tls12_prf(L_CHECKSUM_SHA1, secret, l_s1,
+			label, seed, seed_len,
+			p_hash2, out_len))
+		return false;
+
+	for (i = 0; i < out_len; i++)
+		out[i] ^= p_hash2[i];
+
+	return true;
+}
+
+bool tls12_prf(enum l_checksum_type type,
+		const void *secret, size_t secret_len,
+		const char *label,
+		const void *seed, size_t seed_len,
+		uint8_t *out, size_t out_len)
+{
+	struct l_checksum *hmac = l_checksum_new_hmac(type, secret, secret_len);
+	size_t a_len, chunk_len, prfseed_len = strlen(label) + seed_len;
+	uint8_t a[64 + prfseed_len], prfseed[prfseed_len];
+
+	if (!hmac)
+		return false;
+
+	/* Generate the hash seed or A(0) as label + seed */
+	memcpy(prfseed, label, strlen(label));
+	memcpy(prfseed + strlen(label), seed, seed_len);
+
+	memcpy(a, prfseed, prfseed_len);
+	a_len = prfseed_len;
+
+	while (out_len) {
+		/* Generate A(i) */
+		l_checksum_reset(hmac);
+		l_checksum_update(hmac, a, a_len);
+		a_len = l_checksum_get_digest(hmac, a, sizeof(a));
+
+		/* Append seed & generate output */
+		memcpy(a + a_len, prfseed, prfseed_len);
+		l_checksum_reset(hmac);
+		l_checksum_update(hmac, a, a_len + prfseed_len);
+
+		chunk_len = l_checksum_get_digest(hmac, out, out_len);
+		out += chunk_len;
+		out_len -= chunk_len;
+	}
+
+	l_checksum_free(hmac);
+	return true;
+}
+
+static bool tls_prf_get_bytes(struct l_tls *tls,
+				const void *secret, size_t secret_len,
+				const char *label,
+				const void *seed, size_t seed_len,
+				uint8_t *buf, size_t len)
+{
+	if (tls->negotiated_version >= L_TLS_V12)
+		return tls12_prf(tls->prf_hmac->l_id,
+					secret, secret_len, label,
+					seed, seed_len, buf, len);
+	return tls10_prf(secret, secret_len, label, seed, seed_len,
+					buf, len);
+}
+
+LIB_EXPORT bool l_tls_prf_get_bytes(struct l_tls *tls, bool use_master_secret,
+				const char *label, uint8_t *buf, size_t len)
+{
+	uint8_t seed[64];
+	bool r;
+
+	if (unlikely(!tls || !tls->prf_hmac))
+		return false;
+
+	memcpy(seed +  0, tls->pending.client_random, 32);
+	memcpy(seed + 32, tls->pending.server_random, 32);
+
+	if (use_master_secret)
+		r = tls_prf_get_bytes(tls, tls->pending.master_secret, 48,
+					label, seed, 64, buf, len);
+	else
+		r = tls_prf_get_bytes(tls, "", 0, label, seed, 64, buf, len);
+
+	explicit_bzero(seed, 64);
+
+	return r;
+}
+
+static void tls_write_random(uint8_t *buf)
+{
+	l_put_be32(time(NULL), buf);
+
+	l_getrandom(buf + 4, 28);
+}
+
+static void tls_drop_handshake_hash(struct l_tls *tls,
+					enum handshake_hash_type hash)
+{
+	if (tls->handshake_hash[hash]) {
+		l_checksum_free(tls->handshake_hash[hash]);
+
+		tls->handshake_hash[hash] = NULL;
+	}
+}
+
+static void tls_reset_handshake(struct l_tls *tls)
+{
+	enum handshake_hash_type hash;
+
+	explicit_bzero(tls->pending.key_block, sizeof(tls->pending.key_block));
+
+	if (tls->pending.cipher_suite &&
+			tls->pending.cipher_suite->key_xchg->free_params)
+		tls->pending.cipher_suite->key_xchg->free_params(tls);
+
+	l_cert_free(tls->peer_cert);
+	l_key_free(tls->peer_pubkey);
+
+	tls->peer_cert = NULL;
+	tls->peer_pubkey = NULL;
+	tls->peer_pubkey_size = 0;
+	tls->peer_authenticated = false;
+	tls->negotiated_curve = NULL;
+	tls->negotiated_ff_group = NULL;
+
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+		tls_drop_handshake_hash(tls, hash);
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
+	tls->cert_requested = 0;
+	tls->cert_sent = 0;
+
+	tls->session_id_size = 0;
+	tls->session_id_size_replaced = 0;
+	tls->session_id_new = false;
+	l_free(l_steal_ptr(tls->session_peer_identity));
+	tls->session_resumed = false;
+}
+
+static void tls_cleanup_handshake(struct l_tls *tls)
+{
+	explicit_bzero(tls->pending.client_random, 32);
+	explicit_bzero(tls->pending.server_random, 32);
+	explicit_bzero(tls->pending.master_secret, 48);
+}
+
+static bool tls_change_cipher_spec(struct l_tls *tls, bool txrx,
+					const char **error)
+{
+	struct tls_bulk_encryption_algorithm *enc;
+	struct tls_mac_algorithm *mac;
+	int key_offset;
+	static char error_buf[200];
+
+	if (tls->cipher_type[txrx] == TLS_CIPHER_AEAD) {
+		if (tls->aead_cipher[txrx]) {
+			l_aead_cipher_free(tls->aead_cipher[txrx]);
+			tls->aead_cipher[txrx] = NULL;
+		}
+	} else {
+		if (tls->cipher[txrx]) {
+			l_cipher_free(tls->cipher[txrx]);
+			tls->cipher[txrx] = NULL;
+		}
+	}
+
+	tls->cipher_type[txrx] = TLS_CIPHER_STREAM;
+
+	if (tls->mac[txrx]) {
+		l_checksum_free(tls->mac[txrx]);
+		tls->mac[txrx] = NULL;
+	}
+
+	tls->mac_length[txrx] = 0;
+	tls->block_length[txrx] = 0;
+	tls->record_iv_length[txrx] = 0;
+
+	if (tls->fixed_iv_length[txrx]) {
+		explicit_bzero(tls->fixed_iv[txrx], tls->fixed_iv_length[txrx]);
+		tls->fixed_iv_length[txrx] = 0;
+	}
+
+	tls->auth_tag_length[txrx] = 0;
+	tls->seq_num[txrx] = 0;
+
+	tls->cipher_suite[txrx] = tls->pending.cipher_suite;
+	if (!tls->cipher_suite[txrx])
+		return true;
+
+	key_offset = 0;
+
+	if (tls->cipher_suite[txrx]->mac) {
+		mac = tls->cipher_suite[txrx]->mac;
+
+		/* Server write / client read is 2nd in the key block */
+		if ((tls->server && txrx) || (!tls->server && !txrx))
+			key_offset += mac->mac_length;
+
+		tls->mac[txrx] = l_checksum_new_hmac(mac->hmac_type,
+						tls->pending.key_block +
+						key_offset, mac->mac_length);
+
+		/* Wipe out the now unneeded part of the key block */
+		explicit_bzero(tls->pending.key_block + key_offset,
+				mac->mac_length);
+
+		if (!tls->mac[txrx]) {
+			if (error) {
+				*error = error_buf;
+				snprintf(error_buf, sizeof(error_buf),
+						"Can't create %s's %s HMAC",
+						tls->cipher_suite[txrx]->name,
+						txrx ? "Tx" : "Rx");
+			}
+
+			return false;
+		}
+
+		tls->mac_length[txrx] = mac->mac_length;
+
+		key_offset = 2 * mac->mac_length;
+	}
+
+	if (tls->cipher_suite[txrx]->encryption) {
+		void *cipher;
+
+		enc = tls->cipher_suite[txrx]->encryption;
+
+		/* Server write / client read is 4th in the key block */
+		if ((tls->server && txrx) || (!tls->server && !txrx))
+			key_offset += enc->key_length;
+
+		if (enc->cipher_type == TLS_CIPHER_AEAD) {
+			cipher = l_aead_cipher_new(enc->l_aead_id,
+						tls->pending.key_block +
+						key_offset, enc->key_length,
+						enc->auth_tag_length);
+			tls->aead_cipher[txrx] = cipher;
+		} else {
+			cipher = l_cipher_new(enc->l_id,
+						tls->pending.key_block +
+						key_offset, enc->key_length);
+			tls->cipher[txrx] = cipher;
+		}
+
+		/* Wipe out the now unneeded part of the key block */
+		explicit_bzero(tls->pending.key_block + key_offset,
+				enc->key_length);
+
+		if (!cipher) {
+			if (error) {
+				*error = error_buf;
+				snprintf(error_buf, sizeof(error_buf),
+						"Can't create %s's %s cipher",
+						tls->cipher_suite[txrx]->name,
+						txrx ? "Tx" : "Rx");
+			}
+
+			return false;
+		}
+
+		tls->cipher_type[txrx] = enc->cipher_type;
+		tls->record_iv_length[txrx] = enc->iv_length -
+			enc->fixed_iv_length;
+		tls->block_length[txrx] = enc->block_length;
+		tls->auth_tag_length[txrx] = enc->auth_tag_length;
+
+		if ((tls->server && txrx) || (!tls->server && !txrx))
+			key_offset += enc->key_length;
+		else
+			key_offset += 2 * enc->key_length;
+	}
+
+	if (tls->negotiated_version <= L_TLS_V10 &&
+			tls->cipher_suite[txrx]->encryption &&
+			tls->cipher_suite[txrx]->encryption->cipher_type ==
+			TLS_CIPHER_BLOCK) {
+		enc = tls->cipher_suite[txrx]->encryption;
+
+		/* Server write / client read is 6th in the key block */
+		if ((tls->server && txrx) || (!tls->server && !txrx))
+			key_offset += enc->iv_length;
+
+		l_cipher_set_iv(tls->cipher[txrx], tls->pending.key_block +
+				key_offset, enc->iv_length);
+
+		/* Wipe out the now unneeded part of the key block */
+		explicit_bzero(tls->pending.key_block + key_offset,
+				enc->iv_length);
+	} else if (tls->cipher_suite[txrx]->encryption &&
+			tls->cipher_suite[txrx]->encryption->fixed_iv_length) {
+		enc = tls->cipher_suite[txrx]->encryption;
+
+		/* Server write / client read is 6th in the key block */
+		if ((tls->server && txrx) || (!tls->server && !txrx))
+			key_offset += enc->fixed_iv_length;
+
+		tls->fixed_iv_length[txrx] = enc->fixed_iv_length;
+		memcpy(tls->fixed_iv[txrx], tls->pending.key_block + key_offset,
+			enc->fixed_iv_length);
+
+		/* Wipe out the now unneeded part of the key block */
+		explicit_bzero(tls->pending.key_block + key_offset,
+				enc->fixed_iv_length);
+	}
+
+	return true;
+}
+
+static void tls_reset_cipher_spec(struct l_tls *tls, bool txrx)
+{
+	/* Reset everything to the TLS_NULL_WITH_NULL_NULL state */
+
+	tls->pending.cipher_suite = NULL;
+
+	tls_change_cipher_spec(tls, txrx, NULL);
+}
+
+static bool tls_cipher_suite_is_compatible_no_key_xchg(struct l_tls *tls,
+					const struct tls_cipher_suite *suite,
+					const char **error)
+{
+	static char error_buf[200];
+	struct l_cert *leaf;
+	enum l_tls_version min_version =
+		tls->negotiated_version ?: tls->min_version;
+	enum l_tls_version max_version =
+		tls->negotiated_version ?: tls->max_version;
+
+	if (suite->encryption &&
+			suite->encryption->cipher_type == TLS_CIPHER_AEAD) {
+		if (max_version < L_TLS_V12) {
+			if (error) {
+				*error = error_buf;
+				snprintf(error_buf, sizeof(error_buf),
+						"Cipher suite %s uses an AEAD "
+						"cipher (TLS 1.2+) but "
+						TLS_VER_FMT
+						" was negotiated or is the max "
+						"version allowed", suite->name,
+						TLS_VER_ARGS(tls->max_version));
+			}
+
+			return false;
+		}
+
+		if (!l_aead_cipher_is_supported(suite->encryption->l_aead_id)) {
+			if (error) {
+				*error = error_buf;
+				snprintf(error_buf, sizeof(error_buf),
+						"Cipher suite %s's AEAD cipher "
+						"algorithm not supported by "
+						"the kernel", suite->name);
+			}
+
+			return false;
+		}
+	} else if (suite->encryption) { /* Block or stream cipher */
+		if (!l_cipher_is_supported(suite->encryption->l_id)) {
+			if (error) {
+				*error = error_buf;
+				snprintf(error_buf, sizeof(error_buf),
+						"Cipher suite %s's block/stream"
+						" cipher algorithm not "
+						"supported by the kernel",
+						suite->name);
+			}
+
+			return false;
+		}
+	}
+
+	if (suite->mac &&
+			!l_checksum_is_supported(suite->mac->hmac_type, true)) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"Cipher suite %s's HMAC algorithm not "
+					"supported by the kernel", suite->name);
+		}
+
+		return false;
+	}
+
+	if (
+			(max_version < L_TLS_V12 &&
+			 (!l_checksum_is_supported(L_CHECKSUM_MD5, true) ||
+			  !l_checksum_is_supported(L_CHECKSUM_SHA1, true))) ||
+			(min_version >= L_TLS_V12 &&
+			 !l_checksum_is_supported(
+					suite->prf_hmac != L_CHECKSUM_NONE ?
+					suite->prf_hmac : L_CHECKSUM_SHA256,
+					true))) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"Cipher suite %s's PRF algorithm not "
+					"supported by the kernel", suite->name);
+		}
+
+		return false;
+	}
+
+	/*
+	 * If the certificate is compatible with the signature algorithm it
+	 * also must be compatible with the key exchange mechanism because
+	 * the cipher suites are defined so that the same certificates can
+	 * be used by both.
+	 */
+	leaf = l_certchain_get_leaf(tls->cert);
+	if (leaf && suite->signature &&
+			!suite->signature->validate_cert_key_type(leaf)) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"Local certificate has key type "
+					"incompatible with cipher suite %s's "
+					"signature algorithm", suite->name);
+		}
+
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Assumes that Client Hello extensions have been processed and that we
+ * will want to start a new session using this cipher suite, including the
+ * key exchange.  This is unlike tls_cipher_suite_is_compatible_no_key_xchg()
+ * which runs fewer checks and must succeed even for a cipher suite loaded
+ * during session resumption.
+ */
+bool tls_cipher_suite_is_compatible(struct l_tls *tls,
+					const struct tls_cipher_suite *suite,
+					const char **error)
+{
+	static char error_buf[200];
+
+	if (!tls_cipher_suite_is_compatible_no_key_xchg(tls, suite, error))
+		return false;
+
+	if (suite->key_xchg->need_ffdh &&
+			!l_key_is_supported(L_KEY_FEATURE_DH)) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"Cipher suite %s's key exchange "
+					"mechanism needs kernel DH support",
+					suite->name);
+		}
+
+		return false;
+	}
+
+	/*
+	 * On the server we know what elliptic curve we'll be using as soon
+	 * as we've processed the ClientHello so for EC-based key exchange
+	 * methods require that a curve has been selected.
+	 */
+	if (suite->key_xchg->need_ecc && tls->server &&
+			!tls->negotiated_curve) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"No common supported elliptic curves "
+					"with the client, can't use %s",
+					suite->name);
+		}
+
+		return false;
+	}
+
+	/* Similarly for FF DH groups */
+	if (suite->key_xchg->need_ffdh && tls->server &&
+			!tls->negotiated_ff_group) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"No common supported finite-field "
+					"groups with the client, can't use %s",
+					suite->name);
+		}
+
+		return false;
+	}
+
+	return true;
+}
+
+static struct tls_cipher_suite *tls_find_cipher_suite(const uint8_t *id)
+{
+	struct tls_cipher_suite **suite;
+
+	for (suite = tls_cipher_suite_pref; *suite; suite++)
+		if ((*suite)->id[0] == id[0] && (*suite)->id[1] == id[1])
+			return *suite;
+
+	return NULL;
+}
+
+static struct tls_compression_method tls_compression_pref[] = {
+	{
+		0,
+		"CompressionMethod.null",
+	},
+};
+
+static struct tls_compression_method *tls_find_compression_method(
+							const uint8_t id)
+{
+	int i;
+
+	for (i = 0; i < (int) L_ARRAY_SIZE(tls_compression_pref); i++)
+		if (tls_compression_pref[i].id == id)
+			return &tls_compression_pref[i];
+
+	return NULL;
+}
+
+const struct tls_hash_algorithm tls_handshake_hash_data[] = {
+	[HANDSHAKE_HASH_SHA384]	= { 5, HANDSHAKE_HASH_SHA384,
+						L_CHECKSUM_SHA384, "SHA384" },
+	[HANDSHAKE_HASH_SHA256]	= { 4, HANDSHAKE_HASH_SHA256,
+						L_CHECKSUM_SHA256, "SHA256" },
+	[HANDSHAKE_HASH_MD5]	= { 1, HANDSHAKE_HASH_MD5,
+						L_CHECKSUM_MD5, "MD5" },
+	[HANDSHAKE_HASH_SHA1]	= { 2, HANDSHAKE_HASH_SHA1,
+						L_CHECKSUM_SHA1, "SHA1" },
+};
+
+static bool tls_init_handshake_hash(struct l_tls *tls)
+{
+	enum handshake_hash_type hash;
+	bool tls10 = tls->max_version < L_TLS_V12;
+
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) {
+		/* Skip hash types we already know we won't need */
+		if (tls10 && hash != HANDSHAKE_HASH_SHA1 &&
+				hash != HANDSHAKE_HASH_MD5)
+			continue;
+
+		if (tls->handshake_hash[hash]) {
+			TLS_DEBUG("Handshake hash %s already exists",
+					tls_handshake_hash_data[hash].name);
+			goto err;
+		}
+
+		tls->handshake_hash[hash] = l_checksum_new(
+					tls_handshake_hash_data[hash].l_id);
+
+		if (!tls->handshake_hash[hash]) {
+			TLS_DEBUG("Can't create %s hash",
+					tls_handshake_hash_data[hash].name);
+			goto err;
+		}
+	}
+
+	return true;
+err:
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+		tls_drop_handshake_hash(tls, hash);
+
+	return false;
+}
+
+static const struct tls_hash_algorithm *tls_set_prf_hmac(struct l_tls *tls)
+{
+	enum handshake_hash_type hash;
+
+	if (tls->pending.cipher_suite->prf_hmac == L_CHECKSUM_NONE) {
+		tls->prf_hmac = &tls_handshake_hash_data[HANDSHAKE_HASH_SHA256];
+		return tls->prf_hmac;
+	}
+
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+		if (tls_handshake_hash_data[hash].l_id ==
+				tls->pending.cipher_suite->prf_hmac) {
+			tls->prf_hmac = &tls_handshake_hash_data[hash];
+			return tls->prf_hmac;
+		}
+
+	return NULL;
+}
+
+static bool tls_domain_match_mask(const char *name, size_t name_len,
+					const char *mask, size_t mask_len)
+{
+	bool at_start = true;
+
+	while (1) {
+		const char *name_seg_end = memchr(name, '.', name_len);
+		const char *mask_seg_end = memchr(mask, '.', mask_len);
+		size_t name_seg_len = name_seg_end ?
+			(size_t) (name_seg_end - name) : name_len;
+		size_t mask_seg_len = mask_seg_end ?
+			(size_t) (mask_seg_end - mask) : mask_len;
+
+		if (mask_seg_len == 1 && mask[0] == '*') {
+			/*
+			 * A * at the beginning of the mask matches any
+			 * number of labels.
+			 */
+			if (at_start && name_seg_end &&
+					tls_domain_match_mask(name_seg_end + 1,
+						name_len - name_seg_len - 1,
+						mask, mask_len))
+				return true;
+
+			goto ok_next;
+		}
+
+		if (name_seg_len != mask_seg_len ||
+				memcmp(name, mask, name_seg_len))
+			return false;
+
+ok_next:
+		/* If either string ends here both must end here */
+		if (!name_seg_end || !mask_seg_end)
+			return !name_seg_end && !mask_seg_end;
+
+		at_start = false;
+		name = name_seg_end + 1;
+		name_len -= name_seg_len + 1;
+		mask = mask_seg_end + 1;
+		mask_len -= mask_seg_len + 1;
+	}
+}
+
+static const struct asn1_oid subject_alt_name_oid =
+	{ 3, { 0x55, 0x1d, 0x11 } };
+static const struct asn1_oid dn_common_name_oid =
+	{ 3, { 0x55, 0x04, 0x03 } };
+
+#define SAN_DNS_NAME_ID ASN1_CONTEXT_IMPLICIT(2)
+
+static bool tls_cert_domains_match_mask(struct l_cert *cert, char **mask,
+					char **error_msg)
+{
+	const uint8_t *san, *dn, *end;
+	size_t san_len, dn_len;
+	uint8_t san_tag;
+	const char *cn = NULL;
+	size_t cn_len;
+	char **i;
+	struct l_string *dns_names = NULL;
+	int dns_name_count = 0;
+
+	/*
+	 * Locate SubjectAltName (RFC5280 Section 4.2.1.6) and descend into
+	 * the sole SEQUENCE element, check if any DNSName matches.
+	 */
+	san = cert_get_extension(cert, &subject_alt_name_oid, NULL, &san_len);
+	if (san) {
+		san = asn1_der_find_elem(san, san_len, 0, &san_tag, &san_len);
+		if (unlikely(!san || san_tag != ASN1_ID_SEQUENCE))
+			goto parse_error;
+
+		end = san + san_len;
+		while (san < end) {
+			const uint8_t *value;
+			uint8_t tag;
+			size_t len;
+
+			value = asn1_der_find_elem(san, end - san,
+							SAN_DNS_NAME_ID,
+							&tag, &len);
+			if (!value)
+				break;
+
+			/* Type is implicitly IA5STRING */
+
+			for (i = mask; *i; i++)
+				if (tls_domain_match_mask((const char *) value,
+							len, *i, strlen(*i))) {
+					l_string_free(dns_names);
+					return true;
+				}
+
+			if (!dns_names) {
+				dns_names = l_string_new(128);
+				l_string_append(dns_names, "tried DNSName(s) ");
+				l_string_append_fixed(dns_names,
+							(char *) value, len);
+			} else if (dns_name_count < 20) {
+				l_string_append(dns_names, ", ");
+				l_string_append_fixed(dns_names,
+							(char *) value, len);
+			}
+
+			san = value + len;
+			dns_name_count++;
+		}
+	}
+
+	/*
+	 * Retrieve the Common Name from the Subject DN and check if it
+	 * matches.
+	 *
+	 * We look at the Common Name only if no DNSNames were present in
+	 * the certificate, following Wi-Fi Alliance's Hotspot 2.0
+	 * Specification v3.1 section 7.3.3.2 step 2:
+	 * "Verify in the AAA server certificate that the domain name from
+	 * the FQDN [...] is a suffix match of the domain name in at least
+	 * one of the DNSName SubjectAltName extensions. If a SubjectAltName
+	 * of type DNSName is not present, then the domain name from the
+	 * FQDN shall be a suffix match to the CommonName portion of the
+	 * SubjectName. If neither of these conditions holds, then
+	 * verification fails."
+	 */
+	if (dns_name_count) {
+		if (dns_name_count > 20)
+			l_string_append_printf(dns_names, " and %i other",
+						dns_name_count - 20);
+
+		*error_msg = l_string_unwrap(dns_names);
+		return false;
+	}
+
+	dn = l_cert_get_dn(cert, &dn_len);
+	if (unlikely(!dn))
+		goto parse_error;
+
+	end = dn + dn_len;
+	while (dn < end) {
+		const uint8_t *set, *seq, *oid, *name;
+		uint8_t tag;
+		size_t len, oid_len, name_len;
+
+		set = asn1_der_find_elem(dn, end - dn, 0, &tag, &len);
+		if (unlikely(!set || tag != ASN1_ID_SET))
+			goto parse_error;
+
+		dn = set + len;
+
+		seq = asn1_der_find_elem(set, len, 0, &tag, &len);
+		if (unlikely(!seq || tag != ASN1_ID_SEQUENCE))
+			goto parse_error;
+
+		oid = asn1_der_find_elem(seq, len, 0, &tag, &oid_len);
+		if (unlikely(!oid || tag != ASN1_ID_OID))
+			goto parse_error;
+
+		name = asn1_der_find_elem(seq, len, 1, &tag, &name_len);
+		if (unlikely(!name || (tag != ASN1_ID_PRINTABLESTRING &&
+					tag != ASN1_ID_UTF8STRING &&
+					tag != ASN1_ID_IA5STRING)))
+			continue;
+
+		if (asn1_oid_eq(&dn_common_name_oid, oid_len, oid)) {
+			cn = (const char *) name;
+			cn_len = name_len;
+			break;
+		}
+	}
+
+	if (unlikely(!cn))
+		goto parse_error;
+
+	for (i = mask; *i; i++)
+		if (tls_domain_match_mask(cn, cn_len, *i, strlen(*i)))
+			return true;
+
+	*error_msg = l_strdup_printf("tried CommonName %.*s", (int) cn_len, cn);
+	return false;
+
+parse_error:
+	*error_msg = l_strdup("couldn't locate DNSName or CommonName");
+
+	return false;
+}
+
+static const char *tls_get_cache_group_name(struct l_tls *tls,
+						const uint8_t *session_id,
+						size_t session_id_size)
+{
+	_auto_(l_free) char *session_id_str = NULL;
+	static char group_name[256];
+
+	if (!tls->server)
+		return tls->session_prefix;
+
+	session_id_str = l_util_hexstring(session_id, session_id_size);
+	snprintf(group_name, sizeof(group_name), "%s-%s",
+			tls->session_prefix, session_id_str);
+	return group_name;
+}
+
+static void tls_forget_cached_session(struct l_tls *tls, const char *group_name,
+					const uint8_t *session_id,
+					size_t session_id_size, bool call_back)
+{
+	if (!group_name)
+		group_name = tls_get_cache_group_name(tls, session_id,
+							session_id_size);
+
+	l_settings_remove_group(tls->session_settings, group_name);
+
+	if (call_back && tls->session_update_cb) {
+		tls->in_callback = true;
+		tls->session_update_cb(tls->session_update_user_data);
+		tls->in_callback = false;
+	}
+}
+
+static bool tls_load_cached_session(struct l_tls *tls, const char *group_name,
+					const uint8_t *session_id,
+					size_t session_id_size,
+					const char *session_id_str)
+{
+	_auto_(l_free) uint8_t *master_secret = NULL;
+	int version;
+	_auto_(l_free) uint8_t *cipher_suite_id = NULL;
+	struct tls_cipher_suite *cipher_suite;
+	unsigned int compression_method_id;
+	_auto_(l_free) char *peer_identity = NULL;
+	size_t size;
+	const char *error;
+
+	if (l_settings_has_key(tls->session_settings, group_name,
+				"SessionExpiryTime")) {
+		uint64_t expiry_time;
+
+		if (unlikely(!l_settings_get_uint64(tls->session_settings,
+							group_name,
+							"SessionExpiryTime",
+							&expiry_time)))
+			goto warn_corrupt;
+
+		if (time_realtime_now() > expiry_time) {
+			TLS_DEBUG("Cached session %s is expired, removing it, "
+					"will start a new session",
+					session_id_str);
+			goto forget;
+		}
+	}
+
+	if (unlikely(!l_settings_get_int(tls->session_settings,
+						group_name,
+						"SessionVersion",
+						&version) ||
+			version < TLS_MIN_VERSION || version > TLS_MAX_VERSION))
+		goto warn_corrupt;
+
+	master_secret = l_settings_get_bytes(tls->session_settings,
+						group_name,
+						"SessionMasterSecret",
+						&size);
+	if (unlikely(!master_secret || size != 48))
+		goto warn_corrupt;
+
+	cipher_suite_id = l_settings_get_bytes(tls->session_settings,
+						group_name,
+						"SessionCipherSuite",
+						&size);
+	if (unlikely(!cipher_suite_id || size != 2 ||
+			!(cipher_suite =
+			  tls_find_cipher_suite(cipher_suite_id))))
+		goto warn_corrupt;
+
+	/*
+	 * While we could attempt to resume a session even though we're now
+	 * configured with, say, a different certificate type than what we
+	 * had when we cached that session, that is too questionable of a
+	 * scenario to support it.  We don't specifically check that all of
+	 * the authentication data is the same, e.g. we don't save the
+	 * certificate serial number or path, but ensure the cached cipher
+	 * suite is compatible with current authentication data.
+	 *
+	 * We filter the cipher suites in our Client Hello to only offer the
+	 * ones compatible with current configuration so if we also include
+	 * a Session ID from a session who's cipher suite is not one of those
+	 * listed in that same Client Hello, the server is likely to notice
+	 * and either start a new session or send a fatal Alert.
+	 *
+	 * It is up to the user to keep multiple cache instances if it needs
+	 * to save multiple sessions.
+	 */
+	if (unlikely(!tls_cipher_suite_is_compatible_no_key_xchg(tls,
+								cipher_suite,
+								&error))) {
+		TLS_DEBUG("Cached session %s cipher suite not compatible: %s",
+				session_id_str, error);
+		goto forget;
+	}
+
+	if (unlikely(!l_settings_get_uint(tls->session_settings, group_name,
+						"SessionCompressionMethod",
+						&compression_method_id) ||
+			!tls_find_compression_method(compression_method_id)))
+		goto warn_corrupt;
+
+	if (l_settings_has_key(tls->session_settings, group_name,
+				"SessionPeerIdentity")) {
+		peer_identity = l_settings_get_string(tls->session_settings,
+						group_name,
+						"SessionPeerIdentity");
+		if (unlikely(!peer_identity || !cipher_suite->signature))
+			goto warn_corrupt;
+	}
+
+	tls->session_id_size = session_id_size;
+	memcpy(tls->session_id, session_id, session_id_size);
+	tls->session_id_new = false;
+	tls->client_version = version;
+	memcpy(tls->pending.master_secret, master_secret, 48);
+	memcpy(tls->session_cipher_suite_id, cipher_suite_id, 2);
+	tls->session_compression_method_id = compression_method_id;
+	l_free(tls->session_peer_identity);
+	tls->session_peer_identity = l_steal_ptr(peer_identity);
+	return true;
+
+warn_corrupt:
+	TLS_DEBUG("Cached session %s data is corrupt or has unsupported "
+			"parameters, removing it, will start a new session",
+			session_id_str);
+
+forget:
+	tls_forget_cached_session(tls, group_name, session_id, session_id_size,
+					true);
+	return false;
+}
+
+static bool tls_load_cached_client_session(struct l_tls *tls)
+{
+	/*
+	 * The following settings are required:
+	 *   SessionID,
+	 *   SessionMasterSecret,
+	 *   SessionVersion,
+	 *   SessionCipherSuite,
+	 *   SessionCompressionMethod,
+	 * and these two are optional:
+	 *   SessionExpiryTime,
+	 *   SessionPeerIdentity.
+	 */
+	_auto_(l_free) uint8_t *session_id = NULL;
+	size_t session_id_size;
+	_auto_(l_free) char *session_id_str = NULL;
+	const char *group_name = tls_get_cache_group_name(tls, NULL, 0);
+
+	tls->session_id_size = 0;
+	tls->session_id_new = false;
+
+	if (!tls->session_settings ||
+			!l_settings_has_key(tls->session_settings, group_name,
+						"SessionID"))
+		/* No session cached, no error */
+		return false;
+
+	session_id = l_settings_get_bytes(tls->session_settings, group_name,
+						"SessionID", &session_id_size);
+	if (unlikely(!session_id ||
+			session_id_size < 1 || session_id_size > 32)) {
+		TLS_DEBUG("Bad cached session ID format");
+		tls_forget_cached_session(tls, group_name, NULL, 0, true);
+		return false;
+	}
+
+	session_id_str = l_util_hexstring(session_id, session_id_size);
+
+	return tls_load_cached_session(tls, group_name, session_id,
+					session_id_size, session_id_str);
+}
+
+static bool tls_load_cached_server_session(struct l_tls *tls,
+						const uint8_t *session_id,
+						size_t session_id_size)
+{
+	_auto_(l_free) char *session_id_str =
+		l_util_hexstring(session_id, session_id_size);
+	const char *target_group_name =
+		tls_get_cache_group_name(tls, session_id, session_id_size);
+	_auto_(l_strv_free) char **groups =
+		l_settings_get_groups(tls->session_settings);
+	char **group;
+	unsigned int cnt = 0;
+	size_t prefix_len = strlen(tls->session_prefix);
+	uint64_t now = time_realtime_now();
+	char *oldest_session_group = NULL;
+	uint64_t oldest_session_expiry = UINT64_MAX;
+	bool found = false;
+	bool changed = false;
+	bool loaded = false;
+
+	tls->session_id_size = 0;
+	tls->session_id_new = false;
+
+	/* Clean up expired entries and enforce session count limit */
+	for (group = groups; *group; group++) {
+		uint64_t expiry_time;
+
+		if (memcmp(*group, tls->session_prefix, prefix_len) ||
+				(*group)[prefix_len] != '-')
+			continue;
+
+		/* Group seems to be a session cache entry */
+
+		if (unlikely(!l_settings_get_uint64(tls->session_settings,
+							*group,
+							"SessionExpiryTime",
+							&expiry_time)) ||
+				expiry_time <= now) {
+			TLS_DEBUG("Cached session %s is expired or invalid, "
+					"purging entry",
+					*group + prefix_len + 1);
+			l_settings_remove_group(tls->session_settings, *group);
+			changed = true;
+			continue;
+		}
+
+		cnt++;
+
+		if (!strcmp(*group + prefix_len + 1,
+				target_group_name + prefix_len + 1)) {
+			found = true;
+			continue; /* Don't purge this entry */
+		}
+
+		if (expiry_time < oldest_session_expiry) {
+			oldest_session_group = *group;
+			oldest_session_expiry = expiry_time;
+		}
+	}
+
+	/*
+	 * Enforce tls->session_count_max by dropping the entry for the
+	 * oldest session (more specifically the one closest to its expiry
+	 * time) in the cache, that is not the session we're trying to
+	 * load.  If the target session was not found, do this as soon as
+	 * tls->session_count_max is reached rather than when it's exceeded
+	 * so as to make room for a new entry.  If we end up not saving
+	 * a new session due to an error before the handshake finish, we'll
+	 * be left with tls->session_count_max - 1 entries and will have
+	 * purged that entry unnecessarily but the cache will have room for
+	 * a future session.  Same when we did find the target session but
+	 * later had to forget it because of a fatal alert during or after
+	 * the handshake.
+	 *
+	 * If we did find the target session but we later find that we
+	 * can't resume it, we will forget it so the new session can take
+	 * the old session's place and the limit is not exceeded, see
+	 * discussion in tls_server_resume_error.
+	 */
+	if (tls->session_count_max && oldest_session_group &&
+			cnt >= tls->session_count_max + (found ? 1 : 0)) {
+		l_settings_remove_group(tls->session_settings,
+					oldest_session_group);
+		changed = true;
+	}
+
+	if (!found) {
+		TLS_DEBUG("Requested session %s not found in cache, will "
+				"start a new session", session_id_str);
+		goto call_back;
+	}
+
+	loaded = tls_load_cached_session(tls, target_group_name,
+						session_id, session_id_size,
+						session_id_str);
+
+	/*
+	 * If tls_load_cached_session() returned false it will have called
+	 * session_update_cb for us.
+	 */
+	if (!loaded)
+		changed = false;
+
+call_back:
+	if (changed && tls->session_update_cb) {
+		tls->in_callback = true;
+		tls->session_update_cb(tls->session_update_user_data);
+		tls->in_callback = false;
+	}
+
+	return loaded;
+}
+
+#define SWITCH_ENUM_TO_STR(val) \
+	case (val):		\
+		return L_STRINGIFY(val);
+
+static const char *tls_handshake_type_to_str(enum tls_handshake_type type)
+{
+	static char buf[100];
+
+	switch (type) {
+	SWITCH_ENUM_TO_STR(TLS_HELLO_REQUEST)
+	SWITCH_ENUM_TO_STR(TLS_CLIENT_HELLO)
+	SWITCH_ENUM_TO_STR(TLS_SERVER_HELLO)
+	SWITCH_ENUM_TO_STR(TLS_CERTIFICATE)
+	SWITCH_ENUM_TO_STR(TLS_SERVER_KEY_EXCHANGE)
+	SWITCH_ENUM_TO_STR(TLS_CERTIFICATE_REQUEST)
+	SWITCH_ENUM_TO_STR(TLS_SERVER_HELLO_DONE)
+	SWITCH_ENUM_TO_STR(TLS_CERTIFICATE_VERIFY)
+	SWITCH_ENUM_TO_STR(TLS_CLIENT_KEY_EXCHANGE)
+	SWITCH_ENUM_TO_STR(TLS_FINISHED)
+	}
+
+	snprintf(buf, sizeof(buf), "tls_handshake_type(%i)", type);
+	return buf;
+}
+
+static void tls_send_alert(struct l_tls *tls, bool fatal,
+				enum l_tls_alert_desc alert_desc)
+{
+	uint8_t buf[2];
+
+	TLS_DEBUG("Sending a %s Alert: %s", fatal ? "Fatal" : "Warning",
+			l_tls_alert_to_str(alert_desc));
+
+	buf[0] = fatal ? 2 : 1;
+	buf[1] = alert_desc;
+
+	tls_tx_record(tls, TLS_CT_ALERT, buf, 2);
+}
+
+/*
+ * Callers make sure this is about the last function before returning
+ * from the stack frames up to the exported library call so that the
+ * user-supplied disconnected callback here is free to use l_tls_free
+ * for example.
+ */
+void tls_disconnect(struct l_tls *tls, enum l_tls_alert_desc desc,
+			enum l_tls_alert_desc local_desc)
+{
+	bool forget_session = false;
+	/* Save session_id_size before tls_reset_handshake() */
+	size_t session_id_size = tls->session_id_size;
+
+	if ((desc || local_desc) && tls->session_settings &&
+			session_id_size && !tls->session_id_new)
+		/*
+		 * RFC5246 Section 7.2: "Alert messages with a level of fatal
+		 * result in the immediate termination of the connection.  In
+		 * this case, other connections corresponding to the session
+		 * may continue, but the session identifier MUST be
+		 * invalidated, preventing the failed session from being used
+		 * to establish new connections."
+		 *
+		 * and 7.2.1: "Note that as of TLS 1.1, failure to properly
+		 * close a connection no longer requires that a session not
+		 * be resumed."
+		 *
+		 * I.e. we need to remove the session from the cache here but
+		 * not on l_tls_close().
+		 */
+		forget_session = true;
+
+	tls_send_alert(tls, true, desc);
+
+	tls_reset_handshake(tls);
+	tls_cleanup_handshake(tls);
+
+	tls_reset_cipher_spec(tls, 0);
+	tls_reset_cipher_spec(tls, 1);
+
+	tls->negotiated_version = 0;
+	tls->ready = false;
+	tls->renegotiation_info.secure_renegotiation = false;
+
+	if (forget_session) {
+		tls_forget_cached_session(tls, NULL, tls->session_id,
+						session_id_size, true);
+
+		if (tls->pending_destroy)
+			return;
+	}
+
+	tls->disconnected(local_desc ?: desc, local_desc && !desc,
+				tls->user_data);
+}
+
+void tls_tx_handshake(struct l_tls *tls, int type, uint8_t *buf, size_t length)
+{
+	int i;
+
+	TLS_DEBUG("Sending a %s of %zi bytes",
+			tls_handshake_type_to_str(type),
+			length - TLS_HANDSHAKE_HEADER_SIZE);
+
+	/* Fill in the handshake header */
+
+	buf[0] = type;
+	buf[1] = (length - TLS_HANDSHAKE_HEADER_SIZE) >> 16;
+	buf[2] = (length - TLS_HANDSHAKE_HEADER_SIZE) >>  8;
+	buf[3] = (length - TLS_HANDSHAKE_HEADER_SIZE) >>  0;
+
+	for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++)
+		if (tls->handshake_hash[i])
+			l_checksum_update(tls->handshake_hash[i], buf, length);
+
+	tls_tx_record(tls, TLS_CT_HANDSHAKE, buf, length);
+}
+
+static ssize_t tls_append_hello_extensions(struct l_tls *tls,
+						struct l_queue *extensions,
+						uint8_t *buf, size_t len)
+{
+	uint8_t *ptr = buf;
+	uint8_t *extensions_len_ptr = ptr;
+	bool client_hello = !tls->server;
+	unsigned int i = 0;
+	const struct l_queue_entry *entry = l_queue_get_entries(extensions);
+
+	if (len < 2)
+		return -ENOSPC;
+
+	ptr += 2;
+	len -= 2;
+
+	while (1) {
+		const struct tls_hello_extension *extension;
+		ssize_t ext_len;
+		ssize_t (*ext_write)(struct l_tls *tls,
+					uint8_t *buf, size_t len);
+
+		if (client_hello) {
+			extension = &tls_extensions[i++];
+			if (!extension->name)
+				break;
+
+			ext_write = extension->client_write;
+		} else  {
+			uint16_t ext_id;
+
+			if (!entry)
+				break;
+
+			ext_id = L_PTR_TO_UINT(entry->data);
+			entry = entry->next;
+
+			for (i = 0; tls_extensions[i].name; i++)
+				if (tls_extensions[i].id == ext_id)
+					break;
+
+			extension = &tls_extensions[i];
+			if (!extension->name)
+				continue;
+
+			ext_write = extension->server_write;
+		}
+
+		/*
+		 * Note: could handle NULL client_write with non-NULL
+		 * server_handle or server_handle_absent as "server-oriented"
+		 * extension (7.4.1.4) and write empty extension_data and
+		 * similarly require empty extension_data in
+		 * tls_handle_client_hello if client_handle NULL.
+		 */
+		if (!ext_write)
+			continue;
+
+		if (len < 4)
+			return -ENOSPC;
+
+		ext_len = ext_write(tls, ptr + 4, len - 4);
+		if (ext_len == -ENOMSG)
+			continue;
+
+		if (ext_len < 0) {
+			TLS_DEBUG("%s extension's %s_write: %s",
+					extension->name,
+					client_hello ? "client" : "server",
+					strerror(-ext_len));
+			return ext_len;
+		}
+
+		l_put_be16(extension->id, ptr + 0);
+		l_put_be16(ext_len, ptr + 2);
+		ptr += 4 + ext_len;
+		len -= 4 + ext_len;
+	}
+
+	if (ptr > extensions_len_ptr + 2)
+		l_put_be16(ptr - (extensions_len_ptr + 2), extensions_len_ptr);
+	else /* Skip the length if no extensions */
+		ptr = extensions_len_ptr;
+
+	return ptr - buf;
+}
+
+static bool tls_send_client_hello(struct l_tls *tls)
+{
+	uint8_t buf[1024 + L_ARRAY_SIZE(tls_compression_pref)];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	uint8_t *len_ptr;
+	unsigned int i;
+	ssize_t r;
+	struct tls_cipher_suite **suite;
+
+	/* Fill in the Client Hello body */
+
+	*ptr++ = (uint8_t) (tls->client_version >> 8);
+	*ptr++ = (uint8_t) (tls->client_version >> 0);
+
+	tls_write_random(tls->pending.client_random);
+	memcpy(ptr, tls->pending.client_random, 32);
+	ptr += 32;
+
+	if (tls->session_id_size) {
+		*ptr++ = tls->session_id_size;
+		memcpy(ptr, tls->session_id, tls->session_id_size);
+		ptr += tls->session_id_size;
+	} else
+		*ptr++ = 0;
+
+	len_ptr = ptr;
+	ptr += 2;
+
+	for (suite = tls->cipher_suite_pref_list; *suite; suite++) {
+		const char *error;
+
+		if (!tls_cipher_suite_is_compatible(tls, *suite, &error)) {
+			TLS_DEBUG("non-fatal: %s", error);
+			continue;
+		}
+
+		*ptr++ = (*suite)->id[0];
+		*ptr++ = (*suite)->id[1];
+	}
+
+	if (ptr == len_ptr + 2) {
+		TLS_DEBUG("No compatible cipher suites, check kernel config, "
+				"certificate's key type and TLS version range");
+		return false;
+	}
+
+	l_put_be16((ptr - len_ptr - 2), len_ptr);
+	*ptr++ = L_ARRAY_SIZE(tls_compression_pref);
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_compression_pref); i++)
+		*ptr++ = tls_compression_pref[i].id;
+
+	r = tls_append_hello_extensions(tls, NULL,
+					ptr, buf + sizeof(buf) - ptr);
+	if (r < 0)
+		return false;
+
+	ptr += r;
+
+	tls_tx_handshake(tls, TLS_CLIENT_HELLO, buf, ptr - buf);
+	return true;
+}
+
+static bool tls_send_server_hello(struct l_tls *tls, struct l_queue *extensions)
+{
+	uint8_t buf[1024];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	ssize_t r;
+
+	/* Fill in the Server Hello body */
+
+	*ptr++ = tls->negotiated_version >> 8;
+	*ptr++ = tls->negotiated_version >> 0;
+
+	tls_write_random(tls->pending.server_random);
+	memcpy(ptr, tls->pending.server_random, 32);
+	ptr += 32;
+
+	if (tls->session_id_size) {
+		*ptr++ = tls->session_id_size;
+		memcpy(ptr, tls->session_id, tls->session_id_size);
+		ptr += tls->session_id_size;
+	} else
+		*ptr++ = 0;
+
+	*ptr++ = tls->pending.cipher_suite->id[0];
+	*ptr++ = tls->pending.cipher_suite->id[1];
+
+	*ptr++ = tls->pending.compression_method->id;
+
+	r = tls_append_hello_extensions(tls, extensions,
+					ptr, buf + sizeof(buf) - ptr);
+	if (r < 0) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Error appending extensions: %s",
+				strerror(-r));
+		return false;
+	}
+
+	ptr += r;
+
+	tls_tx_handshake(tls, TLS_SERVER_HELLO, buf, ptr - buf);
+	return true;
+}
+
+static bool tls_cert_list_add_size(struct l_cert *cert, void *user_data)
+{
+	size_t *total = user_data;
+	size_t der_len;
+
+	l_cert_get_der_data(cert, &der_len);
+	*total += 3 + der_len;
+
+	return false;
+}
+
+static bool tls_cert_list_append(struct l_cert *cert, void *user_data)
+{
+	uint8_t **ptr = user_data;
+	const uint8_t *der;
+	size_t der_len;
+
+	der = l_cert_get_der_data(cert, &der_len);
+	*(*ptr)++ = der_len >> 16;
+	*(*ptr)++ = der_len >>  8;
+	*(*ptr)++ = der_len >>  0;
+	memcpy(*ptr, der, der_len);
+	*ptr += der_len;
+
+	return false;
+}
+
+static bool tls_send_certificate(struct l_tls *tls)
+{
+	uint8_t *buf, *ptr;
+	size_t total;
+
+	if (tls->server && !tls->cert) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, TLS_ALERT_BAD_CERT,
+				"Certificate needed in server mode");
+		return false;
+	}
+
+	/*
+	 * TODO: check that the certificate is compatible with hash and
+	 * signature algorithms lists supplied to us in the Client Hello
+	 * extensions (if we're a 1.2+ server) or in the Certificate Request
+	 * (if we act as a 1.2+ client).
+	 *
+	 *  - for the hash and signature_algorithms list, check all
+	 *    certs in the cert chain.
+	 *
+	 *  - also if !cipher_suite->key_xchg->key_exchange_msg, check that the
+	 *    end entity certificate's key type matches and is usable with some
+	 *    hash/signature pair.
+	 *
+	 *  - on client check if any of the supplied DNs (if any) match
+	 *    anything in our cert chain.
+	 */
+
+	total = 0;
+	l_certchain_walk_from_leaf(tls->cert, tls_cert_list_add_size, &total);
+
+	buf = l_malloc(128 + total);
+	ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+
+	/* Fill in the Certificate body */
+
+	*ptr++ = total >> 16;
+	*ptr++ = total >>  8;
+	*ptr++ = total >>  0;
+	l_certchain_walk_from_leaf(tls->cert, tls_cert_list_append, &ptr);
+
+	tls_tx_handshake(tls, TLS_CERTIFICATE, buf, ptr - buf);
+
+	l_free(buf);
+
+	if (tls->cert)
+		tls->cert_sent = true;
+
+	return true;
+}
+
+/*
+ * Note: ClientCertificateType.rsa_sign value coincides with the
+ * SignatureAlgorithm.rsa value but other values in those enum are
+ * different so we don't mix them, can't extract them from
+ * tls->pending.cipher_suite->signature.
+ */
+static uint8_t tls_cert_type_pref[] = {
+	1, /* RSA_sign */
+};
+
+static bool tls_send_certificate_request(struct l_tls *tls)
+{
+	uint8_t *buf, *ptr, *dn_ptr;
+	size_t len;
+	const struct l_queue_entry *entry;
+	unsigned int i;
+	size_t dn_total = 0;
+
+	for (entry = l_queue_get_entries(tls->ca_certs); entry;
+			entry = entry->next) {
+		struct l_cert *ca_cert = entry->data;
+		size_t dn_size;
+
+		if (l_cert_get_dn(ca_cert, &dn_size))
+			dn_total += 10 + dn_size;
+	}
+
+	len = 256 + L_ARRAY_SIZE(tls_cert_type_pref) + dn_total;
+	buf = l_malloc(len);
+	ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+
+	/* Fill in the Certificate Request body */
+
+	*ptr++ = L_ARRAY_SIZE(tls_cert_type_pref);
+	for (i = 0; i < L_ARRAY_SIZE(tls_cert_type_pref); i++)
+		*ptr++ = tls_cert_type_pref[i];
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		ssize_t ret = tls_write_signature_algorithms(tls, ptr,
+							buf + len - ptr);
+
+		if (ret < 0) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"tls_write_signature_algorithms: %s",
+					strerror(-ret));
+			l_free(buf);
+			return false;
+		}
+
+		ptr += ret;
+	}
+
+	dn_ptr = ptr;
+	ptr += 2;			/* Leave space for the total DN size */
+
+	for (entry = l_queue_get_entries(tls->ca_certs); entry;
+			entry = entry->next) {
+		struct l_cert *ca_cert = entry->data;
+		size_t dn_size;
+		const uint8_t *dn = l_cert_get_dn(ca_cert, &dn_size);
+		uint8_t *cur_dn_ptr = ptr;
+
+		if (!dn)
+			continue;
+
+		ptr += 2;		/* Leave space for current DN size */
+		*ptr++ = ASN1_ID_SEQUENCE;	/* DER outer SEQUENCE tag */
+		asn1_write_definite_length(&ptr, dn_size); /* length */
+		memcpy(ptr, dn, dn_size);	/* value */
+		ptr += dn_size;
+		l_put_be16(ptr - cur_dn_ptr - 2, cur_dn_ptr);
+	}
+
+	l_put_be16(ptr - dn_ptr - 2, dn_ptr);	/* DistinguishedNames size */
+
+	tls_tx_handshake(tls, TLS_CERTIFICATE_REQUEST, buf, ptr - buf);
+
+	l_free(buf);
+
+	return true;
+}
+
+static void tls_send_server_hello_done(struct l_tls *tls)
+{
+	uint8_t buf[32];
+
+	/* No body */
+
+	tls_tx_handshake(tls, TLS_SERVER_HELLO_DONE, buf,
+				TLS_HANDSHAKE_HEADER_SIZE);
+}
+
+static void tls_update_key_block(struct l_tls *tls)
+{
+	uint8_t seed[64];
+	int key_block_size = 0;
+
+	if (tls->pending.cipher_suite->encryption)
+		key_block_size += 2 *
+			tls->pending.cipher_suite->encryption->key_length;
+
+	if (tls->pending.cipher_suite->mac)
+		key_block_size += 2 *
+			tls->pending.cipher_suite->mac->mac_length;
+
+	if (tls->pending.cipher_suite->encryption &&
+			tls->negotiated_version <= L_TLS_V10 &&
+			tls->pending.cipher_suite->encryption->cipher_type ==
+			TLS_CIPHER_BLOCK)
+		key_block_size += 2 *
+			tls->pending.cipher_suite->encryption->iv_length;
+
+	if (tls->pending.cipher_suite->encryption)
+		key_block_size += 2 * tls->pending.cipher_suite->encryption->
+			fixed_iv_length;
+
+	/* Reverse order from the master secret seed */
+	memcpy(seed +  0, tls->pending.server_random, 32);
+	memcpy(seed + 32, tls->pending.client_random, 32);
+
+	tls_prf_get_bytes(tls, tls->pending.master_secret, 48,
+				"key expansion", seed, 64,
+				tls->pending.key_block, key_block_size);
+	explicit_bzero(seed, 64);
+}
+
+void tls_generate_master_secret(struct l_tls *tls,
+				const uint8_t *pre_master_secret,
+				int pre_master_secret_len)
+{
+	uint8_t seed[64];
+
+	memcpy(seed +  0, tls->pending.client_random, 32);
+	memcpy(seed + 32, tls->pending.server_random, 32);
+
+	tls_prf_get_bytes(tls, pre_master_secret, pre_master_secret_len,
+				"master secret", seed, 64,
+				tls->pending.master_secret, 48);
+	explicit_bzero(seed, 64);
+
+	/* Directly generate the key block while we're at it */
+	tls_update_key_block(tls);
+}
+
+static void tls_get_handshake_hash(struct l_tls *tls,
+					enum handshake_hash_type type,
+					uint8_t *out)
+{
+	struct l_checksum *hash = l_checksum_clone(tls->handshake_hash[type]);
+
+	if (!hash)
+		return;
+
+	l_checksum_get_digest(hash, out, l_checksum_digest_length(
+					tls_handshake_hash_data[type].l_id));
+	l_checksum_free(hash);
+}
+
+static bool tls_get_handshake_hash_by_type(struct l_tls *tls,
+					enum handshake_hash_type type,
+					const uint8_t *data, size_t data_len,
+					uint8_t *out, size_t *out_len)
+{
+	if (!tls->handshake_hash[type])
+		return false;
+
+	if (out_len)
+		*out_len = l_checksum_digest_length(
+					tls_handshake_hash_data[type].l_id);
+
+	tls_get_handshake_hash(tls, type, out);
+	return true;
+}
+
+static bool tls_send_certificate_verify(struct l_tls *tls)
+{
+	uint8_t buf[2048];
+	int i;
+	ssize_t sign_len;
+
+	/* Fill in the Certificate Verify body */
+
+	sign_len = tls->pending.cipher_suite->signature->sign(tls,
+					buf + TLS_HANDSHAKE_HEADER_SIZE,
+					2048 - TLS_HANDSHAKE_HEADER_SIZE,
+					tls_get_handshake_hash_by_type,
+					NULL, 0);
+
+	if (sign_len < 0)
+		return false;
+
+	/* Stop maintaining handshake message hashes other than the PRF hash */
+	if (tls->negotiated_version >= L_TLS_V12)
+		for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++)
+			if (&tls_handshake_hash_data[i] != tls->prf_hmac)
+				tls_drop_handshake_hash(tls, i);
+
+	tls_tx_handshake(tls, TLS_CERTIFICATE_VERIFY, buf,
+				sign_len + TLS_HANDSHAKE_HEADER_SIZE);
+
+	return true;
+}
+
+static void tls_send_change_cipher_spec(struct l_tls *tls)
+{
+	uint8_t buf = 1;
+
+	tls_tx_record(tls, TLS_CT_CHANGE_CIPHER_SPEC, &buf, 1);
+}
+
+size_t tls_verify_data_length(struct l_tls *tls, unsigned int index)
+{
+	/*
+	 * RFC 5246, Section 7.4.9:
+	 *
+	 * In previous versions of TLS, the verify_data was always 12 octets
+	 * long.  In the current version of TLS, it depends on the cipher
+	 * suite.  Any cipher suite which does not explicitly specify
+	 * verify_data_length has a verify_data_length equal to 12.
+	 */
+	return maxsize(tls->cipher_suite[index]->verify_data_length, 12);
+}
+
+static bool tls_save_verify_data(struct l_tls *tls, bool txrx,
+					const uint8_t *vd, size_t vdl)
+{
+	uint8_t *buf;
+
+	if (tls->server == txrx) {
+		if (vdl > sizeof(tls->renegotiation_info.server_verify_data))
+			goto error;
+
+		buf = tls->renegotiation_info.server_verify_data;
+	} else {
+		if (vdl > sizeof(tls->renegotiation_info.client_verify_data))
+			goto error;
+
+		buf = tls->renegotiation_info.client_verify_data;
+	}
+
+	memcpy(buf, vd, vdl);
+	return true;
+
+error:
+	TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+			"tls->renegotiation_info.*verify too small for %s, "
+			"report an ell bug", tls->cipher_suite[txrx]->name);
+	return false;
+}
+
+static bool tls_send_finished(struct l_tls *tls)
+{
+	uint8_t buf[512];
+	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
+	uint8_t seed[HANDSHAKE_HASH_MAX_SIZE * 2];
+	size_t vdl = tls_verify_data_length(tls, 1);
+	size_t seed_len;
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		/* Same hash type as that used for the PRF (usually SHA256) */
+		tls_get_handshake_hash(tls, tls->prf_hmac->type, seed);
+		seed_len = l_checksum_digest_length(tls->prf_hmac->l_id);
+	} else {
+		tls_get_handshake_hash(tls, HANDSHAKE_HASH_MD5, seed + 0);
+		tls_get_handshake_hash(tls, HANDSHAKE_HASH_SHA1, seed + 16);
+		seed_len = 36;
+	}
+
+	tls_prf_get_bytes(tls, tls->pending.master_secret, 48,
+				tls->server ? "server finished" :
+				"client finished",
+				seed, seed_len,
+				ptr, vdl);
+
+	if (!tls_save_verify_data(tls, 1, ptr, vdl))
+		return false;
+
+	ptr += vdl;
+
+	tls_tx_handshake(tls, TLS_FINISHED, buf, ptr - buf);
+	return true;
+}
+
+static bool tls_verify_finished(struct l_tls *tls, const uint8_t *received,
+				size_t len)
+{
+	size_t vdl = tls_verify_data_length(tls, 0);
+	uint8_t expected[vdl];
+	uint8_t *seed;
+	size_t seed_len;
+
+	if (len != vdl) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"TLS_FINISHED length not %zu", vdl);
+
+		return false;
+	}
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		enum handshake_hash_type hash = tls->prf_hmac->type;
+
+		seed = tls->prev_digest[hash];
+		seed_len = l_checksum_digest_length(tls->prf_hmac->l_id);
+	} else {
+		seed = alloca(36);
+		memcpy(seed + 0, tls->prev_digest[HANDSHAKE_HASH_MD5], 16);
+		memcpy(seed + 16, tls->prev_digest[HANDSHAKE_HASH_SHA1], 20);
+		seed_len = 36;
+	}
+
+	tls_prf_get_bytes(tls, tls->pending.master_secret, 48,
+				tls->server ? "client finished" :
+				"server finished",
+				seed, seed_len,
+				expected, vdl);
+
+	if (memcmp(received, expected, len)) {
+		TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
+				"TLS_FINISHED contents don't match");
+
+		return false;
+	}
+
+	if (!tls_save_verify_data(tls, 0, received, vdl))
+		return false;
+
+	return true;
+}
+
+static bool tls_ptr_match(const void *a, const void *b)
+{
+	return a == b;
+}
+
+static bool tls_handle_hello_extensions(struct l_tls *tls,
+					const uint8_t *buf, size_t len,
+					struct l_queue *seen)
+{
+	unsigned int i;
+	const struct tls_hello_extension *extension;
+	bool client_hello = tls->server;
+	uint16_t extensions_size;
+
+	if (!len)
+		return true;
+
+	if (len < 2 || len > 2 + 65535)
+		goto decode_error;
+
+	extensions_size = l_get_be16(buf);
+	len -= 2;
+	buf += 2;
+
+	if (len != extensions_size)
+		goto decode_error;
+
+	while (len) {
+		uint16_t ext_id;
+		size_t ext_len;
+		bool (*handler)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+
+		if (len < 4)
+			goto decode_error;
+
+		ext_id = l_get_be16(buf + 0);
+		ext_len = l_get_be16(buf + 2);
+		buf += 4;
+		len -= 4;
+
+		if (ext_len > len)
+			goto decode_error;
+
+		/*
+		 * RFC 5246, Section 7.4.1.4: "There MUST NOT be more than
+		 * one extension of the same type."
+		 */
+		if (l_queue_find(seen, tls_ptr_match, L_UINT_TO_PTR(ext_id))) {
+			TLS_DEBUG("Duplicate extension %u", ext_id);
+			goto decode_error;
+		}
+
+		l_queue_push_tail(seen, L_UINT_TO_PTR(ext_id));
+
+		extension = NULL;
+
+		for (i = 0; tls_extensions[i].name; i++)
+			if (tls_extensions[i].id == ext_id) {
+				extension = &tls_extensions[i];
+				break;
+			}
+
+		if (!extension)
+			goto next;
+
+		handler = client_hello ?
+			extension->client_handle : extension->server_handle;
+
+		/*
+		 * RFC 5246, Section 7.4.1.4: "If a client receives an
+		 * extension type in ServerHello that it did not request in
+		 * the associated ClientHello, it MUST abort the handshake
+		 * with an unsupported_extension fatal alert."
+		 * There are however servers that include an unsolicited
+		 * Supported Point Format extension where the handshake
+		 * still completes fine if the extension is ignored so we
+		 * do this instead.
+		 */
+		if (!client_hello && !handler) {
+			TLS_DEBUG("non-fatal: %s extension not expected in "
+					"a ServerHello", extension->name);
+			goto next;
+		}
+
+		if (!handler(tls, buf, ext_len)) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Hello %s extension parse error",
+					extension->name);
+			return false;
+		}
+
+next:
+		buf += ext_len;
+		len -= ext_len;
+	}
+
+	/*
+	 * Trigger any actions needed when an extension is missing and its
+	 * handler has not been called yet.
+	 */
+	for (i = 0; tls_extensions[i].name; i++) {
+		bool (*handler)(struct l_tls *tls);
+
+		extension = &tls_extensions[i];
+		handler = client_hello ?
+			extension->client_handle_absent :
+			extension->server_handle_absent;
+
+		if (!handler)
+			continue;
+
+		if (l_queue_find(seen, tls_ptr_match,
+					L_UINT_TO_PTR(extension->id)))
+			continue;
+
+		if (!handler(tls)) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Hello %s extension missing",
+					extension->name);
+			return false;
+		}
+	}
+
+	return true;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"Hello extensions decode error");
+	return false;
+}
+
+static void tls_server_resume_error(struct l_tls *tls)
+{
+	/*
+	 * When Client Hello parameters don't match the parameters of the
+	 * cached session that was requested by the client, we'll probably
+	 * start and cache a new session.  Even though RFC 5246 doesn't
+	 * specifically mandate that the requested session be forgotten
+	 * (there's no fatal Alert in that case), we overwrite the old
+	 * session's entry in the cache with the new session's data to
+	 * avoid keeping many sessions related to one client in the cache.
+	 * In theory this allows an attacker to connect as a client and
+	 * invalidate a legitimate client's session entry in our cache,
+	 * DoSing the session resumption mechanism so that clients have
+	 * to go through the full handshake.  In practice there are many
+	 * ways for an attacker to do that even without this.
+	 *
+	 * Our client mode only caches one last session anyway, other
+	 * implementations may work that way too.
+	 */
+	memcpy(tls->session_id_replaced, tls->session_id, tls->session_id_size);
+	tls->session_id_size_replaced = tls->session_id_size;
+
+	tls->session_id_size = 0;
+	tls->session_id_new = false;
+	l_free(l_steal_ptr(tls->session_peer_identity));
+}
+
+/* RFC 5746 */
+static const uint8_t tls_empty_renegotiation_info_scsv[2] = { 0x00, 0xff };
+static const uint16_t tls_renegotiation_info_id = 0xff01;
+
+static void tls_handle_client_hello(struct l_tls *tls,
+					const uint8_t *buf, size_t len)
+{
+	uint16_t cipher_suites_size;
+	uint8_t session_id_size, compression_methods_size;
+	const uint8_t *cipher_suites;
+	const uint8_t *compression_methods;
+	int i;
+	struct l_queue *extensions_offered = NULL;
+	enum l_tls_alert_desc alert_desc = TLS_ALERT_HANDSHAKE_FAIL;
+	bool resuming = false;
+	_auto_(l_free) char *session_id_str = NULL;
+	struct tls_cipher_suite *backup_suite = NULL;
+	struct tls_compression_method *backup_cm = NULL;
+
+	/* Do we have enough for ProtocolVersion + Random + SessionID size? */
+	if (len < 2 + 32 + 1)
+		goto decode_error;
+
+	memcpy(tls->pending.client_random, buf + 2, 32);
+	session_id_size = buf[34];
+	len -= 35;
+
+	if (unlikely(session_id_size > 32))
+		goto decode_error;
+
+	/*
+	 * Do we have enough to hold the actual session ID + 2 byte field for
+	 * cipher_suite len + minimum of a single cipher suite identifier
+	 */
+	if (len < (size_t) session_id_size + 4)
+		goto decode_error;
+
+	len -= session_id_size + 2;
+
+	cipher_suites_size = l_get_be16(buf + 35 + session_id_size);
+	cipher_suites = buf + 37 + session_id_size;
+
+	/*
+	 * Check that size is not odd, more than 0 and we have enough
+	 * data in the packet for cipher_suites_size + 2 bytes for
+	 * compression_methods_size + a single compression method
+	 */
+	if (len < (size_t) cipher_suites_size + 2 ||
+			(cipher_suites_size & 1) || cipher_suites_size == 0)
+		goto decode_error;
+
+	len -= cipher_suites_size + 1;
+
+	compression_methods_size = cipher_suites[cipher_suites_size];
+	compression_methods = cipher_suites + cipher_suites_size + 1;
+
+	if (len < (size_t) compression_methods_size ||
+			compression_methods_size == 0)
+		goto decode_error;
+
+	len -= compression_methods_size;
+
+	if (session_id_size && tls->session_settings &&
+			tls_load_cached_server_session(tls, buf + 35,
+							session_id_size)) {
+		/*
+		 * Attempt a session resumption but note later checks may
+		 * spoil this.
+		 */
+		resuming = true;
+		session_id_str = l_util_hexstring(tls->session_id,
+							tls->session_id_size);
+	}
+
+	if (tls->pending_destroy)
+		return;
+
+	extensions_offered = l_queue_new();
+
+	if (!tls_handle_hello_extensions(tls, compression_methods +
+					compression_methods_size,
+					len, extensions_offered))
+		goto cleanup;
+
+	/* Save client_version for Premaster Secret verification */
+	tls->client_version = l_get_be16(buf);
+
+	if (tls->client_version < tls->min_version) {
+		TLS_DISCONNECT(TLS_ALERT_PROTOCOL_VERSION, 0,
+				"Client version too low: %02x",
+				tls->client_version);
+		goto cleanup;
+	}
+
+	tls->negotiated_version = tls->client_version > tls->max_version ?
+		tls->max_version : tls->client_version;
+
+	/* Stop maintaining handshake message hashes other than MD1 and SHA. */
+	if (tls->negotiated_version < L_TLS_V12)
+		for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++)
+			if (i != HANDSHAKE_HASH_SHA1 && i != HANDSHAKE_HASH_MD5)
+				tls_drop_handshake_hash(tls, i);
+
+	TLS_DEBUG("Negotiated TLS " TLS_VER_FMT,
+			TLS_VER_ARGS(tls->negotiated_version));
+
+	if (!tls->cipher_suite_pref_list) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"No usable cipher suites");
+		goto cleanup;
+	}
+
+	if (!tls->renegotiation_info.secure_renegotiation || tls->ready) {
+		for (i = 0; i < cipher_suites_size; i += 2)
+			if (l_get_be16(cipher_suites + i) == l_get_be16(
+					tls_empty_renegotiation_info_scsv))
+				break;
+
+		if (i < cipher_suites_size) {
+			if (unlikely(tls->ready)) {
+				TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
+						"Empty renegotiation_info in "
+						"renegotiation Client Hello");
+				goto cleanup;
+			}
+
+			/*
+			 * RFC 5746 Section 3.6, act as if we had received an
+			 * empty renegotiation_info extension.
+			 */
+			tls->renegotiation_info.secure_renegotiation = true;
+			l_queue_push_tail(extensions_offered, L_UINT_TO_PTR(
+						tls_renegotiation_info_id));
+		}
+	}
+
+	/* Select a cipher suite according to client's preference list */
+	while (cipher_suites_size) {
+		struct tls_cipher_suite *suite =
+			tls_find_cipher_suite(cipher_suites);
+		struct tls_cipher_suite **iter;
+		const char *error;
+
+		for (iter = tls->cipher_suite_pref_list; *iter; iter++)
+			if (*iter == suite)
+				break;
+
+		if (!suite)
+			TLS_DEBUG("non-fatal: Cipher suite %04x unknown",
+					l_get_be16(cipher_suites));
+		else if (!tls_cipher_suite_is_compatible(tls, suite, &error))
+			TLS_DEBUG("non-fatal: %s", error);
+		else if (!*iter) {
+			/*
+			 * We have at least one matching compatible suite but
+			 * it is not allowed in this security profile.  If the
+			 * handshake ends up failing then we blame the security
+			 * profile.
+			 */
+			alert_desc = TLS_ALERT_INSUFFICIENT_SECURITY;
+			TLS_DEBUG("non-fatal: Cipher suite %s disallowed "
+					"by config", suite->name);
+		} else if (resuming && memcmp(tls->session_cipher_suite_id,
+						suite->id, 2)) {
+			/*
+			 * For now skip this cipher suite because we're trying
+			 * to find the one from the cached session state.  But
+			 * keep it as a backup in case we end up starting a new
+			 * session.
+			 */
+			if (!backup_suite)
+				backup_suite = suite;
+		} else {
+			tls->pending.cipher_suite = suite;
+			break;
+		}
+
+		cipher_suites += 2;
+		cipher_suites_size -= 2;
+	}
+
+	if (unlikely(!cipher_suites_size && backup_suite)) {
+		TLS_DEBUG("Cached session %s's cipher suite %04x "
+				"unavailable, will start a new session",
+				session_id_str,
+				l_get_be16(tls->session_cipher_suite_id));
+		tls->pending.cipher_suite = backup_suite;
+		resuming = false;
+		tls_server_resume_error(tls);
+	} else if (unlikely(!cipher_suites_size)) {
+		TLS_DISCONNECT(alert_desc, 0,
+				"No common cipher suites matching negotiated "
+				"TLS version and our certificate's key type");
+		goto cleanup;
+	}
+
+	if (!tls_set_prf_hmac(tls)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Error selecting the PRF HMAC");
+		goto cleanup;
+	}
+
+	/* Select a compression method */
+
+	/* CompressionMethod.null must be present in the vector */
+	while (compression_methods_size) {
+		struct tls_compression_method *cm =
+			tls_find_compression_method(*compression_methods);
+
+		if (!cm)
+			TLS_DEBUG("non-fatal: Compression %02x unknown",
+					*compression_methods);
+		else if (resuming && *compression_methods !=
+				tls->session_compression_method_id) {
+			/*
+			 * For now skip this compression method because we're
+			 * trying to find the one from the cached session state.
+			 * But keep it as a backup in case we end up starting
+			 * a new * session.
+			 */
+			if (!backup_cm)
+				backup_cm = cm;
+		} else {
+			tls->pending.compression_method = cm;
+			break;
+		}
+
+		compression_methods++;
+		compression_methods_size--;
+	}
+
+	if (unlikely(!compression_methods_size && backup_cm)) {
+		TLS_DEBUG("Cached session %s's compression method %02x "
+				"unavailable, will start a new session",
+				session_id_str,
+				tls->session_compression_method_id);
+		tls->pending.compression_method = backup_cm;
+
+		if (backup_suite)
+			tls->pending.cipher_suite = backup_suite;
+
+		resuming = false;
+		tls_server_resume_error(tls);
+	} else if (unlikely(!compression_methods_size)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"No common compression methods");
+		goto cleanup;
+	}
+
+	if (resuming)
+		TLS_DEBUG("Negotiated resumption of cached session %s",
+				session_id_str);
+
+	TLS_DEBUG("Negotiated %s", tls->pending.cipher_suite->name);
+	TLS_DEBUG("Negotiated %s", tls->pending.compression_method->name);
+
+	if (!resuming && tls->session_settings) {
+		tls->session_id_new = true;
+		tls->session_id_size = 32;
+		l_getrandom(tls->session_id, 32);
+	}
+
+	if (!tls_send_server_hello(tls, extensions_offered))
+		goto cleanup;
+
+	l_queue_destroy(extensions_offered, NULL);
+
+	if (resuming) {
+		const char *error;
+
+		tls_update_key_block(tls);
+		tls_send_change_cipher_spec(tls);
+
+		if (!tls_change_cipher_spec(tls, 1, &error)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"change_cipher_spec: %s", error);
+			return;
+		}
+
+		if (!tls_send_finished(tls))
+			return;
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC);
+		return;
+	}
+
+	if (tls->pending.cipher_suite->signature && tls->cert)
+		if (!tls_send_certificate(tls))
+			return;
+
+	if (tls->pending.cipher_suite->key_xchg->send_server_key_exchange)
+		if (!tls->pending.cipher_suite->key_xchg->
+				send_server_key_exchange(tls))
+			return;
+
+	/* TODO: don't bother if configured to not authenticate client */
+	if (tls->pending.cipher_suite->signature && tls->ca_certs)
+		if (!tls_send_certificate_request(tls))
+			return;
+
+	tls_send_server_hello_done(tls);
+
+	if (tls->pending.cipher_suite->signature && tls->ca_certs)
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CERTIFICATE);
+	else
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE);
+
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ClientHello decode error");
+
+cleanup:
+	l_queue_destroy(extensions_offered, NULL);
+}
+
+static void tls_handle_server_hello(struct l_tls *tls,
+					const uint8_t *buf, size_t len)
+{
+	uint8_t session_id_size, cipher_suite_id[2], compression_method_id;
+	const char *error;
+	struct tls_cipher_suite **iter;
+	int i;
+	struct l_queue *extensions_seen;
+	bool result;
+	uint16_t version;
+	bool resuming = false;
+
+	/* Do we have enough for ProtocolVersion + Random + SessionID len ? */
+	if (len < 2 + 32 + 1)
+		goto decode_error;
+
+	version = l_get_be16(buf);
+	memcpy(tls->pending.server_random, buf + 2, 32);
+	session_id_size = buf[34];
+	len -= 35;
+
+	/* Do we have enough for SessionID + CipherSuite ID + Compression ID */
+	if (len < (size_t) session_id_size + 2 + 1)
+		goto decode_error;
+
+	cipher_suite_id[0] = buf[35 + session_id_size + 0];
+	cipher_suite_id[1] = buf[35 + session_id_size + 1];
+	compression_method_id = buf[35 + session_id_size + 2];
+	len -= session_id_size + 2 + 1;
+
+	if (session_id_size > 32)
+		goto decode_error;
+
+	if (tls->session_id_size) {
+		_auto_(l_free) char *session_id_str =
+			l_util_hexstring(tls->session_id, tls->session_id_size);
+
+		if (session_id_size == tls->session_id_size &&
+				!memcmp(buf + 35, tls->session_id,
+					session_id_size)) {
+			TLS_DEBUG("Negotiated resumption of cached session %s",
+					session_id_str);
+			resuming = true;
+		} else {
+			TLS_DEBUG("Server decided not to resume cached session "
+					"%s, sent %s session ID",
+					session_id_str,
+					session_id_size ? "a new" : "no");
+			tls->session_id_size = 0;
+		}
+	}
+
+	if (session_id_size && !resuming && tls->session_settings) {
+		tls->session_id_new = true;
+		tls->session_id_size = session_id_size;
+		memcpy(tls->session_id, buf + 35, session_id_size);
+	}
+
+	extensions_seen = l_queue_new();
+	result = tls_handle_hello_extensions(tls, buf + 38 + session_id_size,
+						len, extensions_seen);
+	l_queue_destroy(extensions_seen, NULL);
+
+	if (!result)
+		return;
+
+	if (version < tls->min_version || version > tls->max_version) {
+		TLS_DISCONNECT(version < tls->min_version ?
+				TLS_ALERT_PROTOCOL_VERSION :
+				TLS_ALERT_ILLEGAL_PARAM, 0,
+				"Unsupported version %02x", version);
+		return;
+	}
+
+	tls->negotiated_version = version;
+
+	/* Stop maintaining handshake message hashes other than MD1 and SHA. */
+	if (tls->negotiated_version < L_TLS_V12)
+		for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++)
+			if (i != HANDSHAKE_HASH_SHA1 && i != HANDSHAKE_HASH_MD5)
+				tls_drop_handshake_hash(tls, i);
+
+	TLS_DEBUG("Negotiated TLS " TLS_VER_FMT,
+			TLS_VER_ARGS(tls->negotiated_version));
+
+	/* Set the new cipher suite and compression method structs */
+	tls->pending.cipher_suite = tls_find_cipher_suite(cipher_suite_id);
+	if (!tls->pending.cipher_suite) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Unknown cipher suite %04x",
+				l_get_be16(cipher_suite_id));
+		return;
+	}
+
+	for (iter = tls->cipher_suite_pref_list; *iter; iter++)
+		if (*iter == tls->pending.cipher_suite)
+			break;
+	if (!*iter) {
+		TLS_DISCONNECT(TLS_ALERT_INSUFFICIENT_SECURITY, 0,
+				"Selected cipher suite %s disallowed by config",
+				tls->pending.cipher_suite->name);
+		return;
+	}
+
+	if (!tls_cipher_suite_is_compatible(tls, tls->pending.cipher_suite,
+						&error)) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Selected cipher suite not compatible: %s",
+				error);
+		return;
+	}
+
+	if (!tls_set_prf_hmac(tls)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Error selecting the PRF HMAC");
+		return;
+	}
+
+	TLS_DEBUG("Negotiated %s", tls->pending.cipher_suite->name);
+
+	tls->pending.compression_method =
+		tls_find_compression_method(compression_method_id);
+	if (!tls->pending.compression_method) {
+		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+				"Unknown compression method %i",
+				compression_method_id);
+		return;
+	}
+
+	TLS_DEBUG("Negotiated %s", tls->pending.compression_method->name);
+
+	if (resuming) {
+		/*
+		 * Now that we've validated the Server Hello parameters and
+		 * know that they're supported by this version of ell and
+		 * consistent with the current configuration, ensure that
+		 * they're identical with the ones in the cached session
+		 * being resumed.  This serves as a sanity check for
+		 * rare situations like a corrupt session cache file or
+		 * a file written by a newer ell version.
+		 */
+		if (tls->negotiated_version != tls->client_version ||
+				memcmp(cipher_suite_id,
+					tls->session_cipher_suite_id, 2) ||
+				compression_method_id !=
+				tls->session_compression_method_id) {
+			TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+					"Session parameters don't match");
+			return;
+		}
+
+		tls_update_key_block(tls);
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC);
+	} else if (tls->pending.cipher_suite->signature)
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CERTIFICATE);
+	else
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE);
+
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"ServerHello decode error");
+}
+
+static void tls_handle_certificate(struct l_tls *tls,
+					const uint8_t *buf, size_t len)
+{
+	size_t total;
+	_auto_(l_certchain_free) struct l_certchain *certchain = NULL;
+	struct l_cert *leaf;
+	size_t der_len;
+	const uint8_t *der;
+	bool dummy;
+	const char *error_str;
+	char *subject_str;
+
+	if (len < 3)
+		goto decode_error;
+
+	/* Length checks */
+	total = *buf++ << 16;
+	total |= *buf++ << 8;
+	total |= *buf++ << 0;
+	if (total + 3 != len)
+		goto decode_error;
+
+	if (tls_parse_certificate_list(buf, total, &certchain) < 0) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"Error decoding peer certificate chain");
+
+		return;
+	}
+
+	/*
+	 * "Note that a client MAY send no certificates if it does not have any
+	 * appropriate certificate to send in response to the server's
+	 * authentication request." -- for now we unconditionally accept
+	 * an empty certificate chain from the client.  Later on we need to
+	 * make this configurable, if we don't want to authenticate the
+	 * client then also don't bother sending a Certificate Request.
+	 */
+	if (!certchain) {
+		if (!tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
+					"Server sent no certificate chain");
+
+			return;
+		}
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE);
+
+		return;
+	}
+
+	if (tls->cert_dump_path) {
+		int r = pem_write_certificate_chain(certchain,
+							tls->cert_dump_path);
+
+		if (r < 0)
+			TLS_DEBUG("Error %i (%s) writing the peer certchain "
+					"to %s",
+					-r, strerror(-r), tls->cert_dump_path);
+		else
+			TLS_DEBUG("Peer certchain written to %s",
+					tls->cert_dump_path);
+	}
+
+	/*
+	 * Validate the certificate chain's consistency and validate it
+	 * against our CAs if we have any.
+	 */
+	if (!l_certchain_verify(certchain, tls->ca_certs, &error_str)) {
+		if (tls->ca_certs) {
+			TLS_DISCONNECT(TLS_ALERT_BAD_CERT, 0,
+					"Peer certchain verification failed "
+					"consistency check%s: %s",
+					tls->ca_certs ?
+					" or against local CA certs" : "",
+					error_str);
+
+			return;
+		}
+
+		/*
+		 * Until the mainstream kernel can handle the occasionally
+		 * used certificates without the AKID extension (both root,
+		 * which is legal, and non-root, which is iffy but still
+		 * happens) don't fail on peer certificate chain verification
+		 * failure when CA certificates were not provided.  Knowing
+		 * that the chain is self-consistent alone doesn't
+		 * authenticate the peer in any way.  Only warn when it looks
+		 * like the chain is bad but parses and we can get the peer
+		 * public key from it below.
+		 */
+		TLS_DEBUG("Peer certchain verification failed (%s.)  No local "
+				"CA certs provided so proceeding anyway.  This "
+				"failure can signal a security issue or a "
+				"known kernel problem with some certificates.",
+				error_str);
+	}
+
+	/*
+	 * RFC5246 7.4.2:
+	 * "The end entity certificate's public key (and associated
+	 * restrictions) MUST be compatible with the selected key exchange
+	 * algorithm."
+	 */
+	leaf = l_certchain_get_leaf(certchain);
+	if (!tls->pending.cipher_suite->signature->
+			validate_cert_key_type(leaf)) {
+		TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_CERT, 0,
+				"Peer certificate key type incompatible with "
+				"pending cipher suite %s",
+				tls->pending.cipher_suite->name);
+
+		return;
+	}
+
+	if (tls->subject_mask && !tls_cert_domains_match_mask(leaf,
+							tls->subject_mask,
+							&subject_str)) {
+		char *mask = l_strjoinv(tls->subject_mask, '|');
+
+		TLS_DISCONNECT(TLS_ALERT_BAD_CERT, 0,
+				"Peer certificate's subject domain "
+				"doesn't match mask %s: %s", mask, subject_str);
+		l_free(mask);
+		l_free(subject_str);
+
+		return;
+	}
+
+	/* Save the end-entity certificate and free the chain */
+	der = l_cert_get_der_data(leaf, &der_len);
+	tls->peer_cert = l_cert_new_from_der(der, der_len);
+
+	tls->peer_pubkey = l_cert_get_pubkey(tls->peer_cert);
+	if (!tls->peer_pubkey) {
+		TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_CERT, 0,
+				"Error loading peer public key to kernel");
+
+		return;
+	}
+
+	switch (l_cert_get_pubkey_type(tls->peer_cert)) {
+	case L_CERT_KEY_RSA:
+		if (!l_key_get_info(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5,
+				L_CHECKSUM_NONE,
+				&tls->peer_pubkey_size, &dummy))
+			goto pubkey_unsupported;
+		break;
+	case L_CERT_KEY_ECC:
+		if (!l_key_get_info(tls->peer_pubkey, L_KEY_ECDSA_X962,
+				L_CHECKSUM_SHA1,
+				&tls->peer_pubkey_size, &dummy))
+			goto pubkey_unsupported;
+		break;
+	case L_CERT_KEY_UNKNOWN:
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Unknown public key type");
+		return;
+	}
+
+	tls->peer_pubkey_size /= 8;
+
+	if (tls->server || tls->pending.cipher_suite->key_xchg->
+			handle_server_key_exchange)
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE);
+	else
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
+
+	return;
+
+pubkey_unsupported:
+	TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"Can't l_key_get_info for peer public key");
+	return;
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"TLS_CERTIFICATE decode error");
+}
+
+static void tls_handle_certificate_request(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	unsigned int cert_type_len, dn_len, i;
+
+	tls->cert_requested = 1;
+
+	cert_type_len = *buf++;
+	if (len < 1 + cert_type_len + 2)
+		goto decode_error;
+
+	for (i = 0; i < sizeof(tls_cert_type_pref); i++)
+		if (memchr(buf, tls_cert_type_pref[i], cert_type_len))
+			break;
+
+	if (i == sizeof(tls_cert_type_pref)) {
+		TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_CERT, 0,
+				"Requested certificate types not supported");
+		return;
+	}
+
+	buf += cert_type_len;
+	len -= 1 + cert_type_len;
+
+	/*
+	 * TODO: parse and save certificate_types,
+	 * supported_signature_algorithms and certificate_authorities
+	 * lists for use in tls_send_certificate.
+	 */
+
+	if (tls->negotiated_version >= L_TLS_V12) {
+		enum handshake_hash_type hash;
+		ssize_t ret = tls_parse_signature_algorithms(tls, buf, len);
+
+		if (ret == -ENOTSUP) {
+			TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_CERT, 0,
+					"No supported signature hash type");
+			return;
+		}
+
+		if (ret < 0)
+			goto decode_error;
+
+		len -= ret;
+		buf += ret;
+
+		/*
+		 * We can now safely stop maintaining handshake message
+		 * hashes other than the PRF hash and the one selected for
+		 * signing.
+		 */
+		for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+			if (&tls_handshake_hash_data[hash] != tls->prf_hmac &&
+					hash != tls->signature_hash)
+				tls_drop_handshake_hash(tls, hash);
+	}
+
+	dn_len = l_get_be16(buf);
+	if (2 + dn_len != len)
+		goto decode_error;
+
+	return;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"CertificateRequest decode error");
+}
+
+static void tls_handle_server_hello_done(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	const char *error;
+
+	if (len) {
+		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+				"ServerHello not empty");
+		return;
+	}
+
+	if (tls->cert_requested)
+		if (!tls_send_certificate(tls))
+			return;
+
+	if (!tls->pending.cipher_suite->key_xchg->send_client_key_exchange(tls))
+		return;
+
+	if (tls->cert_sent)
+		if (!tls_send_certificate_verify(tls))
+			return;
+
+	tls_send_change_cipher_spec(tls);
+
+	if (!tls_change_cipher_spec(tls, 1, &error)) {
+		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+				"change_cipher_spec: %s", error);
+		return;
+	}
+
+	if (!tls_send_finished(tls))
+		return;
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC);
+}
+
+static bool tls_get_prev_digest_by_type(struct l_tls *tls,
+					enum handshake_hash_type type,
+					const uint8_t *data, size_t data_len,
+					uint8_t *out, size_t *out_len)
+{
+	size_t len;
+
+	if (!tls->handshake_hash[type])
+		return false;
+
+	len = l_checksum_digest_length(tls_handshake_hash_data[type].l_id);
+	memcpy(out, tls->prev_digest[type], len);
+
+	if (out_len)
+		*out_len = len;
+
+	return 0;
+}
+
+static void tls_handle_certificate_verify(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	int i;
+
+	if (!tls->pending.cipher_suite->signature->verify(tls, buf, len,
+						tls_get_prev_digest_by_type,
+						NULL, 0))
+		return;
+
+	/* Stop maintaining handshake message hashes other than the PRF hash */
+	if (tls->negotiated_version >= L_TLS_V12)
+		for (i = 0; i < __HANDSHAKE_HASH_COUNT; i++)
+			if (&tls_handshake_hash_data[i] != tls->prf_hmac)
+				tls_drop_handshake_hash(tls, i);
+
+	/*
+	 * The client's certificate is now verified based on the following
+	 * logic:
+	 *   - If we received an (expected) Certificate Verify, we must have
+	 *     sent a Certificate Request.
+	 *   - If we sent a Certificate Request that's because
+	 *     tls->ca_certs is non-NULL.
+	 *   - If tls->ca_certs is non-NULL then tls_handle_certificate
+	 *     will have checked the whole certificate chain to be valid and
+	 *     additionally trusted by our CAs if known.
+	 *   - Additionally cipher_suite->signature->verify has just confirmed
+	 *     that the peer owns the end-entity certificate because it was
+	 *     able to sign the contents of the handshake messages and that
+	 *     signature could be verified with the public key from that
+	 *     certificate.
+	 */
+	tls->peer_authenticated = true;
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC);
+}
+
+struct dn_element_info {
+	const char *str;
+	const struct asn1_oid oid;
+};
+
+static const struct dn_element_info dn_elements[] = {
+	{ "CN", { 3, { 0x55, 0x04, 0x03 } } },
+	{ "SN", { 3, { 0x55, 0x04, 0x04 } } },
+	{ "serialNumber", { 3, { 0x55, 0x04, 0x05 } } },
+	{ "C", { 3, { 0x55, 0x04, 0x06 } } },
+	{ "ST", { 3, { 0x55, 0x04, 0x07 } } },
+	{ "L", { 3, { 0x55, 0x04, 0x08 } } },
+	{ "street", { 3, { 0x55, 0x04, 0x09 } } },
+	{ "O", { 3, { 0x55, 0x04, 0x0a } } },
+	{ "OU", { 3, { 0x55, 0x04, 0x0b } } },
+	{ "title", { 3, { 0x55, 0x04, 0x0c } } },
+	{ "telephoneNumber", { 3, { 0x55, 0x04, 0x14 } } },
+	{ "givenName", { 3, { 0x55, 0x04, 0x2a } } },
+	{ "initials", { 3, { 0x55, 0x04, 0x2b } } },
+	{ "emailAddress", {
+		9,
+		{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 }
+	} },
+	{ "domainComponent", {
+		10,
+		{ 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19 }
+	} },
+	{}
+};
+
+static void tls_str_escape_append(struct l_string *out, char *str, size_t len)
+{
+	while (len--) {
+		switch (*str) {
+		case '\\':
+		case '/':
+		case '=':
+			l_string_append_c(out, '\\');
+			l_string_append_c(out, *str);
+			break;
+		default:
+			l_string_append_c(out, *str);
+			break;
+		}
+
+		str++;
+	}
+}
+
+static char *tls_get_peer_identity_str(struct l_cert *cert)
+{
+	const uint8_t *dn, *end;
+	size_t dn_size;
+	struct l_string *id_str;
+
+	if (!cert)
+		return NULL;
+
+	dn = l_cert_get_dn(cert, &dn_size);
+	if (!dn)
+		return NULL;
+
+	id_str = l_string_new(200);
+
+	end = dn + dn_size;
+	while (dn < end) {
+		const uint8_t *set, *seq, *oid, *name;
+		uint8_t tag;
+		size_t len, oid_len, name_len;
+		const struct dn_element_info *info;
+
+		set = asn1_der_find_elem(dn, end - dn, 0, &tag, &len);
+		if (!set || tag != ASN1_ID_SET)
+			goto error;
+
+		dn = set + len;
+
+		seq = asn1_der_find_elem(set, len, 0, &tag, &len);
+		if (!seq || tag != ASN1_ID_SEQUENCE)
+			goto error;
+
+		oid = asn1_der_find_elem(seq, len, 0, &tag, &oid_len);
+		if (!oid || tag != ASN1_ID_OID)
+			goto error;
+
+		name = asn1_der_find_elem(seq, len, 1, &tag, &name_len);
+		if (!name || (tag != ASN1_ID_PRINTABLESTRING &&
+					tag != ASN1_ID_UTF8STRING &&
+					tag != ASN1_ID_IA5STRING))
+			continue;
+
+		for (info = dn_elements; info->str; info++)
+			if (asn1_oid_eq(&info->oid, oid_len, oid))
+				break;
+		if (!info->str)
+			continue;
+
+		l_string_append_c(id_str, '/');
+		l_string_append(id_str, info->str);
+		l_string_append_c(id_str, '=');
+		tls_str_escape_append(id_str, (char *) name, name_len);
+	}
+
+	return l_string_unwrap(id_str);
+
+error:
+	l_string_free(id_str);
+	return NULL;
+}
+
+static void tls_finished(struct l_tls *tls)
+{
+	_auto_(l_free) char *peer_cert_identity = NULL;
+	char *peer_identity = NULL;
+	uint64_t peer_cert_expiry;
+	bool resuming = tls->session_id_size && !tls->session_id_new;
+	bool session_update = false;
+	bool renegotiation = tls->ready;
+
+	if (tls->peer_authenticated && !resuming) {
+		peer_cert_identity = tls_get_peer_identity_str(tls->peer_cert);
+		if (!peer_cert_identity) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"tls_get_peer_identity_str failed");
+			return;
+		}
+
+		peer_identity = peer_cert_identity;
+
+		if (tls->session_id_new &&
+				!l_cert_get_valid_times(tls->peer_cert, NULL,
+							&peer_cert_expiry)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"l_cert_get_valid_times failed");
+			return;
+		}
+	} else if (tls->peer_authenticated && resuming)
+		peer_identity = tls->session_peer_identity;
+
+	if (tls->session_settings && tls->session_id_new) {
+		_auto_(l_free) char *session_id_str =
+			l_util_hexstring(tls->session_id, tls->session_id_size);
+		uint64_t expiry = tls->session_lifetime ?
+			time_realtime_now() + tls->session_lifetime : 0;
+		const char *group_name =
+			tls_get_cache_group_name(tls, tls->session_id,
+							tls->session_id_size);
+
+		if (tls->peer_authenticated &&
+				(!expiry || peer_cert_expiry < expiry))
+			expiry = peer_cert_expiry;
+
+		if (!tls->server)
+			l_settings_set_bytes(tls->session_settings, group_name,
+						"SessionID", tls->session_id,
+						tls->session_id_size);
+
+		l_settings_set_bytes(tls->session_settings, group_name,
+					"SessionMasterSecret",
+					tls->pending.master_secret, 48);
+		l_settings_set_int(tls->session_settings, group_name,
+					"SessionVersion",
+					tls->negotiated_version);
+		l_settings_set_bytes(tls->session_settings, group_name,
+					"SessionCipherSuite",
+					tls->pending.cipher_suite->id, 2);
+		l_settings_set_uint(tls->session_settings, group_name,
+					"SessionCompressionMethod",
+					tls->pending.compression_method->id);
+
+		if (expiry)
+			l_settings_set_uint64(tls->session_settings,
+						group_name,
+						"SessionExpiryTime", expiry);
+		else
+			/* We may be overwriting an older session's data */
+			l_settings_remove_key(tls->session_settings,
+						group_name,
+						"SessionExpiryTime");
+
+		if (tls->peer_authenticated)
+			l_settings_set_string(tls->session_settings,
+						group_name,
+						"SessionPeerIdentity",
+						peer_identity);
+		else
+			/* We may be overwriting an older session's data */
+			l_settings_remove_key(tls->session_settings,
+						group_name,
+						"SessionPeerIdentity");
+
+		TLS_DEBUG("Saving new session %s to cache", session_id_str);
+		session_update = true;
+
+		if (tls->session_id_size_replaced) {
+			tls_forget_cached_session(tls, NULL,
+						tls->session_id_replaced,
+						tls->session_id_size_replaced,
+						false);
+			tls->session_id_size_replaced = 0;
+		}
+	}
+
+	/* Free up the resources used in the handshake */
+	tls_reset_handshake(tls);
+
+	TLS_SET_STATE(TLS_HANDSHAKE_DONE);
+	tls->ready = true;
+	tls->session_resumed = resuming;
+
+	if (session_update && tls->session_update_cb) {
+		tls->in_callback = true;
+		tls->session_update_cb(tls->session_update_user_data);
+		tls->in_callback = false;
+
+		if (tls->pending_destroy)
+			return;
+	}
+
+	if (!renegotiation) {
+		tls->in_callback = true;
+		tls->ready_handle(peer_identity, tls->user_data);
+		tls->in_callback = false;
+	}
+
+	tls_cleanup_handshake(tls);
+}
+
+static void tls_handle_handshake(struct l_tls *tls, int type,
+					const uint8_t *buf, size_t len)
+{
+	bool resuming;
+
+	TLS_DEBUG("Handling a %s of %zi bytes",
+			tls_handshake_type_to_str(type), len);
+
+	switch (type) {
+	case TLS_HELLO_REQUEST:
+		if (tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in server mode");
+			break;
+		}
+
+		if (len != 0) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"HelloRequest not empty");
+			break;
+		}
+
+		/*
+		 * May be sent by the server at any time but "SHOULD be ignored
+		 * by the client if it arrives in the middle of a handshake"
+		 * and "MAY be ignored by the client if it does not wish to
+		 * renegotiate a session".
+		 */
+		if (tls->state != TLS_HANDSHAKE_DONE) {
+			TLS_DEBUG("Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		if (!tls_send_client_hello(tls))
+			break;
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+		break;
+
+	case TLS_CLIENT_HELLO:
+		if (!tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in client mode");
+			break;
+		}
+
+		if (tls->state != TLS_HANDSHAKE_WAIT_HELLO &&
+				tls->state != TLS_HANDSHAKE_DONE) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		tls_handle_client_hello(tls, buf, len);
+
+		break;
+
+	case TLS_SERVER_HELLO:
+		if (tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in server mode");
+			break;
+		}
+
+		if (tls->state != TLS_HANDSHAKE_WAIT_HELLO) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		tls_handle_server_hello(tls, buf, len);
+
+		break;
+
+	case TLS_CERTIFICATE:
+		if (tls->state != TLS_HANDSHAKE_WAIT_CERTIFICATE) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		tls_handle_certificate(tls, buf, len);
+
+		break;
+
+	case TLS_SERVER_KEY_EXCHANGE:
+		if (tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in server mode");
+			break;
+		}
+
+		if (tls->state != TLS_HANDSHAKE_WAIT_KEY_EXCHANGE) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
+
+		tls->pending.cipher_suite->key_xchg->handle_server_key_exchange(
+								tls, buf, len);
+
+		break;
+
+	case TLS_CERTIFICATE_REQUEST:
+		if (tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in server mode");
+			break;
+		}
+
+		/*
+		 * Server sends this optionally so in the WAIT_HELLO_DONE
+		 * state we accept either this or a Server Hello Done (below).
+		 */
+		if (tls->state != TLS_HANDSHAKE_WAIT_HELLO_DONE ||
+				tls->cert_requested ||
+				!tls->pending.cipher_suite->signature) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in current state "
+					"or certificate check not supported "
+					"in pending cipher suite");
+			break;
+		}
+
+		tls_handle_certificate_request(tls, buf, len);
+
+		break;
+
+	case TLS_SERVER_HELLO_DONE:
+		if (tls->state != TLS_HANDSHAKE_WAIT_HELLO_DONE) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		tls_handle_server_hello_done(tls, buf, len);
+
+		break;
+
+	case TLS_CERTIFICATE_VERIFY:
+		if (tls->state != TLS_HANDSHAKE_WAIT_CERTIFICATE_VERIFY) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		tls_handle_certificate_verify(tls, buf, len);
+
+		break;
+
+	case TLS_CLIENT_KEY_EXCHANGE:
+		if (!tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in client mode");
+			break;
+		}
+
+		if (tls->state != TLS_HANDSHAKE_WAIT_KEY_EXCHANGE) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		/*
+		 * If we accepted a client Certificate message with a
+		 * certificate that has signing capability (TODO: check
+		 * usage bitmask), Certificate Verify is received next.  It
+		 * sounds as if this is mandatory for the client although
+		 * this isn't 100% clear.
+		 */
+		if (tls->peer_pubkey)
+			TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CERTIFICATE_VERIFY);
+		else
+			TLS_SET_STATE(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC);
+
+		tls->pending.cipher_suite->key_xchg->handle_client_key_exchange(
+								tls, buf, len);
+
+		break;
+
+	case TLS_FINISHED:
+		if (tls->state != TLS_HANDSHAKE_WAIT_FINISHED) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+			break;
+		}
+
+		if (!tls_verify_finished(tls, buf, len))
+			break;
+
+		resuming = tls->session_id_size && !tls->session_id_new;
+
+		if ((tls->server && !resuming) || (!tls->server && resuming)) {
+			const char *error;
+
+			tls_send_change_cipher_spec(tls);
+			if (!tls_change_cipher_spec(tls, 1, &error)) {
+				TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+						"change_cipher_spec: %s",
+						error);
+				break;
+			}
+
+			if (!tls_send_finished(tls))
+				break;
+		}
+
+		/*
+		 * When starting a new session on the client, the server's
+		 * certificate is now verified regardless of the key exchange
+		 * method, based on the following logic:
+		 *
+		 *  - tls->ca_certs is non-NULL so tls_handle_certificate
+		 *    (always called on the client) must have veritifed the
+		 *    server's certificate chain to be valid and additionally
+		 *    trusted by our CA.
+		 *
+		 *  - the peer owns the end-entity certificate because:
+		 *    either:
+		 *
+		 *    * (RSA key exchange algorithm case) the correct
+		 *      receival of this Finished message confirms the
+		 *      possession of the master secret, it is verified by
+		 *      both the successful decryption and the MAC of this
+		 *      message (either should be enough) because we entered
+		 *      the TLS_HANDSHAKE_WAIT_FINISHED state only after
+		 *      encryption and MAC were enabled in ChangeCipherSpec.
+		 *      To obtain the master secret the server must have been
+		 *      able to decrypt the pre_master_secret which we had
+		 *      encrypted with the public key from that certificate.
+		 *
+		 *    * (ECDHE and DHE key exchange algorithms) server was
+		 *      able to sign the client random together with the
+		 *      ServerKeyExchange parameters using its certified key
+		 *      pair.
+		 *
+		 * If we're resuming a cached session, we have authenticated
+		 * this peer before and the successful decryption of this
+		 * message confirms their identity hasn't changed.
+		 */
+		if (tls->cipher_suite[0]->signature &&
+				((!tls->server && !resuming && tls->ca_certs) ||
+				 (resuming && tls->session_peer_identity)))
+			tls->peer_authenticated = true;
+
+		tls_finished(tls);
+
+		break;
+
+	default:
+		TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+				"Invalid message");
+	}
+}
+
+LIB_EXPORT struct l_tls *l_tls_new(bool server,
+				l_tls_write_cb_t app_data_handler,
+				l_tls_write_cb_t tx_handler,
+				l_tls_ready_cb_t ready_handler,
+				l_tls_disconnect_cb_t disconnect_handler,
+				void *user_data)
+{
+	struct l_tls *tls;
+
+	if (!l_key_is_supported(L_KEY_FEATURE_CRYPTO))
+		return NULL;
+
+	tls = l_new(struct l_tls, 1);
+	tls->server = server;
+	tls->rx = app_data_handler;
+	tls->tx = tx_handler;
+	tls->ready_handle = ready_handler;
+	tls->disconnected = disconnect_handler;
+	tls->user_data = user_data;
+	tls->cipher_suite_pref_list = tls_cipher_suite_pref;
+	tls->min_version = TLS_MIN_VERSION;
+	tls->max_version = TLS_MAX_VERSION;
+	tls->session_lifetime = 24 * 3600 * L_USEC_PER_SEC;
+
+	/* If we're the server wait for the Client Hello already */
+	if (tls->server)
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+	else
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
+
+	return tls;
+}
+
+LIB_EXPORT void l_tls_free(struct l_tls *tls)
+{
+	enum handshake_hash_type hash;
+
+	if (unlikely(!tls))
+		return;
+
+	if (tls->in_callback) {
+		tls->pending_destroy = true;
+		return;
+	}
+
+	l_tls_set_cacert(tls, NULL);
+	l_tls_set_auth_data(tls, NULL, NULL);
+	l_tls_set_domain_mask(tls, NULL);
+	l_tls_set_cert_dump_path(tls, NULL);
+	l_tls_set_session_cache(tls, NULL, NULL, 0, 0, NULL, NULL);
+
+	tls_reset_handshake(tls);
+	tls_cleanup_handshake(tls);
+
+	tls_reset_cipher_spec(tls, 0);
+	tls_reset_cipher_spec(tls, 1);
+
+	if (tls->record_buf)
+		l_free(tls->record_buf);
+
+	if (tls->message_buf)
+		l_free(tls->message_buf);
+
+	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
+		tls_drop_handshake_hash(tls, hash);
+
+	if (tls->debug_destroy)
+		tls->debug_destroy(tls->debug_data);
+
+	if (tls->cipher_suite_pref_list != tls_cipher_suite_pref)
+		l_free(tls->cipher_suite_pref_list);
+
+	l_free(tls);
+}
+
+LIB_EXPORT void l_tls_write(struct l_tls *tls, const uint8_t *data, size_t len)
+{
+	if (unlikely(!tls->ready)) {
+		return;
+	}
+
+	tls_tx_record(tls, TLS_CT_APPLICATION_DATA, data, len);
+}
+
+bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
+			int len, enum tls_content_type type, uint16_t version)
+{
+	enum handshake_hash_type hash;
+	const char *error;
+
+	switch (type) {
+	case TLS_CT_CHANGE_CIPHER_SPEC:
+		if (len != 1 || message[0] != 0x01) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"ChangeCipherSpec msg decode error");
+
+			return false;
+		}
+
+		if (tls->state != TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"ChangeCipherSpec invalid in state %s",
+					tls_handshake_state_to_str(tls->state));
+
+			return false;
+		}
+
+		if (!tls_change_cipher_spec(tls, 0, &error)) {
+			TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
+					"change_cipher_spec: %s", error);
+
+			return false;
+		}
+
+		TLS_SET_STATE(TLS_HANDSHAKE_WAIT_FINISHED);
+
+		return true;
+
+	case TLS_CT_ALERT:
+		/* Verify AlertLevel */
+		if (message[0] != 0x01 && message[0] != 0x02) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Received bad AlertLevel %i",
+					message[0]);
+
+			return false;
+		}
+
+		/*
+		 * On a fatal alert we are obligated to respond with a
+		 * fatal alert and disconnect but also not complain if
+		 * the connection has been torn down by the peer before
+		 * we were able to send our alert.  However on a non-fatal
+		 * alert (warning) we're also allowed to panic and send
+		 * a fatal alert, then disconnect, so we do that
+		 * regardless of the alert level.
+		 */
+		TLS_DISCONNECT(TLS_ALERT_CLOSE_NOTIFY, message[1],
+				"Peer sent a %s Alert: %s",
+				message[0] == 0x02 ? "Fatal" : "Warning",
+				l_tls_alert_to_str(message[1]));
+
+		return false;
+
+	case TLS_CT_HANDSHAKE:
+		/* Start hashing the handshake contents on first message */
+		if (tls->server && message[0] == TLS_CLIENT_HELLO &&
+				(tls->state == TLS_HANDSHAKE_WAIT_HELLO ||
+				 tls->state == TLS_HANDSHAKE_DONE))
+			if (!tls_init_handshake_hash(tls))
+				return false;
+
+		/*
+		 * Corner case: When handling a Certificate Verify or a
+		 * Finished message we need access to the messages hash from
+		 * before this message was transmitted on the Tx side so we
+		 * can verify it matches the hash the sender included in the
+		 * message.  We save it here for that purpose.  Everywhere
+		 * else we need to update the hash before handling the new
+		 * message because 1. we may need the new hash to build our
+		 * own Certificate Verify or Finished messages, and 2. we
+		 * update the message hash with newly transmitted messages
+		 * inside tls_tx_handshake which may be called as part of
+		 * handling incoming message, and if we didn't call
+		 * l_checksum_update before, the calls would end up being
+		 * out of order.
+		 */
+		if (message[0] == TLS_CERTIFICATE_VERIFY ||
+				message[0] == TLS_FINISHED)
+			for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) {
+				if (!tls->handshake_hash[hash])
+					continue;
+
+				tls_get_handshake_hash(tls, hash,
+							tls->prev_digest[hash]);
+			}
+
+		/*
+		 * RFC 5246, Section 7.4.1.1:
+		 * This message MUST NOT be included in the message hashes
+		 * that are maintained throughout the handshake and used in
+		 * the Finished messages and the certificate verify message.
+		 */
+		if (message[0] != TLS_HELLO_REQUEST)
+			for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) {
+				if (!tls->handshake_hash[hash])
+					continue;
+
+				l_checksum_update(tls->handshake_hash[hash],
+							message, len);
+			}
+
+		tls_handle_handshake(tls, message[0],
+					message + TLS_HANDSHAKE_HEADER_SIZE,
+					len - TLS_HANDSHAKE_HEADER_SIZE);
+
+		if (tls->pending_destroy) {
+			l_tls_free(tls);
+			return false;
+		}
+
+		return true;
+
+	case TLS_CT_APPLICATION_DATA:
+		if (!tls->ready) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Application data message before "
+					"handshake finished");
+
+			return false;
+		}
+
+		if (!len)
+			return true;
+
+		tls->in_callback = true;
+		tls->rx(message, len, tls->user_data);
+		tls->in_callback = false;
+
+		if (tls->pending_destroy) {
+			l_tls_free(tls);
+			return false;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+LIB_EXPORT bool l_tls_start(struct l_tls *tls)
+{
+	if (tls->max_version < tls->min_version)
+		return false;
+
+	if (!tls->cipher_suite_pref_list)
+		return false;
+
+	/* This is a nop in server mode */
+	if (tls->server)
+		return true;
+
+	if (tls->state != TLS_HANDSHAKE_WAIT_START) {
+		TLS_DEBUG("Call invalid in state %s",
+				tls_handshake_state_to_str(tls->state));
+		return false;
+	}
+
+	if (!tls_init_handshake_hash(tls))
+		return false;
+
+	/*
+	 * If we're going to try resuming a cached session, send the Client
+	 * Hello with the version we think is supported.
+	 *
+	 * RFC5246 Appendix E.1:
+	 * "Whenever a client already knows the highest protocol version known
+	 * to a server (for example, when resuming a session), it SHOULD
+	 * initiate the connection in that native protocol."
+	 *
+	 * Don't directly set tls->{min,max}_version as that would make the
+	 * handshake fail if the server decides to start a new session with
+	 * a new version instead of resuming, which it is allowed to do.
+	 */
+	tls->client_version = tls->max_version;
+	tls_load_cached_client_session(tls);
+
+	if (tls->pending_destroy) {
+		l_tls_free(tls);
+		return false;
+	}
+
+	if (!tls_send_client_hello(tls))
+		return false;
+
+	TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+	return true;
+}
+
+LIB_EXPORT void l_tls_close(struct l_tls *tls)
+{
+	tls->record_buf_len = 0;
+	tls->message_buf_len = 0;
+
+	TLS_DISCONNECT(TLS_ALERT_CLOSE_NOTIFY, 0, "Closing session");
+}
+
+LIB_EXPORT void l_tls_reset(struct l_tls *tls)
+{
+	/*
+	 * Similar to l_tls_close but without sending the alert or a
+	 * disconnect callback.
+	 */
+
+	tls_reset_handshake(tls);
+	tls_cleanup_handshake(tls);
+
+	tls_reset_cipher_spec(tls, 0);
+	tls_reset_cipher_spec(tls, 1);
+
+	tls->negotiated_version = 0;
+	tls->ready = false;
+	tls->record_flush = true;
+	tls->record_buf_len = 0;
+	tls->message_buf_len = 0;
+}
+
+LIB_EXPORT bool l_tls_set_cacert(struct l_tls *tls, struct l_queue *ca_certs)
+{
+	if (tls->ca_certs) {
+		l_queue_destroy(tls->ca_certs,
+				(l_queue_destroy_func_t) l_cert_free);
+		tls->ca_certs = NULL;
+	}
+
+	if (ca_certs) {
+		if (!l_key_is_supported(L_KEY_FEATURE_RESTRICT)) {
+			TLS_DEBUG("keyctl restrict support missing, "
+					"check kernel configuration");
+			return false;
+		}
+
+		tls->ca_certs = ca_certs;
+	}
+
+	return true;
+}
+
+LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls,
+					struct l_certchain *certchain,
+					struct l_key *priv_key)
+{
+	if (tls->cert) {
+		l_certchain_free(tls->cert);
+		tls->cert = NULL;
+	}
+
+	if (tls->priv_key) {
+		l_key_free(tls->priv_key);
+		tls->priv_key = NULL;
+		tls->priv_key_size = 0;
+	}
+
+	if (certchain)
+		tls->cert = certchain;
+
+	if (priv_key) {
+		bool is_public = true;
+
+		tls->priv_key = priv_key;
+
+		if (!l_key_get_info(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
+					L_CHECKSUM_NONE, &tls->priv_key_size,
+					&is_public) || is_public) {
+			TLS_DEBUG("Not a private key or l_key_get_info failed");
+			tls->cert = NULL;
+			tls->priv_key = NULL;
+			tls->priv_key_size = 0;
+			return false;
+		}
+
+		tls->priv_key_size /= 8;
+	}
+
+	return true;
+}
+
+bool tls_set_cipher_suites(struct l_tls *tls, const char **suite_list)
+{
+	struct tls_cipher_suite **suite;
+
+	if (tls->cipher_suite_pref_list != tls_cipher_suite_pref)
+		l_free(tls->cipher_suite_pref_list);
+
+	if (!suite_list) {
+		/* Use our default cipher suite preference list */
+		tls->cipher_suite_pref_list = tls_cipher_suite_pref;
+		return true;
+	}
+
+	tls->cipher_suite_pref_list = l_new(struct tls_cipher_suite *,
+				l_strv_length((char **) suite_list) + 1);
+	suite = tls->cipher_suite_pref_list;
+
+	for (; *suite_list; suite_list++) {
+		unsigned int i;
+
+		for (i = 0; tls_cipher_suite_pref[i]; i++)
+			if (!strcmp(tls_cipher_suite_pref[i]->name,
+						*suite_list))
+				break;
+
+		if (tls_cipher_suite_pref[i])
+			*suite++ = tls_cipher_suite_pref[i];
+		else
+			TLS_DEBUG("Cipher suite %s is not supported",
+					*suite_list);
+	}
+
+	if (suite > tls->cipher_suite_pref_list)
+		return true;
+
+	TLS_DEBUG("None of the supplied suite names is supported");
+	l_free(suite);
+	tls->cipher_suite_pref_list = NULL;
+	return false;
+}
+
+LIB_EXPORT void l_tls_set_version_range(struct l_tls *tls,
+					enum l_tls_version min_version,
+					enum l_tls_version max_version)
+{
+	tls->min_version =
+		(min_version && min_version > TLS_MIN_VERSION) ?
+		min_version : TLS_MIN_VERSION;
+	tls->max_version =
+		(max_version && max_version < TLS_MAX_VERSION) ?
+		max_version : TLS_MAX_VERSION;
+}
+
+/**
+ * l_tls_set_domain_mask:
+ * @tls: TLS object being configured
+ * @mask: NULL-terminated array of domain masks
+ *
+ * Sets a mask for domain names contained in the peer certificate
+ * (eg. the subject Common Name) to be matched against.  If none of the
+ * domains match the any mask, authentication will fail.  At least one
+ * domain has to match at least one mask from the list.
+ *
+ * The masks are each split into segments at the dot characters and each
+ * segment must match the corresponding label of the domain name --
+ * a domain name is a sequence of labels joined by dots.  An asterisk
+ * segment in the mask matches any label.  An asterisk segment at the
+ * beginning of the mask matches one or more consecutive labels from
+ * the beginning of the domain string.
+ */
+LIB_EXPORT void l_tls_set_domain_mask(struct l_tls *tls, char **mask)
+{
+	l_strv_free(tls->subject_mask);
+
+	tls->subject_mask = l_strv_copy(mask);
+}
+
+/**
+ * l_tls_set_session_cache:
+ * @tls: TLS object being configured
+ * @settings: l_settings object to read and write session data from/to or
+ *   NULL to disable caching session states.  The object must remain valid
+ *   until this method is called with a different value.
+ * @group_prefix: prefix to build group names inside @settings.  Note:
+ *   existing settings in groups starting with the prefix may be
+ *   overwritten or removed.
+ * @lifetime: a CLOCK_REALTIME-based microsecond resolution lifetime for
+ *   cached sessions.  The RFC recommends 24 hours.
+ * @max_sessions: limit on the number of sessions in the cache, or 0 for
+ *   unlimited.  Ignored in client mode.
+ * @update_cb: a callback to be invoked whenever the settings in @settings
+ *   have been updated and may need to be written to persistent storage if
+ *   desired, or NULL.
+ * @user_data: user data pointer to pass to @update_cb.
+ *
+ * Enables caching and resuming session states as described in RFC 5246 for
+ * faster setup.  l_tls will maintain the required session state data in
+ * @settings including removing expired or erroneous sessions.
+ *
+ * A client's cache contains at most one session state since the client
+ * must request one specific Session ID from the server when resuming a
+ * session.  The resumption will only work while the state is cached by
+ * both the server and the client so clients should keep separate @settings
+ * objects or use separate groups inside one object for every discrete
+ * server they may want to connect to.
+ *
+ * Multiple l_tls clients connecting to the same server can share one cache
+ * to allow reusing an established session that is still active (actual
+ * concurrency is not supported as there's no locking.)
+ */
+LIB_EXPORT void l_tls_set_session_cache(struct l_tls *tls,
+					struct l_settings *settings,
+					const char *group_prefix,
+					uint64_t lifetime,
+					unsigned int max_sessions,
+					l_tls_session_update_cb_t update_cb,
+					void *user_data)
+{
+	if (unlikely(!tls))
+		return;
+
+	tls->session_settings = settings;
+	tls->session_lifetime = lifetime;
+	tls->session_count_max = max_sessions;
+	tls->session_update_cb = update_cb;
+	tls->session_update_user_data = user_data;
+
+	l_free(tls->session_prefix);
+	tls->session_prefix = l_strdup(group_prefix);
+}
+
+LIB_EXPORT bool l_tls_get_session_resumed(struct l_tls *tls)
+{
+	if (unlikely(!tls || !tls->ready))
+		return false;
+
+	return tls->session_resumed;
+}
+
+LIB_EXPORT const char *l_tls_alert_to_str(enum l_tls_alert_desc desc)
+{
+	switch (desc) {
+	case TLS_ALERT_CLOSE_NOTIFY:
+		return "close_notify";
+	case TLS_ALERT_UNEXPECTED_MESSAGE:
+		return "unexpected_message";
+	case TLS_ALERT_BAD_RECORD_MAC:
+		return "bad_record_mac";
+	case TLS_ALERT_DECRYPT_FAIL_RESERVED:
+		return "decryption_failure_RESERVED";
+	case TLS_ALERT_RECORD_OVERFLOW:
+		return "record_overflow";
+	case TLS_ALERT_DECOMPRESS_FAIL:
+		return "decompression_failure";
+	case TLS_ALERT_HANDSHAKE_FAIL:
+		return "handshake_failure";
+	case TLS_ALERT_NO_CERT_RESERVED:
+		return "no_certificate_RESERVED";
+	case TLS_ALERT_BAD_CERT:
+		return "bad_certificate";
+	case TLS_ALERT_UNSUPPORTED_CERT:
+		return "unsupported_certificate";
+	case TLS_ALERT_CERT_REVOKED:
+		return "certificate_revoked";
+	case TLS_ALERT_CERT_EXPIRED:
+		return "certificate_expired";
+	case TLS_ALERT_CERT_UNKNOWN:
+		return "certificate_unknown";
+	case TLS_ALERT_ILLEGAL_PARAM:
+		return "illegal_parameter";
+	case TLS_ALERT_UNKNOWN_CA:
+		return "unknown_ca";
+	case TLS_ALERT_ACCESS_DENIED:
+		return "access_denied";
+	case TLS_ALERT_DECODE_ERROR:
+		return "decode_error";
+	case TLS_ALERT_DECRYPT_ERROR:
+		return "decrypt_error";
+	case TLS_ALERT_EXPORT_RES_RESERVED:
+		return "export_restriction_RESERVED";
+	case TLS_ALERT_PROTOCOL_VERSION:
+		return "protocol_version";
+	case TLS_ALERT_INSUFFICIENT_SECURITY:
+		return "insufficient_security";
+	case TLS_ALERT_INTERNAL_ERROR:
+		return "internal_error";
+	case TLS_ALERT_USER_CANCELED:
+		return "user_canceled";
+	case TLS_ALERT_NO_RENEGOTIATION:
+		return "no_renegotiation";
+	case TLS_ALERT_UNSUPPORTED_EXTENSION:
+		return "unsupported_extension";
+	}
+
+	return NULL;
+}
+
+const char *tls_handshake_state_to_str(enum tls_handshake_state state)
+{
+	static char buf[100];
+
+	switch (state) {
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_START)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_HELLO)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_CERTIFICATE)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_HELLO_DONE)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_CERTIFICATE_VERIFY)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_CHANGE_CIPHER_SPEC)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_FINISHED)
+	SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_DONE)
+	}
+
+	snprintf(buf, sizeof(buf), "tls_handshake_state(%i)", state);
+	return buf;
+}
+
+int tls_parse_certificate_list(const void *data, size_t len,
+				struct l_certchain **out_certchain)
+{
+	const uint8_t *buf = data;
+	struct l_certchain *chain = NULL;
+
+	while (len) {
+		struct l_cert *cert;
+		size_t cert_len;
+
+		if (len < 3)
+			goto decode_error;
+
+		cert_len = *buf++ << 16;
+		cert_len |= *buf++ << 8;
+		cert_len |= *buf++ << 0;
+
+		if (cert_len + 3 > len)
+			goto decode_error;
+
+		cert = l_cert_new_from_der(buf, cert_len);
+		if (!cert)
+			goto decode_error;
+
+		if (!chain) {
+			chain = certchain_new_from_leaf(cert);
+			if (!chain)
+				goto decode_error;
+		} else
+			certchain_link_issuer(chain, cert);
+
+		buf += cert_len;
+		len -= cert_len + 3;
+	}
+
+	if (out_certchain)
+		*out_certchain = chain;
+	else
+		l_certchain_free(chain);
+
+	return 0;
+
+decode_error:
+	l_certchain_free(chain);
+	return -EBADMSG;
+}
+
+LIB_EXPORT bool l_tls_set_debug(struct l_tls *tls, l_tls_debug_cb_t function,
+				void *user_data, l_tls_destroy_cb_t destroy)
+{
+	if (unlikely(!tls))
+		return false;
+
+	if (tls->debug_destroy)
+		tls->debug_destroy(tls->debug_data);
+
+	tls->debug_handler = function;
+	tls->debug_destroy = destroy;
+	tls->debug_data = user_data;
+
+	return true;
+}
+
+LIB_EXPORT bool l_tls_set_cert_dump_path(struct l_tls *tls, const char *path)
+{
+	l_free(tls->cert_dump_path);
+	tls->cert_dump_path = path ? l_strdup(path) : NULL;
+	return true;
+}
diff --git a/ell/tls.h b/ell/tls.h
new file mode 100644
index 0000000..f283316
--- /dev/null
+++ b/ell/tls.h
@@ -0,0 +1,141 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_TLS_H
+#define __ELL_TLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum l_tls_version {
+	L_TLS_V10 = ((3 << 8) | 1),
+	L_TLS_V11 = ((3 << 8) | 2),
+	L_TLS_V12 = ((3 << 8) | 3),
+	L_TLS_V13 = ((3 << 8) | 4),	/* Not supported */
+};
+
+struct l_tls;
+struct l_key;
+struct l_certchain;
+struct l_queue;
+struct l_settings;
+
+enum l_tls_alert_desc {
+	TLS_ALERT_CLOSE_NOTIFY		= 0,
+	TLS_ALERT_UNEXPECTED_MESSAGE	= 10,
+	TLS_ALERT_BAD_RECORD_MAC	= 20,
+	TLS_ALERT_DECRYPT_FAIL_RESERVED	= 21,
+	TLS_ALERT_RECORD_OVERFLOW	= 22,
+	TLS_ALERT_DECOMPRESS_FAIL	= 30,
+	TLS_ALERT_HANDSHAKE_FAIL	= 40,
+	TLS_ALERT_NO_CERT_RESERVED	= 41,
+	TLS_ALERT_BAD_CERT		= 42,
+	TLS_ALERT_UNSUPPORTED_CERT	= 43,
+	TLS_ALERT_CERT_REVOKED		= 44,
+	TLS_ALERT_CERT_EXPIRED		= 45,
+	TLS_ALERT_CERT_UNKNOWN		= 46,
+	TLS_ALERT_ILLEGAL_PARAM		= 47,
+	TLS_ALERT_UNKNOWN_CA		= 48,
+	TLS_ALERT_ACCESS_DENIED		= 49,
+	TLS_ALERT_DECODE_ERROR		= 50,
+	TLS_ALERT_DECRYPT_ERROR		= 51,
+	TLS_ALERT_EXPORT_RES_RESERVED	= 60,
+	TLS_ALERT_PROTOCOL_VERSION	= 70,
+	TLS_ALERT_INSUFFICIENT_SECURITY	= 71,
+	TLS_ALERT_INTERNAL_ERROR	= 80,
+	TLS_ALERT_USER_CANCELED		= 90,
+	TLS_ALERT_NO_RENEGOTIATION	= 100,
+	TLS_ALERT_UNSUPPORTED_EXTENSION	= 110,
+};
+
+typedef void (*l_tls_write_cb_t)(const uint8_t *data, size_t len,
+					void *user_data);
+typedef void (*l_tls_ready_cb_t)(const char *peer_identity, void *user_data);
+typedef void (*l_tls_disconnect_cb_t)(enum l_tls_alert_desc reason,
+					bool remote, void *user_data);
+typedef void (*l_tls_debug_cb_t)(const char *str, void *user_data);
+typedef void (*l_tls_destroy_cb_t)(void *user_data);
+typedef void (*l_tls_session_update_cb_t)(void *user_data);
+
+/*
+ * app_data_handler gets called with newly received decrypted data.
+ * tx_handler gets called to send TLS payloads off to remote end.
+ * ready_handler gets called when l_tls_write calls are first accepted.
+ */
+struct l_tls *l_tls_new(bool server, l_tls_write_cb_t app_data_handler,
+			l_tls_write_cb_t tx_handler,
+			l_tls_ready_cb_t ready_handler,
+			l_tls_disconnect_cb_t disconnect_handler,
+			void *user_data);
+
+void l_tls_free(struct l_tls *tls);
+
+/* Begin sending connection setup messages to the server */
+bool l_tls_start(struct l_tls *tls);
+
+/* Properly disconnect a connected session */
+void l_tls_close(struct l_tls *tls);
+
+/* Reset to initial state without a graceful disconnect or callback */
+void l_tls_reset(struct l_tls *tls);
+
+/* Submit plaintext data to be encrypted and transmitted */
+void l_tls_write(struct l_tls *tls, const uint8_t *data, size_t len);
+
+/* Submit TLS payload from underlying transport to be decrypted */
+void l_tls_handle_rx(struct l_tls *tls, const uint8_t *data, size_t len);
+
+/*
+ * If peer is to be authenticated, supply the CA certificates.  On success
+ * the l_tls object takes ownership of the queue and the individual l_cert
+ * objects and they should not be freed by the caller afterwards.
+ */
+bool l_tls_set_cacert(struct l_tls *tls, struct l_queue *ca_certs);
+
+/*
+ * If we are to be authenticated, supply our certificate and private key.
+ * On the client this is optional.  On success, the l_tls object takes
+ * ownership of the certchain and the key objects and they should not be
+ * freed by the caller afterwards.
+ * TODO: it may also be useful for the caller to be able to supply one
+ * certificate of each type so they can be used depending on which is compatible
+ * with the negotiated parameters.
+ */
+bool l_tls_set_auth_data(struct l_tls *tls,
+				struct l_certchain *certchain,
+				struct l_key *priv_key);
+
+void l_tls_set_version_range(struct l_tls *tls,
+				enum l_tls_version min_version,
+				enum l_tls_version max_version);
+
+void l_tls_set_domain_mask(struct l_tls *tls, char **mask);
+
+void l_tls_set_session_cache(struct l_tls *tls, struct l_settings *settings,
+				const char *group_prefix, uint64_t lifetime,
+				unsigned int max_sessions,
+				l_tls_session_update_cb_t update_cb,
+				void *user_data);
+bool l_tls_get_session_resumed(struct l_tls *tls);
+
+const char *l_tls_alert_to_str(enum l_tls_alert_desc desc);
+
+enum l_checksum_type;
+
+bool l_tls_prf_get_bytes(struct l_tls *tls, bool use_master_secret,
+				const char *label, uint8_t *buf, size_t len);
+
+bool l_tls_set_debug(struct l_tls *tls, l_tls_debug_cb_t function,
+			void *user_data, l_tls_destroy_cb_t destroy);
+bool l_tls_set_cert_dump_path(struct l_tls *tls, const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TLS_H */
diff --git a/ell/useful.h b/ell/useful.h
new file mode 100644
index 0000000..504ea08
--- /dev/null
+++ b/ell/useful.h
@@ -0,0 +1,89 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2021  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#define align_len(len, boundary) (((len)+(boundary)-1) & ~((boundary)-1))
+
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define SWAP(l, r) \
+	do { typeof(l) __tmp = (l); (l) = (r); (r) = __tmp; } while (0)
+
+#ifndef __always_inline
+#define __always_inline inline __attribute__((always_inline))
+#endif
+
+static inline size_t minsize(size_t a, size_t b)
+{
+	if (a <= b)
+		return a;
+
+	return b;
+}
+
+static inline size_t maxsize(size_t a, size_t b)
+{
+	if (a >= b)
+		return a;
+
+	return b;
+}
+
+static inline void set_bit(void *addr, unsigned int bit)
+{
+	unsigned char *field = addr;
+	field[bit / 8] |= 1U << (bit % 8);
+}
+
+static inline int test_bit(const void *addr, unsigned int bit)
+{
+	const unsigned char *field = addr;
+	return (field[bit / 8] & (1U << (bit % 8))) != 0;
+}
+
+static inline unsigned char bit_field(const unsigned char oct,
+					unsigned int start, unsigned int n_bits)
+{
+	unsigned char mask = (1U << n_bits) - 1U;
+	return (oct >> start) & mask;
+}
+
+/* Must be called with n >= 2 and n <= ULONG_MAX / 2 + 1 */
+static inline unsigned long roundup_pow_of_two(unsigned long n)
+{
+	return 1UL << (sizeof(unsigned long) * 8 - __builtin_clzl(n - 1));
+}
+
+#define DIV_ROUND_CLOSEST(x, divisor)			\
+({							\
+	typeof(divisor) _d = (divisor);			\
+	typeof(x) _x = (x) + _d / 2;			\
+	_x / _d;					\
+})
+
+#ifndef _auto_
+#define _auto_(func)					\
+	__L_AUTODESTRUCT(func)
+#endif
+
+/*
+ * Trick the compiler into thinking that var might be changed somehow by
+ * the asm
+ */
+#define DO_NOT_OPTIMIZE(var) \
+	__asm__ ("" : "=r" (var) : "0" (var));
+
+static inline int secure_select(int select_left, int l, int r)
+{
+	int mask = -(!!select_left);
+
+	return r ^ ((l ^ r) & mask);
+}
+
+#define struct_alloc(structname, ...) \
+	(struct structname *) l_memdup(&(struct structname) { __VA_ARGS__ }, \
+					sizeof(struct structname))
diff --git a/ell/utf8.c b/ell/utf8.c
new file mode 100644
index 0000000..f230176
--- /dev/null
+++ b/ell/utf8.c
@@ -0,0 +1,547 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ * Copyright (C) 2024  Cruise, LLC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <wchar.h>
+
+#include "strv.h"
+#include "utf8.h"
+#include "private.h"
+#include "useful.h"
+
+/**
+ * SECTION:utf8
+ * @short_description: UTF-8 utility function
+ *
+ * UTF-8 string handling support
+ */
+
+LIB_EXPORT unsigned char l_ascii_table[256] = {
+	[0x00 ... 0x08] = L_ASCII_CNTRL,
+	[0x09 ... 0x0D] = L_ASCII_CNTRL | L_ASCII_SPACE,
+	[0x0E ... 0x1F] = L_ASCII_CNTRL,
+	[0x20]		= L_ASCII_PRINT | L_ASCII_SPACE,
+	[0x21 ... 0x2F] = L_ASCII_PRINT | L_ASCII_PUNCT,
+	[0x30 ... 0x39] = L_ASCII_DIGIT | L_ASCII_XDIGIT | L_ASCII_PRINT,
+	[0x3A ... 0x40] = L_ASCII_PRINT | L_ASCII_PUNCT,
+	[0x41 ... 0x46] = L_ASCII_PRINT | L_ASCII_XDIGIT | L_ASCII_UPPER,
+	[0x47 ... 0x5A] = L_ASCII_PRINT | L_ASCII_UPPER,
+	[0x5B ... 0x60] = L_ASCII_PRINT | L_ASCII_PUNCT,
+	[0x61 ... 0x66] = L_ASCII_PRINT | L_ASCII_XDIGIT | L_ASCII_LOWER,
+	[0x67 ... 0x7A] = L_ASCII_PRINT | L_ASCII_LOWER,
+	[0x7B ... 0x7E] = L_ASCII_PRINT | L_ASCII_PUNCT,
+	[0x7F]		= L_ASCII_CNTRL,
+	[0x80 ... 0xFF] = 0,
+};
+
+/**
+ * l_ascii_strdown
+ * @str: a pointer to an ASCII string
+ * @len: maximum bytes to process or negative if string is null terminated
+ *
+ * Returns: Newly allocated string with all upper case characters converted
+ * to lower case.
+ **/
+LIB_EXPORT char *l_ascii_strdown(const char *str, ssize_t len)
+{
+	size_t slen;
+	size_t i;
+	char *ret;
+
+	if (!str)
+		return NULL;
+
+	if (len < 0)
+		slen = strlen(str);
+	else
+		slen = len;
+
+	ret = l_malloc(slen + 1);
+
+	for (i = 0; i < slen && str[i]; i++)
+		ret[i] = l_ascii_tolower(str[i]);
+
+	ret[i] = '\0';
+
+	return ret;
+}
+
+/**
+ * l_ascii_strup
+ * @str: a pointer to an ASCII string
+ * @len: maximum bytes to process or negative if string is null terminated
+ *
+ * Returns: Newly allocated string with all lower case characters converted
+ * to upper case.
+ **/
+LIB_EXPORT char *l_ascii_strup(const char *str, ssize_t len)
+{
+	size_t slen;
+	size_t i;
+	char *ret;
+
+	if (!str)
+		return NULL;
+
+	if (len < 0)
+		slen = strlen(str);
+	else
+		slen = len;
+
+	ret = l_malloc(slen + 1);
+
+	for (i = 0; i < slen && str[i]; i++)
+		ret[i] = l_ascii_toupper(str[i]);
+
+	ret[i] = '\0';
+
+	return ret;
+}
+
+static inline bool __attribute__ ((always_inline))
+			valid_unicode(wchar_t c)
+{
+	if (c <= 0xd7ff)
+		return true;
+
+	if (c < 0xe000 || c > 0x10ffff)
+		return false;
+
+	if (c >= 0xfdd0 && c <= 0xfdef)
+		return false;
+
+	if ((c & 0xfffe) == 0xfffe)
+		return false;
+
+	return true;
+}
+
+/**
+ * l_utf8_get_codepoint
+ * @str: a pointer to codepoint data
+ * @len: maximum bytes to read
+ * @cp: destination for codepoint
+ *
+ * Returns: number of bytes read, or -1 for invalid coddepoint
+ **/
+LIB_EXPORT int l_utf8_get_codepoint(const char *str, size_t len, wchar_t *cp)
+{
+	static const wchar_t mins[3] = { 1 << 7, 1 << 11, 1 << 16 };
+	unsigned int expect_bytes;
+	wchar_t val;
+	size_t i;
+
+	if (len == 0)
+		return 0;
+
+	if ((signed char) str[0] > 0) {
+		*cp = str[0];
+		return 1;
+	}
+
+	expect_bytes = __builtin_clz(~((unsigned int)str[0] << 24));
+
+	if (expect_bytes < 2 || expect_bytes > 4)
+		goto error;
+
+	if (expect_bytes > len)
+		goto error;
+
+	val = str[0] & (0xff >> (expect_bytes + 1));
+
+	for (i = 1; i < expect_bytes; i++) {
+		if ((str[i] & 0xc0) != 0x80)
+			goto error;
+
+		val <<= 6;
+		val |= str[i] & 0x3f;
+	}
+
+	if (val < mins[expect_bytes - 2])
+		goto error;
+
+	if (valid_unicode(val) == false)
+		goto error;
+
+	*cp = val;
+	return expect_bytes;
+
+error:
+	return -1;
+}
+
+/**
+ * l_utf8_validate:
+ * @str: a pointer to character data
+ * @len: max bytes to validate
+ * @end: return location for end of valid data
+ *
+ * Validates UTF-8 encoded text. If @end is non-NULL, then the end of
+ * the valid range will be stored there (i.e. the start of the first
+ * invalid character if some bytes were invalid, or the end of the text
+ * being validated otherwise).
+ *
+ * Returns: Whether the text was valid UTF-8
+ **/
+LIB_EXPORT bool l_utf8_validate(const char *str, size_t len, const char **end)
+{
+	size_t pos = 0;
+	int ret;
+	wchar_t val;
+
+	while (pos < len && str[pos]) {
+		ret = l_utf8_get_codepoint(str + pos, len - pos, &val);
+
+		if (ret < 0)
+			goto error;
+
+		pos += ret;
+	}
+
+error:
+	if (end)
+		*end = str + pos;
+
+	if (pos != len)
+		return false;
+
+	return true;
+}
+
+/**
+ * l_utf8_strlen:
+ * @str: a pointer to character data
+ *
+ * Computes the number of UTF-8 characters (not bytes) in the string given
+ * by @str.
+ *
+ * Returns: The number of UTF-8 characters in the string
+ **/
+LIB_EXPORT size_t l_utf8_strlen(const char *str)
+{
+	size_t l = 0;
+	size_t i;
+	unsigned char b;
+
+	for (i = 0; str[i]; i++) {
+		b = str[i];
+
+		if ((b >> 6) == 2)
+			l += 1;
+	}
+
+	return i - l;
+}
+
+static inline int __attribute__ ((always_inline))
+			utf8_length(wchar_t c)
+{
+	if (c <= 0x7f)
+		return 1;
+
+	if (c <= 0x7ff)
+		return 2;
+
+	if (c <= 0xffff)
+		return 3;
+
+	return 4;
+}
+
+static inline uint16_t __attribute__ ((always_inline))
+			surrogate_value(uint16_t h, uint16_t l)
+{
+	return 0x10000 + (h - 0xd800) * 0x400 + l - 0xdc00;
+}
+
+/*
+ * l_utf8_from_wchar:
+ * @c: a wide-character to convert
+ * @out_buf: Buffer to write out to
+ *
+ * Assumes c is valid unicode and out_buf contains enough space for a single
+ * utf8 character (maximum 4 bytes)
+ * Returns: number of characters written
+ */
+LIB_EXPORT size_t l_utf8_from_wchar(wchar_t c, char *out_buf)
+{
+	int len = utf8_length(c);
+	int i;
+
+	if (len == 1) {
+		out_buf[0] = c;
+		return 1;
+	}
+
+	for (i = len - 1; i; i--) {
+		out_buf[i] = (c & 0x3f) | 0x80;
+		c >>= 6;
+	}
+
+	out_buf[0] = (0xff << (8 - len)) | c;
+	return len;
+}
+
+/**
+ * l_utf8_from_utf16:
+ * @utf16: Array of UTF16 characters
+ * @utf16_size: The size of the @utf16 array in bytes.  Must be a multiple of 2.
+ *
+ * Returns: A newly-allocated buffer containing UTF16 encoded string converted
+ * to UTF8.  The UTF8 string will always be null terminated, even if the
+ * original UTF16 string was not.
+ **/
+LIB_EXPORT char *l_utf8_from_utf16(const void *utf16, ssize_t utf16_size)
+{
+	char *utf8;
+	size_t utf8_len = 0;
+	wchar_t high_surrogate = 0;
+	ssize_t i = 0;
+	uint16_t in;
+	wchar_t c;
+
+	if (unlikely(utf16_size % 2))
+		return NULL;
+
+	while (utf16_size < 0 || i < utf16_size) {
+		in = l_get_u16(utf16 + i);
+
+		if (!in)
+			break;
+
+		if (in >= 0xdc00 && in < 0xe000) {
+			if (high_surrogate)
+				c = surrogate_value(high_surrogate, in);
+			else
+				return NULL;
+
+			high_surrogate = 0;
+		} else {
+			if (high_surrogate)
+				return NULL;
+
+			if (in >= 0xd800 && in < 0xdc00) {
+				high_surrogate = in;
+				goto next;
+			}
+
+			c = in;
+		}
+
+		if (!valid_unicode(c))
+			return NULL;
+
+		utf8_len += utf8_length(c);
+next:
+		i += 2;
+	}
+
+	if (high_surrogate)
+		return NULL;
+
+	utf8 = l_malloc(utf8_len + 1);
+	utf8_len = 0;
+	i = 0;
+
+	while (utf16_size < 0 || i < utf16_size) {
+		in = l_get_u16(utf16 + i);
+
+		if (!in)
+			break;
+
+		if (in >= 0xd800 && in < 0xdc00) {
+			high_surrogate = in;
+			i += 2;
+			in = l_get_u16(utf16 + i);
+			c = surrogate_value(high_surrogate, in);
+		} else
+			c = in;
+
+		utf8_len += l_utf8_from_wchar(c, utf8 + utf8_len);
+		i += 2;
+	}
+
+	utf8[utf8_len] = '\0';
+
+	return utf8;
+}
+
+/**
+ * l_utf8_to_utf16:
+ * @utf8: UTF8 formatted string
+ * @out_size: The size in bytes of the converted utf16 string
+ *
+ * Converts a UTF8 formatted string to UTF16.  It is assumed that the string
+ * is valid UTF8 and no sanity checking is performed.
+ *
+ * Returns: A newly-allocated buffer containing UTF8 encoded string converted
+ * to UTF16.  The UTF16 string will always be null terminated.
+ **/
+LIB_EXPORT void *l_utf8_to_utf16(const char *utf8, size_t *out_size)
+{
+	const char *c;
+	wchar_t wc;
+	int len;
+	uint16_t *utf16;
+	size_t n_utf16;
+
+	if (unlikely(!utf8))
+		return NULL;
+
+	c = utf8;
+	n_utf16 = 0;
+
+	while (*c) {
+		len = l_utf8_get_codepoint(c, 4, &wc);
+		if (len < 0)
+			return NULL;
+
+		if (wc < 0x10000)
+			n_utf16 += 1;
+		else
+			n_utf16 += 2;
+
+		c += len;
+	}
+
+	utf16 = l_malloc((n_utf16 + 1) * 2);
+	c = utf8;
+	n_utf16 = 0;
+
+	while (*c) {
+		len = l_utf8_get_codepoint(c, 4, &wc);
+
+		if (wc >= 0x10000) {
+			utf16[n_utf16++] = (wc - 0x1000) / 0x400 + 0xd800;
+			utf16[n_utf16++] = (wc - 0x1000) % 0x400 + 0xdc00;
+		} else
+			utf16[n_utf16++] = wc;
+
+		c += len;
+	}
+
+	utf16[n_utf16] = 0;
+
+	if (out_size)
+		*out_size = (n_utf16 + 1) * 2;
+
+	return utf16;
+}
+
+/**
+ * l_utf8_from_ucs2be:
+ * @ucs2be: Array of UCS2 characters in big-endian format
+ * @ucs2be_size: The size of the @ucs2 array in bytes.  Must be a multiple of 2.
+ *
+ * Returns: A newly-allocated buffer containing UCS2BE encoded string converted
+ * to UTF8.  The UTF8 string will always be null terminated, even if the
+ * original UCS2BE string was not.
+ **/
+LIB_EXPORT char *l_utf8_from_ucs2be(const void *ucs2be, ssize_t ucs2be_size)
+{
+	char *utf8;
+	size_t utf8_len = 0;
+	ssize_t i = 0;
+	uint16_t in;
+
+	if (unlikely(ucs2be_size % 2))
+		return NULL;
+
+	while (ucs2be_size < 0 || i < ucs2be_size) {
+		in = l_get_be16(ucs2be + i);
+
+		if (!in)
+			break;
+
+		if (in >= 0xd800 && in < 0xe000)
+			return NULL;
+
+		if (!valid_unicode(in))
+			return NULL;
+
+		utf8_len += utf8_length(in);
+		i += 2;
+	}
+
+	utf8 = l_malloc(utf8_len + 1);
+	utf8_len = 0;
+	i = 0;
+
+	while (ucs2be_size < 0 || i < ucs2be_size) {
+		in = l_get_be16(ucs2be + i);
+
+		if (!in)
+			break;
+
+		utf8_len += l_utf8_from_wchar(in, utf8 + utf8_len);
+		i += 2;
+	}
+
+	utf8[utf8_len] = '\0';
+
+	return utf8;
+}
+
+/**
+ * l_utf8_to_ucs2be:
+ * @utf8: UTF8 formatted string
+ * @out_size: The size in bytes of the converted ucs2be string
+ *
+ * Converts a UTF8 formatted string to UCS2BE.  It is assumed that the string
+ * is valid UTF8 and no sanity checking is performed.
+ *
+ * Returns: A newly-allocated buffer containing UTF8 encoded string converted
+ * to UCS2BE.  The UCS2BE string will always be null terminated.
+ **/
+LIB_EXPORT void *l_utf8_to_ucs2be(const char *utf8, size_t *out_size)
+{
+	const char *c;
+	wchar_t wc;
+	int len;
+	uint16_t *ucs2be;
+	size_t n_ucs2be;
+
+	if (unlikely(!utf8))
+		return NULL;
+
+	c = utf8;
+	n_ucs2be = 0;
+
+	while (*c) {
+		len = l_utf8_get_codepoint(c, 4, &wc);
+		if (len < 0)
+			return NULL;
+
+		if (wc >= 0x10000)
+			return NULL;
+
+		n_ucs2be += 1;
+		c += len;
+	}
+
+	ucs2be = l_malloc((n_ucs2be + 1) * 2);
+	c = utf8;
+	n_ucs2be = 0;
+
+	while (*c) {
+		len = l_utf8_get_codepoint(c, 4, &wc);
+		ucs2be[n_ucs2be++] = L_CPU_TO_BE16(wc);
+		c += len;
+	}
+
+	ucs2be[n_ucs2be] = 0;
+
+	if (out_size)
+		*out_size = (n_ucs2be + 1) * 2;
+
+	return ucs2be;
+}
diff --git a/ell/utf8.h b/ell/utf8.h
new file mode 100644
index 0000000..a1dd40b
--- /dev/null
+++ b/ell/utf8.h
@@ -0,0 +1,125 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ * Copyright (C) 2024  Cruise, LLC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_UTF8_H
+#define __ELL_UTF8_H
+
+#include <stdbool.h>
+#include <wchar.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char l_ascii_table[];
+
+enum l_ascii {
+	L_ASCII_CNTRL	= 0x80,
+	L_ASCII_PRINT	= 0x40,
+	L_ASCII_PUNCT	= 0x20,
+	L_ASCII_SPACE	= 0x10,
+	L_ASCII_XDIGIT	= 0x08,
+	L_ASCII_UPPER	= 0x04,
+	L_ASCII_LOWER	= 0x02,
+	L_ASCII_DIGIT	= 0x01,
+	L_ASCII_ALPHA	= L_ASCII_LOWER | L_ASCII_UPPER,
+	L_ASCII_ALNUM	= L_ASCII_ALPHA | L_ASCII_DIGIT,
+	L_ASCII_GRAPH	= L_ASCII_ALNUM | L_ASCII_PUNCT,
+};
+
+#define l_ascii_isalnum(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_ALNUM) != 0)
+
+#define l_ascii_isalpha(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_ALPHA) != 0)
+
+#define l_ascii_iscntrl(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_CNTRL) != 0)
+
+#define l_ascii_isdigit(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_DIGIT) != 0)
+
+#define l_ascii_isgraph(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_GRAPH) != 0)
+
+#define l_ascii_islower(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_LOWER) != 0)
+
+#define l_ascii_isprint(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_PRINT) != 0)
+
+#define l_ascii_ispunct(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_PUNCT) != 0)
+
+#define l_ascii_isspace(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_SPACE) != 0)
+
+#define l_ascii_isupper(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_UPPER) != 0)
+
+#define l_ascii_isxdigit(c) \
+	((l_ascii_table[(unsigned char) (c)] & L_ASCII_XDIGIT) != 0)
+
+#if __STDC_VERSION__ <= 199409L
+#define inline __inline__
+#endif
+
+static inline __attribute__ ((always_inline))
+					bool l_ascii_isblank(unsigned char c)
+{
+	if (c == ' ' || c == '\t')
+		return true;
+
+	return false;
+}
+
+static inline __attribute__ ((always_inline)) bool l_ascii_isascii(int c)
+{
+	if (c <= 127)
+		return true;
+
+	return false;
+}
+
+static inline __attribute__ ((always_inline)) char l_ascii_toupper(char c)
+{
+	if (!l_ascii_islower(c))
+		return c;
+
+	return c - 32;
+}
+
+static inline __attribute__ ((always_inline)) char l_ascii_tolower(char c)
+{
+	if (!l_ascii_isupper(c))
+		return c;
+
+	return c + 32;
+}
+
+char *l_ascii_strdown(const char *str, ssize_t len);
+char *l_ascii_strup(const char *str, ssize_t len);
+
+bool l_utf8_validate(const char *src, size_t len, const char **end);
+size_t l_utf8_strlen(const char *str);
+
+int l_utf8_get_codepoint(const char *str, size_t len, wchar_t *cp);
+size_t l_utf8_from_wchar(wchar_t c, char *out_buf);
+
+char *l_utf8_from_utf16(const void *utf16, ssize_t utf16_size);
+void *l_utf8_to_utf16(const char *utf8, size_t *out_size);
+
+char *l_utf8_from_ucs2be(const void *ucs2be, ssize_t ucs2be_size);
+void *l_utf8_to_ucs2be(const char *utf8, size_t *out_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_UTF8_H */
diff --git a/ell/util.c b/ell/util.c
new file mode 100644
index 0000000..f474098
--- /dev/null
+++ b/ell/util.c
@@ -0,0 +1,832 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "utf8.h"
+#include "util.h"
+#include "useful.h"
+#include "private.h"
+
+/**
+ * SECTION:util
+ * @short_description: Utility functions
+ *
+ * Utility functions
+ */
+
+#define STRLOC __FILE__ ":" L_STRINGIFY(__LINE__)
+
+/**
+ * l_malloc:
+ * @size: memory size to allocate
+ *
+ * If for any reason the memory allocation fails, then execution will be
+ * halted via abort().
+ *
+ * In case @size is 0 then #NULL will be returned.
+ *
+ * Returns: pointer to allocated memory
+ **/
+LIB_EXPORT void *l_malloc(size_t size)
+{
+	if (likely(size)) {
+		void *ptr;
+
+		ptr = malloc(size);
+		if (ptr)
+			return ptr;
+
+		fprintf(stderr, "%s:%s(): failed to allocate %zd bytes\n",
+					STRLOC, __func__, size);
+		abort();
+	}
+
+	return NULL;
+}
+
+/**
+ * l_realloc:
+ * @mem: previously allocated memory, or NULL
+ * @size: memory size to allocate
+ *
+ * If for any reason the memory allocation fails, then execution will be
+ * halted via abort().
+ *
+ * In case @mem is NULL, this function acts like l_malloc.
+ * In case @size is 0 then #NULL will be returned.
+ *
+ * Returns: pointer to allocated memory
+ **/
+LIB_EXPORT void *l_realloc(void *mem, size_t size)
+{
+	if (likely(size)) {
+		void *ptr;
+
+		ptr = realloc(mem, size);
+		if (ptr)
+			return ptr;
+
+		fprintf(stderr, "%s:%s(): failed to re-allocate %zd bytes\n",
+					STRLOC, __func__, size);
+		abort();
+	} else
+		l_free(mem);
+
+	return NULL;
+}
+
+/**
+ * l_memdup:
+ * @mem: pointer to memory you want to duplicate
+ * @size: memory size
+ *
+ * If for any reason the memory allocation fails, then execution will be
+ * halted via abort().
+ *
+ * In case @size is 0 then #NULL will be returned.
+ *
+ * Returns: pointer to duplicated memory buffer
+ **/
+LIB_EXPORT void *l_memdup(const void *mem, size_t size)
+{
+	void *ptr;
+
+	ptr = l_malloc(size);
+
+	memcpy(ptr, mem, size);
+
+	return ptr;
+}
+
+/**
+ * l_free:
+ * @ptr: memory pointer
+ *
+ * Free the allocated memory area.
+ **/
+LIB_EXPORT void l_free(void *ptr)
+{
+	free(ptr);
+}
+
+/**
+ * l_strdup:
+ * @str: string pointer
+ *
+ * Allocates and duplicates string
+ *
+ * Returns: a newly allocated string
+ **/
+LIB_EXPORT char *l_strdup(const char *str)
+{
+	if (likely(str)) {
+		char *tmp;
+
+		tmp = strdup(str);
+		if (tmp)
+			return tmp;
+
+		fprintf(stderr, "%s:%s(): failed to allocate string\n",
+						STRLOC, __func__);
+		abort();
+	}
+
+	return NULL;
+}
+
+/**
+ * l_strndup:
+ * @str: string pointer
+ * @max: Maximum number of characters to copy
+ *
+ * Allocates and duplicates string.  If the string is longer than @max
+ * characters, only @max are copied and a null terminating character
+ * is added.
+ *
+ * Returns: a newly allocated string
+ **/
+LIB_EXPORT char *l_strndup(const char *str, size_t max)
+{
+	if (likely(str)) {
+		char *tmp;
+
+		tmp = strndup(str, max);
+		if (tmp)
+			return tmp;
+
+		fprintf(stderr, "%s:%s(): failed to allocate string\n",
+						STRLOC, __func__);
+		abort();
+	}
+
+	return NULL;
+}
+
+/**
+ * l_strdup_printf:
+ * @format: string format
+ * @...: parameters to insert into format string
+ *
+ * Returns: a newly allocated string
+ **/
+LIB_EXPORT char *l_strdup_printf(const char *format, ...)
+{
+	va_list args;
+	char *str;
+	int len;
+
+	va_start(args, format);
+	len = vasprintf(&str, format, args);
+	va_end(args);
+
+	if (len < 0) {
+		fprintf(stderr, "%s:%s(): failed to allocate string\n",
+					STRLOC, __func__);
+		abort();
+
+		return NULL;
+	}
+
+	return str;
+}
+
+/**
+ * l_strdup_vprintf:
+ * @format: string format
+ * @args: parameters to insert into format string
+ *
+ * Returns: a newly allocated string
+ **/
+LIB_EXPORT char *l_strdup_vprintf(const char *format, va_list args)
+{
+	char *str;
+	int len;
+
+	len = vasprintf(&str, format, args);
+
+	if (len < 0) {
+		fprintf(stderr, "%s:%s(): failed to allocate string\n",
+					STRLOC, __func__);
+		abort();
+
+		return NULL;
+	}
+
+	return str;
+}
+
+/**
+ * l_strlcpy:
+ * @dst: Destination buffer for string
+ * @src: Source buffer containing null-terminated string to copy
+ * @len: Maximum destination buffer space to use
+ *
+ * Copies a string from the @src buffer to the @dst buffer, using no
+ * more than @len bytes in @dst. @dst is guaranteed to be
+ * null-terminated. The caller can determine if the copy was truncated by
+ * checking if the return value is greater than or equal to @len.
+ *
+ * NOTE: Passing in a NULL string results in a no-op
+ *
+ * Returns: The length of the @src string, not including the null
+ * terminator.
+ */
+LIB_EXPORT size_t l_strlcpy(char *dst, const char *src, size_t len)
+{
+	size_t src_len = src ? strlen(src) : 0;
+
+	if (!src)
+		goto done;
+
+	if (len) {
+		if (src_len < len) {
+			len = src_len + 1;
+		} else {
+			len -= 1;
+			dst[len] = '\0';
+		}
+
+		memcpy(dst, src, len);
+	}
+
+done:
+	return src_len;
+}
+
+/**
+ * l_str_has_prefix:
+ * @str: A string to be examined
+ * @delim: Prefix string
+ *
+ * Determines if the string given by @str is prefixed by string given by
+ * @prefix.
+ *
+ * Returns: True if @str was prefixed by @prefix.  False otherwise.
+ */
+LIB_EXPORT bool l_str_has_prefix(const char *str, const char *prefix)
+{
+	size_t str_len;
+	size_t prefix_len;
+
+	if (unlikely(!str))
+		return false;
+
+	if (unlikely(!prefix))
+		return false;
+
+	str_len = strlen(str);
+	prefix_len = strlen(prefix);
+
+	if (str_len < prefix_len)
+		return false;
+
+	return !strncmp(str, prefix, prefix_len);
+}
+
+/**
+ * l_str_has_suffix:
+ * @str: A string to be examined
+ * @suffix: Suffix string
+ *
+ * Determines if the string given by @str ends with the specified @suffix.
+ *
+ * Returns: True if @str ends with the specified @suffix.  False otherwise.
+ */
+LIB_EXPORT bool l_str_has_suffix(const char *str, const char *suffix)
+{
+	size_t str_len;
+	size_t suffix_len;
+	size_t len_diff;
+
+	if (unlikely(!str))
+		return false;
+
+	if (unlikely(!suffix))
+		return false;
+
+	str_len = strlen(str);
+	suffix_len = strlen(suffix);
+
+	if (str_len < suffix_len)
+		return false;
+
+	len_diff = str_len - suffix_len;
+
+	return !strcmp(&str[len_diff], suffix);
+}
+
+/**
+ * l_streq0:
+ * @a: First operand
+ * @b: Second operand
+ *
+ * Returns: True if @a and @b are both NULL or both non-NULL and identical
+ * according to strcmp.  False otherwise.
+ */
+LIB_EXPORT bool l_streq0(const char *a, const char *b)
+{
+	return a == b || (a && b && !strcmp(a, b));
+}
+
+static char *hexstring_common(const unsigned char *buf, size_t len,
+				const char hexdigits[static 16])
+{
+	char *str;
+	size_t i;
+
+	if (unlikely(!buf) || unlikely(!len))
+		return NULL;
+
+	str = l_malloc(len * 2 + 1);
+
+	for (i = 0; i < len; i++) {
+		str[(i * 2) + 0] = hexdigits[buf[i] >> 4];
+		str[(i * 2) + 1] = hexdigits[buf[i] & 0xf];
+	}
+
+	str[len * 2] = '\0';
+
+	return str;
+}
+
+static char *hexstringv_common(const struct iovec *iov, size_t n_iov,
+				const char hexdigits[static 16])
+{
+	char *str;
+	size_t i, j, c;
+	size_t len;
+
+	if (unlikely(!iov || !n_iov))
+		return NULL;
+
+	for (i = 0, len = 0; i < n_iov; i++)
+		len += iov[i].iov_len;
+
+	str = l_malloc(len * 2 + 1);
+	c = 0;
+
+	for (i = 0; i < n_iov; i++) {
+		const uint8_t *buf = iov[i].iov_base;
+
+		for (j = 0; j < iov[i].iov_len; j++) {
+			str[c++] = hexdigits[buf[j] >> 4];
+			str[c++] = hexdigits[buf[j] & 0xf];
+		}
+	}
+
+	str[len * 2] = '\0';
+
+	return str;
+}
+
+/**
+ * l_util_hexstring:
+ * @buf: buffer pointer
+ * @len: length of buffer
+ *
+ * Returns: a newly allocated hex string.  Note that the string will contain
+ * lower case hex digits a-f.  If you require upper case hex digits, use
+ * @l_util_hexstring_upper
+ **/
+LIB_EXPORT char *l_util_hexstring(const void *buf, size_t len)
+{
+	static const char hexdigits[] = "0123456789abcdef";
+	return hexstring_common(buf, len, hexdigits);
+}
+
+/**
+ * l_util_hexstring_upper:
+ * @buf: buffer pointer
+ * @len: length of buffer
+ *
+ * Returns: a newly allocated hex string.  Note that the string will contain
+ * upper case hex digits a-f.  If you require lower case hex digits, use
+ * @l_util_hexstring
+ **/
+LIB_EXPORT char *l_util_hexstring_upper(const void *buf, size_t len)
+{
+	static const char hexdigits[] = "0123456789ABCDEF";
+	return hexstring_common(buf, len, hexdigits);
+}
+
+/**
+ * l_util_hexstringv:
+ * @iov: iovec
+ * @n_iov: length of the iovec
+ *
+ * Returns: a newly allocated hex string.  Note that the string will contain
+ * lower case hex digits a-f.  If you require upper case hex digits, use
+ * @l_util_hexstringv_upper
+ **/
+LIB_EXPORT char *l_util_hexstringv(const struct iovec *iov, size_t n_iov)
+{
+	static const char hexdigits[] = "0123456789abcdef";
+	return hexstringv_common(iov, n_iov, hexdigits);
+}
+
+/**
+ * l_util_hexstringv_upper:
+ * @iov: iovec
+ * @n_iov: length of the iovec
+ *
+ * Returns: a newly allocated hex string.  Note that the string will contain
+ * upper case hex digits a-f.  If you require lower case hex digits, use
+ * @l_util_hexstringv
+ **/
+LIB_EXPORT char *l_util_hexstringv_upper(const struct iovec *iov, size_t n_iov)
+{
+	static const char hexdigits[] = "0123456789ABCDEF";
+	return hexstringv_common(iov, n_iov, hexdigits);
+}
+
+/**
+ * l_util_from_hexstring:
+ * @str: Null-terminated string containing the hex-encoded bytes
+ * @out_len: Number of bytes decoded
+ *
+ * Returns: a newly allocated byte array.  Empty strings are treated as
+ * an error condition.
+ **/
+LIB_EXPORT unsigned char *l_util_from_hexstring(const char *str,
+							size_t *out_len)
+{
+	size_t i, j;
+	size_t len;
+	char c;
+	unsigned char *buf;
+
+	if (unlikely(!str))
+		return NULL;
+
+	for (i = 0; str[i]; i++) {
+		c = str[i];
+
+		if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
+				(c >= 'a' && c <= 'f'))
+			continue;
+
+		return NULL;
+	}
+
+	if (!i)
+		return NULL;
+
+	if ((i % 2) != 0)
+		return NULL;
+
+	len = i;
+	buf = l_malloc(i >> 1);
+
+	for (i = 0, j = 0; i < len; i++, j++) {
+		c = str[i];
+
+		if (c >= '0' && c <= '9')
+			buf[j] = c - '0';
+		else if (c >= 'A' && c <= 'F')
+			buf[j] = 10 + c - 'A';
+		else if (c >= 'a' && c <= 'f')
+			buf[j] = 10 + c - 'a';
+
+		i += 1;
+		c = str[i];
+
+		if (c >= '0' && c <= '9')
+			buf[j] = buf[j] * 16 + c - '0';
+		else if (c >= 'A' && c <= 'F')
+			buf[j] = buf[j] * 16 + 10 + c - 'A';
+		else if (c >= 'a' && c <= 'f')
+			buf[j] = buf[j] * 16 + 10 + c - 'a';
+	}
+
+	if (out_len)
+		*out_len = j;
+
+	return buf;
+}
+
+static void hexdump(const char dir, const unsigned char *buf, size_t len,
+			l_util_hexdump_func_t function, void *user_data)
+{
+	static const char hexdigits[] = "0123456789abcdef";
+	char str[68];
+	size_t i;
+
+	if (unlikely(!len))
+		return;
+
+	str[0] = dir;
+
+	for (i = 0; i < len; i++) {
+		str[((i % 16) * 3) + 1] = ' ';
+		str[((i % 16) * 3) + 2] = hexdigits[buf[i] >> 4];
+		str[((i % 16) * 3) + 3] = hexdigits[buf[i] & 0xf];
+		str[(i % 16) + 51] = l_ascii_isprint(buf[i]) ? buf[i] : '.';
+
+		if ((i + 1) % 16 == 0) {
+			str[49] = ' ';
+			str[50] = ' ';
+			str[67] = '\0';
+			function(str, user_data);
+			str[0] = ' ';
+		}
+	}
+
+	if (i % 16 > 0) {
+		size_t j;
+		for (j = (i % 16); j < 16; j++) {
+			str[(j * 3) + 1] = ' ';
+			str[(j * 3) + 2] = ' ';
+			str[(j * 3) + 3] = ' ';
+			str[j + 51] = ' ';
+		}
+		str[49] = ' ';
+		str[50] = ' ';
+		str[67] = '\0';
+		function(str, user_data);
+	}
+}
+
+LIB_EXPORT void l_util_hexdump(bool in, const void *buf, size_t len,
+			l_util_hexdump_func_t function, void *user_data)
+{
+	if (likely(!function))
+		return;
+
+	hexdump(in ? '<' : '>', buf, len, function, user_data);
+}
+
+LIB_EXPORT void l_util_hexdump_two(bool in, const void *buf1, size_t len1,
+			const void *buf2, size_t len2,
+			l_util_hexdump_func_t function, void *user_data)
+{
+	if (likely(!function))
+		return;
+
+	hexdump(in ? '<' : '>', buf1, len1, function, user_data);
+	hexdump(' ', buf2, len2, function, user_data);
+}
+
+LIB_EXPORT void l_util_hexdumpv(bool in, const struct iovec *iov,
+					size_t n_iov,
+					l_util_hexdump_func_t function,
+					void *user_data)
+{
+	static const char hexdigits[] = "0123456789abcdef";
+	char str[68];
+	size_t i;
+	size_t len;
+	size_t c;
+	const uint8_t *buf;
+
+	if (likely(!function))
+		return;
+
+	if (unlikely(!iov || !n_iov))
+		return;
+
+	str[0] = in ? '<' : '>';
+
+	for (i = 0, len = 0; i < n_iov; i++)
+		len += iov[i].iov_len;
+
+	c = 0;
+	buf = iov[0].iov_base;
+
+	for (i = 0; i < len; i++, c++) {
+		if (c == iov[0].iov_len) {
+			c = 0;
+			iov += 1;
+			buf = iov[0].iov_base;
+		}
+
+		str[((i % 16) * 3) + 1] = ' ';
+		str[((i % 16) * 3) + 2] = hexdigits[buf[c] >> 4];
+		str[((i % 16) * 3) + 3] = hexdigits[buf[c] & 0xf];
+		str[(i % 16) + 51] = l_ascii_isprint(buf[c]) ? buf[c] : '.';
+
+		if ((i + 1) % 16 == 0) {
+			str[49] = ' ';
+			str[50] = ' ';
+			str[67] = '\0';
+			function(str, user_data);
+			str[0] = ' ';
+		}
+	}
+
+	if (i % 16 > 0) {
+		size_t j;
+		for (j = (i % 16); j < 16; j++) {
+			str[(j * 3) + 1] = ' ';
+			str[(j * 3) + 2] = ' ';
+			str[(j * 3) + 3] = ' ';
+			str[j + 51] = ' ';
+		}
+		str[49] = ' ';
+		str[50] = ' ';
+		str[67] = '\0';
+		function(str, user_data);
+	}
+}
+
+LIB_EXPORT void l_util_debug(l_util_hexdump_func_t function, void *user_data,
+						const char *format, ...)
+{
+	va_list args;
+	char *str;
+	int len;
+
+	if (likely(!function))
+		return;
+
+	if (unlikely(!format))
+		return;
+
+	va_start(args, format);
+	len = vasprintf(&str, format, args);
+	va_end(args);
+
+	if (unlikely(len < 0))
+		return;
+
+	function(str, user_data);
+
+	free(str);
+}
+
+/**
+ * l_util_get_debugfs_path:
+ *
+ * Returns: a pointer to mount point of debugfs
+ **/
+LIB_EXPORT const char *l_util_get_debugfs_path(void)
+{
+	static char path[PATH_MAX + 1];
+	static bool found = false;
+	char type[100];
+	FILE *fp;
+
+	if (found)
+		return path;
+
+	fp = fopen("/proc/mounts", "r");
+	if (!fp)
+		return NULL;
+
+	while (fscanf(fp, "%*s %" L_STRINGIFY(PATH_MAX) "s %99s %*s %*d %*d\n",
+							path, type) == 2) {
+		if (!strcmp(type, "debugfs")) {
+			found = true;
+			break;
+		}
+	}
+
+	fclose(fp);
+
+	if (!found)
+		return NULL;
+
+	return path;
+}
+
+LIB_EXPORT bool l_memeq(const void *field, size_t size, uint8_t byte)
+{
+	const uint8_t *mem = field;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		if (mem[i] != byte)
+			return false;
+
+	return true;
+}
+
+__attribute__((noinline)) static int __secure_memeq(const void *field,
+						size_t size, uint8_t byte)
+{
+	unsigned int diff = 0;
+	size_t i;
+
+	for (i = 0; i < size; i++) {
+		diff |= ((uint8_t *) field)[i] ^ byte;
+		DO_NOT_OPTIMIZE(diff);
+	}
+
+	return diff;
+}
+
+LIB_EXPORT bool l_secure_memeq(const void *field, size_t size, uint8_t byte)
+{
+	return __secure_memeq(field, size, byte) == 0 ? true : false;
+}
+
+static int safe_atou(const char *s, int base, unsigned int *out_u)
+{
+	unsigned long int r;
+	unsigned int t;
+	char *endp;
+
+	errno = 0;
+
+	t = r = strtoul(s, &endp, base);
+	if (unlikely(errno > 0))
+		return -errno;
+
+	if (endp == s || *endp != '\0')
+		return -EINVAL;
+
+	if (unlikely(r != t))
+		return -ERANGE;
+
+	if (out_u)
+		*out_u = t;
+
+	return 0;
+}
+
+LIB_EXPORT int l_safe_atou32(const char *s, uint32_t *out_u)
+{
+	if (unlikely(!s))
+		return -EINVAL;
+
+	if (!l_ascii_isdigit(s[0]))
+		return -EINVAL;
+
+	/* Don't allow leading zeros */
+	if (s[0] == '0' && s[1] != '\0')
+		return -EINVAL;
+
+	return safe_atou(s, 10, out_u);
+}
+
+LIB_EXPORT int l_safe_atox8(const char *s, uint8_t *out_x)
+{
+	uint32_t x;
+	int r;
+
+	r = l_safe_atox32(s, &x);
+	if (r < 0)
+		return r;
+
+	if (x > UINT8_MAX)
+		return -ERANGE;
+
+	if (out_x)
+		*out_x = x;
+
+	return 0;
+}
+
+LIB_EXPORT int l_safe_atox16(const char *s, uint16_t *out_x)
+{
+	uint32_t x;
+	int r;
+
+	r = l_safe_atox32(s, &x);
+	if (r < 0)
+		return r;
+
+	if (x > UINT16_MAX)
+		return -ERANGE;
+
+	if (out_x)
+		*out_x = x;
+
+	return 0;
+}
+
+LIB_EXPORT int l_safe_atox32(const char *s, uint32_t *out_x)
+{
+	if (unlikely(!s))
+		return -EINVAL;
+
+	if (!l_ascii_isxdigit(s[0]))
+		return -EINVAL;
+
+	return safe_atou(s, 16, out_x);
+}
+
+LIB_EXPORT size_t l_util_pagesize(void)
+{
+	static size_t page_size = 0;
+
+	if (likely(page_size > 0))
+		return page_size;
+
+	page_size = sysconf(_SC_PAGESIZE);
+	return page_size;
+}
diff --git a/ell/util.h b/ell/util.h
new file mode 100644
index 0000000..c56f182
--- /dev/null
+++ b/ell/util.h
@@ -0,0 +1,524 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_UTIL_H
+#define __ELL_UTIL_H
+
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/uio.h>
+#include <ell/cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define l_container_of(ptr, type, member) ({				\
+_Pragma("GCC diagnostic push")						\
+_Pragma("GCC diagnostic ignored \"-Wcast-align\"")			\
+		const __typeof__(((type *) 0)->member) *__mptr = (ptr);	\
+		(type *)((char *) __mptr - offsetof(type, member));	\
+_Pragma("GCC diagnostic pop")						\
+	})
+
+#define L_STRINGIFY(val) L_STRINGIFY_ARG(val)
+#define L_STRINGIFY_ARG(contents) #contents
+
+#define L_WARN_ON(condition) __extension__ ({				\
+		bool r = !!(condition);					\
+		if (__builtin_expect(r, 0))				\
+			l_warn("WARNING: %s:%s() condition %s failed",	\
+				__FILE__, __func__,			\
+				#condition);				\
+		r;							\
+	})
+
+/*
+ * If ELL headers and iterfaces end up getting compiled in a C++
+ * environment, even though ELL itself is a C source based and is
+ * compiled as such, certain assignments may be flagged by the C++
+ * compiler as errors or warnings. The following portable casts should
+ * be used in such cases, with a preference towards L_PERMISSIVE_CAST
+ * where possible since it is not a cast in C and, therefore, will not
+ * mask otherwise-legitimate warnings in that environment.
+ */
+#ifdef __cplusplus
+#define L_CONST_CAST(t, v)       const_cast<t>(v)
+#define L_REINTERPRET_CAST(t, v) reinterpret_cast<t>(v)
+#define L_STATIC_CAST(t, v)      static_cast<t>(v)
+#define L_PERMISSIVE_CAST(t, v)  L_STATIC_CAST(t, v)
+#else
+#define L_CONST_CAST(t, v)       ((t)(v))
+#define L_REINTERPRET_CAST(t, v) ((t)(v))
+#define L_STATIC_CAST(t, v)      ((t)(v))
+#define L_PERMISSIVE_CAST(t, v)  (v)
+#endif
+
+#define L_PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define L_UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+
+#define L_PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define L_INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
+
+#define L_GET_UNALIGNED(ptr) __extension__	\
+({						\
+	struct __attribute__((packed)) {	\
+            __typeof__(*(ptr)) __v;		\
+	} *__p = (__typeof__(__p)) (ptr);	\
+	__p->__v;				\
+})
+
+#define L_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
+#define L_LE16_TO_CPU(val) (val)
+#define L_LE32_TO_CPU(val) (val)
+#define L_LE64_TO_CPU(val) (val)
+#define L_CPU_TO_LE16(val) (val)
+#define L_CPU_TO_LE32(val) (val)
+#define L_CPU_TO_LE64(val) (val)
+#define L_BE16_TO_CPU(val) bswap_16(val)
+#define L_BE32_TO_CPU(val) bswap_32(val)
+#define L_BE64_TO_CPU(val) bswap_64(val)
+#define L_CPU_TO_BE16(val) bswap_16(val)
+#define L_CPU_TO_BE32(val) bswap_32(val)
+#define L_CPU_TO_BE64(val) bswap_64(val)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define L_LE16_TO_CPU(val) bswap_16(val)
+#define L_LE32_TO_CPU(val) bswap_32(val)
+#define L_LE64_TO_CPU(val) bswap_64(val)
+#define L_CPU_TO_LE16(val) bswap_16(val)
+#define L_CPU_TO_LE32(val) bswap_32(val)
+#define L_CPU_TO_LE64(val) bswap_64(val)
+#define L_BE16_TO_CPU(val) (val)
+#define L_BE32_TO_CPU(val) (val)
+#define L_BE64_TO_CPU(val) (val)
+#define L_CPU_TO_BE16(val) (val)
+#define L_CPU_TO_BE32(val) (val)
+#define L_CPU_TO_BE64(val) (val)
+#else
+#error "Unknown byte order"
+#endif
+
+#if __STDC_VERSION__ <= 199409L
+#define inline __inline__
+#endif
+
+static inline uint8_t l_get_u8(const void *ptr)
+{
+	return *((const uint8_t *) ptr);
+}
+
+static inline void l_put_u8(uint8_t val, void *ptr)
+{
+	*((uint8_t *) ptr) = val;
+}
+
+static inline uint16_t l_get_u16(const void *ptr)
+{
+	return L_GET_UNALIGNED((const uint16_t *) ptr);
+}
+
+static inline void l_put_u16(uint16_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(val, (uint16_t *) ptr);
+}
+
+static inline uint32_t l_get_u32(const void *ptr)
+{
+	return L_GET_UNALIGNED((const uint32_t *) ptr);
+}
+
+static inline void l_put_u32(uint32_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(val, (uint32_t *) ptr);
+}
+
+static inline uint64_t l_get_u64(const void *ptr)
+{
+	return L_GET_UNALIGNED((const uint64_t *) ptr);
+}
+
+static inline void l_put_u64(uint64_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(val, (uint64_t *) ptr);
+}
+
+static inline int16_t l_get_s16(const void *ptr)
+{
+	return L_GET_UNALIGNED((const int16_t *) ptr);
+}
+
+static inline int32_t l_get_s32(const void *ptr)
+{
+	return L_GET_UNALIGNED((const int32_t *) ptr);
+}
+
+static inline int64_t l_get_s64(const void *ptr)
+{
+	return L_GET_UNALIGNED((const int64_t *) ptr);
+}
+
+static inline uint16_t l_get_le16(const void *ptr)
+{
+	return L_LE16_TO_CPU(L_GET_UNALIGNED((const uint16_t *) ptr));
+}
+
+static inline uint16_t l_get_be16(const void *ptr)
+{
+	return L_BE16_TO_CPU(L_GET_UNALIGNED((const uint16_t *) ptr));
+}
+
+static inline uint32_t l_get_le32(const void *ptr)
+{
+	return L_LE32_TO_CPU(L_GET_UNALIGNED((const uint32_t *) ptr));
+}
+
+static inline uint32_t l_get_be32(const void *ptr)
+{
+	return L_BE32_TO_CPU(L_GET_UNALIGNED((const uint32_t *) ptr));
+}
+
+static inline uint64_t l_get_le64(const void *ptr)
+{
+	return L_LE64_TO_CPU(L_GET_UNALIGNED((const uint64_t *) ptr));
+}
+
+static inline uint64_t l_get_be64(const void *ptr)
+{
+	return L_BE64_TO_CPU(L_GET_UNALIGNED((const uint64_t *) ptr));
+}
+
+static inline void l_put_le16(uint16_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_LE16(val), (uint16_t *) ptr);
+}
+
+static inline void l_put_be16(uint16_t val, const void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_BE16(val), (uint16_t *) ptr);
+}
+
+static inline void l_put_le32(uint32_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_LE32(val), (uint32_t *) ptr);
+}
+
+static inline void l_put_be32(uint32_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_BE32(val), (uint32_t *) ptr);
+}
+
+static inline void l_put_le64(uint64_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_LE64(val), (uint64_t *) ptr);
+}
+
+static inline void l_put_be64(uint64_t val, void *ptr)
+{
+	L_PUT_UNALIGNED(L_CPU_TO_BE64(val), (uint64_t *) ptr);
+}
+
+#define L_AUTO_FREE_VAR(vartype,varname) \
+	vartype varname __attribute__((cleanup(auto_free)))
+
+#define L_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+void *l_malloc(size_t size) __attribute__ ((warn_unused_result, malloc));
+void *l_memdup(const void *mem, size_t size)
+			__attribute__ ((warn_unused_result, malloc));
+void l_free(void *ptr);
+DEFINE_CLEANUP_FUNC(l_free);
+
+void *l_realloc(void *mem, size_t size)
+			__attribute__ ((warn_unused_result, malloc));
+
+static inline void auto_free(void *a)
+{
+	void **p = (void **)a;
+	l_free(*p);
+}
+
+#define l_steal_ptr(ptr) \
+	(__extension__ ({ typeof(ptr) _tmp = (ptr); (ptr) = NULL; _tmp; }))
+
+/**
+ * l_new:
+ * @type: type of structure
+ * @count: amount of structures
+ *
+ * Returns: pointer to allocated memory
+ **/
+#define l_new(type, count)			\
+	(type *) (__extension__ ({		\
+		size_t __n = (size_t) (count);	\
+		size_t __s = sizeof(type);	\
+		void *__p;			\
+		__p = l_malloc(__n * __s);	\
+		memset(__p, 0, __n * __s);	\
+		__p;				\
+	}))
+
+/**
+ * l_newa:
+ * @type: type of structure
+ * @count: amount of structures
+ *
+ * Allocates stack space for @count structures of @type.  Memory is allocated
+ * using alloca and initialized to 0.
+ *
+ * Returns: Pointer to memory allocated on the stack.
+ */
+#define l_newa(type, count)			\
+	(type *) (__extension__ ({		\
+		size_t __n = (size_t) (count);	\
+		size_t __s = sizeof(type);	\
+		void *__p;			\
+		__p = alloca(__n * __s);	\
+		memset(__p, 0, __n * __s);	\
+		__p;				\
+	}))
+
+char *l_strdup(const char *str);
+char *l_strndup(const char *str, size_t max);
+char *l_strdup_printf(const char *format, ...)
+			__attribute__((format(printf, 1, 2)));
+char *l_strdup_vprintf(const char *format, va_list args)
+			__attribute__((format(printf, 1, 0)));
+
+size_t l_strlcpy(char* dst, const char *src, size_t len);
+
+bool l_str_has_prefix(const char *str, const char *prefix);
+bool l_str_has_suffix(const char *str, const char *suffix);
+bool l_streq0(const char *a, const char *b);
+
+char *l_util_hexstring(const void *buf, size_t len);
+char *l_util_hexstring_upper(const void *buf, size_t len);
+char *l_util_hexstringv(const struct iovec *iov, size_t n_iov);
+char *l_util_hexstringv_upper(const struct iovec *iov, size_t n_iov);
+unsigned char *l_util_from_hexstring(const char *str, size_t *out_len);
+
+typedef void (*l_util_hexdump_func_t) (const char *str, void *user_data);
+
+void l_util_hexdump(bool in, const void *buf, size_t len,
+			l_util_hexdump_func_t function, void *user_data);
+void l_util_hexdump_two(bool in, const void *buf1, size_t len1,
+			const void *buf2, size_t len2,
+			l_util_hexdump_func_t function, void *user_data);
+void l_util_hexdumpv(bool in, const struct iovec *iov, size_t n_iov,
+					l_util_hexdump_func_t function,
+					void *user_data);
+void l_util_debug(l_util_hexdump_func_t function, void *user_data,
+						const char *format, ...)
+			__attribute__((format(printf, 3, 4)));
+
+const char *l_util_get_debugfs_path(void);
+
+#define L_TFR(expression)                          \
+  (__extension__                                   \
+    ({ long int __result;                          \
+       do __result = (long int) (expression);      \
+       while (__result == -1L && errno == EINTR);  \
+       __result; }))
+
+/* Enables declaring _auto_(close) int fd = <-1 or L_TFR(open(...))>; */
+inline __attribute__((always_inline)) void _l_close_cleanup(void *p)
+{
+	int fd = *(int *) p;
+
+	if (fd >= 0)
+		L_TFR(close(fd));
+}
+
+#define _L_IN_SET_CMP(val, type, cmp, ...) __extension__ ({		\
+		const type __v = (val);					\
+		const typeof(__v) __elems[] = {__VA_ARGS__};		\
+		size_t __i;						\
+		const size_t __n = L_ARRAY_SIZE(__elems);		\
+		bool __r = false;					\
+		for (__i = 0; __i < __n && !__r; __i++)			\
+			__r = (cmp);					\
+		__r;							\
+	})
+
+/* Warning: evaluates all set elements even after @val has matched one */
+#define L_IN_SET(val, ...)	\
+	_L_IN_SET_CMP((val), __auto_type, __v == __elems[__i], ##__VA_ARGS__)
+
+#define L_IN_STRSET(val, ...)						\
+	_L_IN_SET_CMP((val), char *, __v == __elems[__i] ||		\
+				(__v && __elems[__i] &&			\
+				 !strcmp(__v, __elems[__i])), ##__VA_ARGS__)
+
+#define _L_BIT_TO_MASK(bits, nr) __extension__ ({			\
+	typeof(*(bits)) _one = 1U;					\
+	const unsigned int _shift = (nr) % (sizeof(_one) * 8);		\
+	_one << _shift;							\
+})
+
+#define _L_BIT_TO_OFFSET(bits, nr) __extension__ ({			\
+	__auto_type _bits = (bits);					\
+	const size_t _offset = (nr) / (sizeof(*_bits) * 8);		\
+	_bits + _offset;						\
+})
+
+#define L_BIT_SET(bits, nr) __extension__ ({				\
+	size_t _nr = (nr);						\
+	__auto_type _offset = _L_BIT_TO_OFFSET(bits, _nr);		\
+	*_offset |= _L_BIT_TO_MASK(_offset, _nr);			\
+})
+
+#define L_BIT_CLEAR(bits, nr) __extension__ ({				\
+	size_t _nr = (nr);						\
+	__auto_type _offset = _L_BIT_TO_OFFSET(bits, _nr);		\
+	*_offset &= ~_L_BIT_TO_MASK(_offset, _nr);			\
+})
+
+#define L_BIT_TEST(bits, nr) __extension__ ({				\
+	size_t _nr = (nr);						\
+	__auto_type _offset = _L_BIT_TO_OFFSET(bits, _nr);		\
+	(*_offset & _L_BIT_TO_MASK(_offset, _nr)) != 0;			\
+})
+
+#define L_BITS_SET(bits, ...) __extension__ ({				\
+	const unsigned int __elems[] = {__VA_ARGS__};			\
+	size_t __i;							\
+	for (__i = 0; __i < L_ARRAY_SIZE(__elems); __i++)		\
+		L_BIT_SET(bits, __elems[__i]);				\
+})
+
+#define L_BITS_CLEAR(bits, ...) __extension__ ({			\
+	const unsigned int __elems[] = {__VA_ARGS__};			\
+	size_t __i;							\
+	for (__i = 0; __i < L_ARRAY_SIZE(__elems); __i++)		\
+		L_BIT_CLEAR(bits, __elems[__i]);			\
+})
+
+/*
+ * Taken from https://github.com/chmike/cst_time_memcmp, adding a volatile to
+ * ensure the compiler does not try to optimize the constant time behavior.
+ * The code has been modified to add comments and project specific code
+ * styling.
+ * This specific piece of code is subject to the following copyright:
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Christophe Meessen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This function performs a secure memory comparison of two buffers of size
+ * bytes, representing an integer (byte order is big endian). It returns
+ * a negative, zero or positif value if a < b, a == b or a > b respectively.
+ */
+static inline int l_secure_memcmp(const void *a, const void *b,
+					size_t size)
+{
+	const volatile uint8_t *aa =
+		L_PERMISSIVE_CAST(const volatile uint8_t *, a);
+	const volatile uint8_t *bb =
+		L_PERMISSIVE_CAST(const volatile uint8_t *, b);
+	int res = 0, diff, mask;
+
+	/*
+	 * We will compare all bytes, starting with the less significant. When
+	 * we find a non-zero difference, we update the result accordingly.
+	 */
+	if (size > 0) {
+		/*
+		 * The following couple of lines can be summarized as a
+		 * constant time/memory access version of:
+		 * if (diff != 0) res = diff;
+		 *
+		 * From the previous operation, we know that diff is in
+		 * [-255, 255]
+		 *
+		 * The following figure show the possible value of mask, based
+		 * on different cases of diff:
+		 *
+		 * diff  |   diff-1   |   ~diff    | ((diff-1) & ~diff) |  mask
+		 * ------|------------|------------|--------------------|------
+		 *   < 0 | 0xFFFFFFXX | 0x000000YY |     0x000000ZZ     |   0
+		 *  == 0 | 0xFFFFFFFF | 0xFFFFFFFF |     0xFFFFFFFF     | 0xF..F
+		 *  > 0  | 0x000000XX | 0xFFFFFFYY |     0x000000ZZ     |   0
+		 *
+		 * Hence, the mask allows to keep res when diff == 0, and to
+		 * set res to diff otherwise.
+		*/
+		do {
+			--size;
+			diff = aa[size] - bb[size];
+			mask = (((diff - 1) & ~diff) >> 8);
+			res = (res & mask) | diff;
+		} while (size != 0);
+	}
+
+	return res;
+}
+
+bool l_memeq(const void *field, size_t size, uint8_t byte);
+bool l_secure_memeq(const void *field, size_t size, uint8_t byte);
+
+static inline bool l_memeqzero(const void *field, size_t size)
+{
+	return l_memeq(field, size, 0);
+}
+
+static inline void l_secure_select(bool select_left,
+				const void *left, const void *right,
+				void *out, size_t len)
+{
+	const uint8_t *l = L_PERMISSIVE_CAST(const uint8_t *, left);
+	const uint8_t *r = L_PERMISSIVE_CAST(const uint8_t *, right);
+	uint8_t *o = L_PERMISSIVE_CAST(uint8_t *, out);
+	uint8_t mask = -(!!select_left);
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		o[i] = r[i] ^ ((l[i] ^ r[i]) & mask);
+}
+
+int l_safe_atou32(const char *s, uint32_t *out_u);
+int l_safe_atox32(const char *s, uint32_t *out_u);
+int l_safe_atox16(const char *s, uint16_t *out_u);
+int l_safe_atox8(const char *s, uint8_t *out_u);
+
+size_t l_util_pagesize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_UTIL_H */
diff --git a/ell/uuid.c b/ell/uuid.c
new file mode 100644
index 0000000..851bae4
--- /dev/null
+++ b/ell/uuid.c
@@ -0,0 +1,246 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2014  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "checksum.h"
+#include "random.h"
+#include "private.h"
+#include "useful.h"
+#include "uuid.h"
+
+const uint8_t L_UUID_NAMESPACE_DNS[16] = {
+	0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+};
+
+const uint8_t L_UUID_NAMESPACE_URL[16] = {
+	0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+};
+
+const uint8_t L_UUID_NAMESPACE_OID[16] = {
+	0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+};
+
+const uint8_t L_UUID_NAMESPACE_X500[16] = {
+	0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+};
+
+/* RFC 4122, Section 4.3 */
+static bool name_from_namespace(int version, const uint8_t nsid[16],
+				const void *name,
+				size_t name_size, uint8_t out_uuid[16])
+{
+	enum l_checksum_type type;
+	struct l_checksum *hash;
+	struct iovec iov[2];
+
+	if (unlikely(!out_uuid))
+		return false;
+
+	switch (version) {
+	case 3:
+		type = L_CHECKSUM_MD5;
+		break;
+	case 5:
+		type = L_CHECKSUM_SHA1;
+		break;
+	default:
+		return false;
+	}
+
+	hash = l_checksum_new(type);
+	if (!hash)
+		return false;
+
+	iov[0].iov_base = (void *) nsid;
+	iov[0].iov_len = 16;
+	iov[1].iov_base = (void *) name;
+	iov[1].iov_len = name_size;
+
+	/* Compute the hash of the name space ID concatenated with the name. */
+	l_checksum_updatev(hash, iov, 2);
+
+	/* o Set octets zero through 3 of the time_low field to octets zero
+	 * through 3 of the hash.
+	 *
+	 * o Set octets zero and one of the time_mid field to octets 4 and 5 of
+	 * the hash.
+	 *
+	 * o Set octets zero and one of the time_hi_and_version field to octets
+	 * 6 and 7 of the hash.
+	 * o Set the four most significant bits (bits 12 through 15) of the
+	 * time_hi_and_version field to the appropriate 4-bit version number
+	 * from Section 4.1.3.
+	 *
+	 * o Set the clock_seq_hi_and_reserved field to octet 8 of the hash.
+	 * o Set the two most significant bits (bits 6 and 7) of the
+	 * clock_seq_hi_and_reserved to zero and one, respectively.
+	 *
+	 * o  Set the clock_seq_low field to octet 9 of the hash.
+	 *
+	 * o  Set octets zero through five of the node field to octets 10
+	 * through 15 of the hash.
+	 */
+
+	l_checksum_get_digest(hash, out_uuid, 16);
+
+	/* Set 4 MSB bits of time_hi_and_version field */
+	out_uuid[6] &= 0x0f;
+	out_uuid[6] |= version << 4;
+
+	/* Set 2 MSB of clock_seq_hi_and_reserved to 10 */
+	out_uuid[8] &= 0x3f;
+	out_uuid[8] |= 0x80;
+
+	l_checksum_free(hash);
+
+	return true;
+}
+
+LIB_EXPORT bool l_uuid_v3(const uint8_t nsid[16], const void *name,
+				size_t name_size, uint8_t out_uuid[16])
+{
+	return name_from_namespace(3, nsid, name, name_size, out_uuid);
+}
+
+LIB_EXPORT bool l_uuid_v5(const uint8_t nsid[16], const void *name,
+				size_t name_size, uint8_t out_uuid[16])
+{
+	return name_from_namespace(5, nsid, name, name_size, out_uuid);
+}
+
+/* RFC 4122, Section 4.4 */
+LIB_EXPORT bool l_uuid_v4(uint8_t out_uuid[16])
+{
+	if (unlikely(!out_uuid))
+		return false;
+
+	if (!l_getrandom(out_uuid, 16))
+		return false;
+
+	/*
+	 * o Set the two most significant bits (bits 6 and 7) of the
+	 * clock_seq_hi_and_reserved to zero and one, respectively.
+	 *
+	 * o Set the four most significant bits (bits 12 through 15) of the
+	 * time_hi_and_version field to the 4-bit version number from
+	 * Section 4.1.3.
+	 *
+	 * o Set all the other bits to randomly (or pseudo-randomly) chosen
+	 * values.
+	 */
+
+	/* Set 4 MSB bits of time_hi_and_version field */
+	out_uuid[6] &= 0x0f;
+	out_uuid[6] |= 4 << 4;
+
+	/* Set 2 MSB of clock_seq_hi_and_reserved to 10 */
+	out_uuid[8] &= 0x3f;
+	out_uuid[8] |= 0x80;
+
+	return true;
+}
+
+/**
+ * l_uuid_is_valid:
+ * @uuid: UUID to check.
+ *
+ * Checks whether the given UUID is valid according to RFC 4122.  This function
+ * checks that the version field is set properly and the variant of the UUID
+ * is set to RFC 4122.
+ *
+ * Returns: Whether the UUID is valid
+ **/
+LIB_EXPORT bool l_uuid_is_valid(const uint8_t uuid[16])
+{
+	unsigned int version;
+	unsigned int variant;
+
+	if (!uuid)
+		return false;
+
+	variant = uuid[8] >> 6;
+	if (variant != 2)
+		return false;
+
+	version = uuid[6] >> 4;
+	if (version < 1 || version > 5)
+		return false;
+
+	return true;
+}
+
+LIB_EXPORT enum l_uuid_version l_uuid_get_version(const uint8_t uuid[16])
+{
+	unsigned int version;
+
+	version = uuid[6] >> 4;
+	return version;
+}
+
+LIB_EXPORT bool l_uuid_to_string(const uint8_t uuid[16],
+						char *dest, size_t dest_size)
+{
+	int n;
+
+	n = snprintf(dest, dest_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+					"%02x%02x-%02x%02x%02x%02x%02x%02x",
+					uuid[0], uuid[1], uuid[2], uuid[3],
+					uuid[4], uuid[5],
+					uuid[6], uuid[7],
+					uuid[8], uuid[9],
+					uuid[10], uuid[11], uuid[12],
+					uuid[13], uuid[14], uuid[15]);
+
+	if (n < 0 || (size_t) n >= dest_size)
+		return false;
+
+	return true;
+}
+
+LIB_EXPORT bool l_uuid_from_string(const char *src, uint8_t uuid[16])
+{
+	uint8_t buf[16];
+	int n;
+
+	/*
+	 * textual representation: 32 hex digits + 4 group separators
+	 */
+	if (strlen(src) < 16 * 2 + 4)
+		return false;
+
+	n = sscanf(src,
+			"%02hhx%02hhx%02hhx%02hhx-"
+			"%02hhx%02hhx-"
+			"%02hhx%02hhx-"
+			"%02hhx%02hhx-"
+			"%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+			&buf[0], &buf[1], &buf[2], &buf[3],
+			&buf[4], &buf[5],
+			&buf[6], &buf[7],
+			&buf[8], &buf[9],
+			&buf[10], &buf[11], &buf[12],
+			&buf[13], &buf[14], &buf[15]);
+
+	if (n != 16)
+		return false;
+
+	if (!l_uuid_is_valid(buf))
+		return false;
+
+	memcpy(uuid, buf, sizeof(buf));
+	return true;
+}
diff --git a/ell/uuid.h b/ell/uuid.h
new file mode 100644
index 0000000..a3173b0
--- /dev/null
+++ b/ell/uuid.h
@@ -0,0 +1,47 @@
+/*
+ * Embedded Linux library
+ * Copyright (C) 2011-2015  Intel Corporation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __ELL_UUID_H
+#define __ELL_UUID_H
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum l_uuid_version {
+	L_UUID_VERSION_1_TIME = 1,
+	L_UUID_VERSION_2_DCE = 2,
+	L_UUID_VERSION_3_MD5 = 3,
+	L_UUID_VERSION_4_RANDOM = 4,
+	L_UUID_VERSION_5_SHA1 = 5,
+};
+
+extern const uint8_t L_UUID_NAMESPACE_DNS[];
+extern const uint8_t L_UUID_NAMESPACE_URL[];
+extern const uint8_t L_UUID_NAMESPACE_OID[];
+extern const uint8_t L_UUID_NAMESPACE_X500[];
+
+bool l_uuid_v3(const uint8_t nsid[16], const void *name, size_t name_size,
+			uint8_t out_uuid[16]);
+bool l_uuid_v4(uint8_t out_uuid[16]);
+bool l_uuid_v5(const uint8_t nsid[16], const void *name, size_t name_size,
+			uint8_t out_uuid[16]);
+
+bool l_uuid_is_valid(const uint8_t uuid[16]);
+enum l_uuid_version l_uuid_get_version(const uint8_t uuid[16]);
+
+bool l_uuid_to_string(const uint8_t uuid[16], char *dest, size_t dest_size);
+bool l_uuid_from_string(const char *src, uint8_t uuid[16]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_UTIL_H */
diff --git a/emulator/amp.c b/emulator/amp.c
index 49d2df7..6daf001 100644
--- a/emulator/amp.c
+++ b/emulator/amp.c
@@ -680,7 +680,8 @@ static void cmd_read_local_amp_assoc(struct bt_amp *amp,
 {
 	const struct bt_hci_cmd_read_local_amp_assoc *cmd = data;
 	struct bt_hci_rsp_read_local_amp_assoc rsp;
-	uint16_t len_so_far, remain_assoc_len, fragment_len;
+	uint16_t len_so_far, remain_assoc_len;
+	size_t fragment_len;
 
 	if (cmd->phy_handle != amp->phy_handle) {
 		cmd_status(amp, BT_HCI_ERR_INVALID_PARAMETERS,
diff --git a/emulator/btdev.c b/emulator/btdev.c
index 549f936..5752a2f 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2012  Intel Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -41,6 +42,9 @@
 #define RL_SIZE			16
 #define CIS_SIZE		3
 #define BIS_SIZE		3
+#define CIG_SIZE		3
+
+#define MAX_PA_DATA_LEN	252
 
 #define has_bredr(btdev)	(!((btdev)->features[4] & 0x20))
 #define has_le(btdev)		(!!((btdev)->features[4] & 0x40))
@@ -60,6 +64,7 @@ struct hook {
 
 #define MAX_HOOK_ENTRIES 16
 #define MAX_EXT_ADV_SETS 3
+#define MAX_PENDING_CONN 16
 
 struct btdev_conn {
 	uint16_t handle;
@@ -100,6 +105,12 @@ struct le_ext_adv {
 	unsigned int id;
 };
 
+struct le_cig {
+	struct bt_hci_cmd_le_set_cig_params params;
+	struct bt_hci_cis_params cis[CIS_SIZE];
+	bool activated;
+} __attribute__ ((packed));
+
 struct btdev {
 	enum btdev_type type;
 	uint16_t id;
@@ -137,6 +148,8 @@ struct btdev {
 	uint8_t  feat_page_2[8];
 	uint16_t acl_mtu;
 	uint16_t acl_max_pkt;
+	uint16_t sco_mtu;
+	uint16_t sco_max_pkt;
 	uint16_t iso_mtu;
 	uint16_t iso_max_pkt;
 	uint8_t  country_code;
@@ -198,15 +211,12 @@ struct btdev {
 	uint16_t le_pa_min_interval;
 	uint16_t le_pa_max_interval;
 	uint8_t  le_pa_data_len;
-	uint8_t  le_pa_data[31];
+	uint8_t  le_pa_data[MAX_PA_DATA_LEN];
 	struct bt_hci_cmd_le_pa_create_sync pa_sync_cmd;
 	uint16_t le_pa_sync_handle;
 	uint8_t  big_handle;
 	uint8_t  le_ltk[16];
-	struct {
-		struct bt_hci_cmd_le_set_cig_params params;
-		struct bt_hci_cis_params cis[CIS_SIZE];
-	} __attribute__ ((packed)) le_cig;
+	struct le_cig le_cig[CIG_SIZE];
 	uint8_t  le_iso_path[2];
 
 	/* Real time length of AL array */
@@ -218,6 +228,8 @@ struct btdev {
 	uint8_t  le_rl_enable;
 	uint16_t le_rl_timeout;
 
+	struct btdev *pending_conn[MAX_PENDING_CONN];
+
 	uint8_t le_local_sk256[32];
 
 	uint16_t sync_train_interval;
@@ -309,6 +321,18 @@ static inline int del_btdev(struct btdev *btdev)
 	return index;
 }
 
+static inline bool valid_btdev(struct btdev *btdev)
+{
+	int i;
+
+	for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
+		if (btdev_list[i] == btdev)
+			return true;
+	}
+
+	return false;
+}
+
 static inline struct btdev *find_btdev_by_bdaddr(const uint8_t *bdaddr)
 {
 	int i;
@@ -554,6 +578,8 @@ static void btdev_reset(struct btdev *btdev)
 	btdev->le_scan_enable		= 0x00;
 	btdev->le_adv_enable		= 0x00;
 	btdev->le_pa_enable		= 0x00;
+	btdev->le_pa_sync_handle	= 0x0000;
+	btdev->big_handle		= 0xff;
 
 	al_clear(btdev);
 	rl_clear(btdev);
@@ -629,9 +655,9 @@ static int cmd_read_buffer_size(struct btdev *dev, const void *data,
 
 	rsp.status = BT_HCI_ERR_SUCCESS;
 	rsp.acl_mtu = cpu_to_le16(dev->acl_mtu);
-	rsp.sco_mtu = 0;
+	rsp.sco_mtu = cpu_to_le16(dev->sco_mtu);
 	rsp.acl_max_pkt = cpu_to_le16(dev->acl_max_pkt);
-	rsp.sco_max_pkt = cpu_to_le16(0);
+	rsp.sco_max_pkt = cpu_to_le16(dev->sco_max_pkt);
 
 	cmd_complete(dev, BT_HCI_CMD_READ_BUFFER_SIZE, &rsp, sizeof(rsp));
 
@@ -745,7 +771,9 @@ static int cmd_disconnect_complete(struct btdev *dev, const void *data,
 		return 0;
 	}
 
-	disconnect_complete(dev, conn->handle, BT_HCI_ERR_SUCCESS, cmd->reason);
+	/* Local host has different reason (Core v5.3 Vol 4 Part E Sec 7.1.6) */
+	disconnect_complete(dev, conn->handle, BT_HCI_ERR_SUCCESS,
+						BT_HCI_ERR_LOCAL_HOST_TERM);
 
 	if (conn->link)
 		disconnect_complete(conn->link->dev, conn->link->handle,
@@ -1204,10 +1232,39 @@ static struct btdev_conn *conn_link_bis(struct btdev *dev, struct btdev *remote,
 	return conn;
 }
 
+static void pending_conn_add(struct btdev *btdev, struct btdev *remote)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(btdev->pending_conn); ++i) {
+		if (!btdev->pending_conn[i]) {
+			btdev->pending_conn[i] = remote;
+			return;
+		}
+	}
+}
+
+static bool pending_conn_del(struct btdev *btdev, struct btdev *remote)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(btdev->pending_conn); ++i) {
+		if (btdev->pending_conn[i] == remote) {
+			btdev->pending_conn[i] = NULL;
+			return true;
+		}
+	}
+	return false;
+}
+
 static void conn_complete(struct btdev *btdev,
 					const uint8_t *bdaddr, uint8_t status)
 {
 	struct bt_hci_evt_conn_complete cc;
+	struct btdev *remote = find_btdev_by_bdaddr(bdaddr);
+
+	if (!remote)
+		return;
 
 	if (!status) {
 		struct btdev_conn *conn;
@@ -1216,6 +1273,8 @@ static void conn_complete(struct btdev *btdev,
 		if (!conn)
 			return;
 
+		pending_conn_del(conn->link->dev, btdev);
+
 		cc.status = status;
 		memcpy(cc.bdaddr, btdev->bdaddr, 6);
 		cc.encr_mode = 0x00;
@@ -1233,6 +1292,8 @@ static void conn_complete(struct btdev *btdev,
 		cc.link_type = 0x01;
 	}
 
+	pending_conn_del(btdev, remote);
+
 	cc.status = status;
 	memcpy(cc.bdaddr, bdaddr, 6);
 	cc.encr_mode = 0x00;
@@ -1240,6 +1301,28 @@ static void conn_complete(struct btdev *btdev,
 	send_event(btdev, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
 }
 
+struct page_timeout_data {
+	struct btdev *btdev;
+	uint8_t bdaddr[6];
+	unsigned int timeout_id;
+};
+
+static bool page_timeout(void *user_data)
+{
+	struct page_timeout_data *pt_data = user_data;
+	struct btdev *btdev = pt_data->btdev;
+	const uint8_t *bdaddr = pt_data->bdaddr;
+
+	timeout_remove(pt_data->timeout_id);
+	pt_data->timeout_id = 0;
+
+	if (valid_btdev(btdev))
+		conn_complete(btdev, bdaddr, BT_HCI_ERR_PAGE_TIMEOUT);
+
+	free(pt_data);
+	return false;
+}
+
 static int cmd_create_conn_complete(struct btdev *dev, const void *data,
 						uint8_t len)
 {
@@ -1253,9 +1336,22 @@ static int cmd_create_conn_complete(struct btdev *dev, const void *data,
 		memcpy(cr.dev_class, dev->dev_class, 3);
 		cr.link_type = 0x01;
 
+		pending_conn_add(dev, remote);
+
 		send_event(remote, BT_HCI_EVT_CONN_REQUEST, &cr, sizeof(cr));
 	} else {
-		conn_complete(dev, cmd->bdaddr, BT_HCI_ERR_PAGE_TIMEOUT);
+		struct page_timeout_data *pt_data =
+			new0(struct page_timeout_data, 1);
+
+		pt_data->btdev = dev;
+		memcpy(pt_data->bdaddr, cmd->bdaddr, 6);
+
+		/* Send page timeout after 5.12 seconds to emulate real
+		 * paging.
+		 */
+		pt_data->timeout_id = timeout_add(5120,
+						  page_timeout,
+						  pt_data, NULL);
 	}
 
 	return 0;
@@ -1289,16 +1385,24 @@ static int cmd_add_sco_conn(struct btdev *dev, const void *data, uint8_t len)
 	cc.encr_mode = 0x00;
 
 done:
+	pending_conn_del(dev, conn->link->dev);
+
 	send_event(dev, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
 
 	return 0;
 }
 
+static bool match_bdaddr(const void *data, const void *match_data)
+{
+	const struct btdev_conn *conn = data;
+	const uint8_t *bdaddr = match_data;
+
+	return !memcmp(conn->link->dev->bdaddr, bdaddr, 6);
+}
+
 static int cmd_create_conn_cancel(struct btdev *dev, const void *data,
 							uint8_t len)
 {
-	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_CREATE_CONN_CANCEL);
-
 	return 0;
 }
 
@@ -1306,8 +1410,37 @@ static int cmd_create_conn_cancel_complete(struct btdev *dev, const void *data,
 							uint8_t len)
 {
 	const struct bt_hci_cmd_create_conn_cancel *cmd = data;
+	struct bt_hci_rsp_create_conn_cancel rp;
+	struct btdev *remote = find_btdev_by_bdaddr(cmd->bdaddr);
+	struct btdev_conn *conn;
 
-	conn_complete(dev, cmd->bdaddr, BT_HCI_ERR_UNKNOWN_CONN_ID);
+	/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E page 1848
+	 *
+	 * If the connection is already established, and the
+	 * HCI_Connection_Complete event has been sent, then the Controller
+	 * shall return an HCI_Command_Complete event with the error code
+	 * Connection Already Exists (0x0B). If the HCI_Create_Connection_Cancel
+	 * command is sent to the Controller without a preceding
+	 * HCI_Create_Connection command to the same device, the BR/EDR
+	 * Controller shall return an HCI_Command_Complete event with the error
+	 * code Unknown Connection Identifier (0x02).
+	 */
+	if (pending_conn_del(dev, remote)) {
+		rp.status = BT_HCI_ERR_SUCCESS;
+	} else {
+		conn = queue_find(dev->conns, match_bdaddr, cmd->bdaddr);
+		if (conn)
+			rp.status = BT_HCI_ERR_CONN_ALREADY_EXISTS;
+		else
+			rp.status = BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	memcpy(rp.bdaddr, cmd->bdaddr, sizeof(rp.bdaddr));
+
+	cmd_complete(dev, BT_HCI_CMD_CREATE_CONN_CANCEL, &rp, sizeof(rp));
+
+	if (!rp.status)
+		conn_complete(dev, cmd->bdaddr, BT_HCI_ERR_UNKNOWN_CONN_ID);
 
 	return 0;
 }
@@ -1365,14 +1498,6 @@ static int cmd_link_key_reply(struct btdev *dev, const void *data, uint8_t len)
 	return 0;
 }
 
-static bool match_bdaddr(const void *data, const void *match_data)
-{
-	const struct btdev_conn *conn = data;
-	const uint8_t *bdaddr = match_data;
-
-	return !memcmp(conn->link->dev->bdaddr, bdaddr, 6);
-}
-
 static void auth_complete(struct btdev_conn *conn, uint8_t status)
 {
 	struct bt_hci_evt_auth_complete ev;
@@ -2614,7 +2739,7 @@ static int cmd_enhanced_setup_sync_conn(struct btdev *dev, const void *data,
 	if (cmd->tx_coding_format[0] > 5)
 		status = BT_HCI_ERR_INVALID_PARAMETERS;
 
-	cmd_status(dev, status, BT_HCI_EVT_SYNC_CONN_COMPLETE);
+	cmd_status(dev, status, BT_HCI_CMD_ENHANCED_SETUP_SYNC_CONN);
 
 	return 0;
 }
@@ -2641,6 +2766,8 @@ static int cmd_enhanced_setup_sync_conn_complete(struct btdev *dev,
 		goto done;
 	}
 
+	/* TODO: HCI_Connection_Request connection flow */
+
 	cc.status = BT_HCI_ERR_SUCCESS;
 	memcpy(cc.bdaddr, conn->link->dev->bdaddr, 6);
 
@@ -2660,7 +2787,7 @@ done:
 
 static int cmd_setup_sync_conn(struct btdev *dev, const void *data, uint8_t len)
 {
-	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_EVT_SYNC_CONN_COMPLETE);
+	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_SETUP_SYNC_CONN);
 
 	return 0;
 }
@@ -5106,9 +5233,13 @@ static int cmd_set_pa_data(struct btdev *dev, const void *data,
 {
 	const struct bt_hci_cmd_le_set_pa_data *cmd = data;
 	uint8_t status = BT_HCI_ERR_SUCCESS;
+	uint8_t data_len = cmd->data_len;
+
+	if (data_len > MAX_PA_DATA_LEN)
+		data_len = MAX_PA_DATA_LEN;
 
-	dev->le_pa_data_len = cmd->data_len;
-	memcpy(dev->le_pa_data, cmd->data, 31);
+	dev->le_pa_data_len = data_len;
+	memcpy(dev->le_pa_data, cmd->data, data_len);
 	cmd_complete(dev, BT_HCI_CMD_LE_SET_PA_DATA, &status,
 							sizeof(status));
 
@@ -5154,7 +5285,7 @@ static void send_pa(struct btdev *dev, const struct btdev *remote,
 {
 	struct __packed {
 		struct bt_hci_le_pa_report ev;
-		uint8_t data[31];
+		uint8_t data[247];
 	} pdu;
 
 	memset(&pdu.ev, 0, sizeof(pdu.ev));
@@ -5756,6 +5887,36 @@ static int cmd_read_iso_tx_sync(struct btdev *dev, const void *data,
 	return -ENOTSUP;
 }
 
+static int find_cig(struct btdev *dev, uint8_t cig_id)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(dev->le_cig); ++i)
+		if (dev->le_cig[i].params.cig_id == cig_id)
+			return i;
+	return -1;
+}
+
+static uint16_t make_cis_handle(uint8_t cig_idx, uint8_t cis_idx)
+{
+	/* Put CIG+CIS idxs to handle so don't need to track separately */
+	return ISO_HANDLE + cig_idx*CIS_SIZE + cis_idx;
+}
+
+static int parse_cis_handle(uint16_t handle, int *cis_idx)
+{
+	int cig_idx;
+
+	if (handle < ISO_HANDLE || handle >= ISO_HANDLE + CIS_SIZE*CIG_SIZE)
+		return -1;
+
+	cig_idx = (handle - ISO_HANDLE) / CIS_SIZE;
+	if (cis_idx)
+		*cis_idx = (handle - ISO_HANDLE) % CIS_SIZE;
+
+	return cig_idx;
+}
+
 static int cmd_set_cig_params(struct btdev *dev, const void *data,
 							uint8_t len)
 {
@@ -5765,12 +5926,15 @@ static int cmd_set_cig_params(struct btdev *dev, const void *data,
 		uint16_t handle[CIS_SIZE];
 	} __attribute__ ((packed)) rsp;
 	int i = 0;
+	int cig_idx;
 	uint32_t interval;
 	uint16_t latency;
 
 	memset(&rsp, 0, sizeof(rsp));
 
-	if (cmd->num_cis > ARRAY_SIZE(dev->le_cig.cis)) {
+	rsp.params.cig_id = cmd->cig_id;
+
+	if (cmd->num_cis > ARRAY_SIZE(dev->le_cig[0].cis)) {
 		rsp.params.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
 		goto done;
 	}
@@ -5819,39 +5983,35 @@ static int cmd_set_cig_params(struct btdev *dev, const void *data,
 		goto done;
 	}
 
-	if (dev->le_cig.params.cig_id != 0xff &&
-				dev->le_cig.params.cig_id != cmd->cig_id) {
-		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+	cig_idx = find_cig(dev, cmd->cig_id);
+	if (cig_idx < 0)
+		cig_idx = find_cig(dev, 0xff);
+	if (cig_idx < 0) {
+		rsp.params.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
 		goto done;
 	}
 
-	memcpy(&dev->le_cig, data, len);
+	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
+	 * page 2553
+	 *
+	 * If the Host issues this command when the CIG is not in the
+	 * configurable state, the Controller shall return the error
+	 * code Command Disallowed (0x0C).
+	 */
+	if (dev->le_cig[cig_idx].activated) {
+		rsp.params.status = BT_HCI_ERR_COMMAND_DISALLOWED;
+		goto done;
+	}
 
 	rsp.params.status = BT_HCI_ERR_SUCCESS;
-	rsp.params.cig_id = cmd->cig_id;
 
 	for (i = 0; i < cmd->num_cis; i++) {
-		struct btdev_conn *iso;
-
 		rsp.params.num_handles++;
-		rsp.handle[i] = cpu_to_le16(ISO_HANDLE + i);
-
-		/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
-		 * page 2553
-		 *
-		 * If the Host issues this command when the CIG is not in the
-		 * configurable state, the Controller shall return the error
-		 * code Command Disallowed (0x0C).
-		 */
-		iso = queue_find(dev->conns, match_handle,
-				UINT_TO_PTR(cpu_to_le16(rsp.handle[i])));
-		if (iso) {
-			rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
-			i = 0;
-			goto done;
-		}
+		rsp.handle[i] = cpu_to_le16(make_cis_handle(cig_idx, i));
 	}
 
+	memcpy(&dev->le_cig[cig_idx], data, len);
+
 done:
 	cmd_complete(dev, BT_HCI_CMD_LE_SET_CIG_PARAMS, &rsp,
 				sizeof(rsp.params) + (i * sizeof(uint16_t)));
@@ -5868,43 +6028,106 @@ static int cmd_set_cig_params_test(struct btdev *dev, const void *data,
 
 static int cmd_create_cis(struct btdev *dev, const void *data, uint8_t len)
 {
+	const struct bt_hci_cmd_le_create_cis *cmd = data;
+	int i, j;
+
+	for (i = 0; i < cmd->num_cis; i++) {
+		const struct bt_hci_cis *cis = &cmd->cis[i];
+		struct btdev_conn *acl;
+		struct btdev_conn *iso;
+		int cig_idx, cis_idx;
+
+		/* Check for errors (Core v5.3 Vol 4 Part E Sec. 7.8.99) */
+		for (j = 0; j < i; j++)
+			if (cis->cis_handle == cmd->cis[j].cis_handle)
+				return -EINVAL;
+
+		cig_idx = parse_cis_handle(le16_to_cpu(cis->cis_handle),
+								&cis_idx);
+		if (cig_idx < 0)
+			return -ENOENT;
+		if (cis_idx >= dev->le_cig[cig_idx].params.num_cis)
+			return -ENOENT;
+
+		acl = queue_find(dev->conns, match_handle,
+				 UINT_TO_PTR(le16_to_cpu(cis->acl_handle)));
+		if (!acl)
+			return -ENOENT;
+
+		iso = queue_find(dev->conns, match_handle,
+				 UINT_TO_PTR(le16_to_cpu(cis->cis_handle)));
+		if (iso)
+			return -EEXIST;
+	}
+
 	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_LE_CREATE_CIS);
 
 	return 0;
 }
 
+static uint8_t le_cis_interval(uint8_t sdu_interval[3])
+{
+	/* ISO Interval (slots of 1.25 ms) = SDU_Interval (us) */
+	return get_le24(sdu_interval) / 1250;
+}
+
+static uint32_t le_cis_latecy(uint8_t ft, uint8_t iso_interval,
+					uint8_t sdu_interval[3])
+{
+	uint32_t latency;
+	uint32_t interval = get_le24(sdu_interval);
+
+	/* Transport_Latency = FT × ISO_Interval - SDU_Interval */
+	latency = ft * (iso_interval * 1250) - interval;
+
+	return latency >= interval ? latency : interval;
+}
+
 static void le_cis_estabilished(struct btdev *dev, struct btdev_conn *conn,
 						uint8_t status)
 {
 	struct bt_hci_evt_le_cis_established evt;
+	int cig_idx, cis_idx = -1;
 
 	memset(&evt, 0, sizeof(evt));
 
 	evt.status = status;
 	evt.conn_handle = conn ? cpu_to_le16(conn->handle) : 0x0000;
 
+	cig_idx = conn ? parse_cis_handle(conn->link->handle, &cis_idx) : -1;
+	if (cig_idx < 0 && !evt.status)
+		evt.status = BT_HCI_ERR_UNSPECIFIED_ERROR;
+
 	if (!evt.status) {
 		struct btdev *remote = conn->link->dev;
+		struct le_cig *le_cig = &remote->le_cig[cig_idx];
+
+		memset(evt.cig_sync_delay, 0, sizeof(evt.cig_sync_delay));
+		memset(evt.cis_sync_delay, 0, sizeof(evt.cis_sync_delay));
 
-		/* TODO: Figure out if these values makes sense */
-		memcpy(evt.cig_sync_delay, remote->le_cig.params.c_interval,
-				sizeof(remote->le_cig.params.c_interval));
-		memcpy(evt.cis_sync_delay, remote->le_cig.params.p_interval,
-				sizeof(remote->le_cig.params.p_interval));
-		memcpy(evt.c_latency, &remote->le_cig.params.c_interval,
-				sizeof(remote->le_cig.params.c_interval));
-		memcpy(evt.p_latency, &remote->le_cig.params.p_interval,
-				sizeof(remote->le_cig.params.p_interval));
-		evt.c_phy = remote->le_cig.cis[0].c_phy;
-		evt.p_phy = remote->le_cig.cis[0].p_phy;
+		evt.c_phy = le_cig->cis[cis_idx].c_phy;
+		evt.p_phy = le_cig->cis[cis_idx].p_phy;
 		evt.nse = 0x01;
 		evt.c_bn = 0x01;
 		evt.p_bn = 0x01;
-		evt.c_ft = 0x01;
-		evt.p_ft = 0x01;
-		evt.c_mtu = remote->le_cig.cis[0].c_sdu;
-		evt.p_mtu = remote->le_cig.cis[0].p_sdu;
-		evt.interval = remote->le_cig.params.c_latency;
+		evt.c_ft = 0x02;
+		evt.p_ft = 0x02;
+		evt.c_mtu = le_cig->cis[cis_idx].c_sdu;
+		evt.p_mtu = le_cig->cis[cis_idx].p_sdu;
+		evt.interval = le_cis_interval(le_cig->params.c_interval);
+
+		/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 6, Part G
+		 * page 3050:
+		 *
+		 * Transport_Latency_C_To_P = CIG_Sync_Delay + FT_C_To_P ×
+		 * ISO_Interval - SDU_Interval_C_To_P
+		 * Transport_Latency_P_To_C = CIG_Sync_Delay + FT_P_To_C ×
+		 * ISO_Interval - SDU_Interval_P_To_C
+		 */
+		put_le24(le_cis_latecy(evt.c_ft, evt.interval,
+				le_cig->params.c_interval), evt.c_latency);
+		put_le24(le_cis_latecy(evt.p_ft, evt.interval,
+				le_cig->params.p_interval), evt.p_latency);
 	}
 
 	le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt));
@@ -5925,9 +6148,20 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
 		struct btdev_conn *acl;
 		struct btdev_conn *iso;
 		struct bt_hci_evt_le_cis_req evt;
+		struct le_cig *le_cig;
+		int cig_idx, cis_idx;
+
+		cig_idx = parse_cis_handle(le16_to_cpu(cis->cis_handle),
+								&cis_idx);
+		if (cig_idx < 0) {
+			le_cis_estabilished(dev, NULL,
+						BT_HCI_ERR_UNKNOWN_CONN_ID);
+			break;
+		}
+		le_cig = &dev->le_cig[cig_idx];
 
 		acl = queue_find(dev->conns, match_handle,
-				UINT_TO_PTR(cpu_to_le16(cis->acl_handle)));
+				UINT_TO_PTR(le16_to_cpu(cis->acl_handle)));
 		if (!acl) {
 			le_cis_estabilished(dev, NULL,
 						BT_HCI_ERR_UNKNOWN_CONN_ID);
@@ -5935,9 +6169,9 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
 		}
 
 		iso = queue_find(dev->conns, match_handle,
-				UINT_TO_PTR(cpu_to_le16(cis->cis_handle)));
+				UINT_TO_PTR(le16_to_cpu(cis->cis_handle)));
 		if (!iso) {
-			iso = conn_add_cis(acl, cpu_to_le16(cis->cis_handle));
+			iso = conn_add_cis(acl, le16_to_cpu(cis->cis_handle));
 			if (!iso) {
 				le_cis_estabilished(dev, NULL,
 						BT_HCI_ERR_UNKNOWN_CONN_ID);
@@ -5947,8 +6181,10 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
 
 		evt.acl_handle = cpu_to_le16(acl->handle);
 		evt.cis_handle = cpu_to_le16(iso->handle);
-		evt.cig_id = iso->dev->le_cig.params.cig_id;
-		evt.cis_id = iso->dev->le_cig.cis[0].cis_id;
+		evt.cig_id = le_cig->params.cig_id;
+		evt.cis_id = le_cig->cis[cis_idx].cis_id;
+
+		le_cig->activated = true;
 
 		le_meta_event(iso->link->dev, BT_HCI_EVT_LE_CIS_REQ, &evt,
 					sizeof(evt));
@@ -5957,20 +6193,37 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
 	return 0;
 }
 
+static bool match_handle_cig_idx(const void *data, const void *match_data)
+{
+	const struct btdev_conn *conn = data;
+	int cig_idx = PTR_TO_INT(match_data);
+
+	return cig_idx >= 0 && parse_cis_handle(conn->handle, NULL) == cig_idx;
+}
+
 static int cmd_remove_cig(struct btdev *dev, const void *data, uint8_t len)
 {
 	const struct bt_hci_cmd_le_remove_cig *cmd = data;
 	struct bt_hci_rsp_le_remove_cig rsp;
+	struct btdev_conn *conn = NULL;
+	int idx;
 
-	memset(&dev->le_cig, 0, sizeof(dev->le_cig));
 	memset(&rsp, 0, sizeof(rsp));
 
 	rsp.cig_id = cmd->cig_id;
 
-	if (dev->le_cig.params.cig_id == cmd->cig_id)
+	idx = find_cig(dev, cmd->cig_id);
+	conn = queue_find(dev->conns, match_handle_cig_idx, INT_TO_PTR(idx));
+
+	if (idx >= 0 && !conn) {
+		memset(&dev->le_cig[idx], 0, sizeof(struct le_cig));
+		dev->le_cig[idx].params.cig_id = 0xff;
 		rsp.status = BT_HCI_ERR_SUCCESS;
-	else
+	} else if (conn) {
+		rsp.status = BT_HCI_ERR_COMMAND_DISALLOWED;
+	} else {
 		rsp.status = BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
 
 	cmd_complete(dev, BT_HCI_CMD_LE_REMOVE_CIG, &rsp, sizeof(rsp));
 
@@ -6028,35 +6281,49 @@ static int cmd_create_big_complete(struct btdev *dev, const void *data,
 	const struct bt_hci_cmd_le_create_big *cmd = data;
 	const struct bt_hci_bis *bis = &cmd->bis;
 	int i;
+	struct bt_hci_evt_le_big_complete evt;
+	uint16_t *bis_handle;
+	uint8_t *pdu;
+	uint8_t pdu_len;
+
+	pdu_len = sizeof(evt) + cmd->num_bis * sizeof(*bis_handle);
+
+	pdu = malloc(pdu_len);
+	if (!pdu)
+		return -ENOMEM;
+
+	bis_handle = (uint16_t *)(pdu + sizeof(evt));
+
+	memset(&evt, 0, sizeof(evt));
 
 	for (i = 0; i < cmd->num_bis; i++) {
 		struct btdev_conn *conn;
-		struct {
-			struct bt_hci_evt_le_big_complete evt;
-			uint16_t handle;
-		} pdu;
-
-		memset(&pdu, 0, sizeof(pdu));
 
-		conn = conn_add_bis(dev, ISO_HANDLE, bis);
+		conn = conn_add_bis(dev, ISO_HANDLE + i, bis);
 		if (!conn) {
-			pdu.evt.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+			evt.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
 			goto done;
 		}
 
-		pdu.evt.handle = cmd->handle;
-		pdu.evt.num_bis++;
-		pdu.evt.phy = bis->phy;
-		pdu.evt.max_pdu = bis->sdu;
-		memcpy(pdu.evt.sync_delay, bis->sdu_interval, 3);
-		memcpy(pdu.evt.latency, bis->sdu_interval, 3);
-		pdu.evt.interval = bis->latency / 1.25;
-		pdu.handle = cpu_to_le16(conn->handle);
+		*bis_handle = cpu_to_le16(conn->handle);
+		bis_handle++;
+	}
+
+	evt.handle = cmd->handle;
+	evt.phy = bis->phy;
+	evt.max_pdu = bis->sdu;
+	memcpy(evt.sync_delay, bis->sdu_interval, 3);
+	memcpy(evt.latency, bis->sdu_interval, 3);
+	evt.interval = bis->latency / 1.25;
+	evt.num_bis = cmd->num_bis;
 
 done:
-		le_meta_event(dev, BT_HCI_EVT_LE_BIG_COMPLETE, &pdu,
-					sizeof(pdu));
-	}
+	memcpy(pdu, &evt, sizeof(evt));
+
+	le_meta_event(dev, BT_HCI_EVT_LE_BIG_COMPLETE, pdu,
+						pdu_len);
+
+	free(pdu);
 
 	return 0;
 }
@@ -6161,6 +6428,13 @@ static int cmd_big_create_sync_complete(struct btdev *dev, const void *data,
 	dev->big_handle = cmd->handle;
 	bis = conn->data;
 
+	if (bis->encryption != cmd->encryption) {
+		pdu.ev.status = BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE;
+		le_meta_event(dev, BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED, &pdu,
+					sizeof(pdu.ev));
+		return 0;
+	}
+
 	pdu.ev.handle = cmd->handle;
 	memcpy(pdu.ev.latency, bis->sdu_interval, sizeof(pdu.ev.interval));
 	pdu.ev.nse = 0x01;
@@ -6210,9 +6484,13 @@ static int cmd_big_term_sync(struct btdev *dev, const void *data, uint8_t len)
 								0x16);
 
 		conn_remove(conn);
+		break;
 	}
 
 done:
+	if (rsp.status == BT_HCI_ERR_SUCCESS)
+		dev->big_handle = 0xff;
+
 	cmd_complete(dev, BT_HCI_CMD_LE_BIG_TERM_SYNC, &rsp, sizeof(rsp));
 
 	return 0;
@@ -6833,6 +7111,7 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
 {
 	struct btdev *btdev;
 	int index;
+	unsigned int i;
 
 	btdev = malloc(sizeof(*btdev));
 	if (!btdev)
@@ -6898,11 +7177,16 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
 	btdev->acl_mtu = 192;
 	btdev->acl_max_pkt = 1;
 
+	btdev->sco_mtu = 72;
+	btdev->sco_max_pkt = 1;
+
 	btdev->iso_mtu = 251;
 	btdev->iso_max_pkt = 1;
-	btdev->le_cig.params.cig_id = 0xff;
 	btdev->big_handle = 0xff;
 
+	for (i = 0; i < ARRAY_SIZE(btdev->le_cig); ++i)
+		btdev->le_cig[i].params.cig_id = 0xff;
+
 	btdev->country_code = 0x00;
 
 	index = add_btdev(btdev);
@@ -7061,6 +7345,12 @@ static const struct btdev_cmd *run_cmd(struct btdev *btdev,
 	case -EPERM:
 		status = BT_HCI_ERR_COMMAND_DISALLOWED;
 		break;
+	case -EEXIST:
+		status = BT_HCI_ERR_CONN_ALREADY_EXISTS;
+		break;
+	case -ENOENT:
+		status = BT_HCI_ERR_UNKNOWN_CONN_ID;
+		break;
 	default:
 		status = BT_HCI_ERR_UNSPECIFIED_ERROR;
 		break;
@@ -7075,16 +7365,17 @@ static const struct btdev_cmd *vnd_cmd(struct btdev *btdev, uint8_t op,
 					const struct btdev_cmd *cmd,
 					const void *data, uint8_t len)
 {
+	uint8_t opcode = ((const uint8_t *)data)[0];
+
 	for (; cmd && cmd->func; cmd++) {
-		if (cmd->opcode != ((uint8_t *)data)[0])
+		if (cmd->opcode != opcode)
 			continue;
 
 		return run_cmd(btdev, cmd, data, len);
 	}
 
 	util_debug(btdev->debug_callback, btdev->debug_data,
-			"Unsupported Vendor subcommand 0x%2.2x\n",
-			((uint8_t *)data)[0]);
+			"Unsupported Vendor subcommand 0x%2.2x", opcode);
 
 	cmd_status(btdev, BT_HCI_ERR_UNKNOWN_COMMAND, op);
 
@@ -7110,7 +7401,7 @@ static const struct btdev_cmd *default_cmd(struct btdev *btdev, uint16_t opcode,
 	}
 
 	util_debug(btdev->debug_callback, btdev->debug_data,
-			"Unsupported command 0x%4.4x\n", opcode);
+			"Unsupported command 0x%4.4x", opcode);
 
 	cmd_status(btdev, BT_HCI_ERR_UNKNOWN_COMMAND, opcode);
 
@@ -7298,7 +7589,7 @@ void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len)
 		break;
 	default:
 		util_debug(btdev->debug_callback, btdev->debug_data,
-				"Unsupported packet 0x%2.2x\n", pkt_type);
+				"Unsupported packet 0x%2.2x", pkt_type);
 		break;
 	}
 }
diff --git a/emulator/bthost.c b/emulator/bthost.c
index b051989..9516050 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2012  Intel Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -26,6 +27,7 @@
 #include "src/shared/util.h"
 #include "src/shared/tester.h"
 #include "src/shared/queue.h"
+#include "src/shared/ad.h"
 #include "monitor/bt.h"
 #include "monitor/rfcomm.h"
 #include "bthost.h"
@@ -38,6 +40,8 @@
 #define acl_flags(h)		(h >> 12)
 
 #define iso_flags_pb(f)		(f & 0x0003)
+#define iso_flags_ts(f)		((f >> 2) & 0x0001)
+#define iso_flags_pack(pb, ts)	(((pb) & 0x03) | (((ts) & 0x01) << 2))
 #define iso_data_len_pack(h, f)	((uint16_t) ((h) | ((f) << 14)))
 
 #define L2CAP_FEAT_FIXED_CHAN	0x00000080
@@ -56,7 +60,7 @@
 /* RFCOMM FCS calculation */
 #define CRC(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
 
-static unsigned char rfcomm_crc_table[256] = {
+static const unsigned char rfcomm_crc_table[256] = {
 	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
 	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
 	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
@@ -159,11 +163,21 @@ struct btconn {
 	void *recv_data;
 };
 
+enum l2cap_mode {
+	L2CAP_MODE_OTHER,
+	L2CAP_MODE_LE_CRED,
+	L2CAP_MODE_LE_ENH_CRED,
+};
+
 struct l2conn {
+	struct l2conn *next;
 	uint16_t scid;
 	uint16_t dcid;
 	uint16_t psm;
-	struct l2conn *next;
+	enum l2cap_mode mode;
+	uint16_t data_len;
+	uint16_t recv_len;
+	void *recv_data;
 };
 
 struct rcconn {
@@ -181,6 +195,9 @@ struct l2cap_pending_req {
 
 struct l2cap_conn_cb_data {
 	uint16_t psm;
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
 	bthost_l2cap_connect_cb func;
 	bthost_l2cap_disconnect_cb disconn_func;
 	void *user_data;
@@ -224,6 +241,7 @@ struct bthost {
 	void *cmd_complete_data;
 	bthost_new_conn_cb new_conn_cb;
 	void *new_conn_data;
+	bthost_accept_conn_cb accept_iso_cb;
 	bthost_new_conn_cb new_iso_cb;
 	void *new_iso_data;
 	struct rfcomm_connection_data *rfcomm_conn_data;
@@ -271,6 +289,7 @@ struct bthost *bthost_create(void)
 
 static void l2conn_free(struct l2conn *conn)
 {
+	free(conn->recv_data);
 	free(conn);
 }
 
@@ -356,6 +375,7 @@ static struct l2conn *bthost_add_l2cap_conn(struct bthost *bthost,
 	l2conn->psm = psm;
 	l2conn->scid = scid;
 	l2conn->dcid = dcid;
+	l2conn->mode = L2CAP_MODE_OTHER;
 
 	l2conn->next = conn->l2conns;
 	conn->l2conns = l2conn;
@@ -411,6 +431,19 @@ static struct l2conn *btconn_find_l2cap_conn_by_scid(struct btconn *conn,
 	return NULL;
 }
 
+static struct l2conn *btconn_find_l2cap_conn_by_dcid(struct btconn *conn,
+								uint16_t dcid)
+{
+	struct l2conn *l2conn;
+
+	for (l2conn = conn->l2conns; l2conn != NULL; l2conn = l2conn->next) {
+		if (l2conn->dcid == dcid)
+			return l2conn;
+	}
+
+	return NULL;
+}
+
 static struct l2cap_conn_cb_data *bthost_find_l2cap_cb_by_psm(
 					struct bthost *bthost, uint16_t psm)
 {
@@ -605,14 +638,24 @@ static void send_iov(struct bthost *bthost, uint16_t handle, uint16_t cid,
 }
 
 static void send_acl(struct bthost *bthost, uint16_t handle, uint16_t cid,
-						const void *data, uint16_t len)
+				bool sdu_hdr, const void *data, uint16_t len)
 {
-	struct iovec iov;
+	struct iovec iov[2];
+	uint16_t sdu;
+	int num = 0;
+
+	if (sdu_hdr) {
+		sdu = cpu_to_le16(len);
+		iov[num].iov_base = &sdu;
+		iov[num].iov_len = sizeof(sdu);
+		num++;
+	}
 
-	iov.iov_base = (void *) data;
-	iov.iov_len = len;
+	iov[num].iov_base = (void *) data;
+	iov[num].iov_len = len;
+	num++;
 
-	send_iov(bthost, handle, cid, &iov, 1);
+	send_iov(bthost, handle, cid, iov, num);
 }
 
 static uint8_t l2cap_sig_send(struct bthost *bthost, struct btconn *conn,
@@ -707,12 +750,19 @@ void bthost_send_cid(struct bthost *bthost, uint16_t handle, uint16_t cid,
 					const void *data, uint16_t len)
 {
 	struct btconn *conn;
+	struct l2conn *l2conn;
+	bool sdu_hdr = false;
 
 	conn = bthost_find_conn(bthost, handle);
 	if (!conn)
 		return;
 
-	send_acl(bthost, handle, cid, data, len);
+	l2conn = btconn_find_l2cap_conn_by_dcid(conn, cid);
+	if (l2conn && (l2conn->mode == L2CAP_MODE_LE_CRED ||
+			l2conn->mode == L2CAP_MODE_LE_ENH_CRED))
+		sdu_hdr = true;
+
+	send_acl(bthost, handle, cid, sdu_hdr, data, len);
 }
 
 void bthost_send_cid_v(struct bthost *bthost, uint16_t handle, uint16_t cid,
@@ -727,42 +777,59 @@ void bthost_send_cid_v(struct bthost *bthost, uint16_t handle, uint16_t cid,
 	send_iov(bthost, handle, cid, iov, iovcnt);
 }
 
-static void send_iso(struct bthost *bthost, uint16_t handle,
-					const struct iovec *iov, int iovcnt)
+static void send_iso(struct bthost *bthost, uint16_t handle, bool ts,
+			uint16_t sn, uint32_t timestamp, uint8_t pkt_status,
+			const struct iovec *iov, int iovcnt)
 {
 	struct bt_hci_iso_hdr iso_hdr;
 	struct bt_hci_iso_data_start data_hdr;
 	uint8_t pkt = BT_H4_ISO_PKT;
-	struct iovec pdu[3 + iovcnt];
+	struct iovec pdu[4 + iovcnt];
+	uint16_t flags, dlen;
 	int i, len = 0;
-	static uint16_t sn;
 
 	for (i = 0; i < iovcnt; i++) {
-		pdu[3 + i].iov_base = iov[i].iov_base;
-		pdu[3 + i].iov_len = iov[i].iov_len;
+		pdu[4 + i].iov_base = iov[i].iov_base;
+		pdu[4 + i].iov_len = iov[i].iov_len;
 		len += iov[i].iov_len;
 	}
 
 	pdu[0].iov_base = &pkt;
 	pdu[0].iov_len = sizeof(pkt);
 
-	iso_hdr.handle = acl_handle_pack(handle, 0x02);
-	iso_hdr.dlen = cpu_to_le16(len + sizeof(data_hdr));
+	flags = iso_flags_pack(0x02, ts);
+	dlen = len + sizeof(data_hdr);
+	if (ts)
+		dlen += sizeof(timestamp);
+
+	iso_hdr.handle = acl_handle_pack(handle, flags);
+	iso_hdr.dlen = cpu_to_le16(dlen);
 
 	pdu[1].iov_base = &iso_hdr;
 	pdu[1].iov_len = sizeof(iso_hdr);
 
-	data_hdr.sn = cpu_to_le16(sn++);
-	data_hdr.slen = cpu_to_le16(iso_data_len_pack(len, 0));
+	if (ts) {
+		timestamp = cpu_to_le32(timestamp);
 
-	pdu[2].iov_base = &data_hdr;
-	pdu[2].iov_len = sizeof(data_hdr);
+		pdu[2].iov_base = &timestamp;
+		pdu[2].iov_len = sizeof(timestamp);
+	} else {
+		pdu[2].iov_base = NULL;
+		pdu[2].iov_len = 0;
+	}
 
-	send_packet(bthost, pdu, 3 + iovcnt);
+	data_hdr.sn = cpu_to_le16(sn);
+	data_hdr.slen = cpu_to_le16(iso_data_len_pack(len, pkt_status));
+
+	pdu[3].iov_base = &data_hdr;
+	pdu[3].iov_len = sizeof(data_hdr);
+
+	send_packet(bthost, pdu, 4 + iovcnt);
 }
 
-void bthost_send_iso(struct bthost *bthost, uint16_t handle,
-					const struct iovec *iov, int iovcnt)
+void bthost_send_iso(struct bthost *bthost, uint16_t handle, bool ts,
+			uint16_t sn, uint32_t timestamp, uint8_t pkt_status,
+			const struct iovec *iov, int iovcnt)
 {
 	struct btconn *conn;
 
@@ -770,7 +837,7 @@ void bthost_send_iso(struct bthost *bthost, uint16_t handle,
 	if (!conn)
 		return;
 
-	send_iso(bthost, handle, iov, iovcnt);
+	send_iso(bthost, handle, ts, sn, timestamp, pkt_status, iov, iovcnt);
 }
 
 bool bthost_l2cap_req(struct bthost *bthost, uint16_t handle, uint8_t code,
@@ -1465,12 +1532,25 @@ static void evt_le_cis_req(struct bthost *bthost, const void *data, uint8_t len)
 {
 	const struct bt_hci_evt_le_cis_req *ev = data;
 	struct bt_hci_cmd_le_accept_cis cmd;
+	struct bt_hci_cmd_le_reject_cis rej;
 
 	if (len < sizeof(*ev))
 		return;
 
-	memset(&cmd, 0, sizeof(cmd));
+	if (bthost->accept_iso_cb) {
+		memset(&rej, 0, sizeof(rej));
 
+		rej.reason = bthost->accept_iso_cb(le16_to_cpu(ev->cis_handle),
+							bthost->new_iso_data);
+		if (rej.reason) {
+			rej.handle = ev->cis_handle;
+			send_command(bthost, BT_HCI_CMD_LE_REJECT_CIS,
+						     &rej, sizeof(rej));
+			return;
+		}
+	}
+
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.handle = ev->cis_handle;
 
 	send_command(bthost, BT_HCI_CMD_LE_ACCEPT_CIS, &cmd, sizeof(cmd));
@@ -1745,7 +1825,7 @@ static void rfcomm_sabm_send(struct bthost *bthost, struct btconn *conn,
 	cmd.length = RFCOMM_LEN8(0);
 	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
 
-	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+	send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd));
 }
 
 static bool l2cap_conn_rsp(struct bthost *bthost, struct btconn *conn,
@@ -2076,6 +2156,7 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn,
 				uint8_t ident, const void *data, uint16_t len)
 {
 	const struct bt_l2cap_pdu_le_conn_req *req = data;
+	struct l2cap_conn_cb_data *cb_data;
 	struct bt_l2cap_pdu_le_conn_rsp rsp;
 	uint16_t psm;
 
@@ -2086,18 +2167,32 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn,
 
 	memset(&rsp, 0, sizeof(rsp));
 
-	rsp.mtu = 23;
-	rsp.mps = 23;
-	rsp.credits = 1;
-
-	if (bthost_find_l2cap_cb_by_psm(bthost, psm))
+	cb_data = bthost_find_l2cap_cb_by_psm(bthost, psm);
+	if (cb_data) {
 		rsp.dcid = cpu_to_le16(conn->next_cid++);
-	else
+		rsp.mtu = cpu_to_le16(cb_data->mtu) ? : cpu_to_le16(23);
+		rsp.mps = cpu_to_le16(cb_data->mps) ? : cpu_to_le16(23);
+		rsp.credits = cpu_to_le16(cb_data->credits) ? : cpu_to_le16(1);
+	} else
 		rsp.result = cpu_to_le16(0x0002); /* PSM Not Supported */
 
 	l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_LE_CONN_RSP, ident, &rsp,
 								sizeof(rsp));
 
+	if (!rsp.result) {
+		struct l2conn *l2conn;
+
+		l2conn = bthost_add_l2cap_conn(bthost, conn,
+							le16_to_cpu(rsp.dcid),
+							le16_to_cpu(req->scid),
+							le16_to_cpu(psm));
+		l2conn->mode = L2CAP_MODE_LE_CRED;
+
+		if (cb_data && l2conn->psm == cb_data->psm && cb_data->func)
+			cb_data->func(conn->handle, l2conn->dcid,
+							cb_data->user_data);
+	}
+
 	return true;
 }
 
@@ -2105,11 +2200,14 @@ static bool l2cap_le_conn_rsp(struct bthost *bthost, struct btconn *conn,
 				uint8_t ident, const void *data, uint16_t len)
 {
 	const struct bt_l2cap_pdu_le_conn_rsp *rsp = data;
+	struct l2conn *l2conn;
 
 	if (len < sizeof(*rsp))
 		return false;
 	/* TODO add L2CAP connection before with proper PSM */
-	bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->dcid), 0);
+	l2conn = bthost_add_l2cap_conn(bthost, conn, 0,
+						le16_to_cpu(rsp->dcid), 0);
+	l2conn->mode = L2CAP_MODE_LE_CRED;
 
 	return true;
 }
@@ -2162,16 +2260,19 @@ static bool l2cap_ecred_conn_rsp(struct bthost *bthost, struct btconn *conn,
 		uint16_t scid[5];
 	} __attribute__ ((packed)) *rsp = data;
 	int num_scid, i;
+	struct l2conn *l2conn;
 
 	if (len < sizeof(*rsp))
 		return false;
 
 	num_scid = len / sizeof(*rsp->scid);
 
-	for (i = 0; i < num_scid; i++)
+	for (i = 0; i < num_scid; i++) {
 		/* TODO add L2CAP connection before with proper PSM */
-		bthost_add_l2cap_conn(bthost, conn, 0,
+		l2conn = bthost_add_l2cap_conn(bthost, conn, 0,
 				      le16_to_cpu(rsp->scid[i]), 0);
+		l2conn->mode = L2CAP_MODE_LE_ENH_CRED;
+	}
 
 
 	return true;
@@ -2299,7 +2400,7 @@ static void rfcomm_ua_send(struct bthost *bthost, struct btconn *conn,
 	cmd.length = RFCOMM_LEN8(0);
 	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
 
-	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+	send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd));
 }
 
 static void rfcomm_dm_send(struct bthost *bthost, struct btconn *conn,
@@ -2313,7 +2414,7 @@ static void rfcomm_dm_send(struct bthost *bthost, struct btconn *conn,
 	cmd.length = RFCOMM_LEN8(0);
 	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
 
-	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+	send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd));
 }
 
 static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn,
@@ -2602,12 +2703,97 @@ static void process_rfcomm(struct bthost *bthost, struct btconn *conn,
 	}
 }
 
+static void append_l2conn_data(struct bthost *bthost, struct l2conn *conn,
+				const void *data, uint16_t len)
+{
+	if (!conn->recv_data) {
+		bthost_debug(bthost, "Unexpected L2CAP SDU data: sCID 0x%4.4x ",
+								conn->scid);
+		return;
+	}
+
+	if (conn->recv_len + len > conn->data_len) {
+		bthost_debug(bthost, "Unexpected L2CAP SDU data: sCID 0x%4.4x ",
+								conn->scid);
+		return;
+	}
+
+	memcpy(conn->recv_data + conn->recv_len, data, len);
+	conn->recv_len += len;
+
+	bthost_debug(bthost, "L2CAP SDU data: %u/%u bytes", conn->recv_len,
+							conn->data_len);
+}
+
+static void free_l2conn_data(struct l2conn *conn)
+{
+	free(conn->recv_data);
+	conn->recv_data = NULL;
+	conn->recv_len = 0;
+	conn->data_len = 0;
+}
+
+static void new_l2conn_data(struct bthost *bthost, struct l2conn *conn,
+								uint16_t len)
+{
+	free(conn->recv_data);
+	conn->recv_data = malloc(len);
+	conn->recv_len = 0;
+	conn->data_len = len;
+}
+
+static bool process_l2cap_conn(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, struct iovec *data)
+{
+	struct bt_l2cap_pdu_le_flowctl_creds creds;
+	uint16_t sdu;
+
+	if (!l2conn)
+		return true;
+
+	switch (l2conn->mode) {
+	case L2CAP_MODE_LE_CRED:
+	case L2CAP_MODE_LE_ENH_CRED:
+		break;
+	case L2CAP_MODE_OTHER:
+		return true;
+	}
+
+	/* Credit-based flow control */
+
+	creds.cid = cpu_to_le16(l2conn->scid);
+	creds.credits = cpu_to_le16(1);
+	l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_LE_FLOWCTL_CREDS, 0,
+							&creds, sizeof(creds));
+
+	if (!l2conn->data_len) {
+		if (!util_iov_pull_le16(data, &sdu)) {
+			free_l2conn_data(l2conn);
+			bthost_debug(bthost, "L2CAP invalid SDU");
+			return false;
+		}
+		new_l2conn_data(bthost, l2conn, sdu);
+	}
+
+	append_l2conn_data(bthost, l2conn, data->iov_base, data->iov_len);
+
+	if (l2conn->recv_len < l2conn->data_len)
+		return false;  /* SDU incomplete */
+
+	l2conn->data_len = 0;
+	data->iov_base = l2conn->recv_data;
+	data->iov_len = l2conn->recv_len;
+
+	return true;
+}
+
 static void process_l2cap(struct bthost *bthost, struct btconn *conn,
-					const void *data, uint16_t len)
+					const void *buf, uint16_t len)
 {
-	const struct bt_l2cap_hdr *l2_hdr = data;
+	const struct bt_l2cap_hdr *l2_hdr = buf;
 	struct cid_hook *hook;
 	struct l2conn *l2conn;
+	struct iovec data;
 	uint16_t cid, l2_len;
 
 	l2_len = le16_to_cpu(l2_hdr->len);
@@ -2620,31 +2806,37 @@ static void process_l2cap(struct bthost *bthost, struct btconn *conn,
 	bthost_debug(bthost, "L2CAP data: %u bytes", l2_len);
 
 	cid = le16_to_cpu(l2_hdr->cid);
+	l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
+
+	data.iov_base = (void *)l2_hdr->data;
+	data.iov_len = l2_len;
+
+	if (!process_l2cap_conn(bthost, conn, l2conn, &data))
+		return;
 
 	hook = find_cid_hook(conn, cid);
 	if (hook) {
-		hook->func(l2_hdr->data, l2_len, hook->user_data);
+		hook->func(data.iov_base, data.iov_len, hook->user_data);
 		return;
 	}
 
 	switch (cid) {
 	case 0x0001:
-		l2cap_sig(bthost, conn, l2_hdr->data, l2_len);
+		l2cap_sig(bthost, conn, data.iov_base, data.iov_len);
 		break;
 	case 0x0005:
-		l2cap_le_sig(bthost, conn, l2_hdr->data, l2_len);
+		l2cap_le_sig(bthost, conn, data.iov_base, data.iov_len);
 		break;
 	case 0x0006:
-		smp_data(conn->smp_data, l2_hdr->data, l2_len);
+		smp_data(conn->smp_data, data.iov_base, data.iov_len);
 		break;
 	case 0x0007:
-		smp_bredr_data(conn->smp_data, l2_hdr->data, l2_len);
+		smp_bredr_data(conn->smp_data, data.iov_base, data.iov_len);
 		break;
 	default:
-		l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
 		if (l2conn && l2conn->psm == 0x0003)
-			process_rfcomm(bthost, conn, l2conn, l2_hdr->data,
-								l2_len);
+			process_rfcomm(bthost, conn, l2conn, data.iov_base,
+								data.iov_len);
 		else
 			bthost_debug(bthost,
 					"Packet for unknown CID 0x%04x (%u)",
@@ -2893,9 +3085,10 @@ void bthost_set_connect_cb(struct bthost *bthost, bthost_new_conn_cb cb,
 	bthost->new_conn_data = user_data;
 }
 
-void bthost_set_iso_cb(struct bthost *bthost, bthost_new_conn_cb cb,
-							void *user_data)
+void bthost_set_iso_cb(struct bthost *bthost, bthost_accept_conn_cb accept,
+				bthost_new_conn_cb cb, void *user_data)
 {
+	bthost->accept_iso_cb = accept;
 	bthost->new_iso_cb = cb;
 	bthost->new_iso_data = user_data;
 }
@@ -3092,6 +3285,73 @@ void bthost_set_pa_params(struct bthost *bthost)
 	send_command(bthost, BT_HCI_CMD_LE_SET_PA_PARAMS, &cp, sizeof(cp));
 }
 
+static void set_pa_data(struct bthost *bthost, const uint8_t *data,
+				uint8_t len, uint8_t offset)
+{
+	struct bt_hci_cmd_le_set_pa_data *cp;
+	uint8_t buf[sizeof(*cp) + BT_PA_MAX_DATA_LEN];
+	size_t data_len;
+
+	cp = (void *)buf;
+
+	memset(cp, 0, sizeof(*cp));
+	memset(cp->data, 0, BT_PA_MAX_DATA_LEN);
+
+	cp->handle = 1;
+
+	if (len - offset > BT_PA_MAX_DATA_LEN) {
+		data_len = BT_PA_MAX_DATA_LEN;
+
+		if (!offset)
+			cp->operation = 0x01;
+		else
+			cp->operation = 0x00;
+	} else {
+		data_len = len - offset;
+
+		if (!offset)
+			cp->operation = 0x03;
+		else
+			cp->operation = 0x02;
+	}
+
+	memcpy(cp->data, data + offset, data_len);
+	cp->data_len = data_len;
+
+	send_command(bthost, BT_HCI_CMD_LE_SET_PA_DATA, buf,
+					sizeof(*cp) + cp->data_len);
+
+	if (cp->operation == 0x01 || cp->operation == 0x00) {
+		offset += cp->data_len;
+		set_pa_data(bthost, data, len, offset);
+	}
+}
+
+void bthost_set_pa_data(struct bthost *bthost, const uint8_t *data,
+							uint8_t len)
+{
+	set_pa_data(bthost, data, len, 0);
+}
+
+void bthost_set_base(struct bthost *bthost, const uint8_t *data, uint8_t len)
+{
+	struct bt_ad *ad;
+	bt_uuid_t uuid;
+	uint8_t *pa_data;
+	size_t pa_len;
+
+	bt_uuid16_create(&uuid, BAA_SERVICE);
+
+	ad = bt_ad_new();
+	bt_ad_set_max_len(ad, BT_PA_MAX_DATA_LEN);
+	bt_ad_add_service_data(ad, &uuid, (void *)data, len);
+
+	pa_data = bt_ad_generate(ad, &pa_len);
+	bthost_set_pa_data(bthost, pa_data, pa_len);
+
+	bt_ad_unref(ad);
+}
+
 void bthost_set_pa_enable(struct bthost *bthost, uint8_t enable)
 {
 	struct bt_hci_cmd_le_set_pa_enable cp;
@@ -3102,7 +3362,8 @@ void bthost_set_pa_enable(struct bthost *bthost, uint8_t enable)
 	send_command(bthost, BT_HCI_CMD_LE_SET_PA_ENABLE, &cp, sizeof(cp));
 }
 
-void bthost_create_big(struct bthost *bthost, uint8_t num_bis)
+void bthost_create_big(struct bthost *bthost, uint8_t num_bis,
+				uint8_t enc, const uint8_t *bcode)
 {
 	struct bt_hci_cmd_le_create_big cp;
 
@@ -3115,6 +3376,8 @@ void bthost_create_big(struct bthost *bthost, uint8_t num_bis)
 	cp.bis.latency = cpu_to_le16(10);
 	cp.bis.rtn = 0x02;
 	cp.bis.phy = 0x02;
+	cp.bis.encryption = enc;
+	memcpy(cp.bis.bcode, bcode, sizeof(cp.bis.bcode));
 	send_command(bthost, BT_HCI_CMD_LE_CREATE_BIG, &cp, sizeof(cp));
 }
 
@@ -3144,22 +3407,24 @@ void bthost_set_cig_params(struct bthost *bthost, uint8_t cig_id,
 	cp = malloc(sizeof(*cp) + sizeof(*cp->cis));
 	memset(cp, 0, sizeof(*cp) + sizeof(*cp->cis));
 	cp->cig_id = cig_id;
-	put_le24(qos->in.interval ? qos->in.interval : qos->out.interval,
-							cp->c_interval);
-	put_le24(qos->out.interval ? qos->out.interval : qos->in.interval,
-							cp->p_interval);
-	cp->c_latency = cpu_to_le16(qos->in.latency ? qos->in.latency :
-							qos->out.latency);
-	cp->p_latency = cpu_to_le16(qos->out.latency ? qos->out.latency :
-							qos->in.latency);
+	put_le24(qos->ucast.in.interval ? qos->ucast.in.interval :
+				qos->ucast.out.interval, cp->c_interval);
+	put_le24(qos->ucast.out.interval ? qos->ucast.out.interval :
+				qos->ucast.in.interval, cp->p_interval);
+	cp->c_latency = cpu_to_le16(qos->ucast.in.latency ?
+				qos->ucast.in.latency : qos->ucast.out.latency);
+	cp->p_latency = cpu_to_le16(qos->ucast.out.latency ?
+				qos->ucast.out.latency : qos->ucast.in.latency);
 	cp->num_cis = 0x01;
 	cp->cis[0].cis_id = cis_id;
-	cp->cis[0].c_sdu = qos->in.sdu;
-	cp->cis[0].p_sdu = qos->out.sdu;
-	cp->cis[0].c_phy = qos->in.phy ? qos->in.phy : qos->out.phy;
-	cp->cis[0].p_phy = qos->out.phy ? qos->out.phy : qos->in.phy;
-	cp->cis[0].c_rtn = qos->in.rtn;
-	cp->cis[0].p_rtn = qos->out.rtn;
+	cp->cis[0].c_sdu = qos->ucast.in.sdu;
+	cp->cis[0].p_sdu = qos->ucast.out.sdu;
+	cp->cis[0].c_phy = qos->ucast.in.phy ? qos->ucast.in.phy :
+							qos->ucast.out.phy;
+	cp->cis[0].p_phy = qos->ucast.out.phy ? qos->ucast.out.phy :
+							qos->ucast.in.phy;
+	cp->cis[0].c_rtn = qos->ucast.in.rtn;
+	cp->cis[0].p_rtn = qos->ucast.out.rtn;
 
 	send_command(bthost, BT_HCI_CMD_LE_SET_CIG_PARAMS, cp,
 				sizeof(*cp) + sizeof(*cp->cis));
@@ -3250,7 +3515,8 @@ uint64_t bthost_conn_get_fixed_chan(struct bthost *bthost, uint16_t handle)
 	return conn->fixed_chan;
 }
 
-void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
+void bthost_add_l2cap_server_custom(struct bthost *bthost, uint16_t psm,
+				uint16_t mtu, uint16_t mps, uint16_t credits,
 				bthost_l2cap_connect_cb func,
 				bthost_l2cap_disconnect_cb disconn_func,
 				void *user_data)
@@ -3262,6 +3528,9 @@ void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
 		return;
 
 	data->psm = psm;
+	data->mtu = mtu;
+	data->mps = mps;
+	data->credits = credits;
 	data->user_data = user_data;
 	data->func = func;
 	data->disconn_func = disconn_func;
@@ -3270,6 +3539,15 @@ void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
 	bthost->new_l2cap_conn_data = data;
 }
 
+void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
+				bthost_l2cap_connect_cb func,
+				bthost_l2cap_disconnect_cb disconn_func,
+				void *user_data)
+{
+	bthost_add_l2cap_server_custom(bthost, psm, 0, 0, 0, func,
+					disconn_func, user_data);
+}
+
 void bthost_set_sc_support(struct bthost *bthost, bool enable)
 {
 	struct bt_hci_cmd_write_secure_conn_support cmd;
@@ -3454,7 +3732,7 @@ void bthost_send_rfcomm_data(struct bthost *bthost, uint16_t handle,
 	}
 
 	uih_frame[uih_len - 1] = rfcomm_fcs((void *)hdr);
-	send_acl(bthost, handle, rcconn->scid, uih_frame, uih_len);
+	send_acl(bthost, handle, rcconn->scid, false, uih_frame, uih_len);
 
 	free(uih_frame);
 }
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 2cfdef7..2c5b0d5 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2012  Intel Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -44,13 +45,14 @@ typedef void (*bthost_cmd_complete_cb) (uint16_t opcode, uint8_t status,
 void bthost_set_cmd_complete_cb(struct bthost *bthost,
 				bthost_cmd_complete_cb cb, void *user_data);
 
+typedef uint8_t (*bthost_accept_conn_cb) (uint16_t handle, void *user_data);
 typedef void (*bthost_new_conn_cb) (uint16_t handle, void *user_data);
 
 void bthost_set_connect_cb(struct bthost *bthost, bthost_new_conn_cb cb,
 							void *user_data);
 
-void bthost_set_iso_cb(struct bthost *bthost, bthost_new_conn_cb cb,
-							void *user_data);
+void bthost_set_iso_cb(struct bthost *bthost, bthost_accept_conn_cb accept,
+				bthost_new_conn_cb cb, void *user_data);
 
 void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
 							uint8_t addr_type);
@@ -78,8 +80,9 @@ void bthost_send_cid(struct bthost *bthost, uint16_t handle, uint16_t cid,
 					const void *data, uint16_t len);
 void bthost_send_cid_v(struct bthost *bthost, uint16_t handle, uint16_t cid,
 					const struct iovec *iov, int iovcnt);
-void bthost_send_iso(struct bthost *bthost, uint16_t handle,
-					const struct iovec *iov, int iovcnt);
+void bthost_send_iso(struct bthost *bthost, uint16_t handle, bool ts,
+			uint16_t sn, uint32_t timestamp, uint8_t pkt_status,
+			const struct iovec *iov, int iovcnt);
 
 typedef void (*bthost_l2cap_rsp_cb) (uint8_t code, const void *data,
 						uint16_t len, void *user_data);
@@ -99,8 +102,12 @@ void bthost_set_ext_adv_data(struct bthost *bthost, const uint8_t *data,
 void bthost_set_ext_adv_params(struct bthost *bthost);
 void bthost_set_ext_adv_enable(struct bthost *bthost, uint8_t enable);
 void bthost_set_pa_params(struct bthost *bthost);
+void bthost_set_pa_data(struct bthost *bthost, const uint8_t *data,
+								uint8_t len);
+void bthost_set_base(struct bthost *bthost, const uint8_t *data, uint8_t len);
 void bthost_set_pa_enable(struct bthost *bthost, uint8_t enable);
-void bthost_create_big(struct bthost *bthost, uint8_t num_bis);
+void bthost_create_big(struct bthost *bthost, uint8_t num_bis, uint8_t enc,
+				const uint8_t *bcode);
 bool bthost_search_ext_adv_addr(struct bthost *bthost, const uint8_t *addr);
 
 void bthost_set_cig_params(struct bthost *bthost, uint8_t cig_id,
@@ -129,6 +136,11 @@ void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
 				bthost_l2cap_connect_cb func,
 				bthost_l2cap_disconnect_cb disconn_func,
 				void *user_data);
+void bthost_add_l2cap_server_custom(struct bthost *bthost, uint16_t psm,
+				uint16_t mtu, uint16_t mps, uint16_t credits,
+				bthost_l2cap_connect_cb func,
+				bthost_l2cap_disconnect_cb disconn_func,
+				void *user_data);
 
 void bthost_set_sc_support(struct bthost *bthost, bool enable);
 
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index dcfed9b..f13b4bd 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -21,6 +21,7 @@
 #include <stdbool.h>
 #include <errno.h>
 #include <sys/socket.h>
+#include <sys/ioctl.h>
 
 #include <glib.h>
 
@@ -41,6 +42,7 @@ struct hciemu_client {
 	guint start_source;
 	guint host_source;
 	guint source;
+	int sock[2];
 };
 
 struct hciemu {
@@ -54,6 +56,8 @@ struct hciemu {
 	hciemu_debug_func_t debug_callback;
 	hciemu_destroy_func_t debug_destroy;
 	void *debug_data;
+
+	unsigned int flush_id;
 };
 
 struct hciemu_command_hook {
@@ -186,14 +190,7 @@ static gboolean receive_btdev(GIOChannel *channel, GIOCondition condition,
 	if (len < 1)
 		return FALSE;
 
-	switch (buf[0]) {
-	case BT_H4_CMD_PKT:
-	case BT_H4_ACL_PKT:
-	case BT_H4_SCO_PKT:
-	case BT_H4_ISO_PKT:
-		btdev_receive_h4(btdev, buf, len);
-		break;
-	}
+	btdev_receive_h4(btdev, buf, len);
 
 	return TRUE;
 }
@@ -338,6 +335,9 @@ static struct hciemu_client *hciemu_client_new(struct hciemu *hciemu,
 		return NULL;
 	}
 
+	client->sock[0] = sv[0];
+	client->sock[1] = sv[1];
+
 	client->source = create_source_btdev(sv[0], client->dev);
 	client->host_source = create_source_bthost(sv[1], client->host);
 	client->start_source = g_idle_add(start_host, client);
@@ -435,6 +435,9 @@ void hciemu_unref(struct hciemu *hciemu)
 	queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
 	queue_destroy(hciemu->clients, hciemu_client_destroy);
 
+	if (hciemu->flush_id)
+		g_source_remove(hciemu->flush_id);
+
 	vhci_close(hciemu->vhci);
 
 	free(hciemu);
@@ -547,6 +550,15 @@ const uint8_t *hciemu_client_bdaddr(struct hciemu_client *client)
 	return btdev_get_bdaddr(client->dev);
 }
 
+bool hciemu_set_client_bdaddr(struct hciemu_client *client,
+				const uint8_t *bdaddr)
+{
+	if (!client)
+		return NULL;
+
+	return btdev_set_bdaddr(client->dev, bdaddr);
+}
+
 const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
 {
 	struct hciemu_client *client;
@@ -744,3 +756,47 @@ bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
 
 	return btdev_del_hook(dev, hook_type, opcode);
 }
+
+static bool client_is_pending(const void *data, const void *match_data)
+{
+	struct hciemu_client *client = (struct hciemu_client *)data;
+	int used, i;
+
+	if (!client->source || !client->host_source)
+		return false;
+
+	for (i = 0; i < 2; ++i) {
+		if (!ioctl(client->sock[i], TIOCOUTQ, &used) && used > 0)
+			return true;
+		if (!ioctl(client->sock[i], TIOCINQ, &used) && used > 0)
+			return true;
+	}
+
+	return false;
+}
+
+static gboolean flush_client_events(gpointer user_data)
+{
+	struct hciemu *hciemu = user_data;
+
+	if (queue_find(hciemu->clients, client_is_pending, NULL))
+		return TRUE;
+
+	hciemu->flush_id = 0;
+
+	util_debug(hciemu->debug_callback, hciemu->debug_data, "vhci: resume");
+	if (hciemu->vhci)
+		vhci_pause_input(hciemu->vhci, false);
+
+	return FALSE;
+}
+
+void hciemu_flush_client_events(struct hciemu *hciemu)
+{
+	if (hciemu->flush_id || !hciemu->vhci)
+		return;
+
+	util_debug(hciemu->debug_callback, hciemu->debug_data, "vhci: pause");
+	vhci_pause_input(hciemu->vhci, true);
+	hciemu->flush_id = g_idle_add(flush_client_events, hciemu);
+}
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index 3a06ca5..dba920f 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -39,6 +39,8 @@ void hciemu_unref(struct hciemu *hciemu);
 struct hciemu_client *hciemu_get_client(struct hciemu *hciemu, int num);
 struct bthost *hciemu_client_host(struct hciemu_client *client);
 const uint8_t *hciemu_client_bdaddr(struct hciemu_client *client);
+bool hciemu_set_client_bdaddr(struct hciemu_client *client,
+				const uint8_t *bdaddr);
 
 typedef void (*hciemu_debug_func_t)(const char *str, void *user_data);
 typedef void (*hciemu_destroy_func_t)(void *user_data);
@@ -48,6 +50,9 @@ bool hciemu_set_debug(struct hciemu *hciemu, hciemu_debug_func_t callback,
 struct vhci *hciemu_get_vhci(struct hciemu *hciemu);
 struct bthost *hciemu_client_get_host(struct hciemu *hciemu);
 
+/* Process pending client events before new VHCI events */
+void hciemu_flush_client_events(struct hciemu *hciemu);
+
 const char *hciemu_get_address(struct hciemu *hciemu);
 uint8_t *hciemu_get_features(struct hciemu *hciemu);
 
diff --git a/emulator/serial.c b/emulator/serial.c
index c9e6d7c..b74556b 100644
--- a/emulator/serial.c
+++ b/emulator/serial.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <sys/param.h>
 #include <sys/epoll.h>
 #include <sys/uio.h>
diff --git a/emulator/vhci.c b/emulator/vhci.c
index a12b11e..cab3535 100644
--- a/emulator/vhci.c
+++ b/emulator/vhci.c
@@ -22,6 +22,8 @@
 #include <sys/uio.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
@@ -32,6 +34,7 @@
 #include "vhci.h"
 
 #define DEBUGFS_PATH "/sys/kernel/debug/bluetooth"
+#define DEVCORE_PATH "/sys/class/devcoredump"
 
 struct vhci {
 	enum btdev_type type;
@@ -72,14 +75,7 @@ static bool vhci_read_callback(struct io *io, void *user_data)
 	if (len < 1)
 		return false;
 
-	switch (buf[0]) {
-	case BT_H4_CMD_PKT:
-	case BT_H4_ACL_PKT:
-	case BT_H4_SCO_PKT:
-	case BT_H4_ISO_PKT:
-		btdev_receive_h4(vhci->btdev, buf, len);
-		break;
-	}
+	btdev_receive_h4(vhci->btdev, buf, len);
 
 	return true;
 }
@@ -127,14 +123,16 @@ struct vhci *vhci_open(uint8_t type)
 		break;
 	}
 
-	if (write(fd, &req, sizeof(req)) < 0) {
+	if (write(fd, &req, sizeof(req)) != sizeof(req)) {
 		close(fd);
 		return NULL;
 	}
 
 	memset(&rsp, 0, sizeof(rsp));
 
-	if (read(fd, &rsp, sizeof(rsp)) < 0) {
+	if (read(fd, &rsp, sizeof(rsp)) != sizeof(rsp) ||
+			rsp.pkt_type != HCI_VENDOR_PKT ||
+			rsp.opcode != req.opcode) {
 		close(fd);
 		return NULL;
 	}
@@ -176,6 +174,15 @@ void vhci_close(struct vhci *vhci)
 	vhci_destroy(vhci);
 }
 
+bool vhci_pause_input(struct vhci *vhci, bool paused)
+{
+	if (paused)
+		return io_set_read_handler(vhci->io, NULL, NULL, NULL);
+	else
+		return io_set_read_handler(vhci->io, vhci_read_callback, vhci,
+									NULL);
+}
+
 struct btdev *vhci_get_btdev(struct vhci *vhci)
 {
 	if (!vhci)
@@ -184,7 +191,7 @@ struct btdev *vhci_get_btdev(struct vhci *vhci)
 	return vhci->btdev;
 }
 
-static int vhci_debugfs_write(struct vhci *vhci, char *option, void *data,
+static int vhci_debugfs_write(struct vhci *vhci, char *option, const void *data,
 			      size_t len)
 {
 	char path[64];
@@ -267,3 +274,60 @@ int vhci_set_force_static_address(struct vhci *vhci, bool enable)
 	return vhci_debugfs_write(vhci, "force_static_address", &val,
 							sizeof(val));
 }
+
+int vhci_force_devcd(struct vhci *vhci, const void *data, size_t len)
+{
+	return vhci_debugfs_write(vhci, "force_devcoredump", data, len);
+}
+
+int vhci_read_devcd(struct vhci *vhci, void *buf, size_t size)
+{
+	DIR *dir;
+	struct dirent *entry;
+	char filename[PATH_MAX];
+	int fd;
+	int ret;
+
+	dir = opendir(DEVCORE_PATH);
+	if (dir == NULL)
+		return -errno;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strstr(entry->d_name, "devcd"))
+			break;
+	}
+
+	if (entry == NULL) {
+		ret = -ENOENT;
+		goto close_dir;
+	}
+
+	sprintf(filename, DEVCORE_PATH "/%s/data", entry->d_name);
+	fd  = open(filename, O_RDWR);
+	if (fd < 0) {
+		ret = -errno;
+		goto close_dir;
+	}
+
+	ret = read(fd, buf, size);
+	if (ret < 0) {
+		ret = -errno;
+		goto close_file;
+	}
+
+	/* Once the devcoredump is read, write anything to it to mark it for
+	 * cleanup.
+	 */
+	if (write(fd, "0", 1) < 0) {
+		ret = -errno;
+		goto close_file;
+	}
+
+close_file:
+	close(fd);
+
+close_dir:
+	closedir(dir);
+
+	return ret;
+}
diff --git a/emulator/vhci.h b/emulator/vhci.h
index 6da56cb..12c4b55 100644
--- a/emulator/vhci.h
+++ b/emulator/vhci.h
@@ -29,3 +29,6 @@ int vhci_set_msft_opcode(struct vhci *vhci, uint16_t opcode);
 int vhci_set_aosp_capable(struct vhci *vhci, bool enable);
 int vhci_set_emu_opcode(struct vhci *vhci, uint16_t opcode);
 int vhci_set_force_static_address(struct vhci *vhci, bool enable);
+int vhci_force_devcd(struct vhci *vhci, const void *data, size_t len);
+int vhci_read_devcd(struct vhci *vhci, void *buf, size_t size);
+bool vhci_pause_input(struct vhci *vhci, bool paused);
diff --git a/gdbus/client.c b/gdbus/client.c
index 3b7faa4..deeb01d 100644
--- a/gdbus/client.c
+++ b/gdbus/client.c
@@ -4,6 +4,7 @@
  *  D-Bus helper library
  *
  *  Copyright (C) 2004-2011  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2024 NXP
  *
  *
  */
@@ -15,6 +16,7 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <string.h>
+#include <stdarg.h>
 #include <glib.h>
 #include <dbus/dbus.h>
 
@@ -208,6 +210,44 @@ void g_dbus_dict_append_array(DBusMessageIter *dict,
 								n_elements);
 }
 
+static void append_dict_variant(DBusMessageIter *iter, char *entry, int type,
+							void *val, ...)
+{
+	DBusMessageIter variant, dict;
+	va_list args;
+	int array_type, size;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+					DBUS_TYPE_ARRAY_AS_STRING
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&variant);
+
+	dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	va_start(args, val);
+
+	if (type == DBUS_TYPE_ARRAY) {
+		array_type = va_arg(args, int);
+		size = va_arg(args, int);
+		g_dbus_dict_append_array(&dict, entry, array_type, val, size);
+	} else
+		g_dbus_dict_append_entry(&dict, entry, type, val);
+
+	va_end(args);
+
+	dbus_message_iter_close_container(&variant, &dict);
+
+	dbus_message_iter_close_container(iter, &variant);
+}
+
 static void iter_append_iter(DBusMessageIter *base, DBusMessageIter *iter)
 {
 	int type;
@@ -885,6 +925,81 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
 	return TRUE;
 }
 
+gboolean g_dbus_proxy_set_property_dict(GDBusProxy *proxy,
+				const char *name, GDBusResultFunction function,
+				void *user_data, GDBusDestroyFunction destroy,
+				char *entry, ...)
+{
+	struct set_property_data *data;
+	GDBusClient *client;
+	DBusMessage *msg;
+	DBusMessageIter iter;
+	DBusPendingCall *call;
+	va_list args;
+	int type, array_type, size;
+	void *value;
+
+	if (proxy == NULL || name == NULL)
+		return FALSE;
+
+	client = proxy->client;
+	if (client == NULL)
+		return FALSE;
+
+	data = g_try_new0(struct set_property_data, 1);
+	if (data == NULL)
+		return FALSE;
+
+	data->function = function;
+	data->user_data = user_data;
+	data->destroy = destroy;
+
+	msg = dbus_message_new_method_call(client->service_name,
+			proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Set");
+	if (msg == NULL) {
+		g_free(data);
+		return FALSE;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+							&proxy->interface);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+	va_start(args, entry);
+
+	while (entry != NULL) {
+		type = va_arg(args, int);
+		if (type == DBUS_TYPE_ARRAY) {
+			array_type = va_arg(args, int);
+			size = va_arg(args, int);
+			value = va_arg(args, void *);
+			append_dict_variant(&iter, entry, type, &value,
+							array_type, size);
+		} else {
+			value = va_arg(args, void *);
+			append_dict_variant(&iter, entry, type, &value);
+		}
+		entry = va_arg(args, char *);
+	}
+
+	va_end(args);
+
+	if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
+							&call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		g_free(data);
+		return FALSE;
+	}
+
+	dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
+	dbus_pending_call_unref(call);
+
+	dbus_message_unref(msg);
+
+	return TRUE;
+}
+
 gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
 				const char *name, int type, const void *value,
 				size_t size, GDBusResultFunction function,
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 28b8022..49ea587 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -4,6 +4,7 @@
  *  D-Bus helper library
  *
  *  Copyright (C) 2004-2011  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2024 NXP
  *
  *
  */
@@ -72,6 +73,7 @@ typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
 
 enum GDBusFlags {
 	G_DBUS_FLAG_ENABLE_EXPERIMENTAL = (1 << 0),
+	G_DBUS_FLAG_ENABLE_TESTING      = (1 << 1),
 };
 
 enum GDBusMethodFlags {
@@ -79,16 +81,19 @@ enum GDBusMethodFlags {
 	G_DBUS_METHOD_FLAG_NOREPLY      = (1 << 1),
 	G_DBUS_METHOD_FLAG_ASYNC        = (1 << 2),
 	G_DBUS_METHOD_FLAG_EXPERIMENTAL = (1 << 3),
+	G_DBUS_METHOD_FLAG_TESTING      = (1 << 4),
 };
 
 enum GDBusSignalFlags {
 	G_DBUS_SIGNAL_FLAG_DEPRECATED   = (1 << 0),
 	G_DBUS_SIGNAL_FLAG_EXPERIMENTAL = (1 << 1),
+	G_DBUS_SIGNAL_FLAG_TESTING      = (1 << 2),
 };
 
 enum GDBusPropertyFlags {
 	G_DBUS_PROPERTY_FLAG_DEPRECATED   = (1 << 0),
 	G_DBUS_PROPERTY_FLAG_EXPERIMENTAL = (1 << 1),
+	G_DBUS_PROPERTY_FLAG_TESTING      = (1 << 2),
 };
 
 enum GDBusSecurityFlags {
@@ -186,6 +191,20 @@ struct GDBusSecurityTable {
 	.function = _function, \
 	.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_EXPERIMENTAL
 
+#define GDBUS_TESTING_METHOD(_name, _in_args, _out_args, _function) \
+	.name = _name, \
+	.in_args = _in_args, \
+	.out_args = _out_args, \
+	.function = _function, \
+	.flags = G_DBUS_METHOD_FLAG_TESTING
+
+#define GDBUS_TESTING_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+	.name = _name, \
+	.in_args = _in_args, \
+	.out_args = _out_args, \
+	.function = _function, \
+	.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_TESTING
+
 #define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \
 	.name = _name, \
 	.in_args = _in_args, \
@@ -207,9 +226,20 @@ struct GDBusSecurityTable {
 	.args = _args, \
 	.flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL
 
+#define GDBUS_TESTING_SIGNAL(_name, _args) \
+	.name = _name, \
+	.args = _args, \
+	.flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL
+
 void g_dbus_set_flags(int flags);
 int g_dbus_get_flags(void);
 
+typedef void (*g_dbus_destroy_func_t)(void *user_data);
+typedef void (*g_dbus_debug_func_t)(const char *str, void *user_data);
+
+void g_dbus_set_debug(g_dbus_debug_func_t cb, void *user_data,
+				g_dbus_destroy_func_t destroy);
+
 gboolean g_dbus_register_interface(DBusConnection *connection,
 					const char *path, const char *name,
 					const GDBusMethodTable *methods,
@@ -284,6 +314,7 @@ guint g_dbus_add_properties_watch(DBusConnection *connection,
 gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
 void g_dbus_remove_all_watches(DBusConnection *connection);
 
+const char *g_dbus_pending_property_get_sender(GDBusPendingPropertySet id);
 void g_dbus_pending_property_success(GDBusPendingPropertySet id);
 void g_dbus_pending_property_error_valist(GDBusPendingReply id,
 			const char *name, const char *format, va_list args);
@@ -339,6 +370,11 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
 				GDBusResultFunction function, void *user_data,
 				GDBusDestroyFunction destroy);
 
+gboolean g_dbus_proxy_set_property_dict(GDBusProxy *proxy,
+				const char *name, GDBusResultFunction function,
+				void *user_data, GDBusDestroyFunction destroy,
+				char *entry, ...);
+
 gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
 				const char *name, int type, const void *value,
 				size_t size, GDBusResultFunction function,
diff --git a/gdbus/object.c b/gdbus/object.c
index f7c8c2b..84f116b 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -14,11 +14,13 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 
 #include "gdbus.h"
+#include "src/shared/util.h"
 
 #define info(fmt...)
 #define error(fmt...)
@@ -71,9 +73,16 @@ struct property_data {
 	DBusMessage *message;
 };
 
+struct debug_data {
+	g_dbus_debug_func_t func;
+	g_dbus_destroy_func_t destroy;
+	void *data;
+};
+
 static int global_flags = 0;
 static struct generic_data *root;
 static GSList *pending = NULL;
+static struct debug_data debug = { NULL, NULL, NULL };
 
 static gboolean process_changes(gpointer user_data);
 static void process_properties_from_interface(struct generic_data *data,
@@ -115,6 +124,28 @@ static gboolean check_experimental(int flags, int flag)
 	return !(global_flags & G_DBUS_FLAG_ENABLE_EXPERIMENTAL);
 }
 
+static bool check_testing(int flags, int flag)
+{
+	if (!(flags & flag))
+		return false;
+
+	return !(global_flags & G_DBUS_FLAG_ENABLE_TESTING);
+}
+
+static void g_dbus_debug(const char *format, ...)
+{
+	va_list va;
+	char str[MAX_INPUT];
+
+	if (!format || !debug.func)
+		return;
+
+	va_start(va, format);
+	vsnprintf(str, sizeof(str), format, va);
+	debug.func(str, debug.data);
+	va_end(va);
+}
+
 static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 {
 	const GDBusMethodTable *method;
@@ -126,6 +157,9 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<method name=\"%s\">",
 								method->name);
 		print_arguments(gstr, method->in_args, "in");
@@ -146,6 +180,9 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(signal->flags, G_DBUS_SIGNAL_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<signal name=\"%s\">",
 								signal->name);
 		print_arguments(gstr, signal->args, NULL);
@@ -163,6 +200,10 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(property->flags,
+					G_DBUS_PROPERTY_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<property name=\"%s\""
 					" type=\"%s\" access=\"%s%s\">",
 					property->name,	property->type,
@@ -411,28 +452,45 @@ static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
 static GDBusPendingPropertySet next_pending_property = 1;
 static GSList *pending_property_set;
 
+static int pending_property_data_compare_id(const void *data,
+						const void *user_data)
+{
+	const struct property_data *propdata = data;
+	const GDBusPendingPropertySet *id = user_data;
+	return propdata->id - *id;
+}
+
 static struct property_data *remove_pending_property_data(
 						GDBusPendingPropertySet id)
 {
 	struct property_data *propdata;
 	GSList *l;
 
-	for (l = pending_property_set; l != NULL; l = l->next) {
-		propdata = l->data;
-		if (propdata->id != id)
-			continue;
-
-		break;
-	}
-
+	l = g_slist_find_custom(pending_property_set, &id,
+				pending_property_data_compare_id);
 	if (l == NULL)
 		return NULL;
 
+	propdata = l->data;
 	pending_property_set = g_slist_delete_link(pending_property_set, l);
 
 	return propdata;
 }
 
+const char *g_dbus_pending_property_get_sender(GDBusPendingPropertySet id)
+{
+	struct property_data *propdata;
+	GSList *l;
+
+	l = g_slist_find_custom(pending_property_set, &id,
+					pending_property_data_compare_id);
+	if (l == NULL)
+		return NULL;
+
+	propdata = l->data;
+	return dbus_message_get_sender(propdata->message);
+}
+
 void g_dbus_pending_property_success(GDBusPendingPropertySet id)
 {
 	struct property_data *propdata;
@@ -518,6 +576,9 @@ static void append_properties(struct interface_data *data,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(p->flags, G_DBUS_PROPERTY_FLAG_TESTING))
+			continue;
+
 		if (p->get == NULL)
 			continue;
 
@@ -543,6 +604,22 @@ static void append_interface(gpointer data, gpointer user_data)
 	dbus_message_iter_close_container(array, &entry);
 }
 
+static const char *dbus_message_type_string(DBusMessage *msg)
+{
+	return dbus_message_type_to_string(dbus_message_get_type(msg));
+}
+
+static void g_dbus_send_unref(DBusConnection *conn, DBusMessage *msg)
+{
+	g_dbus_debug("[%s] %s.%s",
+			dbus_message_type_string(msg),
+			dbus_message_get_interface(msg),
+			dbus_message_get_member(msg));
+
+	dbus_connection_send(conn, msg, NULL);
+	dbus_message_unref(msg);
+}
+
 static void emit_interfaces_added(struct generic_data *data)
 {
 	DBusMessage *signal;
@@ -583,9 +660,8 @@ static void emit_interfaces_added(struct generic_data *data)
 
 	dbus_message_iter_close_container(&iter, &array);
 
-	/* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
-	dbus_connection_send(data->conn, signal, NULL);
-	dbus_message_unref(signal);
+	/* Use g_dbus_send_unref to avoid recursive calls to g_dbus_flush */
+	g_dbus_send_unref(data->conn, signal);
 }
 
 static struct interface_data *find_interface(GSList *interfaces,
@@ -749,6 +825,9 @@ static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			break;
 
+		if (check_testing(p->flags, G_DBUS_PROPERTY_FLAG_TESTING))
+			break;
+
 		return p;
 	}
 
@@ -977,9 +1056,8 @@ static void emit_interfaces_removed(struct generic_data *data)
 
 	dbus_message_iter_close_container(&iter, &array);
 
-	/* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
-	dbus_connection_send(data->conn, signal, NULL);
-	dbus_message_unref(signal);
+	/* Use g_dbus_send_unref to avoid recursive calls to g_dbus_flush */
+	g_dbus_send_unref(data->conn, signal);
 }
 
 static void remove_pending(struct generic_data *data)
@@ -1044,6 +1122,13 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
 	const GDBusMethodTable *method;
 	const char *interface;
 
+	g_dbus_debug("[%s:%s] > %s.%s [#%d]",
+			dbus_message_get_sender(message),
+			dbus_message_type_string(message),
+			dbus_message_get_interface(message),
+			dbus_message_get_member(message),
+			dbus_message_get_serial(message));
+
 	interface = dbus_message_get_interface(message);
 
 	iface = find_interface(data->interfaces, interface);
@@ -1061,6 +1146,9 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
+		if (check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
 		if (g_dbus_args_have_signature(method->in_args,
 							message) == FALSE)
 			continue;
@@ -1190,18 +1278,26 @@ static gboolean add_interface(struct generic_data *data,
 		if (!check_experimental(method->flags,
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			goto done;
+
+		if (!check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			goto done;
 	}
 
 	for (signal = signals; signal && signal->name; signal++) {
 		if (!check_experimental(signal->flags,
 					G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
 			goto done;
+		if (!check_testing(signal->flags, G_DBUS_SIGNAL_FLAG_TESTING))
+			goto done;
 	}
 
 	for (property = properties; property && property->name; property++) {
 		if (!check_experimental(property->flags,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			goto done;
+		if (!check_testing(property->flags,
+					G_DBUS_PROPERTY_FLAG_TESTING))
+			goto done;
 	}
 
 	/* Nothing to register */
@@ -1523,6 +1619,35 @@ gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
 	/* Flush pending signal to guarantee message order */
 	g_dbus_flush(connection);
 
+	switch (dbus_message_get_type(message)) {
+	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+		g_dbus_debug("[%s:%s] < [#%d]",
+				dbus_message_get_destination(message),
+				dbus_message_type_string(message),
+				dbus_message_get_reply_serial(message));
+		break;
+	case DBUS_MESSAGE_TYPE_ERROR:
+		g_dbus_debug("[%s:%s] < %s [#%d]",
+				dbus_message_get_destination(message),
+				dbus_message_type_string(message),
+				dbus_message_get_error_name(message),
+				dbus_message_get_reply_serial(message));
+		break;
+	case DBUS_MESSAGE_TYPE_SIGNAL:
+		g_dbus_debug("[%s] %s.%s",
+				dbus_message_type_string(message),
+				dbus_message_get_interface(message),
+				dbus_message_get_member(message));
+		break;
+	default:
+		g_dbus_debug("[%s:%s] < %s.%s",
+				dbus_message_get_destination(message),
+				dbus_message_type_string(message),
+				dbus_message_get_interface(message),
+				dbus_message_get_member(message));
+		break;
+	}
+
 	result = dbus_connection_send(connection, message, NULL);
 
 out:
@@ -1548,6 +1673,12 @@ gboolean g_dbus_send_message_with_reply(DBusConnection *connection,
 		return FALSE;
 	}
 
+	g_dbus_debug("[%s:%s] < %s.%s",
+			dbus_message_get_destination(message),
+			dbus_message_type_string(message),
+			dbus_message_get_interface(message),
+			dbus_message_get_member(message));
+
 	return ret;
 }
 
@@ -1720,9 +1851,8 @@ static void process_properties_from_interface(struct generic_data *data,
 	g_slist_free(iface->pending_prop);
 	iface->pending_prop = NULL;
 
-	/* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
-	dbus_connection_send(data->conn, signal, NULL);
-	dbus_message_unref(signal);
+	/* Use g_dbus_send_unref to avoid recursive calls to g_dbus_flush */
+	g_dbus_send_unref(data->conn, signal);
 }
 
 static void process_property_changes(struct generic_data *data)
@@ -1849,3 +1979,14 @@ int g_dbus_get_flags(void)
 {
 	return global_flags;
 }
+
+void g_dbus_set_debug(g_dbus_debug_func_t cb, void *user_data,
+				g_dbus_destroy_func_t destroy)
+{
+	if (debug.destroy)
+		debug.destroy(debug.data);
+
+	debug.func = cb;
+	debug.destroy = destroy;
+	debug.data = user_data;
+}
diff --git a/gdbus/watch.c b/gdbus/watch.c
index 25f3676..22f77ea 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -123,29 +123,51 @@ static struct filter_data *filter_data_find(DBusConnection *connection)
 	return NULL;
 }
 
-static void format_rule(struct filter_data *data, char *rule, size_t size)
+static gboolean format_rule(struct filter_data *data, char *rule, size_t size)
 {
 	const char *sender;
-	int offset;
+	int offset, ret;
 
 	offset = snprintf(rule, size, "type='signal'");
+	if (offset < 0)
+		return FALSE;
 	sender = data->name ? : data->owner;
 
-	if (sender)
-		offset += snprintf(rule + offset, size - offset,
+	if (sender) {
+		ret = snprintf(rule + offset, size - offset,
 				",sender='%s'", sender);
-	if (data->path)
-		offset += snprintf(rule + offset, size - offset,
+		if (ret < 0)
+			return FALSE;
+		offset += ret;
+	}
+	if (data->path) {
+		ret = snprintf(rule + offset, size - offset,
 				",path='%s'", data->path);
-	if (data->interface)
-		offset += snprintf(rule + offset, size - offset,
+		if (ret < 0)
+			return FALSE;
+		offset += ret;
+	}
+	if (data->interface) {
+		ret = snprintf(rule + offset, size - offset,
 				",interface='%s'", data->interface);
-	if (data->member)
-		offset += snprintf(rule + offset, size - offset,
+		if (ret < 0)
+			return FALSE;
+		offset += ret;
+	}
+	if (data->member) {
+		ret = snprintf(rule + offset, size - offset,
 				",member='%s'", data->member);
-	if (data->argument)
-		snprintf(rule + offset, size - offset,
+		if (ret < 0)
+			return FALSE;
+		offset += ret;
+	}
+	if (data->argument) {
+		ret = snprintf(rule + offset, size - offset,
 				",arg0='%s'", data->argument);
+		if (ret < 0)
+			return FALSE;
+	}
+	return TRUE;
 }
 
 static gboolean add_match(struct filter_data *data,
diff --git a/gobex/gobex-header.c b/gobex/gobex-header.c
index 002ba88..f368f0e 100644
--- a/gobex/gobex-header.c
+++ b/gobex/gobex-header.c
@@ -62,6 +62,34 @@ static glong utf8_to_utf16(gunichar2 **utf16, const char *utf8) {
 	return utf16_len;
 }
 
+static glong utf16_to_utf8(char **utf8, const gunichar2 *utf16, guint16 len,
+				GError **err)
+{
+	glong utf8_len;
+	guint16 utf16_len, i;
+	gunichar2 *buf;
+
+	if (*utf16 == '\0') {
+		*utf8 = NULL;
+		return 0;
+	}
+
+	/* OBEX requires network byteorder (big endian) UTF-16
+	 * but g_utf16_to_utf8 expects host-byteorder UTF-8
+	 */
+	utf16_len = len / sizeof(gunichar2);
+	buf = alloca(sizeof(gunichar2) * (utf16_len + 1));
+	for (i = 0; i < utf16_len; i++)
+		(buf)[i] = g_ntohs(utf16[i]);
+	buf[utf16_len] = '\0';
+
+	*utf8 = g_utf16_to_utf8(buf, -1, NULL, &utf8_len, err);
+	if (*utf8 == NULL)
+		utf8_len = -1;
+
+	return utf8_len;
+}
+
 static guint8 *put_bytes(guint8 *to, const void *from, gsize count)
 {
 	memcpy(to, from, count);
@@ -130,7 +158,7 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
 	GObexHeader *header;
 	const guint8 *ptr = data;
 	guint16 hdr_len;
-	gsize str_len;
+	glong str_len;
 	GError *conv_err = NULL;
 
 	if (len < 2) {
@@ -177,13 +205,14 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
 			goto failed;
 		}
 
-		header->v.string = g_convert((const char *) ptr, hdr_len - 5,
-						"UTF-8", "UTF-16BE",
-						NULL, &str_len, &conv_err);
-		if (header->v.string == NULL) {
+		str_len = utf16_to_utf8(&header->v.string,
+					(const gunichar2 *) ptr,
+					hdr_len - 5,
+					&conv_err);
+		if (str_len < 0) {
 			g_set_error(err, G_OBEX_ERROR,
 					G_OBEX_ERROR_PARSE_ERROR,
-					"Unicode conversion failed: %s",
+					"UTF16 to UTF8 conversion failed: %s",
 					conv_err->message);
 			g_error_free(conv_err);
 			goto failed;
diff --git a/gobex/gobex.c b/gobex/gobex.c
index e9b89ce..07e4662 100644
--- a/gobex/gobex.c
+++ b/gobex/gobex.c
@@ -122,7 +122,7 @@ struct setpath_data {
 	guint8 constants;
 } __attribute__ ((packed));
 
-static struct error_code {
+static const struct error_code {
 	guint8 code;
 	const char *name;
 } obex_errors[] = {
@@ -169,7 +169,7 @@ static struct error_code {
 
 const char *g_obex_strerror(guint8 err_code)
 {
-	struct error_code *error;
+	const struct error_code *error;
 
 	for (error = obex_errors; error->name != NULL; error++) {
 		if (error->code == err_code)
@@ -317,6 +317,15 @@ static void set_srm(GObex *obex, guint8 op, guint8 srm)
 	struct srm_config *config = obex->srm;
 	gboolean enable;
 
+	switch (srm) {
+	case G_OBEX_SRM_ENABLE:
+	case G_OBEX_SRM_DISABLE:
+	case G_OBEX_SRM_INDICATE:
+		break;
+	default:
+		return;
+	}
+
 	if (config == NULL) {
 		if (srm == G_OBEX_SRM_DISABLE)
 			return;
@@ -1423,7 +1432,7 @@ failed:
 	return FALSE;
 }
 
-static GDebugKey keys[] = {
+static const GDebugKey keys[] = {
 	{ "error",	G_OBEX_DEBUG_ERROR },
 	{ "command",	G_OBEX_DEBUG_COMMAND },
 	{ "transfer",	G_OBEX_DEBUG_TRANSFER },
@@ -1443,7 +1452,8 @@ GObex *g_obex_new(GIOChannel *io, GObexTransportType transport_type,
 		const char *env = g_getenv("GOBEX_DEBUG");
 
 		if (env) {
-			gobex_debug = g_parse_debug_string(env, keys, 7);
+			gobex_debug = g_parse_debug_string(env, keys,
+							G_N_ELEMENTS(keys));
 			g_setenv("G_MESSAGES_DEBUG", "gobex", FALSE);
 		} else
 			gobex_debug = G_OBEX_DEBUG_NONE;
@@ -1610,7 +1620,7 @@ guint g_obex_setpath(GObex *obex, const char *path, GObexResponseFunc func,
 
 	memset(&data, 0, sizeof(data));
 
-	if (path != NULL && strncmp("..", path, 2) == 0) {
+	if (path != NULL && strlen(path) >= 2 && strncmp("..", path, 2) == 0) {
 		data.flags = 0x03;
 		folder = (path[2] == '/') ? &path[3] : NULL;
 	} else {
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..ec298b5
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,541 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2020-11-14.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+tab='	'
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+# Create dirs (including intermediate dirs) using mode 755.
+# This is like GNU 'install' as of coreutils 8.32 (2020).
+mkdir_umask=22
+
+backupsuffix=
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+is_target_a_directory=possibly
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -p            pass -p to $cpprog.
+  -s            $stripprog installed files.
+  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+
+By default, rm is invoked with -f; when overridden with RMPROG,
+it's up to you to specify -f if you want it.
+
+If -S is not specified, no backups are attempted.
+
+Email bug reports to bug-automake@gnu.org.
+Automake home page: https://www.gnu.org/software/automake/
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+        case $mode in
+          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+            echo "$0: invalid mode: $mode" >&2
+            exit 1;;
+        esac
+        shift;;
+
+    -o) chowncmd="$chownprog $2"
+        shift;;
+
+    -p) cpprog="$cpprog -p";;
+
+    -s) stripcmd=$stripprog;;
+
+    -S) backupsuffix="$2"
+        shift;;
+
+    -t)
+        is_target_a_directory=always
+        dst_arg=$2
+        # Protect names problematic for 'test' and other utilities.
+        case $dst_arg in
+          -* | [=\(\)!]) dst_arg=./$dst_arg;;
+        esac
+        shift;;
+
+    -T) is_target_a_directory=never;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --) shift
+        break;;
+
+    -*) echo "$0: invalid option: $1" >&2
+        exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+  if test -n "$dst_arg"; then
+    echo "$0: target directory not allowed when installing a directory." >&2
+    exit 1
+  fi
+fi
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for 'test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call 'install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  if test $# -gt 1 || test "$is_target_a_directory" = always; then
+    if test ! -d "$dst_arg"; then
+      echo "$0: $dst_arg: Is not a directory." >&2
+      exit 1
+    fi
+  fi
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+        u_plus_rw=
+      else
+        u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+        u_plus_rw=
+      else
+        u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for 'test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+    # Don't chown directories that already exist.
+    if test $dstdir_status = 0; then
+      chowncmd=""
+    fi
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename.
+    if test -d "$dst"; then
+      if test "$is_target_a_directory" = never; then
+        echo "$0: $dst_arg: Is a directory" >&2
+        exit 1
+      fi
+      dstdir=$dst
+      dstbase=`basename "$src"`
+      case $dst in
+	*/) dst=$dst$dstbase;;
+	*)  dst=$dst/$dstbase;;
+      esac
+      dstdir_status=0
+    else
+      dstdir=`dirname "$dst"`
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  case $dstdir in
+    */) dstdirslash=$dstdir;;
+    *)  dstdirslash=$dstdir/;;
+  esac
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+        # With -d, create the new directory with the user-specified mode.
+        # Otherwise, rely on $mkdir_umask.
+        if test -n "$dir_arg"; then
+          mkdir_mode=-m$mode
+        else
+          mkdir_mode=
+        fi
+
+        posix_mkdir=false
+	# The $RANDOM variable is not portable (e.g., dash).  Use it
+	# here however when possible just to lower collision chance.
+	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+	trap '
+	  ret=$?
+	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
+	  exit $ret
+	' 0
+
+	# Because "mkdir -p" follows existing symlinks and we likely work
+	# directly in world-writeable /tmp, make sure that the '$tmpdir'
+	# directory is successfully created first before we actually test
+	# 'mkdir -p'.
+	if (umask $mkdir_umask &&
+	    $mkdirprog $mkdir_mode "$tmpdir" &&
+	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+	then
+	  if test -z "$dir_arg" || {
+	       # Check for POSIX incompatibilities with -m.
+	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+	       # other-writable bit of parent directory when it shouldn't.
+	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+	       test_tmpdir="$tmpdir/a"
+	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+	       case $ls_ld_tmpdir in
+		 d????-?r-*) different_mode=700;;
+		 d????-?--*) different_mode=755;;
+		 *) false;;
+	       esac &&
+	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+	       }
+	     }
+	  then posix_mkdir=:
+	  fi
+	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+	else
+	  # Remove any dirs left behind by ancient mkdir implementations.
+	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+	fi
+	trap '' 0;;
+    esac
+
+    if
+      $posix_mkdir && (
+        umask $mkdir_umask &&
+        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+        /*) prefix='/';;
+        [-=\(\)!]*) prefix='./';;
+        *)  prefix='';;
+      esac
+
+      oIFS=$IFS
+      IFS=/
+      set -f
+      set fnord $dstdir
+      shift
+      set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+        test X"$d" = X && continue
+
+        prefix=$prefix$d
+        if test -d "$prefix"; then
+          prefixes=
+        else
+          if $posix_mkdir; then
+            (umask $mkdir_umask &&
+             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+            # Don't fail if two instances are running concurrently.
+            test -d "$prefix" || exit 1
+          else
+            case $prefix in
+              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+              *) qprefix=$prefix;;
+            esac
+            prefixes="$prefixes '$qprefix'"
+          fi
+        fi
+        prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+        # Don't fail if two instances are running concurrently.
+        (umask $mkdir_umask &&
+         eval "\$doit_exec \$mkdirprog $prefixes") ||
+          test -d "$dstdir" || exit 1
+        obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=${dstdirslash}_inst.$$_
+    rmtmp=${dstdirslash}_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask &&
+     { test -z "$stripcmd" || {
+	 # Create $dsttmp read-write so that cp doesn't create it read-only,
+	 # which would cause strip to fail.
+	 if test -z "$doit"; then
+	   : >"$dsttmp" # No need to fork-exec 'touch'.
+	 else
+	   $doit touch "$dsttmp"
+	 fi
+       }
+     } &&
+     $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
+       set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       set +f &&
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # If $backupsuffix is set, and the file being installed
+      # already exists, attempt a backup.  Don't worry if it fails,
+      # e.g., if mv doesn't support -f.
+      if test -n "$backupsuffix" && test -f "$dst"; then
+        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
+      fi
+
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+        # Now remove or move aside any old file at destination location.
+        # We try this two ways since rm can't unlink itself on some
+        # systems and the destination file might be busy for other
+        # reasons.  In this case, the final cleanup might fail but the new
+        # file should still install successfully.
+        {
+          test ! -f "$dst" ||
+          $doit $rmcmd "$dst" 2>/dev/null ||
+          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
+          } ||
+          { echo "$0: cannot unlink or rename $dst" >&2
+            (exit 1); exit 1
+          }
+        } &&
+
+        # Now rename the file to the real destination.
+        $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index af5fbcf..073ed87 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -6,6 +6,7 @@
  *  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 2023 NXP
  *
  *
  */
@@ -140,12 +141,21 @@ struct bt_voice {
 #define BT_PKT_STATUS		16
 
 #define BT_SCM_PKT_STATUS	0x03
+#define BT_SCM_ERROR		0x04
 
 #define BT_ISO_QOS		17
 
 #define BT_ISO_QOS_CIG_UNSET	0xff
 #define BT_ISO_QOS_CIS_UNSET	0xff
 
+#define BT_ISO_QOS_BIG_UNSET	0xff
+#define BT_ISO_QOS_BIS_UNSET	0xff
+
+#define BT_ISO_SYNC_TIMEOUT	0x07d0 /* 20 secs */
+
+#define BT_ISO_QOS_GROUP_UNSET	0xff
+#define BT_ISO_QOS_STREAM_UNSET	0xff
+
 struct bt_iso_io_qos {
 	uint32_t interval;
 	uint16_t latency;
@@ -154,23 +164,46 @@ struct bt_iso_io_qos {
 	uint8_t  rtn;
 };
 
-struct bt_iso_qos {
-	union {
-		uint8_t  cig;
-		uint8_t  big;
-	};
-	union {
-		uint8_t  cis;
-		uint8_t  bis;
-	};
-	union {
-		uint8_t  sca;
-		uint8_t  sync_interval;
-	};
+struct bt_iso_ucast_qos {
+	uint8_t  cig;
+	uint8_t  cis;
+	uint8_t  sca;
+	uint8_t  packing;
+	uint8_t  framing;
+	struct bt_iso_io_qos in;
+	struct bt_iso_io_qos out;
+};
+
+struct bt_iso_bcast_qos {
+	uint8_t  big;
+	uint8_t  bis;
+	uint8_t  sync_factor;
 	uint8_t  packing;
 	uint8_t  framing;
 	struct bt_iso_io_qos in;
 	struct bt_iso_io_qos out;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  options;
+	uint16_t skip;
+	uint16_t sync_timeout;
+	uint8_t  sync_cte_type;
+	uint8_t  mse;
+	uint16_t timeout;
+};
+
+/* (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH) */
+#define BASE_MAX_LENGTH 248
+struct bt_iso_base {
+	uint8_t base_len;
+	uint8_t base[BASE_MAX_LENGTH];
+};
+
+struct bt_iso_qos {
+	union {
+		struct bt_iso_ucast_qos ucast;
+		struct bt_iso_bcast_qos bcast;
+	};
 };
 
 #define BT_CODEC		19
@@ -207,6 +240,8 @@ enum {
 
 #define BT_ISO_BASE		20
 
+#define BT_POLL_ERRQUEUE	21
+
 /* Byte order conversions */
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define htobs(d)  (d)
diff --git a/lib/hci.c b/lib/hci.c
index 5228c2a..937e65d 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -42,7 +42,7 @@ typedef struct {
 	unsigned int val;
 } hci_map;
 
-static char *hci_bit2str(hci_map *m, unsigned int val)
+static char *hci_bit2str(const hci_map *m, unsigned int val)
 {
 	char *str = malloc(120);
 	char *ptr = str;
@@ -59,10 +59,10 @@ static char *hci_bit2str(hci_map *m, unsigned int val)
 	return str;
 }
 
-static int hci_str2bit(hci_map *map, char *str, unsigned int *val)
+static int hci_str2bit(const hci_map *map, char *str, unsigned int *val)
 {
 	char *t, *ptr;
-	hci_map *m;
+	const hci_map *m;
 	int set;
 
 	if (!str || !(str = ptr = strdup(str)))
@@ -83,7 +83,7 @@ static int hci_str2bit(hci_map *map, char *str, unsigned int *val)
 	return set;
 }
 
-static char *hci_uint2str(hci_map *m, unsigned int val)
+static char *hci_uint2str(const hci_map *m, unsigned int val)
 {
 	char *str = malloc(50);
 	char *ptr = str;
@@ -102,10 +102,10 @@ static char *hci_uint2str(hci_map *m, unsigned int val)
 	return str;
 }
 
-static int hci_str2uint(hci_map *map, char *str, unsigned int *val)
+static int hci_str2uint(const hci_map *map, char *str, unsigned int *val)
 {
 	char *t, *ptr;
-	hci_map *m;
+	const hci_map *m;
 	int set = 0;
 
 	if (!str)
@@ -127,7 +127,7 @@ static int hci_str2uint(hci_map *map, char *str, unsigned int *val)
 	return set;
 }
 
-char *hci_bustostr(int bus)
+const char *hci_bustostr(int bus)
 {
 	switch (bus) {
 	case HCI_VIRTUAL:
@@ -157,7 +157,7 @@ char *hci_bustostr(int bus)
 	}
 }
 
-char *hci_dtypetostr(int type)
+const char *hci_dtypetostr(int type)
 {
 	return hci_bustostr(type & 0x0f);
 }
@@ -175,7 +175,7 @@ char *hci_typetostr(int type)
 }
 
 /* HCI dev flags mapping */
-static hci_map dev_flags_map[] = {
+static const hci_map dev_flags_map[] = {
 	{ "UP",      HCI_UP      },
 	{ "INIT",    HCI_INIT    },
 	{ "RUNNING", HCI_RUNNING },
@@ -192,7 +192,7 @@ char *hci_dflagstostr(uint32_t flags)
 {
 	char *str = bt_malloc(50);
 	char *ptr = str;
-	hci_map *m = dev_flags_map;
+	const hci_map *m = dev_flags_map;
 
 	if (!str)
 		return NULL;
@@ -211,7 +211,7 @@ char *hci_dflagstostr(uint32_t flags)
 }
 
 /* HCI packet type mapping */
-static hci_map pkt_type_map[] = {
+static const hci_map pkt_type_map[] = {
 	{ "DM1",   HCI_DM1  },
 	{ "DM3",   HCI_DM3  },
 	{ "DM5",   HCI_DM5  },
@@ -230,7 +230,7 @@ static hci_map pkt_type_map[] = {
 	{ NULL }
 };
 
-static hci_map sco_ptype_map[] = {
+static const hci_map sco_ptype_map[] = {
 	{ "HV1",   0x0001   },
 	{ "HV2",   0x0002   },
 	{ "HV3",   0x0004   },
@@ -265,7 +265,7 @@ int hci_strtoscoptype(char *str, unsigned int *val)
 }
 
 /* Link policy mapping */
-static hci_map link_policy_map[] = {
+static const hci_map link_policy_map[] = {
 	{ "NONE",	0		},
 	{ "RSWITCH",	HCI_LP_RSWITCH	},
 	{ "HOLD",	HCI_LP_HOLD	},
@@ -285,7 +285,7 @@ int hci_strtolp(char *str, unsigned int *val)
 }
 
 /* Link mode mapping */
-static hci_map link_mode_map[] = {
+static const hci_map link_mode_map[] = {
 	{ "NONE",	0		},
 	{ "ACCEPT",	HCI_LM_ACCEPT	},
 	{ "CENTRAL",	HCI_LM_MASTER	},
@@ -332,7 +332,7 @@ int hci_strtolm(char *str, unsigned int *val)
 }
 
 /* Command mapping */
-static hci_map commands_map[] = {
+static const hci_map commands_map[] = {
 	{ "Inquiry",					0   },
 	{ "Inquiry Cancel",				1   },
 	{ "Periodic Inquiry Mode",			2   },
@@ -605,7 +605,7 @@ char *hci_cmdtostr(unsigned int cmd)
 char *hci_commandstostr(uint8_t *commands, char *pref, int width)
 {
 	unsigned int maxwidth = width - 3;
-	hci_map *m;
+	const hci_map *m;
 	char *off, *ptr, *str;
 	int size = 10;
 
@@ -645,7 +645,7 @@ char *hci_commandstostr(uint8_t *commands, char *pref, int width)
 }
 
 /* Version mapping */
-static hci_map ver_map[] = {
+static const hci_map ver_map[] = {
 	{ "1.0b",	0x00 },
 	{ "1.1",	0x01 },
 	{ "1.2",	0x02 },
@@ -658,6 +658,8 @@ static hci_map ver_map[] = {
 	{ "5.0",	0x09 },
 	{ "5.1",	0x0a },
 	{ "5.2",	0x0b },
+	{ "5.3",	0x0c },
+	{ "5.4",	0x0d },
 	{ NULL }
 };
 
@@ -681,7 +683,7 @@ int lmp_strtover(char *str, unsigned int *ver)
 	return hci_str2uint(ver_map, str, ver);
 }
 
-static hci_map pal_map[] = {
+static const hci_map pal_map[] = {
 	{ "3.0",	0x01 },
 	{ NULL }
 };
@@ -697,7 +699,7 @@ int pal_strtover(char *str, unsigned int *ver)
 }
 
 /* LMP features mapping */
-static hci_map lmp_features_map[8][9] = {
+static const hci_map lmp_features_map[8][9] = {
 	{	/* Byte 0 */
 		{ "<3-slot packets>",	LMP_3SLOT	},	/* Bit 0 */
 		{ "<5-slot packets>",	LMP_5SLOT	},	/* Bit 1 */
@@ -792,7 +794,7 @@ char *lmp_featurestostr(uint8_t *features, char *pref, int width)
 	int i, size = 10;
 
 	for (i = 0; i < 8; i++) {
-		hci_map *m = lmp_features_map[i];
+		const hci_map *m = lmp_features_map[i];
 
 		while (m->str) {
 			if (m->val & features[i])
@@ -814,7 +816,7 @@ char *lmp_featurestostr(uint8_t *features, char *pref, int width)
 	off = ptr;
 
 	for (i = 0; i < 8; i++) {
-		hci_map *m = lmp_features_map[i];
+		const hci_map *m = lmp_features_map[i];
 
 		while (m->str) {
 			if (m->val & features[i]) {
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index 6b1a548..baf3d3e 100644
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -132,9 +132,9 @@ int hci_le_read_remote_features(int dd, uint16_t handle, uint8_t *features, int
 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);
+const char *hci_bustostr(int bus);
 char *hci_typetostr(int type);
-char *hci_dtypetostr(int type);
+const 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);
diff --git a/lib/l2cap.h b/lib/l2cap.h
index 9197800..62cc04b 100644
--- a/lib/l2cap.h
+++ b/lib/l2cap.h
@@ -184,6 +184,8 @@ typedef struct {
 #define L2CAP_MODE_FLOWCTL	0x02
 #define L2CAP_MODE_ERTM		0x03
 #define L2CAP_MODE_STREAMING	0x04
+#define L2CAP_MODE_LE_FLOWCTL	0x80
+#define L2CAP_MODE_ECRED		0x81
 
 #define L2CAP_SERVTYPE_NOTRAFFIC	0x00
 #define L2CAP_SERVTYPE_BESTEFFORT	0x01
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 796190c..8f92b77 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -12,6 +12,10 @@
 #define __packed __attribute__((packed))
 #endif
 
+#ifndef BIT
+#define BIT(n)  (1 << (n))
+#endif
+
 #define MGMT_INDEX_NONE			0xFFFF
 
 #define MGMT_STATUS_SUCCESS		0x00
@@ -78,24 +82,28 @@ struct mgmt_rp_read_index_list {
 #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_SETTING_PHY_CONFIGURATION	0x00010000
-#define MGMT_SETTING_WIDEBAND_SPEECH	0x00020000
+#define MGMT_SETTING_POWERED		BIT(0)
+#define MGMT_SETTING_CONNECTABLE	BIT(1)
+#define MGMT_SETTING_FAST_CONNECTABLE	BIT(2)
+#define MGMT_SETTING_DISCOVERABLE	BIT(3)
+#define MGMT_SETTING_BONDABLE		BIT(4)
+#define MGMT_SETTING_LINK_SECURITY	BIT(5)
+#define MGMT_SETTING_SSP		BIT(6)
+#define MGMT_SETTING_BREDR		BIT(7)
+#define MGMT_SETTING_HS			BIT(8)
+#define MGMT_SETTING_LE			BIT(9)
+#define MGMT_SETTING_ADVERTISING	BIT(10)
+#define MGMT_SETTING_SECURE_CONN	BIT(11)
+#define MGMT_SETTING_DEBUG_KEYS		BIT(12)
+#define MGMT_SETTING_PRIVACY		BIT(13)
+#define MGMT_SETTING_CONFIGURATION	BIT(14)
+#define MGMT_SETTING_STATIC_ADDRESS	BIT(15)
+#define MGMT_SETTING_PHY_CONFIGURATION	BIT(16)
+#define MGMT_SETTING_WIDEBAND_SPEECH	BIT(17)
+#define MGMT_SETTING_CIS_CENTRAL	BIT(18)
+#define MGMT_SETTING_CIS_PERIPHERAL	BIT(19)
+#define MGMT_SETTING_ISO_BROADCASTER	BIT(20)
+#define MGMT_SETTING_ISO_SYNC_RECEIVER	BIT(21)
 
 #define MGMT_OP_READ_INFO		0x0004
 struct mgmt_rp_read_info {
@@ -493,23 +501,23 @@ 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_ADV_FLAG_SEC_1M		(1 << 7)
-#define MGMT_ADV_FLAG_SEC_2M		(1 << 8)
-#define MGMT_ADV_FLAG_SEC_CODED		(1 << 9)
-#define MGMT_ADV_FLAG_CAN_SET_TX_POWER	(1 << 10)
-#define MGMT_ADV_FLAG_HW_OFFLOAD	(1 << 11)
-#define MGMT_ADV_PARAM_DURATION		(1 << 12)
-#define MGMT_ADV_PARAM_TIMEOUT		(1 << 13)
-#define MGMT_ADV_PARAM_INTERVALS	(1 << 14)
-#define MGMT_ADV_PARAM_TX_POWER		(1 << 15)
-#define MGMT_ADV_PARAM_SCAN_RSP		(1 << 16)
+#define MGMT_ADV_FLAG_CONNECTABLE	BIT(0)
+#define MGMT_ADV_FLAG_DISCOV		BIT(1)
+#define MGMT_ADV_FLAG_LIMITED_DISCOV	BIT(2)
+#define MGMT_ADV_FLAG_MANAGED_FLAGS	BIT(3)
+#define MGMT_ADV_FLAG_TX_POWER		BIT(4)
+#define MGMT_ADV_FLAG_APPEARANCE	BIT(5)
+#define MGMT_ADV_FLAG_LOCAL_NAME	BIT(6)
+#define MGMT_ADV_FLAG_SEC_1M		BIT(7)
+#define MGMT_ADV_FLAG_SEC_2M		BIT(8)
+#define MGMT_ADV_FLAG_SEC_CODED		BIT(9)
+#define MGMT_ADV_FLAG_CAN_SET_TX_POWER	BIT(10)
+#define MGMT_ADV_FLAG_HW_OFFLOAD	BIT(11)
+#define MGMT_ADV_PARAM_DURATION		BIT(12)
+#define MGMT_ADV_PARAM_TIMEOUT		BIT(13)
+#define MGMT_ADV_PARAM_INTERVALS	BIT(14)
+#define MGMT_ADV_PARAM_TX_POWER		BIT(15)
+#define MGMT_ADV_PARAM_SCAN_RSP		BIT(16)
 
 #define MGMT_ADV_FLAG_SEC_MASK	(MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
 				 MGMT_ADV_FLAG_SEC_CODED)
@@ -561,21 +569,21 @@ struct mgmt_rp_get_phy_confguration {
 	uint32_t	selected_phys;
 } __packed;
 
-#define MGMT_PHY_BR_1M_1SLOT	0x00000001
-#define MGMT_PHY_BR_1M_3SLOT	0x00000002
-#define MGMT_PHY_BR_1M_5SLOT	0x00000004
-#define MGMT_PHY_EDR_2M_1SLOT	0x00000008
-#define MGMT_PHY_EDR_2M_3SLOT	0x00000010
-#define MGMT_PHY_EDR_2M_5SLOT	0x00000020
-#define MGMT_PHY_EDR_3M_1SLOT	0x00000040
-#define MGMT_PHY_EDR_3M_3SLOT	0x00000080
-#define MGMT_PHY_EDR_3M_5SLOT	0x00000100
-#define MGMT_PHY_LE_1M_TX		0x00000200
-#define MGMT_PHY_LE_1M_RX		0x00000400
-#define MGMT_PHY_LE_2M_TX		0x00000800
-#define MGMT_PHY_LE_2M_RX		0x00001000
-#define MGMT_PHY_LE_CODED_TX	0x00002000
-#define MGMT_PHY_LE_CODED_RX	0x00004000
+#define MGMT_PHY_BR_1M_1SLOT		BIT(0)
+#define MGMT_PHY_BR_1M_3SLOT		BIT(1)
+#define MGMT_PHY_BR_1M_5SLOT		BIT(2)
+#define MGMT_PHY_EDR_2M_1SLOT		BIT(3)
+#define MGMT_PHY_EDR_2M_3SLOT		BIT(4)
+#define MGMT_PHY_EDR_2M_5SLOT		BIT(5)
+#define MGMT_PHY_EDR_3M_1SLOT		BIT(6)
+#define MGMT_PHY_EDR_3M_3SLOT		BIT(7)
+#define MGMT_PHY_EDR_3M_5SLOT		BIT(8)
+#define MGMT_PHY_LE_1M_TX		BIT(9)
+#define MGMT_PHY_LE_1M_RX		BIT(10)
+#define MGMT_PHY_LE_2M_TX		BIT(11)
+#define MGMT_PHY_LE_2M_RX		BIT(12)
+#define MGMT_PHY_LE_CODED_TX		BIT(13)
+#define MGMT_PHY_LE_CODED_RX		BIT(14)
 
 #define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
 			     MGMT_PHY_LE_CODED_TX)
@@ -889,10 +897,12 @@ struct mgmt_ev_auth_failed {
 	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_DEV_FOUND_NAME_REQUEST_FAILED	0x10
+#define MGMT_DEV_FOUND_CONFIRM_NAME		BIT(0)
+#define MGMT_DEV_FOUND_LEGACY_PAIRING		BIT(1)
+#define MGMT_DEV_FOUND_NOT_CONNECTABLE		BIT(2)
+#define MGMT_DEV_FOUND_INITIATED_CONN		BIT(3)
+#define MGMT_DEV_FOUND_NAME_REQUEST_FAILED	BIT(4)
+#define MGMT_DEV_FOUND_SCAN_RSP			BIT(5)
 
 #define MGMT_EV_DEVICE_FOUND		0x0012
 struct mgmt_ev_device_found {
@@ -1228,6 +1238,9 @@ static const char *mgmt_ev[] = {
 	"Advertisement Monitor Device Lost",
 	"Mesh Packet Found",
 	"Mesh Packet Complete",
+	"PA Sync Established",
+	"BIG Sync Established",
+	"BIG Sync Lost",
 };
 
 static const char *mgmt_status[] = {
diff --git a/lib/sdp.c b/lib/sdp.c
index 844ae0d..411a95b 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -47,7 +47,7 @@
 #define SDPDBG(fmt...)
 #endif
 
-static uint128_t bluetooth_base_uuid = {
+static const uint128_t bluetooth_base_uuid = {
 	.data = {	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
 			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
 };
@@ -65,10 +65,10 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d);
 /* Message structure. */
 struct tupla {
 	int index;
-	char *str;
+	const char *str;
 };
 
-static struct tupla Protocol[] = {
+static const struct tupla Protocol[] = {
 	{ SDP_UUID,		"SDP"		},
 	{ UDP_UUID,		"UDP"		},
 	{ RFCOMM_UUID,		"RFCOMM"	},
@@ -97,7 +97,7 @@ static struct tupla Protocol[] = {
 	{ 0 }
 };
 
-static struct tupla ServiceClass[] = {
+static const struct tupla ServiceClass[] = {
 	{ SDP_SERVER_SVCLASS_ID,		"SDP Server"			},
 	{ BROWSE_GRP_DESC_SVCLASS_ID,		"Browse Group Descriptor"	},
 	{ PUBLIC_BROWSE_GROUP,			"Public Browse Group"		},
@@ -176,9 +176,9 @@ static struct tupla ServiceClass[] = {
 
 #define Profile ServiceClass
 
-static char *string_lookup(struct tupla *pt0, int index)
+static const char *string_lookup(const struct tupla *pt0, int index)
 {
-	struct tupla *pt;
+	const struct tupla *pt;
 
 	for (pt = pt0; pt->index; pt++)
 		if (pt->index == index)
@@ -187,7 +187,8 @@ static char *string_lookup(struct tupla *pt0, int index)
 	return "";
 }
 
-static char *string_lookup_uuid(struct tupla *pt0, const uuid_t *uuid)
+static const char *string_lookup_uuid(const struct tupla *pt0,
+					const uuid_t *uuid)
 {
 	uuid_t tmp_uuid;
 
@@ -209,9 +210,10 @@ static char *string_lookup_uuid(struct tupla *pt0, const uuid_t *uuid)
  * Prints into a string the Protocol UUID
  * coping a maximum of n characters.
  */
-static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n)
+static int uuid2str(const struct tupla *message, const uuid_t *uuid, char *str,
+			size_t n)
 {
-	char *str2;
+	const char *str2;
 
 	if (!uuid) {
 		snprintf(str, n, "NULL");
@@ -420,7 +422,7 @@ sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value,
 
 		d->unitSize += length;
 		if (length <= USHRT_MAX) {
-			d->val.str = malloc(length);
+			d->val.str = bt_malloc0(length + 1);
 			if (!d->val.str) {
 				free(d);
 				return NULL;
@@ -504,15 +506,17 @@ sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length,
 
 	for (i = 0; i < len; i++) {
 		sdp_data_t *data;
-		int8_t dtd = *(uint8_t *) dtds[i];
+		uint8_t dtd = *(uint8_t *) dtds[i];
 
 		if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32)
 			data = (sdp_data_t *) values[i];
 		else
 			data = sdp_data_alloc_with_length(dtd, values[i], length[i]);
 
-		if (!data)
+		if (!data) {
+			sdp_data_free(seq);
 			return NULL;
+		}
 
 		if (curr)
 			curr->next = data;
@@ -539,8 +543,10 @@ sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len)
 		else
 			data = sdp_data_alloc(dtd, values[i]);
 
-		if (!data)
+		if (!data) {
+			sdp_data_free(seq);
 			return NULL;
+		}
 
 		if (curr)
 			curr->next = data;
@@ -576,6 +582,8 @@ int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d)
 
 	if (p)
 		return -1;
+	if (!d)
+		return -1;
 
 	d->attrId = attr;
 	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func);
@@ -958,6 +966,8 @@ static void data_seq_free(sdp_data_t *seq)
 
 void sdp_data_free(sdp_data_t *d)
 {
+	if (!d)
+		return;
 	switch (d->dtd) {
 	case SDP_SEQ8:
 	case SDP_SEQ16:
@@ -1505,7 +1515,7 @@ static void *sdp_data_value(sdp_data_t *data, uint32_t *len)
 	case SDP_TEXT_STR32:
 		val = data->val.str;
 		if (len)
-			*len = data->unitSize - 1;
+			*len = data->unitSize - sizeof(uint8_t);
 		break;
 	case SDP_ALT8:
 	case SDP_ALT16:
@@ -1527,10 +1537,15 @@ static sdp_data_t *sdp_copy_seq(sdp_data_t *data)
 	for (tmp = data; tmp; tmp = tmp->next) {
 		sdp_data_t *datatmp;
 		void *value;
+		uint32_t len = 0;
 
-		value = sdp_data_value(tmp, NULL);
-		datatmp = sdp_data_alloc_with_length(tmp->dtd, value,
-								tmp->unitSize);
+		value = sdp_data_value(tmp, &len);
+		datatmp = sdp_data_alloc_with_length(tmp->dtd, value, len);
+
+		if (!datatmp) {
+			sdp_data_free(seq);
+			return NULL;
+		}
 
 		if (cur)
 			cur->next = datatmp;
@@ -2180,16 +2195,21 @@ int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value)
 }
 
 int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value,
-								int valuelen)
+								size_t valuelen)
 {
 	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);
-	if (sdpdata)
-		/* Verify that it is what the caller expects */
-		if (SDP_IS_TEXT_STR(sdpdata->dtd))
-			if ((int) strlen(sdpdata->val.str) < valuelen) {
-				strcpy(value, sdpdata->val.str);
-				return 0;
-			}
+
+	/* Verify that it is what the caller expects */
+	if (!sdpdata || !SDP_IS_TEXT_STR(sdpdata->dtd))
+		goto fail;
+
+	/* Have to copy the NULL terminator too, so check len < valuelen. */
+	if (strlen(sdpdata->val.str) < valuelen) {
+		strcpy(value, sdpdata->val.str);
+		return 0;
+	}
+
+fail:
 	errno = EINVAL;
 	return -1;
 }
@@ -2292,7 +2312,7 @@ static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto)
 	sdp_list_t *p;
 
 	seqlen = sdp_list_len(proto);
-	seqDTDs = malloc(seqlen * sizeof(void *));
+	seqDTDs = bt_malloc0(seqlen * sizeof(void *));
 	if (!seqDTDs)
 		return NULL;
 
@@ -2758,7 +2778,7 @@ uuid_t *sdp_uuid_to_uuid128(const uuid_t *uuid)
  */
 int sdp_uuid128_to_uuid(uuid_t *uuid)
 {
-	uint128_t *b = &bluetooth_base_uuid;
+	const uint128_t *b = &bluetooth_base_uuid;
 	uint128_t *u = &uuid->value.uuid128;
 	uint32_t data;
 	unsigned int i;
@@ -3597,7 +3617,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
 	/* get attr seq PDU form */
 	seqlen = gen_attridseq_pdu(pdata, attrids,
 		reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32);
-	if (seqlen == -1) {
+	if (seqlen < 0) {
 		errno = EINVAL;
 		goto end;
 	}
@@ -3952,7 +3972,7 @@ int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_
 	/* get attr seq PDU form */
 	seqlen = gen_attridseq_pdu(pdata, attrid_list,
 			reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32);
-	if (seqlen == -1) {
+	if (seqlen < 0) {
 		t->err = EINVAL;
 		goto end;
 	}
@@ -4074,7 +4094,7 @@ int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *sear
 	/* get attr seq PDU form */
 	seqlen = gen_attridseq_pdu(pdata, attrid_list,
 			reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32);
-	if (seqlen == -1) {
+	if (seqlen < 0) {
 		t->err = EINVAL;
 		goto end;
 	}
@@ -4458,7 +4478,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
 	/* get attr seq PDU form */
 	seqlen = gen_attridseq_pdu(pdata, attrids,
 		reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32);
-	if (seqlen == -1) {
+	if (seqlen < 0) {
 		errno = EINVAL;
 		status = -1;
 		goto end;
diff --git a/lib/sdp_lib.h b/lib/sdp_lib.h
index 22776b6..aad664f 100644
--- a/lib/sdp_lib.h
+++ b/lib/sdp_lib.h
@@ -141,7 +141,8 @@ int sdp_general_inquiry(inquiry_info *ii, int dev_num, int duration, uint8_t *fo
 
 /* 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);
+int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attr, char *value,
+							size_t valuelen);
 
 /*
  * Basic sdp data functions
@@ -543,32 +544,38 @@ 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)
+static inline int sdp_get_service_name(const sdp_record_t *rec, char *str,
+								size_t 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)
+static inline int sdp_get_service_desc(const sdp_record_t *rec, char *str,
+								size_t 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)
+static inline int sdp_get_provider_name(const sdp_record_t *rec, char *str,
+								size_t 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)
+static inline int sdp_get_doc_url(const sdp_record_t *rec, char *str,
+								size_t 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)
+static inline int sdp_get_clnt_exec_url(const sdp_record_t *rec, char *str,
+								size_t 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)
+static inline int sdp_get_icon_url(const sdp_record_t *rec, char *str,
+								size_t len)
 {
 	return sdp_get_string_attr(rec, SDP_ATTR_ICON_URL, str, len);
 }
diff --git a/lib/uuid.c b/lib/uuid.c
index 1d2e1f7..9a216e7 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -120,6 +120,15 @@ int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
 	return bt_uuid128_cmp(&u1, &u2);
 }
 
+int bt_uuid16_cmp(const bt_uuid_t *uuid1, uint16_t uuid2)
+{
+
+	if (!uuid1 || (uuid1->type != BT_UUID16))
+		return 0;
+
+	return (uuid1->value.u16 == uuid2);
+}
+
 /*
  * convert the UUID to string, copying a maximum of n characters.
  */
diff --git a/lib/uuid.h b/lib/uuid.h
index d5e5665..479986f 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011  Nokia Corporation
  *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -156,6 +157,15 @@ extern "C" {
 #define PAC_SOURCE_UUID		"00002bcb-0000-1000-8000-00805f9b34fb"
 #define PAC_SOURCE_LOC_CHRC_UUID			0x2bcc
 
+#define BCAA_SERVICE				0x1852
+#define BCAA_SERVICE_UUID	"00001852-0000-1000-8000-00805f9b34fb"
+
+#define BAA_SERVICE					0x1851
+#define BAA_SERVICE_UUID	"00001851-0000-1000-8000-00805f9b34fb"
+
+#define ASHA_SERVICE					0xFDF0
+#define ASHA_PROFILE_UUID	"0000FDF0-0000-1000-8000-00805f9b34fb"
+
 #define PAC_CONTEXT					0x2bcd
 #define PAC_SUPPORTED_CONTEXT				0x2bce
 
@@ -164,6 +174,10 @@ extern "C" {
 #define ASE_SOURCE_UUID					0x2bc5
 #define ASE_CP_UUID					0x2bc6
 
+#define BASS_UUID					0x184f
+#define BCAST_AUDIO_SCAN_CP_UUID			0x2bc7
+#define BCAST_RECV_STATE_UUID				0x2bc8
+
 #define VCS_UUID					0x1844
 #define VOL_OFFSET_CS_UUID				0x1845
 #define AUDIO_INPUT_CS_UUID				0x1843
@@ -171,6 +185,18 @@ extern "C" {
 #define VOL_CP_CHRC_UUID				0x2B7E
 #define VOL_FLAG_CHRC_UUID				0x2B7F
 
+#define VOCS_STATE_CHAR_UUID			0x2B80
+#define VOCS_AUDIO_LOC_CHRC_UUID		0x2B81
+#define VOCS_CP_CHRC_UUID			0x2B82
+#define VOCS_AUDIO_OP_DESC_CHAR_UUID		0x2B83
+
+#define	AICS_INPUT_STATE_CHAR_UUID		0x2B77
+#define	AICS_GAIN_SETTING_PROP_CHAR_UUID	0x2B78
+#define	AICS_AUDIO_INPUT_TYPE_CHAR_UUID		0x2B79
+#define	AICS_INPUT_STATUS_CHAR_UUID		0X2B7A
+#define	AICS_AUDIO_INPUT_CP_CHRC_UUID		0X2B7B
+#define	AICS_INPUT_DESCR_CHAR_UUID		0X2B7C
+
 #define GMCS_UUID                               0x1849
 #define MEDIA_PLAYER_NAME_CHRC_UUID             0x2b93
 #define MEDIA_TRACK_CHNGD_CHRC_UUID             0x2b96
@@ -186,6 +212,39 @@ extern "C" {
 #define MEDIA_CP_OP_SUPPORTED_CHRC_UUID         0x2ba5
 #define MEDIA_CONTENT_CONTROL_ID_CHRC_UUID      0x2bba
 
+/* Coordinated Set Identification Profile(CSIP) */
+#define CSIS_UUID					0x1846
+#define CS_SIRK						0x2B84
+#define CS_SIZE						0x2B85
+#define CS_LOCK						0x2B86
+#define CS_RANK						0x2B87
+
+
+/* Microphone Control Service(MICS) */
+#define MICS_UUID					0x184D
+#define MUTE_CHRC_UUID					0x2BC3
+
+/* Call Control Service(TBS/CCS) */
+#define TBS_UUID                                0x184B
+#define GTBS_UUID                               0x184C
+
+#define BEARER_PROVIDER_NAME_CHRC_UUID          0x2bb3
+#define BEARER_UCI_CHRC_UUID                    0x2bb4
+#define BEARER_TECH_CHRC_UUID                   0x2bb5
+#define BEARER_URI_SCHEME_CHRC_UUID             0x2bb6
+#define BEARER_SIGNAL_STR_CHRC_UUID             0x2bb7
+#define BEARER_SIGNAL_INTRVL_CHRC_UUID          0x2bb8
+#define CURR_CALL_LIST_CHRC_UUID                0x2bb9
+#define BEARER_CCID_CHRC_UUID                   0x2bba
+#define CALL_STATUS_FLAG_CHRC_UUID              0x2bbb
+#define INCOM_CALL_TARGET_URI_CHRC_UUID         0x2bbc
+#define CALL_STATE_CHRC_UUID                    0x2bbd
+#define CALL_CTRL_POINT_CHRC_UUID               0x2bbe
+#define CALL_CTRL_POINT_OPT_OPCODE_CHRC_UUID    0x2bbf
+#define TERMINATION_REASON_CHRC_UUID            0x2bc0
+#define INCOMING_CALL_CHRC_UUID                 0x2bc1
+#define CALL_FRIENDLY_NAME_CHRC_UUID            0x2bc2
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
@@ -207,6 +266,7 @@ 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);
+int bt_uuid16_cmp(const bt_uuid_t *uuid1, uint16_t uuid2);
 void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 
 #define MAX_LEN_UUID_STR 37
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100755
index 0000000..1dea62a
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,11436 @@
+#! /usr/bin/env sh
+## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
+##               by inline-source v2019-02-19.15
+
+# libtool (GNU libtool) 2.4.7
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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, see <http://www.gnu.org/licenses/>.
+
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION="2.4.7 Debian-2.4.7-7"
+package_revision=2.4.7
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Run './libtool --help' for help with using this script from the
+# command line.
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# After configure completes, it has a better idea of some of the
+# shell tools we need than the defaults used by the functions shared
+# with bootstrap, so set those here where they can still be over-
+# ridden by the user, but otherwise take precedence.
+
+: ${AUTOCONF="autoconf"}
+: ${AUTOMAKE="automake"}
+
+
+## -------------------------- ##
+## Source external libraries. ##
+## -------------------------- ##
+
+# Much of our low-level functionality needs to be sourced from external
+# libraries, which are installed to $pkgauxdir.
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+# General shell script boiler plate, and helper functions.
+# Written by Gary V. Vaughan, 2004
+
+# This is free software.  There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2004-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>.  You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it.  See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Evaluate this file near the top of your script to gain access to
+# the functions and variables defined here:
+#
+#   . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
+#
+# If you need to override any of the default environment variable
+# settings, do that before evaluating this file.
+
+
+## -------------------- ##
+## Shell normalisation. ##
+## -------------------- ##
+
+# Some shells need a little help to be as Bourne compatible as possible.
+# Before doing anything else, make sure all that help has been provided!
+
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
+fi
+
+# NLS nuisances: We save the old values in case they are required later.
+_G_user_locale=
+_G_safe_locale=
+for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test set = \"\${$_G_var+set}\"; then
+          save_$_G_var=\$$_G_var
+          $_G_var=C
+	  export $_G_var
+	  _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
+	  _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
+	fi"
+done
+# These NLS vars are set unconditionally (bootstrap issue #24).  Unset those
+# in case the environment reset is needed later and the $save_* variant is not
+# defined (see the code above).
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+# Make sure IFS has a sensible default
+sp=' '
+nl='
+'
+IFS="$sp	$nl"
+
+# There are apparently some retarded systems that use ';' as a PATH separator!
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# func_unset VAR
+# --------------
+# Portably unset VAR.
+# In some shells, an 'unset VAR' statement leaves a non-zero return
+# status if VAR is already unset, which might be problematic if the
+# statement is used at the end of a function (thus poisoning its return
+# value) or when 'set -e' is active (causing even a spurious abort of
+# the script in this case).
+func_unset ()
+{
+    { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; }
+}
+
+
+# Make sure CDPATH doesn't cause `cd` commands to output the target dir.
+func_unset CDPATH
+
+# Make sure ${,E,F}GREP behave sanely.
+func_unset GREP_OPTIONS
+
+
+## ------------------------- ##
+## Locate command utilities. ##
+## ------------------------- ##
+
+
+# func_executable_p FILE
+# ----------------------
+# Check that FILE is an executable regular file.
+func_executable_p ()
+{
+    test -f "$1" && test -x "$1"
+}
+
+
+# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
+# --------------------------------------------
+# Search for either a program that responds to --version with output
+# containing "GNU", or else returned by CHECK_FUNC otherwise, by
+# trying all the directories in PATH with each of the elements of
+# PROGS_LIST.
+#
+# CHECK_FUNC should accept the path to a candidate program, and
+# set $func_check_prog_result if it truncates its output less than
+# $_G_path_prog_max characters.
+func_path_progs ()
+{
+    _G_progs_list=$1
+    _G_check_func=$2
+    _G_PATH=${3-"$PATH"}
+
+    _G_path_prog_max=0
+    _G_path_prog_found=false
+    _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
+    for _G_dir in $_G_PATH; do
+      IFS=$_G_save_IFS
+      test -z "$_G_dir" && _G_dir=.
+      for _G_prog_name in $_G_progs_list; do
+        for _exeext in '' .EXE; do
+          _G_path_prog=$_G_dir/$_G_prog_name$_exeext
+          func_executable_p "$_G_path_prog" || continue
+          case `"$_G_path_prog" --version 2>&1` in
+            *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
+            *)     $_G_check_func $_G_path_prog
+		   func_path_progs_result=$func_check_prog_result
+		   ;;
+          esac
+          $_G_path_prog_found && break 3
+        done
+      done
+    done
+    IFS=$_G_save_IFS
+    test -z "$func_path_progs_result" && {
+      echo "no acceptable sed could be found in \$PATH" >&2
+      exit 1
+    }
+}
+
+
+# We want to be able to use the functions in this file before configure
+# has figured out where the best binaries are kept, which means we have
+# to search for them ourselves - except when the results are already set
+# where we skip the searches.
+
+# Unless the user overrides by setting SED, search the path for either GNU
+# sed, or the sed that truncates its output the least.
+test -z "$SED" && {
+  _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+  for _G_i in 1 2 3 4 5 6 7; do
+    _G_sed_script=$_G_sed_script$nl$_G_sed_script
+  done
+  echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
+  _G_sed_script=
+
+  func_check_prog_sed ()
+  {
+    _G_path_prog=$1
+
+    _G_count=0
+    printf 0123456789 >conftest.in
+    while :
+    do
+      cat conftest.in conftest.in >conftest.tmp
+      mv conftest.tmp conftest.in
+      cp conftest.in conftest.nl
+      echo '' >> conftest.nl
+      "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break
+      diff conftest.out conftest.nl >/dev/null 2>&1 || break
+      _G_count=`expr $_G_count + 1`
+      if test "$_G_count" -gt "$_G_path_prog_max"; then
+        # Best one so far, save it but keep looking for a better one
+        func_check_prog_result=$_G_path_prog
+        _G_path_prog_max=$_G_count
+      fi
+      # 10*(2^10) chars as input seems more than enough
+      test 10 -lt "$_G_count" && break
+    done
+    rm -f conftest.in conftest.tmp conftest.nl conftest.out
+  }
+
+  func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin"
+  rm -f conftest.sed
+  SED=$func_path_progs_result
+}
+
+
+# Unless the user overrides by setting GREP, search the path for either GNU
+# grep, or the grep that truncates its output the least.
+test -z "$GREP" && {
+  func_check_prog_grep ()
+  {
+    _G_path_prog=$1
+
+    _G_count=0
+    _G_path_prog_max=0
+    printf 0123456789 >conftest.in
+    while :
+    do
+      cat conftest.in conftest.in >conftest.tmp
+      mv conftest.tmp conftest.in
+      cp conftest.in conftest.nl
+      echo 'GREP' >> conftest.nl
+      "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break
+      diff conftest.out conftest.nl >/dev/null 2>&1 || break
+      _G_count=`expr $_G_count + 1`
+      if test "$_G_count" -gt "$_G_path_prog_max"; then
+        # Best one so far, save it but keep looking for a better one
+        func_check_prog_result=$_G_path_prog
+        _G_path_prog_max=$_G_count
+      fi
+      # 10*(2^10) chars as input seems more than enough
+      test 10 -lt "$_G_count" && break
+    done
+    rm -f conftest.in conftest.tmp conftest.nl conftest.out
+  }
+
+  func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin"
+  GREP=$func_path_progs_result
+}
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# All uppercase variable names are used for environment variables.  These
+# variables can be overridden by the user before calling a script that
+# uses them if a suitable command of that name is not already available
+# in the command search PATH.
+
+: ${CP="cp -f"}
+: ${ECHO="printf %s\n"}
+: ${EGREP="$GREP -E"}
+: ${FGREP="$GREP -F"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+
+
+## -------------------- ##
+## Useful sed snippets. ##
+## -------------------- ##
+
+sed_dirname='s|/[^/]*$||'
+sed_basename='s|^.*/||'
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Same as above, but do not quote variable references.
+sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'
+
+# Sed substitution that converts a w32 file name or path
+# that contains forward slashes, into one that contains
+# (escaped) backslashes.  A very naive implementation.
+sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-'\' parameter expansions in output of sed_double_quote_subst that
+# were '\'-ed in input to the same.  If an odd number of '\' preceded a
+# '$' in input to sed_double_quote_subst, that '$' was protected from
+# expansion.  Since each input '\' is now two '\'s, look for any number
+# of runs of four '\'s followed by two '\'s and then a '$'.  '\' that '$'.
+_G_bs='\\'
+_G_bs2='\\\\'
+_G_bs4='\\\\\\\\'
+_G_dollar='\$'
+sed_double_backslash="\
+  s/$_G_bs4/&\\
+/g
+  s/^$_G_bs2$_G_dollar/$_G_bs&/
+  s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
+  s/\n//g"
+
+# require_check_ifs_backslash
+# ---------------------------
+# Check if we can use backslash as IFS='\' separator, and set
+# $check_ifs_backshlash_broken to ':' or 'false'.
+require_check_ifs_backslash=func_require_check_ifs_backslash
+func_require_check_ifs_backslash ()
+{
+  _G_save_IFS=$IFS
+  IFS='\'
+  _G_check_ifs_backshlash='a\\b'
+  for _G_i in $_G_check_ifs_backshlash
+  do
+  case $_G_i in
+  a)
+    check_ifs_backshlash_broken=false
+    ;;
+  '')
+    break
+    ;;
+  *)
+    check_ifs_backshlash_broken=:
+    break
+    ;;
+  esac
+  done
+  IFS=$_G_save_IFS
+  require_check_ifs_backslash=:
+}
+
+
+## ----------------- ##
+## Global variables. ##
+## ----------------- ##
+
+# Except for the global variables explicitly listed below, the following
+# functions in the '^func_' namespace, and the '^require_' namespace
+# variables initialised in the 'Resource management' section, sourcing
+# this file will not pollute your global namespace with anything
+# else. There's no portable way to scope variables in Bourne shell
+# though, so actually running these functions will sometimes place
+# results into a variable named after the function, and often use
+# temporary variables in the '^_G_' namespace. If you are careful to
+# avoid using those namespaces casually in your sourcing script, things
+# should continue to work as you expect. And, of course, you can freely
+# overwrite any of the functions or variables defined here before
+# calling anything to customize them.
+
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+# Allow overriding, eg assuming that you follow the convention of
+# putting '$debug_cmd' at the start of all your functions, you can get
+# bash to show function call trace with:
+#
+#    debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+debug_cmd=${debug_cmd-":"}
+exit_cmd=:
+
+# By convention, finish your script with:
+#
+#    exit $exit_status
+#
+# so that you can set exit_status to non-zero if you want to indicate
+# something went wrong during execution without actually bailing out at
+# the point of failure.
+exit_status=$EXIT_SUCCESS
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath=$0
+
+# The name of this program.
+progname=`$ECHO "$progpath" |$SED "$sed_basename"`
+
+# Make sure we have an absolute progpath for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
+     progdir=`cd "$progdir" && pwd`
+     progpath=$progdir/$progname
+     ;;
+  *)
+     _G_IFS=$IFS
+     IFS=${PATH_SEPARATOR-:}
+     for progdir in $PATH; do
+       IFS=$_G_IFS
+       test -x "$progdir/$progname" && break
+     done
+     IFS=$_G_IFS
+     test -n "$progdir" || progdir=`pwd`
+     progpath=$progdir/$progname
+     ;;
+esac
+
+
+## ----------------- ##
+## Standard options. ##
+## ----------------- ##
+
+# The following options affect the operation of the functions defined
+# below, and should be set appropriately depending on run-time para-
+# meters passed on the command line.
+
+opt_dry_run=false
+opt_quiet=false
+opt_verbose=false
+
+# Categories 'all' and 'none' are always available.  Append any others
+# you will pass as the first argument to func_warning from your own
+# code.
+warning_categories=
+
+# By default, display warnings according to 'opt_warning_types'.  Set
+# 'warning_func'  to ':' to elide all warnings, or func_fatal_error to
+# treat the next displayed warning as a fatal error.
+warning_func=func_warn_and_continue
+
+# Set to 'all' to display all warnings, 'none' to suppress all
+# warnings, or a space delimited list of some subset of
+# 'warning_categories' to display only the listed warnings.
+opt_warning_types=all
+
+
+## -------------------- ##
+## Resource management. ##
+## -------------------- ##
+
+# This section contains definitions for functions that each ensure a
+# particular resource (a file, or a non-empty configuration variable for
+# example) is available, and if appropriate to extract default values
+# from pertinent package files. Call them using their associated
+# 'require_*' variable to ensure that they are executed, at most, once.
+#
+# It's entirely deliberate that calling these functions can set
+# variables that don't obey the namespace limitations obeyed by the rest
+# of this file, in order that that they be as useful as possible to
+# callers.
+
+
+# require_term_colors
+# -------------------
+# Allow display of bold text on terminals that support it.
+require_term_colors=func_require_term_colors
+func_require_term_colors ()
+{
+    $debug_cmd
+
+    test -t 1 && {
+      # COLORTERM and USE_ANSI_COLORS environment variables take
+      # precedence, because most terminfo databases neglect to describe
+      # whether color sequences are supported.
+      test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
+
+      if test 1 = "$USE_ANSI_COLORS"; then
+        # Standard ANSI escape sequences
+        tc_reset=''
+        tc_bold='';   tc_standout=''
+        tc_red='';   tc_green=''
+        tc_blue='';  tc_cyan=''
+      else
+        # Otherwise trust the terminfo database after all.
+        test -n "`tput sgr0 2>/dev/null`" && {
+          tc_reset=`tput sgr0`
+          test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
+          tc_standout=$tc_bold
+          test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
+          test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
+          test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
+          test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
+          test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
+        }
+      fi
+    }
+
+    require_term_colors=:
+}
+
+
+## ----------------- ##
+## Function library. ##
+## ----------------- ##
+
+# This section contains a variety of useful functions to call in your
+# scripts. Take note of the portable wrappers for features provided by
+# some modern shells, which will fall back to slower equivalents on
+# less featureful shells.
+
+
+# func_append VAR VALUE
+# ---------------------
+# Append VALUE onto the existing contents of VAR.
+
+  # _G_HAVE_PLUSEQ_OP
+  # Can be empty, in which case the shell is probed, "yes" if += is
+  # useable or anything else if it does not work.
+  if test -z "$_G_HAVE_PLUSEQ_OP" &&  \
+      __PLUSEQ_TEST="a" &&  \
+      __PLUSEQ_TEST+=" b" 2>/dev/null &&  \
+      test "a b" = "$__PLUSEQ_TEST"; then
+    _G_HAVE_PLUSEQ_OP=yes
+  fi
+
+if test yes = "$_G_HAVE_PLUSEQ_OP"
+then
+  # This is an XSI compatible shell, allowing a faster implementation...
+  eval 'func_append ()
+  {
+    $debug_cmd
+
+    eval "$1+=\$2"
+  }'
+else
+  # ...otherwise fall back to using expr, which is often a shell builtin.
+  func_append ()
+  {
+    $debug_cmd
+
+    eval "$1=\$$1\$2"
+  }
+fi
+
+
+# func_append_quoted VAR VALUE
+# ----------------------------
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+if test yes = "$_G_HAVE_PLUSEQ_OP"; then
+  eval 'func_append_quoted ()
+  {
+    $debug_cmd
+
+    func_quote_arg pretty "$2"
+    eval "$1+=\\ \$func_quote_arg_result"
+  }'
+else
+  func_append_quoted ()
+  {
+    $debug_cmd
+
+    func_quote_arg pretty "$2"
+    eval "$1=\$$1\\ \$func_quote_arg_result"
+  }
+fi
+
+
+# func_append_uniq VAR VALUE
+# --------------------------
+# Append unique VALUE onto the existing contents of VAR, assuming
+# entries are delimited by the first character of VALUE.  For example:
+#
+#   func_append_uniq options " --another-option option-argument"
+#
+# will only append to $options if " --another-option option-argument "
+# is not already present somewhere in $options already (note spaces at
+# each end implied by leading space in second argument).
+func_append_uniq ()
+{
+    $debug_cmd
+
+    eval _G_current_value='`$ECHO $'$1'`'
+    _G_delim=`expr "$2" : '\(.\)'`
+
+    case $_G_delim$_G_current_value$_G_delim in
+      *"$2$_G_delim"*) ;;
+      *) func_append "$@" ;;
+    esac
+}
+
+
+# func_arith TERM...
+# ------------------
+# Set func_arith_result to the result of evaluating TERMs.
+  test -z "$_G_HAVE_ARITH_OP" \
+    && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
+    && _G_HAVE_ARITH_OP=yes
+
+if test yes = "$_G_HAVE_ARITH_OP"; then
+  eval 'func_arith ()
+  {
+    $debug_cmd
+
+    func_arith_result=$(( $* ))
+  }'
+else
+  func_arith ()
+  {
+    $debug_cmd
+
+    func_arith_result=`expr "$@"`
+  }
+fi
+
+
+# func_basename FILE
+# ------------------
+# Set func_basename_result to FILE with everything up to and including
+# the last / stripped.
+if test yes = "$_G_HAVE_XSI_OPS"; then
+  # If this shell supports suffix pattern removal, then use it to avoid
+  # forking. Hide the definitions single quotes in case the shell chokes
+  # on unsupported syntax...
+  _b='func_basename_result=${1##*/}'
+  _d='case $1 in
+        */*) func_dirname_result=${1%/*}$2 ;;
+        *  ) func_dirname_result=$3        ;;
+      esac'
+
+else
+  # ...otherwise fall back to using sed.
+  _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
+  _d='func_dirname_result=`$ECHO "$1"  |$SED "$sed_dirname"`
+      if test "X$func_dirname_result" = "X$1"; then
+        func_dirname_result=$3
+      else
+        func_append func_dirname_result "$2"
+      fi'
+fi
+
+eval 'func_basename ()
+{
+    $debug_cmd
+
+    '"$_b"'
+}'
+
+
+# func_dirname FILE APPEND NONDIR_REPLACEMENT
+# -------------------------------------------
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+eval 'func_dirname ()
+{
+    $debug_cmd
+
+    '"$_d"'
+}'
+
+
+# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
+# --------------------------------------------------------
+# Perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# For efficiency, we do not delegate to the functions above but instead
+# duplicate the functionality here.
+eval 'func_dirname_and_basename ()
+{
+    $debug_cmd
+
+    '"$_b"'
+    '"$_d"'
+}'
+
+
+# func_echo ARG...
+# ----------------
+# Echo program name prefixed message.
+func_echo ()
+{
+    $debug_cmd
+
+    _G_message=$*
+
+    func_echo_IFS=$IFS
+    IFS=$nl
+    for _G_line in $_G_message; do
+      IFS=$func_echo_IFS
+      $ECHO "$progname: $_G_line"
+    done
+    IFS=$func_echo_IFS
+}
+
+
+# func_echo_all ARG...
+# --------------------
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+
+# func_echo_infix_1 INFIX ARG...
+# ------------------------------
+# Echo program name, followed by INFIX on the first line, with any
+# additional lines not showing INFIX.
+func_echo_infix_1 ()
+{
+    $debug_cmd
+
+    $require_term_colors
+
+    _G_infix=$1; shift
+    _G_indent=$_G_infix
+    _G_prefix="$progname: $_G_infix: "
+    _G_message=$*
+
+    # Strip color escape sequences before counting printable length
+    for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
+    do
+      test -n "$_G_tc" && {
+        _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
+        _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
+      }
+    done
+    _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`"  " ## exclude from sc_prohibit_nested_quotes
+
+    func_echo_infix_1_IFS=$IFS
+    IFS=$nl
+    for _G_line in $_G_message; do
+      IFS=$func_echo_infix_1_IFS
+      $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
+      _G_prefix=$_G_indent
+    done
+    IFS=$func_echo_infix_1_IFS
+}
+
+
+# func_error ARG...
+# -----------------
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $debug_cmd
+
+    $require_term_colors
+
+    func_echo_infix_1 "  $tc_standout${tc_red}error$tc_reset" "$*" >&2
+}
+
+
+# func_fatal_error ARG...
+# -----------------------
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    $debug_cmd
+
+    func_error "$*"
+    exit $EXIT_FAILURE
+}
+
+
+# func_grep EXPRESSION FILENAME
+# -----------------------------
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $debug_cmd
+
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_len STRING
+# ---------------
+# Set func_len_result to the length of STRING. STRING may not
+# start with a hyphen.
+  test -z "$_G_HAVE_XSI_OPS" \
+    && (eval 'x=a/b/c;
+      test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+    && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+  eval 'func_len ()
+  {
+    $debug_cmd
+
+    func_len_result=${#1}
+  }'
+else
+  func_len ()
+  {
+    $debug_cmd
+
+    func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+  }
+fi
+
+
+# func_mkdir_p DIRECTORY-PATH
+# ---------------------------
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    $debug_cmd
+
+    _G_directory_path=$1
+    _G_dir_list=
+
+    if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
+
+      # Protect directory names starting with '-'
+      case $_G_directory_path in
+        -*) _G_directory_path=./$_G_directory_path ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$_G_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        _G_dir_list=$_G_directory_path:$_G_dir_list
+
+        # If the last portion added has no slash in it, the list is done
+        case $_G_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
+      done
+      _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
+
+      func_mkdir_p_IFS=$IFS; IFS=:
+      for _G_dir in $_G_dir_list; do
+	IFS=$func_mkdir_p_IFS
+        # mkdir can fail with a 'File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$_G_dir" 2>/dev/null || :
+      done
+      IFS=$func_mkdir_p_IFS
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$_G_directory_path" || \
+        func_fatal_error "Failed to create '$1'"
+    fi
+}
+
+
+# func_mktempdir [BASENAME]
+# -------------------------
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, BASENAME is the basename for that directory.
+func_mktempdir ()
+{
+    $debug_cmd
+
+    _G_template=${TMPDIR-/tmp}/${1-$progname}
+
+    if test : = "$opt_dry_run"; then
+      # Return a directory name, but don't create it in dry-run mode
+      _G_tmpdir=$_G_template-$$
+    else
+
+      # If mktemp works, use that first and foremost
+      _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$_G_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        _G_tmpdir=$_G_template-${RANDOM-0}$$
+
+        func_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$_G_tmpdir"
+        umask $func_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$_G_tmpdir" || \
+        func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
+    fi
+
+    $ECHO "$_G_tmpdir"
+}
+
+
+# func_normal_abspath PATH
+# ------------------------
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+func_normal_abspath ()
+{
+    $debug_cmd
+
+    # These SED scripts presuppose an absolute path with a trailing slash.
+    _G_pathcar='s|^/\([^/]*\).*$|\1|'
+    _G_pathcdr='s|^/[^/]*||'
+    _G_removedotparts=':dotsl
+		s|/\./|/|g
+		t dotsl
+		s|/\.$|/|'
+    _G_collapseslashes='s|/\{1,\}|/|g'
+    _G_finalslash='s|/*$|/|'
+
+    # Start from root dir and reassemble the path.
+    func_normal_abspath_result=
+    func_normal_abspath_tpath=$1
+    func_normal_abspath_altnamespace=
+    case $func_normal_abspath_tpath in
+      "")
+        # Empty path, that just means $cwd.
+        func_stripname '' '/' "`pwd`"
+        func_normal_abspath_result=$func_stripname_result
+        return
+        ;;
+      # The next three entries are used to spot a run of precisely
+      # two leading slashes without using negated character classes;
+      # we take advantage of case's first-match behaviour.
+      ///*)
+        # Unusual form of absolute path, do nothing.
+        ;;
+      //*)
+        # Not necessarily an ordinary path; POSIX reserves leading '//'
+        # and for example Cygwin uses it to access remote file shares
+        # over CIFS/SMB, so we conserve a leading double slash if found.
+        func_normal_abspath_altnamespace=/
+        ;;
+      /*)
+        # Absolute path, do nothing.
+        ;;
+      *)
+        # Relative path, prepend $cwd.
+        func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+        ;;
+    esac
+
+    # Cancel out all the simple stuff to save iterations.  We also want
+    # the path to end with a slash for ease of parsing, so make sure
+    # there is one (and only one) here.
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+          -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
+    while :; do
+      # Processed it all yet?
+      if test / = "$func_normal_abspath_tpath"; then
+        # If we ascended to the root using ".." the result may be empty now.
+        if test -z "$func_normal_abspath_result"; then
+          func_normal_abspath_result=/
+        fi
+        break
+      fi
+      func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+          -e "$_G_pathcar"`
+      func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+          -e "$_G_pathcdr"`
+      # Figure out what to do with it
+      case $func_normal_abspath_tcomponent in
+        "")
+          # Trailing empty path component, ignore it.
+          ;;
+        ..)
+          # Parent dir; strip last assembled component from result.
+          func_dirname "$func_normal_abspath_result"
+          func_normal_abspath_result=$func_dirname_result
+          ;;
+        *)
+          # Actual path component, append it.
+          func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
+          ;;
+      esac
+    done
+    # Restore leading double-slash if one was found on entry.
+    func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+
+# func_notquiet ARG...
+# --------------------
+# Echo program name prefixed message only when not in quiet mode.
+func_notquiet ()
+{
+    $debug_cmd
+
+    $opt_quiet || func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+
+# func_relative_path SRCDIR DSTDIR
+# --------------------------------
+# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
+func_relative_path ()
+{
+    $debug_cmd
+
+    func_relative_path_result=
+    func_normal_abspath "$1"
+    func_relative_path_tlibdir=$func_normal_abspath_result
+    func_normal_abspath "$2"
+    func_relative_path_tbindir=$func_normal_abspath_result
+
+    # Ascend the tree starting from libdir
+    while :; do
+      # check if we have found a prefix of bindir
+      case $func_relative_path_tbindir in
+        $func_relative_path_tlibdir)
+          # found an exact match
+          func_relative_path_tcancelled=
+          break
+          ;;
+        $func_relative_path_tlibdir*)
+          # found a matching prefix
+          func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+          func_relative_path_tcancelled=$func_stripname_result
+          if test -z "$func_relative_path_result"; then
+            func_relative_path_result=.
+          fi
+          break
+          ;;
+        *)
+          func_dirname $func_relative_path_tlibdir
+          func_relative_path_tlibdir=$func_dirname_result
+          if test -z "$func_relative_path_tlibdir"; then
+            # Have to descend all the way to the root!
+            func_relative_path_result=../$func_relative_path_result
+            func_relative_path_tcancelled=$func_relative_path_tbindir
+            break
+          fi
+          func_relative_path_result=../$func_relative_path_result
+          ;;
+      esac
+    done
+
+    # Now calculate path; take care to avoid doubling-up slashes.
+    func_stripname '' '/' "$func_relative_path_result"
+    func_relative_path_result=$func_stripname_result
+    func_stripname '/' '/' "$func_relative_path_tcancelled"
+    if test -n "$func_stripname_result"; then
+      func_append func_relative_path_result "/$func_stripname_result"
+    fi
+
+    # Normalisation. If bindir is libdir, return '.' else relative path.
+    if test -n "$func_relative_path_result"; then
+      func_stripname './' '' "$func_relative_path_result"
+      func_relative_path_result=$func_stripname_result
+    fi
+
+    test -n "$func_relative_path_result" || func_relative_path_result=.
+
+    :
+}
+
+
+# func_quote_portable EVAL ARG
+# ----------------------------
+# Internal function to portably implement func_quote_arg.  Note that we still
+# keep attention to performance here so we as much as possible try to avoid
+# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
+func_quote_portable ()
+{
+    $debug_cmd
+
+    $require_check_ifs_backslash
+
+    func_quote_portable_result=$2
+
+    # one-time-loop (easy break)
+    while true
+    do
+      if $1; then
+        func_quote_portable_result=`$ECHO "$2" | $SED \
+          -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
+        break
+      fi
+
+      # Quote for eval.
+      case $func_quote_portable_result in
+        *[\\\`\"\$]*)
+          # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string
+          # contains the shell wildcard characters.
+          case $check_ifs_backshlash_broken$func_quote_portable_result in
+            :*|*[\[\*\?]*)
+              func_quote_portable_result=`$ECHO "$func_quote_portable_result" \
+                  | $SED "$sed_quote_subst"`
+              break
+              ;;
+          esac
+
+          func_quote_portable_old_IFS=$IFS
+          for _G_char in '\' '`' '"' '$'
+          do
+            # STATE($1) PREV($2) SEPARATOR($3)
+            set start "" ""
+            func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
+            IFS=$_G_char
+            for _G_part in $func_quote_portable_result
+            do
+              case $1 in
+              quote)
+                func_append func_quote_portable_result "$3$2"
+                set quote "$_G_part" "\\$_G_char"
+                ;;
+              start)
+                set first "" ""
+                func_quote_portable_result=
+                ;;
+              first)
+                set quote "$_G_part" ""
+                ;;
+              esac
+            done
+          done
+          IFS=$func_quote_portable_old_IFS
+          ;;
+        *) ;;
+      esac
+      break
+    done
+
+    func_quote_portable_unquoted_result=$func_quote_portable_result
+    case $func_quote_portable_result in
+      # double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and variable expansion
+      # for a subsequent eval.
+      # many bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_portable_result=\"$func_quote_portable_result\"
+        ;;
+    esac
+}
+
+
+# func_quotefast_eval ARG
+# -----------------------
+# Quote one ARG (internal).  This is equivalent to 'func_quote_arg eval ARG',
+# but optimized for speed.  Result is stored in $func_quotefast_eval.
+if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
+  printf -v _GL_test_printf_tilde %q '~'
+  if test '\~' = "$_GL_test_printf_tilde"; then
+    func_quotefast_eval ()
+    {
+      printf -v func_quotefast_eval_result %q "$1"
+    }
+  else
+    # Broken older Bash implementations.  Make those faster too if possible.
+    func_quotefast_eval ()
+    {
+      case $1 in
+        '~'*)
+          func_quote_portable false "$1"
+          func_quotefast_eval_result=$func_quote_portable_result
+          ;;
+        *)
+          printf -v func_quotefast_eval_result %q "$1"
+          ;;
+      esac
+    }
+  fi
+else
+  func_quotefast_eval ()
+  {
+    func_quote_portable false "$1"
+    func_quotefast_eval_result=$func_quote_portable_result
+  }
+fi
+
+
+# func_quote_arg MODEs ARG
+# ------------------------
+# Quote one ARG to be evaled later.  MODEs argument may contain zero or more
+# specifiers listed below separated by ',' character.  This function returns two
+# values:
+#   i) func_quote_arg_result
+#      double-quoted (when needed), suitable for a subsequent eval
+#  ii) func_quote_arg_unquoted_result
+#      has all characters that are still active within double
+#      quotes backslashified.  Available only if 'unquoted' is specified.
+#
+# Available modes:
+# ----------------
+# 'eval' (default)
+#       - escape shell special characters
+# 'expand'
+#       - the same as 'eval';  but do not quote variable references
+# 'pretty'
+#       - request aesthetic output, i.e. '"a b"' instead of 'a\ b'.  This might
+#         be used later in func_quote to get output like: 'echo "a b"' instead
+#         of 'echo a\ b'.  This is slower than default on some shells.
+# 'unquoted'
+#       - produce also $func_quote_arg_unquoted_result which does not contain
+#         wrapping double-quotes.
+#
+# Examples for 'func_quote_arg pretty,unquoted string':
+#
+#   string      | *_result              | *_unquoted_result
+#   ------------+-----------------------+-------------------
+#   "           | \"                    | \"
+#   a b         | "a b"                 | a b
+#   "a b"       | "\"a b\""             | \"a b\"
+#   *           | "*"                   | *
+#   z="${x-$y}" | "z=\"\${x-\$y}\""     | z=\"\${x-\$y}\"
+#
+# Examples for 'func_quote_arg pretty,unquoted,expand string':
+#
+#   string        |   *_result          |  *_unquoted_result
+#   --------------+---------------------+--------------------
+#   z="${x-$y}"   | "z=\"${x-$y}\""     | z=\"${x-$y}\"
+func_quote_arg ()
+{
+    _G_quote_expand=false
+    case ,$1, in
+      *,expand,*)
+        _G_quote_expand=:
+        ;;
+    esac
+
+    case ,$1, in
+      *,pretty,*|*,expand,*|*,unquoted,*)
+        func_quote_portable $_G_quote_expand "$2"
+        func_quote_arg_result=$func_quote_portable_result
+        func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
+        ;;
+      *)
+        # Faster quote-for-eval for some shells.
+        func_quotefast_eval "$2"
+        func_quote_arg_result=$func_quotefast_eval_result
+        ;;
+    esac
+}
+
+
+# func_quote MODEs ARGs...
+# ------------------------
+# Quote all ARGs to be evaled later and join them into single command.  See
+# func_quote_arg's description for more info.
+func_quote ()
+{
+    $debug_cmd
+    _G_func_quote_mode=$1 ; shift
+    func_quote_result=
+    while test 0 -lt $#; do
+      func_quote_arg "$_G_func_quote_mode" "$1"
+      if test -n "$func_quote_result"; then
+        func_append func_quote_result " $func_quote_arg_result"
+      else
+        func_append func_quote_result "$func_quote_arg_result"
+      fi
+      shift
+    done
+}
+
+
+# func_stripname PREFIX SUFFIX NAME
+# ---------------------------------
+# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+if test yes = "$_G_HAVE_XSI_OPS"; then
+  eval 'func_stripname ()
+  {
+    $debug_cmd
+
+    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+    # positional parameters, so assign one to ordinary variable first.
+    func_stripname_result=$3
+    func_stripname_result=${func_stripname_result#"$1"}
+    func_stripname_result=${func_stripname_result%"$2"}
+  }'
+else
+  func_stripname ()
+  {
+    $debug_cmd
+
+    case $2 in
+      .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
+      *)  func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
+    esac
+  }
+fi
+
+
+# func_show_eval CMD [FAIL_EXP]
+# -----------------------------
+# Unless opt_quiet is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    $debug_cmd
+
+    _G_cmd=$1
+    _G_fail_exp=${2-':'}
+
+    func_quote_arg pretty,expand "$_G_cmd"
+    eval "func_notquiet $func_quote_arg_result"
+
+    $opt_dry_run || {
+      eval "$_G_cmd"
+      _G_status=$?
+      if test 0 -ne "$_G_status"; then
+	eval "(exit $_G_status); $_G_fail_exp"
+      fi
+    }
+}
+
+
+# func_show_eval_locale CMD [FAIL_EXP]
+# ------------------------------------
+# Unless opt_quiet is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    $debug_cmd
+
+    _G_cmd=$1
+    _G_fail_exp=${2-':'}
+
+    $opt_quiet || {
+      func_quote_arg expand,pretty "$_G_cmd"
+      eval "func_echo $func_quote_arg_result"
+    }
+
+    $opt_dry_run || {
+      eval "$_G_user_locale
+	    $_G_cmd"
+      _G_status=$?
+      eval "$_G_safe_locale"
+      if test 0 -ne "$_G_status"; then
+	eval "(exit $_G_status); $_G_fail_exp"
+      fi
+    }
+}
+
+
+# func_tr_sh
+# ----------
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result.  All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+    $debug_cmd
+
+    case $1 in
+    [0-9]* | *[!a-zA-Z0-9_]*)
+      func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
+      ;;
+    * )
+      func_tr_sh_result=$1
+      ;;
+    esac
+}
+
+
+# func_verbose ARG...
+# -------------------
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $debug_cmd
+
+    $opt_verbose && func_echo "$*"
+
+    :
+}
+
+
+# func_warn_and_continue ARG...
+# -----------------------------
+# Echo program name prefixed warning message to standard error.
+func_warn_and_continue ()
+{
+    $debug_cmd
+
+    $require_term_colors
+
+    func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
+}
+
+
+# func_warning CATEGORY ARG...
+# ----------------------------
+# Echo program name prefixed warning message to standard error. Warning
+# messages can be filtered according to CATEGORY, where this function
+# elides messages where CATEGORY is not listed in the global variable
+# 'opt_warning_types'.
+func_warning ()
+{
+    $debug_cmd
+
+    # CATEGORY must be in the warning_categories list!
+    case " $warning_categories " in
+      *" $1 "*) ;;
+      *) func_internal_error "invalid warning category '$1'" ;;
+    esac
+
+    _G_category=$1
+    shift
+
+    case " $opt_warning_types " in
+      *" $_G_category "*) $warning_func ${1+"$@"} ;;
+    esac
+}
+
+
+# func_sort_ver VER1 VER2
+# -----------------------
+# 'sort -V' is not generally available.
+# Note this deviates from the version comparison in automake
+# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
+# but this should suffice as we won't be specifying old
+# version formats or redundant trailing .0 in bootstrap.conf.
+# If we did want full compatibility then we should probably
+# use m4_version_compare from autoconf.
+func_sort_ver ()
+{
+    $debug_cmd
+
+    printf '%s\n%s\n' "$1" "$2" \
+      | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
+}
+
+# func_lt_ver PREV CURR
+# ---------------------
+# Return true if PREV and CURR are in the correct order according to
+# func_sort_ver, otherwise false.  Use it like this:
+#
+#  func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
+func_lt_ver ()
+{
+    $debug_cmd
+
+    test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+#! /bin/sh
+
+# A portable, pluggable option parser for Bourne shell.
+# Written by Gary V. Vaughan, 2010
+
+# This is free software.  There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2010-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>.  You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it.  See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# This file is a library for parsing options in your shell scripts along
+# with assorted other useful supporting features that you can make use
+# of too.
+#
+# For the simplest scripts you might need only:
+#
+#   #!/bin/sh
+#   . relative/path/to/funclib.sh
+#   . relative/path/to/options-parser
+#   scriptversion=1.0
+#   func_options ${1+"$@"}
+#   eval set dummy "$func_options_result"; shift
+#   ...rest of your script...
+#
+# In order for the '--version' option to work, you will need to have a
+# suitably formatted comment like the one at the top of this file
+# starting with '# Written by ' and ending with '# Copyright'.
+#
+# For '-h' and '--help' to work, you will also need a one line
+# description of your script's purpose in a comment directly above the
+# '# Written by ' line, like the one at the top of this file.
+#
+# The default options also support '--debug', which will turn on shell
+# execution tracing (see the comment above debug_cmd below for another
+# use), and '--verbose' and the func_verbose function to allow your script
+# to display verbose messages only when your user has specified
+# '--verbose'.
+#
+# After sourcing this file, you can plug in processing for additional
+# options by amending the variables from the 'Configuration' section
+# below, and following the instructions in the 'Option parsing'
+# section further down.
+
+## -------------- ##
+## Configuration. ##
+## -------------- ##
+
+# You should override these variables in your script after sourcing this
+# file so that they reflect the customisations you have added to the
+# option parser.
+
+# The usage line for option parsing errors and the start of '-h' and
+# '--help' output messages. You can embed shell variables for delayed
+# expansion at the time the message is displayed, but you will need to
+# quote other shell meta-characters carefully to prevent them being
+# expanded when the contents are evaled.
+usage='$progpath [OPTION]...'
+
+# Short help message in response to '-h' and '--help'.  Add to this or
+# override it after sourcing this library to reflect the full set of
+# options your script accepts.
+usage_message="\
+       --debug        enable verbose shell tracing
+   -W, --warnings=CATEGORY
+                      report the warnings falling in CATEGORY [all]
+   -v, --verbose      verbosely report processing
+       --version      print version information and exit
+   -h, --help         print short or long help message and exit
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+long_help_message="
+Warning categories include:
+       'all'          show all warnings
+       'none'         turn off all the warnings
+       'error'        warnings are treated as fatal errors"
+
+# Help message printed before fatal option parsing errors.
+fatal_help="Try '\$progname --help' for more information."
+
+
+
+## ------------------------- ##
+## Hook function management. ##
+## ------------------------- ##
+
+# This section contains functions for adding, removing, and running hooks
+# in the main code.  A hook is just a list of function names that can be
+# run in order later on.
+
+# func_hookable FUNC_NAME
+# -----------------------
+# Declare that FUNC_NAME will run hooks added with
+# 'func_add_hook FUNC_NAME ...'.
+func_hookable ()
+{
+    $debug_cmd
+
+    func_append hookable_fns " $1"
+}
+
+
+# func_add_hook FUNC_NAME HOOK_FUNC
+# ---------------------------------
+# Request that FUNC_NAME call HOOK_FUNC before it returns.  FUNC_NAME must
+# first have been declared "hookable" by a call to 'func_hookable'.
+func_add_hook ()
+{
+    $debug_cmd
+
+    case " $hookable_fns " in
+      *" $1 "*) ;;
+      *) func_fatal_error "'$1' does not accept hook functions." ;;
+    esac
+
+    eval func_append ${1}_hooks '" $2"'
+}
+
+
+# func_remove_hook FUNC_NAME HOOK_FUNC
+# ------------------------------------
+# Remove HOOK_FUNC from the list of hook functions to be called by
+# FUNC_NAME.
+func_remove_hook ()
+{
+    $debug_cmd
+
+    eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
+}
+
+
+# func_propagate_result FUNC_NAME_A FUNC_NAME_B
+# ---------------------------------------------
+# If the *_result variable of FUNC_NAME_A _is set_, assign its value to
+# *_result variable of FUNC_NAME_B.
+func_propagate_result ()
+{
+    $debug_cmd
+
+    func_propagate_result_result=:
+    if eval "test \"\${${1}_result+set}\" = set"
+    then
+      eval "${2}_result=\$${1}_result"
+    else
+      func_propagate_result_result=false
+    fi
+}
+
+
+# func_run_hooks FUNC_NAME [ARG]...
+# ---------------------------------
+# Run all hook functions registered to FUNC_NAME.
+# It's assumed that the list of hook functions contains nothing more
+# than a whitespace-delimited list of legal shell function names, and
+# no effort is wasted trying to catch shell meta-characters or preserve
+# whitespace.
+func_run_hooks ()
+{
+    $debug_cmd
+
+    _G_rc_run_hooks=false
+
+    case " $hookable_fns " in
+      *" $1 "*) ;;
+      *) func_fatal_error "'$1' does not support hook functions." ;;
+    esac
+
+    eval _G_hook_fns=\$$1_hooks; shift
+
+    for _G_hook in $_G_hook_fns; do
+      func_unset "${_G_hook}_result"
+      eval $_G_hook '${1+"$@"}'
+      func_propagate_result $_G_hook func_run_hooks
+      if $func_propagate_result_result; then
+        eval set dummy "$func_run_hooks_result"; shift
+      fi
+    done
+}
+
+
+
+## --------------- ##
+## Option parsing. ##
+## --------------- ##
+
+# In order to add your own option parsing hooks, you must accept the
+# full positional parameter list from your hook function.  You may remove
+# or edit any options that you action, and then pass back the remaining
+# unprocessed options in '<hooked_function_name>_result', escaped
+# suitably for 'eval'.
+#
+# The '<hooked_function_name>_result' variable is automatically unset
+# before your hook gets called; for best performance, only set the
+# *_result variable when necessary (i.e. don't call the 'func_quote'
+# function unnecessarily because it can be an expensive operation on some
+# machines).
+#
+# Like this:
+#
+#    my_options_prep ()
+#    {
+#        $debug_cmd
+#
+#        # Extend the existing usage message.
+#        usage_message=$usage_message'
+#      -s, --silent       don'\''t print informational messages
+#    '
+#        # No change in '$@' (ignored completely by this hook).  Leave
+#        # my_options_prep_result variable intact.
+#    }
+#    func_add_hook func_options_prep my_options_prep
+#
+#
+#    my_silent_option ()
+#    {
+#        $debug_cmd
+#
+#        args_changed=false
+#
+#        # Note that, for efficiency, we parse as many options as we can
+#        # recognise in a loop before passing the remainder back to the
+#        # caller on the first unrecognised argument we encounter.
+#        while test $# -gt 0; do
+#          opt=$1; shift
+#          case $opt in
+#            --silent|-s) opt_silent=:
+#                         args_changed=:
+#                         ;;
+#            # Separate non-argument short options:
+#            -s*)         func_split_short_opt "$_G_opt"
+#                         set dummy "$func_split_short_opt_name" \
+#                             "-$func_split_short_opt_arg" ${1+"$@"}
+#                         shift
+#                         args_changed=:
+#                         ;;
+#            *)           # Make sure the first unrecognised option "$_G_opt"
+#                         # is added back to "$@" in case we need it later,
+#                         # if $args_changed was set to 'true'.
+#                         set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+#          esac
+#        done
+#
+#        # Only call 'func_quote' here if we processed at least one argument.
+#        if $args_changed; then
+#          func_quote eval ${1+"$@"}
+#          my_silent_option_result=$func_quote_result
+#        fi
+#    }
+#    func_add_hook func_parse_options my_silent_option
+#
+#
+#    my_option_validation ()
+#    {
+#        $debug_cmd
+#
+#        $opt_silent && $opt_verbose && func_fatal_help "\
+#    '--silent' and '--verbose' options are mutually exclusive."
+#    }
+#    func_add_hook func_validate_options my_option_validation
+#
+# You'll also need to manually amend $usage_message to reflect the extra
+# options you parse.  It's preferable to append if you can, so that
+# multiple option parsing hooks can be added safely.
+
+
+# func_options_finish [ARG]...
+# ----------------------------
+# Finishing the option parse loop (call 'func_options' hooks ATM).
+func_options_finish ()
+{
+    $debug_cmd
+
+    func_run_hooks func_options ${1+"$@"}
+    func_propagate_result func_run_hooks func_options_finish
+}
+
+
+# func_options [ARG]...
+# ---------------------
+# All the functions called inside func_options are hookable. See the
+# individual implementations for details.
+func_hookable func_options
+func_options ()
+{
+    $debug_cmd
+
+    _G_options_quoted=false
+
+    for my_func in options_prep parse_options validate_options options_finish
+    do
+      func_unset func_${my_func}_result
+      func_unset func_run_hooks_result
+      eval func_$my_func '${1+"$@"}'
+      func_propagate_result func_$my_func func_options
+      if $func_propagate_result_result; then
+        eval set dummy "$func_options_result"; shift
+        _G_options_quoted=:
+      fi
+    done
+
+    $_G_options_quoted || {
+      # As we (func_options) are top-level options-parser function and
+      # nobody quoted "$@" for us yet, we need to do it explicitly for
+      # caller.
+      func_quote eval ${1+"$@"}
+      func_options_result=$func_quote_result
+    }
+}
+
+
+# func_options_prep [ARG]...
+# --------------------------
+# All initialisations required before starting the option parse loop.
+# Note that when calling hook functions, we pass through the list of
+# positional parameters.  If a hook function modifies that list, and
+# needs to propagate that back to rest of this script, then the complete
+# modified list must be put in 'func_run_hooks_result' before returning.
+func_hookable func_options_prep
+func_options_prep ()
+{
+    $debug_cmd
+
+    # Option defaults:
+    opt_verbose=false
+    opt_warning_types=
+
+    func_run_hooks func_options_prep ${1+"$@"}
+    func_propagate_result func_run_hooks func_options_prep
+}
+
+
+# func_parse_options [ARG]...
+# ---------------------------
+# The main option parsing loop.
+func_hookable func_parse_options
+func_parse_options ()
+{
+    $debug_cmd
+
+    _G_parse_options_requote=false
+    # this just eases exit handling
+    while test $# -gt 0; do
+      # Defer to hook functions for initial option parsing, so they
+      # get priority in the event of reusing an option name.
+      func_run_hooks func_parse_options ${1+"$@"}
+      func_propagate_result func_run_hooks func_parse_options
+      if $func_propagate_result_result; then
+        eval set dummy "$func_parse_options_result"; shift
+        # Even though we may have changed "$@", we passed the "$@" array
+        # down into the hook and it quoted it for us (because we are in
+        # this if-branch).  No need to quote it again.
+        _G_parse_options_requote=false
+      fi
+
+      # Break out of the loop if we already parsed every option.
+      test $# -gt 0 || break
+
+      # We expect that one of the options parsed in this function matches
+      # and thus we remove _G_opt from "$@" and need to re-quote.
+      _G_match_parse_options=:
+      _G_opt=$1
+      shift
+      case $_G_opt in
+        --debug|-x)   debug_cmd='set -x'
+                      func_echo "enabling shell trace mode" >&2
+                      $debug_cmd
+                      ;;
+
+        --no-warnings|--no-warning|--no-warn)
+                      set dummy --warnings none ${1+"$@"}
+                      shift
+		      ;;
+
+        --warnings|--warning|-W)
+                      if test $# = 0 && func_missing_arg $_G_opt; then
+                        _G_parse_options_requote=:
+                        break
+                      fi
+                      case " $warning_categories $1" in
+                        *" $1 "*)
+                          # trailing space prevents matching last $1 above
+                          func_append_uniq opt_warning_types " $1"
+                          ;;
+                        *all)
+                          opt_warning_types=$warning_categories
+                          ;;
+                        *none)
+                          opt_warning_types=none
+                          warning_func=:
+                          ;;
+                        *error)
+                          opt_warning_types=$warning_categories
+                          warning_func=func_fatal_error
+                          ;;
+                        *)
+                          func_fatal_error \
+                             "unsupported warning category: '$1'"
+                          ;;
+                      esac
+                      shift
+                      ;;
+
+        --verbose|-v) opt_verbose=: ;;
+        --version)    func_version ;;
+        -\?|-h)       func_usage ;;
+        --help)       func_help ;;
+
+	# Separate optargs to long options (plugins may need this):
+	--*=*)        func_split_equals "$_G_opt"
+	              set dummy "$func_split_equals_lhs" \
+                          "$func_split_equals_rhs" ${1+"$@"}
+                      shift
+                      ;;
+
+       # Separate optargs to short options:
+        -W*)
+                      func_split_short_opt "$_G_opt"
+                      set dummy "$func_split_short_opt_name" \
+                          "$func_split_short_opt_arg" ${1+"$@"}
+                      shift
+                      ;;
+
+        # Separate non-argument short options:
+        -\?*|-h*|-v*|-x*)
+                      func_split_short_opt "$_G_opt"
+                      set dummy "$func_split_short_opt_name" \
+                          "-$func_split_short_opt_arg" ${1+"$@"}
+                      shift
+                      ;;
+
+        --)           _G_parse_options_requote=: ; break ;;
+        -*)           func_fatal_help "unrecognised option: '$_G_opt'" ;;
+        *)            set dummy "$_G_opt" ${1+"$@"}; shift
+                      _G_match_parse_options=false
+                      break
+                      ;;
+      esac
+
+      if $_G_match_parse_options; then
+        _G_parse_options_requote=:
+      fi
+    done
+
+    if $_G_parse_options_requote; then
+      # save modified positional parameters for caller
+      func_quote eval ${1+"$@"}
+      func_parse_options_result=$func_quote_result
+    fi
+}
+
+
+# func_validate_options [ARG]...
+# ------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+func_hookable func_validate_options
+func_validate_options ()
+{
+    $debug_cmd
+
+    # Display all warnings if -W was not given.
+    test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
+
+    func_run_hooks func_validate_options ${1+"$@"}
+    func_propagate_result func_run_hooks func_validate_options
+
+    # Bail if the options were screwed!
+    $exit_cmd $EXIT_FAILURE
+}
+
+
+
+## ----------------- ##
+## Helper functions. ##
+## ----------------- ##
+
+# This section contains the helper functions used by the rest of the
+# hookable option parser framework in ascii-betical order.
+
+
+# func_fatal_help ARG...
+# ----------------------
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    $debug_cmd
+
+    eval \$ECHO \""Usage: $usage"\"
+    eval \$ECHO \""$fatal_help"\"
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+
+# func_help
+# ---------
+# Echo long help message to standard output and exit.
+func_help ()
+{
+    $debug_cmd
+
+    func_usage_message
+    $ECHO "$long_help_message"
+    exit 0
+}
+
+
+# func_missing_arg ARGNAME
+# ------------------------
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    $debug_cmd
+
+    func_error "Missing argument for '$1'."
+    exit_cmd=exit
+}
+
+
+# func_split_equals STRING
+# ------------------------
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables
+# after splitting STRING at the '=' sign.
+test -z "$_G_HAVE_XSI_OPS" \
+    && (eval 'x=a/b/c;
+      test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+    && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+  # This is an XSI compatible shell, allowing a faster implementation...
+  eval 'func_split_equals ()
+  {
+      $debug_cmd
+
+      func_split_equals_lhs=${1%%=*}
+      func_split_equals_rhs=${1#*=}
+      if test "x$func_split_equals_lhs" = "x$1"; then
+        func_split_equals_rhs=
+      fi
+  }'
+else
+  # ...otherwise fall back to using expr, which is often a shell builtin.
+  func_split_equals ()
+  {
+      $debug_cmd
+
+      func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
+      func_split_equals_rhs=
+      test "x$func_split_equals_lhs=" = "x$1" \
+        || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
+  }
+fi #func_split_equals
+
+
+# func_split_short_opt SHORTOPT
+# -----------------------------
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+  # This is an XSI compatible shell, allowing a faster implementation...
+  eval 'func_split_short_opt ()
+  {
+      $debug_cmd
+
+      func_split_short_opt_arg=${1#??}
+      func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+  }'
+else
+  # ...otherwise fall back to using expr, which is often a shell builtin.
+  func_split_short_opt ()
+  {
+      $debug_cmd
+
+      func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'`
+      func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
+  }
+fi #func_split_short_opt
+
+
+# func_usage
+# ----------
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $debug_cmd
+
+    func_usage_message
+    $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
+    exit 0
+}
+
+
+# func_usage_message
+# ------------------
+# Echo short help message to standard output.
+func_usage_message ()
+{
+    $debug_cmd
+
+    eval \$ECHO \""Usage: $usage"\"
+    echo
+    $SED -n 's|^# ||
+        /^Written by/{
+          x;p;x
+        }
+	h
+	/^Written by/q' < "$progpath"
+    echo
+    eval \$ECHO \""$usage_message"\"
+}
+
+
+# func_version
+# ------------
+# Echo version message to standard output and exit.
+# The version message is extracted from the calling file's header
+# comments, with leading '# ' stripped:
+#   1. First display the progname and version
+#   2. Followed by the header comment line matching  /^# Written by /
+#   3. Then a blank line followed by the first following line matching
+#      /^# Copyright /
+#   4. Immediately followed by any lines between the previous matches,
+#      except lines preceding the intervening completely blank line.
+# For example, see the header comments of this file.
+func_version ()
+{
+    $debug_cmd
+
+    printf '%s\n' "$progname $scriptversion"
+    $SED -n '
+        /^# Written by /!b
+        s|^# ||; p; n
+
+        :fwd2blnk
+        /./ {
+          n
+          b fwd2blnk
+        }
+        p; n
+
+        :holdwrnt
+        s|^# ||
+        s|^# *$||
+        /^Copyright /!{
+          /./H
+          n
+          b holdwrnt
+        }
+
+        s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+        G
+        s|\(\n\)\n*|\1|g
+        p; q' < "$progpath"
+
+    exit $?
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+
+# Set a version string.
+scriptversion='(GNU libtool) 2.4.7'
+
+
+# func_echo ARG...
+# ----------------
+# Libtool also displays the current mode in messages, so override
+# funclib.sh func_echo with this custom definition.
+func_echo ()
+{
+    $debug_cmd
+
+    _G_message=$*
+
+    func_echo_IFS=$IFS
+    IFS=$nl
+    for _G_line in $_G_message; do
+      IFS=$func_echo_IFS
+      $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
+    done
+    IFS=$func_echo_IFS
+}
+
+
+# func_warning ARG...
+# -------------------
+# Libtool warnings are not categorized, so override funclib.sh
+# func_warning with this simpler definition.
+func_warning ()
+{
+    $debug_cmd
+
+    $warning_func ${1+"$@"}
+}
+
+
+## ---------------- ##
+## Options parsing. ##
+## ---------------- ##
+
+# Hook in the functions to make sure our own options are parsed during
+# the option parsing loop.
+
+usage='$progpath [OPTION]... [MODE-ARG]...'
+
+# Short help message in response to '-h'.
+usage_message="Options:
+       --config             show all configuration variables
+       --debug              enable verbose shell tracing
+   -n, --dry-run            display commands without modifying any files
+       --features           display basic configuration information and exit
+       --mode=MODE          use operation mode MODE
+       --no-warnings        equivalent to '-Wnone'
+       --preserve-dup-deps  don't remove duplicate dependency libraries
+       --quiet, --silent    don't print informational messages
+       --tag=TAG            use configuration variables from tag TAG
+   -v, --verbose            print more informational messages than default
+       --version            print version information
+   -W, --warnings=CATEGORY  report the warnings falling in CATEGORY [all]
+   -h, --help, --help-all   print short, long, or detailed help message
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+func_help ()
+{
+    $debug_cmd
+
+    func_usage_message
+    $ECHO "$long_help_message
+
+MODE must be one of the following:
+
+       clean           remove files from the build directory
+       compile         compile a source file into a libtool object
+       execute         automatically set library path, then run a program
+       finish          complete the installation of libtool libraries
+       install         install libraries or executables
+       link            create a library or an executable
+       uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  When passed as first option,
+'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
+Try '$progname --help --mode=MODE' for a more detailed description of MODE.
+
+When reporting a bug, please describe a test case to reproduce it and
+include the following information:
+
+       host-triplet:   $host
+       shell:          $SHELL
+       compiler:       $LTCC
+       compiler flags: $LTCFLAGS
+       linker:         $LD (gnu? $with_gnu_ld)
+       version:        $progname $scriptversion Debian-2.4.7-7
+       automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
+       autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`
+
+Report bugs to <bug-libtool@gnu.org>.
+GNU libtool home page: <http://www.gnu.org/s/libtool/>.
+General help using GNU software: <http://www.gnu.org/gethelp/>."
+    exit 0
+}
+
+
+# func_lo2o OBJECT-NAME
+# ---------------------
+# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
+# object suffix.
+
+lo2o=s/\\.lo\$/.$objext/
+o2lo=s/\\.$objext\$/.lo/
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+  eval 'func_lo2o ()
+  {
+    case $1 in
+      *.lo) func_lo2o_result=${1%.lo}.$objext ;;
+      *   ) func_lo2o_result=$1               ;;
+    esac
+  }'
+
+  # func_xform LIBOBJ-OR-SOURCE
+  # ---------------------------
+  # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
+  # suffix to a '.lo' libtool-object suffix.
+  eval 'func_xform ()
+  {
+    func_xform_result=${1%.*}.lo
+  }'
+else
+  # ...otherwise fall back to using sed.
+  func_lo2o ()
+  {
+    func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
+  }
+
+  func_xform ()
+  {
+    func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
+  }
+fi
+
+
+# func_fatal_configuration ARG...
+# -------------------------------
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_fatal_error ${1+"$@"} \
+      "See the $PACKAGE documentation for more information." \
+      "Fatal configuration error."
+}
+
+
+# func_config
+# -----------
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+
+# func_features
+# -------------
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test yes = "$build_libtool_libs"; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test yes = "$build_old_libs"; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+
+# func_enable_tag TAGNAME
+# -----------------------
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+    # Global variable:
+    tagname=$1
+
+    re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+    re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+    sed_extractcf=/$re_begincf/,/$re_endcf/p
+
+    # Validate tagname.
+    case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+        func_fatal_error "invalid tag name: $tagname"
+        ;;
+    esac
+
+    # Don't test for the "default" C tag, as we know it's
+    # there but not specially marked.
+    case $tagname in
+        CC) ;;
+    *)
+        if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	  taglist="$taglist $tagname"
+
+	  # Evaluate the configuration.  Be careful to quote the path
+	  # and the sed script, to avoid splitting on whitespace, but
+	  # also don't use non-portable quotes within backquotes within
+	  # quotes we have to do it in 2 steps:
+	  extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	  eval "$extractedcf"
+        else
+	  func_error "ignoring unknown tag $tagname"
+        fi
+        ;;
+    esac
+}
+
+
+# func_check_version_match
+# ------------------------
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+    if test "$package_revision" != "$macro_revision"; then
+      if test "$VERSION" != "$macro_version"; then
+        if test -z "$macro_version"; then
+          cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+        else
+          cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+        fi
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+      fi
+
+      exit $EXIT_MISMATCH
+    fi
+}
+
+
+# libtool_options_prep [ARG]...
+# -----------------------------
+# Preparation for options parsed by libtool.
+libtool_options_prep ()
+{
+    $debug_mode
+
+    # Option defaults:
+    opt_config=false
+    opt_dlopen=
+    opt_dry_run=false
+    opt_help=false
+    opt_mode=
+    opt_preserve_dup_deps=false
+    opt_quiet=false
+
+    nonopt=
+    preserve_args=
+
+    _G_rc_lt_options_prep=:
+
+    _G_rc_lt_options_prep=:
+
+    # Shorthand for --mode=foo, only valid as the first argument
+    case $1 in
+    clean|clea|cle|cl)
+      shift; set dummy --mode clean ${1+"$@"}; shift
+      ;;
+    compile|compil|compi|comp|com|co|c)
+      shift; set dummy --mode compile ${1+"$@"}; shift
+      ;;
+    execute|execut|execu|exec|exe|ex|e)
+      shift; set dummy --mode execute ${1+"$@"}; shift
+      ;;
+    finish|finis|fini|fin|fi|f)
+      shift; set dummy --mode finish ${1+"$@"}; shift
+      ;;
+    install|instal|insta|inst|ins|in|i)
+      shift; set dummy --mode install ${1+"$@"}; shift
+      ;;
+    link|lin|li|l)
+      shift; set dummy --mode link ${1+"$@"}; shift
+      ;;
+    uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+      shift; set dummy --mode uninstall ${1+"$@"}; shift
+      ;;
+    *)
+      _G_rc_lt_options_prep=false
+      ;;
+    esac
+
+    if $_G_rc_lt_options_prep; then
+      # Pass back the list of options.
+      func_quote eval ${1+"$@"}
+      libtool_options_prep_result=$func_quote_result
+    fi
+}
+func_add_hook func_options_prep libtool_options_prep
+
+
+# libtool_parse_options [ARG]...
+# ---------------------------------
+# Provide handling for libtool specific options.
+libtool_parse_options ()
+{
+    $debug_cmd
+
+    _G_rc_lt_parse_options=false
+
+    # Perform our own loop to consume as many options as possible in
+    # each iteration.
+    while test $# -gt 0; do
+      _G_match_lt_parse_options=:
+      _G_opt=$1
+      shift
+      case $_G_opt in
+        --dry-run|--dryrun|-n)
+                        opt_dry_run=:
+                        ;;
+
+        --config)       func_config ;;
+
+        --dlopen|-dlopen)
+                        opt_dlopen="${opt_dlopen+$opt_dlopen
+}$1"
+                        shift
+                        ;;
+
+        --preserve-dup-deps)
+                        opt_preserve_dup_deps=: ;;
+
+        --features)     func_features ;;
+
+        --finish)       set dummy --mode finish ${1+"$@"}; shift ;;
+
+        --help)         opt_help=: ;;
+
+        --help-all)     opt_help=': help-all' ;;
+
+        --mode)         test $# = 0 && func_missing_arg $_G_opt && break
+                        opt_mode=$1
+                        case $1 in
+                          # Valid mode arguments:
+                          clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+                          # Catch anything else as an error
+                          *) func_error "invalid argument for $_G_opt"
+                             exit_cmd=exit
+                             break
+                             ;;
+                        esac
+                        shift
+                        ;;
+
+        --no-silent|--no-quiet)
+                        opt_quiet=false
+                        func_append preserve_args " $_G_opt"
+                        ;;
+
+        --no-warnings|--no-warning|--no-warn)
+                        opt_warning=false
+                        func_append preserve_args " $_G_opt"
+                        ;;
+
+        --no-verbose)
+                        opt_verbose=false
+                        func_append preserve_args " $_G_opt"
+                        ;;
+
+        --silent|--quiet)
+                        opt_quiet=:
+                        opt_verbose=false
+                        func_append preserve_args " $_G_opt"
+                        ;;
+
+        --tag)          test $# = 0 && func_missing_arg $_G_opt && break
+                        opt_tag=$1
+                        func_append preserve_args " $_G_opt $1"
+                        func_enable_tag "$1"
+                        shift
+                        ;;
+
+        --verbose|-v)   opt_quiet=false
+                        opt_verbose=:
+                        func_append preserve_args " $_G_opt"
+                        ;;
+
+        # An option not handled by this hook function:
+        *)              set dummy "$_G_opt" ${1+"$@"} ; shift
+                        _G_match_lt_parse_options=false
+                        break
+                        ;;
+      esac
+      $_G_match_lt_parse_options && _G_rc_lt_parse_options=:
+    done
+
+    if $_G_rc_lt_parse_options; then
+      # save modified positional parameters for caller
+      func_quote eval ${1+"$@"}
+      libtool_parse_options_result=$func_quote_result
+    fi
+}
+func_add_hook func_parse_options libtool_parse_options
+
+
+
+# libtool_validate_options [ARG]...
+# ---------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+libtool_validate_options ()
+{
+    # save first non-option argument
+    if test 0 -lt $#; then
+      nonopt=$1
+      shift
+    fi
+
+    # preserve --debug
+    test : = "$debug_cmd" || func_append preserve_args " --debug"
+
+    case $host in
+      # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
+      # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
+      *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
+        # don't eliminate duplications in $postdeps and $predeps
+        opt_duplicate_compiler_generated_deps=:
+        ;;
+      *)
+        opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+        ;;
+    esac
+
+    $opt_help || {
+      # Sanity checks first:
+      func_check_version_match
+
+      test yes != "$build_libtool_libs" \
+        && test yes != "$build_old_libs" \
+        && func_fatal_configuration "not configured to build any kind of library"
+
+      # Darwin sucks
+      eval std_shrext=\"$shrext_cmds\"
+
+      # Only execute mode is allowed to have -dlopen flags.
+      if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
+        func_error "unrecognized option '-dlopen'"
+        $ECHO "$help" 1>&2
+        exit $EXIT_FAILURE
+      fi
+
+      # Change the help message to a mode-specific one.
+      generic_help=$help
+      help="Try '$progname --help --mode=$opt_mode' for more information."
+    }
+
+    # Pass back the unparsed argument list
+    func_quote eval ${1+"$@"}
+    libtool_validate_options_result=$func_quote_result
+}
+func_add_hook func_validate_options libtool_validate_options
+
+
+# Process options as early as possible so that --help and --version
+# can return quickly.
+func_options ${1+"$@"}
+eval set dummy "$func_options_result"; shift
+
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+magic='%%%MAGIC variable%%%'
+magic_exe='%%%MAGIC EXE variable%%%'
+
+# Global variables.
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# func_generated_by_libtool
+# True iff stdin has been generated by Libtool. This function is only
+# a basic sanity check; it will hardly flush out determined imposters.
+func_generated_by_libtool_p ()
+{
+  $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if 'file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case $lalib_p_line in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test yes = "$lalib_p"
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    test -f "$1" &&
+      $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_dirname_and_basename "$1" "" "."
+    func_stripname '' '.exe' "$func_basename_result"
+    func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $debug_cmd
+
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$sp$nl
+      eval cmd=\"$cmd\"
+      IFS=$save_ifs
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# 'FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $debug_cmd
+
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot.  Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+  func_resolve_sysroot_result=$1
+  case $func_resolve_sysroot_result in
+  =*)
+    func_stripname '=' '' "$func_resolve_sysroot_result"
+    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+    ;;
+  esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+  case $lt_sysroot:$1 in
+  ?*:"$lt_sysroot"*)
+    func_stripname "$lt_sysroot" '' "$1"
+    func_replace_sysroot_result='='$func_stripname_result
+    ;;
+  *)
+    # Including no sysroot.
+    func_replace_sysroot_result=$1
+    ;;
+  esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $debug_cmd
+
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+	func_append_quoted CC_quoted "$arg"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_append_quoted CC_quoted "$arg"
+	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
+	    case "$@ " in
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with '--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=$1
+    if test yes = "$build_libtool_libs"; then
+      write_lobj=\'$2\'
+    else
+      write_lobj=none
+    fi
+
+    if test yes = "$build_old_libs"; then
+      write_oldobj=\'$3\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "$write_libobj"
+    }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+  $debug_cmd
+
+  func_convert_core_file_wine_to_w32_result=$1
+  if test -n "$1"; then
+    # Unfortunately, winepath does not exit with a non-zero error code, so we
+    # are forced to check the contents of stdout. On the other hand, if the
+    # command is not found, the shell will set an exit code of 127 and print
+    # *an error message* to stdout. So we must check for both error code of
+    # zero AND non-empty stdout, which explains the odd construction:
+    func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+    if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
+      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+        $SED -e "$sed_naive_backslashify"`
+    else
+      func_convert_core_file_wine_to_w32_result=
+    fi
+  fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+  $debug_cmd
+
+  # unfortunately, winepath doesn't convert paths, only file names
+  func_convert_core_path_wine_to_w32_result=
+  if test -n "$1"; then
+    oldIFS=$IFS
+    IFS=:
+    for func_convert_core_path_wine_to_w32_f in $1; do
+      IFS=$oldIFS
+      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+      if test -n "$func_convert_core_file_wine_to_w32_result"; then
+        if test -z "$func_convert_core_path_wine_to_w32_result"; then
+          func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
+        else
+          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+        fi
+      fi
+    done
+    IFS=$oldIFS
+  fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+  $debug_cmd
+
+  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+    if test "$?" -ne 0; then
+      # on failure, ensure result is empty
+      func_cygpath_result=
+    fi
+  else
+    func_cygpath_result=
+    func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
+  fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format.  Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+  $debug_cmd
+
+  # awkward: cmd appends spaces to result
+  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+    $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+  $debug_cmd
+
+  if test -z "$2" && test -n "$1"; then
+    func_error "Could not determine host file name corresponding to"
+    func_error "  '$1'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback:
+    func_to_host_file_result=$1
+  fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+  $debug_cmd
+
+  if test -z "$4" && test -n "$3"; then
+    func_error "Could not determine the host path corresponding to"
+    func_error "  '$3'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback.  This is a deliberately simplistic "conversion" and
+    # should not be "improved".  See libtool.info.
+    if test "x$1" != "x$2"; then
+      lt_replace_pathsep_chars="s|$1|$2|g"
+      func_to_host_path_result=`echo "$3" |
+        $SED -e "$lt_replace_pathsep_chars"`
+    else
+      func_to_host_path_result=$3
+    fi
+  fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+  $debug_cmd
+
+  case $4 in
+  $1 ) func_to_host_path_result=$3$func_to_host_path_result
+    ;;
+  esac
+  case $4 in
+  $2 ) func_append func_to_host_path_result "$3"
+    ;;
+  esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via '$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+  $debug_cmd
+
+  $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result.  If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+  $debug_cmd
+
+  case ,$2, in
+    *,"$to_tool_file_cmd",*)
+      func_to_tool_file_result=$1
+      ;;
+    *)
+      $to_tool_file_cmd "$1"
+      func_to_tool_file_result=$func_to_host_file_result
+      ;;
+  esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+  func_to_host_file_result=$1
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_file_result=$1
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_to_host_file_result=$func_convert_core_msys_to_w32_result
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_file_result=$1
+  if test -n "$1"; then
+    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+    # LT_CYGPATH in this case.
+    func_to_host_file_result=`cygpath -m "$1"`
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format.  Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_file_result=$1
+  if test -n "$1"; then
+    func_convert_core_file_wine_to_w32 "$1"
+    func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+  $debug_cmd
+
+  func_to_host_file_result=$1
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_msys_to_w32_result"
+    func_to_host_file_result=$func_cygpath_result
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+  $debug_cmd
+
+  func_to_host_file_result=$1
+  if test -n "$1"; then
+    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+    func_convert_core_file_wine_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+    func_to_host_file_result=$func_cygpath_result
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via '$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format.  If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+#   file name conversion function    : func_convert_file_X_to_Y ()
+#   path conversion function         : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same.  If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+  $debug_cmd
+
+  if test -z "$to_host_path_cmd"; then
+    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+    to_host_path_cmd=func_convert_path_$func_stripname_result
+  fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+  $debug_cmd
+
+  func_init_to_host_path_cmd
+  $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+  func_to_host_path_result=$1
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_path_result=$1
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from ARG.  MSYS
+    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+    # and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result=$func_convert_core_msys_to_w32_result
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_path_result=$1
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format.  Requires a wine environment and
+# a working winepath.  Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+  $debug_cmd
+
+  func_to_host_path_result=$1
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+  $debug_cmd
+
+  func_to_host_path_result=$1
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+    func_to_host_path_result=$func_cygpath_result
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+  $debug_cmd
+
+  func_to_host_path_result=$1
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from
+    # ARG. msys behavior is inconsistent here, cygpath turns them
+    # into '.;' and ';.', and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+    func_to_host_path_result=$func_cygpath_result
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+  $debug_cmd
+
+  func_dll_def_p_tmp=`$SED -n \
+    -e 's/^[	 ]*//' \
+    -e '/^\(;.*\)*$/d' \
+    -e 's/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p' \
+    -e q \
+    "$1"`
+  test DEF = "$func_dll_def_p_tmp"
+}
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $debug_cmd
+
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile=$nonopt  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg=$arg
+	arg_mode=normal
+	;;
+
+      target )
+	libobj=$arg
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify '-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          func_append pie_flag " $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  func_append later " $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs=$IFS; IFS=,
+	  for arg in $args; do
+	    IFS=$save_ifs
+	    func_append_quoted lastarg "$arg"
+	  done
+	  IFS=$save_ifs
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  func_append base_compile " $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg=$srcfile
+	  srcfile=$arg
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_append_quoted base_compile "$lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with '-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj=$func_basename_result
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from '$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test yes = "$build_libtool_libs" \
+	  || func_fatal_configuration "cannot build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_arg pretty "$libobj"
+    test "X$libobj" != "X$func_quote_arg_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name '$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname=$func_basename_result
+    xdir=$func_dirname_result
+    lobj=$xdir$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test yes = "$build_old_libs"; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test no = "$compiler_c_o"; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
+      lockfile=$output_obj.lock
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test yes = "$need_locks"; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test warn = "$need_locks"; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      func_append removelist " $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    func_append removelist " $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+    srcfile=$func_to_tool_file_result
+    func_quote_arg pretty "$srcfile"
+    qsrcfile=$func_quote_arg_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test yes = "$build_libtool_libs"; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test no != "$pic_mode"; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	func_append command " -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test warn = "$need_locks" &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test yes = "$suppress_opt"; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test yes = "$build_old_libs"; then
+      if test yes != "$pic_mode"; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test yes = "$compiler_c_o"; then
+	func_append command " -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      func_append command "$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test warn = "$need_locks" &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test no != "$need_locks"; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $opt_mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm').  RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to build PIC objects only
+  -prefer-non-pic   try to build non-PIC objects only
+  -shared           do not build a '.o' file suitable for static linking
+  -static           only build a '.o' file suitable for static linking
+  -Wc,FLAG
+  -Xcompiler FLAG   pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a 'standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix '.c' with the
+library object suffix, '.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to '-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the '--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the 'install' or 'cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      '-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  use a list of object files found in FILE to specify objects
+  -os2dllname NAME  force a short DLL name on OS/2 (no effect on other OSes)
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wa,FLAG
+  -Xassembler FLAG  pass linker-specific FLAG directly to the assembler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with '-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in '.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in '.la', then a libtool library is created,
+only library objects ('.lo' files) may be specified, and '-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
+using 'ar' and 'ranlib', or on Windows using 'lib'.
+
+If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm').  RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode '$opt_mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try '$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test : = "$opt_help"; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | $SED -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    $SED '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $debug_cmd
+
+    # The first argument is the command name.
+    cmd=$nonopt
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $opt_dlopen; do
+      test -f "$file" \
+	|| func_fatal_help "'$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "'$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "'$file' was not linked with '-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir=$func_dirname_result
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  func_append dir "/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir=$func_dirname_result
+	;;
+
+      *)
+	func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir=$absdir
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic=$magic
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file=$progdir/$program
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file=$progdir/$program
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_append_quoted args "$file"
+    done
+
+    if $opt_dry_run; then
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    else
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd=\$cmd$args
+    fi
+}
+
+test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $debug_cmd
+
+    libs=
+    libdirs=
+    admincmds=
+
+    for opt in "$nonopt" ${1+"$@"}
+    do
+      if test -d "$opt"; then
+	func_append libdirs " $opt"
+
+      elif test -f "$opt"; then
+	if func_lalib_unsafe_p "$opt"; then
+	  func_append libs " $opt"
+	else
+	  func_warning "'$opt' is not a valid libtool archive"
+	fi
+
+      else
+	func_fatal_error "invalid argument '$opt'"
+      fi
+    done
+
+    if test -n "$libs"; then
+      if test -n "$lt_sysroot"; then
+        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+      else
+        sysroot_cmd=
+      fi
+
+      # Remove sysroot references
+      if $opt_dry_run; then
+        for lib in $libs; do
+          echo "removing references to $lt_sysroot and '=' prefixes from $lib"
+        done
+      else
+        tmpdir=`func_mktempdir`
+        for lib in $libs; do
+	  $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+	    > $tmpdir/tmp-la
+	  mv -f $tmpdir/tmp-la $lib
+	done
+        ${RM}r "$tmpdir"
+      fi
+    fi
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || func_append admincmds "
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_quiet && exit $EXIT_SUCCESS
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      echo "----------------------------------------------------------------------"
+      echo "Libraries have been installed in:"
+      for libdir in $libdirs; do
+	$ECHO "   $libdir"
+      done
+      echo
+      echo "If you ever happen to want to link against installed libraries"
+      echo "in a given directory, LIBDIR, you must either use libtool, and"
+      echo "specify the full pathname of the library, or use the '-LLIBDIR'"
+      echo "flag during linking and do at least one of the following:"
+      if test -n "$shlibpath_var"; then
+	echo "   - add LIBDIR to the '$shlibpath_var' environment variable"
+	echo "     during execution"
+      fi
+      if test -n "$runpath_var"; then
+	echo "   - add LIBDIR to the '$runpath_var' environment variable"
+	echo "     during linking"
+      fi
+      if test -n "$hardcode_libdir_flag_spec"; then
+	libdir=LIBDIR
+	eval flag=\"$hardcode_libdir_flag_spec\"
+
+	$ECHO "   - use the '$flag' linker flag"
+      fi
+      if test -n "$admincmds"; then
+	$ECHO "   - have your system administrator run these commands:$admincmds"
+      fi
+      if test -f /etc/ld.so.conf; then
+	echo "   - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
+      fi
+      echo
+
+      echo "See any operating system documentation about shared libraries for"
+      case $host in
+	solaris2.[6789]|solaris2.1[0-9])
+	  echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	  echo "pages."
+	  ;;
+	*)
+	  echo "more information, such as the ld(1) and ld.so(8) manual pages."
+	  ;;
+      esac
+      echo "----------------------------------------------------------------------"
+    fi
+    exit $EXIT_SUCCESS
+}
+
+test finish = "$opt_mode" && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $debug_cmd
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac
+    then
+      # Aesthetically quote it.
+      func_quote_arg pretty "$nonopt"
+      install_prog="$func_quote_arg_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_arg pretty "$arg"
+    func_append install_prog "$func_quote_arg_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=false
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+	func_append files " $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=: ;;
+      -f)
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  if test X-m = "X$prev" && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_arg pretty "$arg"
+      func_append install_prog " $func_quote_arg_result"
+      if test -n "$arg2"; then
+	func_quote_arg pretty "$arg2"
+      fi
+      func_append install_shared_prog " $func_quote_arg_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the '$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_arg pretty "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_arg_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=:
+    if $isdir; then
+      destdir=$dest
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir=$func_dirname_result
+      destname=$func_basename_result
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "'$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "'$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic=$magic
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	func_append staticlibs " $file"
+	;;
+
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "'$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) func_append current_libdirs " $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) func_append future_libdirs " $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir=$func_dirname_result
+	func_append dir "$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking '$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname=$1
+	  shift
+
+	  srcname=$realname
+	  test -n "$relink_command" && srcname=${realname}T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme=$stripme
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=
+	      ;;
+	    esac
+	    ;;
+	  os2*)
+	    case $realname in
+	    *_dll.a)
+	      tstripme=
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try 'ln -sf' first, because the 'ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib=$destdir/$realname
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name=$func_basename_result
+	instname=$dir/${name}i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile=$destdir/$destname
+	else
+	  func_basename "$file"
+	  destfile=$func_basename_result
+	  destfile=$destdir/$destfile
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest=$destfile
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to '$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test yes = "$build_old_libs"; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile=$destdir/$destname
+	else
+	  func_basename "$file"
+	  destfile=$func_basename_result
+	  destfile=$destdir/$destfile
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=.exe
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script '$wrapper'"
+
+	  finalize=:
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "'$lib' has not been installed in '$libdir'"
+	      finalize=false
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test no = "$fast_install" && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if $finalize; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file=$func_basename_result
+	        outputname=$tmpdir/$file
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_quiet || {
+	          func_quote_arg expand,pretty "$relink_command"
+		  eval "func_echo $func_quote_arg_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink '$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file=$outputname
+	      else
+	        func_warning "cannot relink '$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name=$func_basename_result
+
+      # Set up the ranlib parameters.
+      oldlib=$destdir/$name
+      func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+      tool_oldlib=$func_to_tool_file_result
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run '$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test install = "$opt_mode" && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $debug_cmd
+
+    my_outputname=$1
+    my_originator=$2
+    my_pic_p=${3-false}
+    my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms=${my_outputname}S.c
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist=$output_objdir/$my_outputname.nm
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test yes = "$dlself"; then
+	  func_verbose "generating symbol list for '$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+	    func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
+	    $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols=$output_objdir/$outputname.exp
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	      case $host in
+	        *cygwin* | *mingw* | *cegcc* )
+	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from '$dlprefile'"
+	  func_basename "$dlprefile"
+	  name=$func_basename_result
+          case $host in
+	    *cygwin* | *mingw* | *cegcc* )
+	      # if an import library, we need to obtain dlname
+	      if func_win32_import_lib_p "$dlprefile"; then
+	        func_tr_sh "$dlprefile"
+	        eval "curr_lafile=\$libfile_$func_tr_sh_result"
+	        dlprefile_dlbasename=
+	        if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+	          # Use subshell, to avoid clobbering current variable values
+	          dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+	          if test -n "$dlprefile_dlname"; then
+	            func_basename "$dlprefile_dlname"
+	            dlprefile_dlbasename=$func_basename_result
+	          else
+	            # no lafile. user explicitly requested -dlpreopen <import library>.
+	            $sharedlib_from_linklib_cmd "$dlprefile"
+	            dlprefile_dlbasename=$sharedlib_from_linklib_result
+	          fi
+	        fi
+	        $opt_dry_run || {
+	          if test -n "$dlprefile_dlbasename"; then
+	            eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+	          else
+	            func_warning "Could not compute DLL name from $name"
+	            eval '$ECHO ": $name " >> "$nlist"'
+	          fi
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+	            $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+	        }
+	      else # not an import lib
+	        $opt_dry_run || {
+	          eval '$ECHO ": $name " >> "$nlist"'
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	        }
+	      fi
+	    ;;
+	    *)
+	      $opt_dry_run || {
+	        eval '$ECHO ": $name " >> "$nlist"'
+	        func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	        eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	      }
+	    ;;
+          esac
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  func_show_eval '$RM "${nlist}I"'
+	  if test -n "$global_symbol_to_import"; then
+	    eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+	  fi
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];\
+"
+
+	  if test -s "$nlist"I; then
+	    echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+  LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+  for (; symbol->name; ++symbol)
+    {"
+	    $SED 's/.*/      if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+	    echo >> "$output_objdir/$my_dlsyms" "\
+    }
+}"
+	  fi
+	  echo >> "$output_objdir/$my_dlsyms" "\
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{ {\"$my_originator\", (void *) 0},"
+
+	  if test -s "$nlist"I; then
+	    echo >> "$output_objdir/$my_dlsyms" "\
+  {\"@INIT@\", (void *) &lt_syminit},"
+	  fi
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    $my_pic_p && pic_flag_for_symtable=" $pic_flag"
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) func_append symtab_cflags " $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj=$output_objdir/${my_outputname}S.$objext
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for '$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+  $debug_cmd
+
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+  test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $debug_cmd
+
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+  test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $debug_cmd
+
+  win32_libid_type=unknown
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      case $nm_interface in
+      "MS dumpbin")
+	if func_cygming_ms_implib_p "$1" ||
+	   func_cygming_gnu_implib_p "$1"
+	then
+	  win32_nmres=import
+	else
+	  win32_nmres=
+	fi
+	;;
+      *)
+	func_to_tool_file "$1" func_convert_file_msys_to_w32
+	win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+	  $SED -n -e '
+	    1,100{
+		/ I /{
+		    s|.*|import|
+		    p
+		    q
+		}
+	    }'`
+	;;
+      esac
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+  $debug_cmd
+
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+  $debug_cmd
+
+  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    $SED '/^Contents of section '"$match_literal"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[	 ]*file format pe[i]\{,1\}-/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    $SED -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive that possess that section. Heuristic: eliminate
+    # all those that have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $debug_cmd
+
+  if func_cygming_gnu_implib_p "$1"; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1"; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=
+  fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $debug_cmd
+
+    f_ex_an_ar_dir=$1; shift
+    f_ex_an_ar_oldlib=$1
+    if test yes = "$lock_old_archive_extraction"; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test yes = "$lock_old_archive_extraction"; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $debug_cmd
+
+    my_gentop=$1; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=
+    my_xlib=
+    my_xabs=
+    my_xdir=
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib=$func_basename_result
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir=$my_gentop/$my_xlib_u
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  func_basename "$darwin_archive"
+	  darwin_base_archive=$func_basename_result
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches; do
+	      func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
+	      cd "unfat-$$/$darwin_base_archive-$darwin_arch"
+	      func_extract_an_archive "`pwd`" "$darwin_base_archive"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+    done
+
+    func_extract_archives_result=$my_oldobjs
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory where it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=${1-no}
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    func_quote_arg pretty "$ECHO"
+    qECHO=$func_quote_arg_result
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=$qECHO
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=\$0
+  shift
+  for lt_opt
+  do
+    case \"\$lt_opt\" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+        cat \"\$lt_dump_D/\$lt_dump_F\"
+        exit 0
+      ;;
+    --lt-*)
+        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n \"\$lt_option_debug\"; then
+    echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
+    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+  case $host in
+  # Backslashes separate directories on plain windows
+  *-*-mingw | *-*-os2* | *-cegcc*)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+    ;;
+
+  *)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+    ;;
+  esac
+  $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case \" \$* \" in
+  *\\ --lt-*)
+    for lt_wr_arg
+    do
+      case \$lt_wr_arg in
+      --lt-*) ;;
+      *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core \${1+\"\$@\"}
+}
+
+  # Parse options
+  func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test yes = "$fast_install"; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	\$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# fixup the dll searchpath if we need to.
+	#
+	# Fix the DLL searchpath if we need to.  Do this before prepending
+	# to shlibpath, because on Windows, both are PATH and uninstalled
+	# libraries must come first.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	# Export our shlibpath_var if we have one.
+	if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+      func_exec_program \${1+\"\$@\"}
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+*/
+EOF
+	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* declarations of non-ANSI functions */
+#if defined __MINGW32__
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined __CYGWIN__
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined other_platform || defined ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined _MSC_VER
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+#elif defined __MINGW32__
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined __CYGWIN__
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined other platforms ... */
+#endif
+
+#if defined PATH_MAX
+# define LT_PATHMAX PATH_MAX
+#elif defined MAXPATHLEN
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
+  defined __OS2__
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free (stale); stale = 0; } \
+} while (0)
+
+#if defined LT_DEBUGWRAPPER
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+	    cat <<EOF
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
+# define externally_visible volatile
+#else
+# define externally_visible __attribute__((externally_visible)) volatile
+#endif
+externally_visible const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_path "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_path "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test yes = "$fast_install"; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt            = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  int rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  newargz = XMALLOC (char *, (size_t) argc + 1);
+
+  /* very simple arg parsing; don't want to rely on getopt
+   * also, copy all non cwrapper options to newargz, except
+   * argz[0], which is handled differently
+   */
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (STREQ (argv[i], dumpscript_opt))
+	{
+EOF
+	    case $host in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  lt_dump_script (stdout);
+	  return 0;
+	}
+      if (STREQ (argv[i], debug_opt))
+	{
+          lt_debug = 1;
+          continue;
+	}
+      if (STREQ (argv[i], ltwrapper_option_prefix))
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal (__FILE__, __LINE__,
+		    "unrecognized %s option: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+EOF
+	    cat <<EOF
+  /* The GNU banner must be the first non-error debug message */
+  lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE) $VERSION\n");
+EOF
+	    cat <<"EOF"
+  lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (before symlink chase) at: %s\n",
+		  tmp_pathspec);
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (after symlink chase) at: %s\n",
+		  actual_cwrapper_path);
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(main) libtool target name: %s\n",
+		  target_name);
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  /* Update the DLL searchpath.  EXE_PATH_VALUE ($dllsearchpath) must
+     be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+     because on Windows, both *_VARNAMEs are PATH but uninstalled
+     libraries must come first. */
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+  lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+		  nonnull (lt_argv_zero));
+  for (i = 0; i < newargc; i++)
+    {
+      lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+		      i, nonnull (newargz[i]));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = (int) _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      lt_debugprintf (__FILE__, __LINE__,
+		      "(main) failed to launch target \"%s\": %s\n",
+		      lt_argv_zero, nonnull (strerror (errno)));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  size_t tmp_len;
+  char *concat_name;
+
+  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+                  nonempty (wrapper));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = (size_t) (q - p);
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+                              nonnull (strerror (errno)));
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+              nonnull (strerror (errno)));
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      lt_debugprintf (__FILE__, __LINE__,
+		      "checking path component for symlinks: %s\n",
+		      tmp_pathspec);
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  lt_fatal (__FILE__, __LINE__,
+		    "error accessing file \"%s\": %s",
+		    tmp_pathspec, nonnull (strerror (errno)));
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal (__FILE__, __LINE__,
+		"could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (STREQ (str, pat))
+	*str = '\0';
+    }
+  return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+  va_list args;
+  if (lt_debug)
+    {
+      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+      va_start (args, fmt);
+      (void) vfprintf (stderr, fmt, args);
+      va_end (args);
+    }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+	       int line, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+  va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+  return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+  return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_setenv) setting '%s' to '%s'\n",
+                  nonnull (name), nonnull (value));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    size_t len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      size_t orig_value_len = strlen (orig_value);
+      size_t add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      size_t len = strlen (new_value);
+      while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[--len] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+	      $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/  fputs ("\1", f);/p
+g
+D'
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $debug_cmd
+
+    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_suncc_cstd_abi
+# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
+# Several compiler flags select an ABI that is incompatible with the
+# Cstd library. Avoid specifying it if any are in CXXFLAGS.
+func_suncc_cstd_abi ()
+{
+    $debug_cmd
+
+    case " $compile_command " in
+    *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
+      suncc_use_cstd_abi=no
+      ;;
+    *)
+      suncc_use_cstd_abi=yes
+      ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $debug_cmd
+
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # what system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll that has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    os2dllname=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=false
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module=$wl-single_module
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test yes != "$build_libtool_libs" \
+	  && func_fatal_configuration "cannot build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg=$1
+      shift
+      func_quote_arg pretty,unquoted "$arg"
+      qarg=$func_quote_arg_unquoted_result
+      func_append libtool_args " $func_quote_arg_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	bindir)
+	  bindir=$arg
+	  prev=
+	  continue
+	  ;;
+	dlfiles|dlprefiles)
+	  $preload || {
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=:
+	  }
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test no = "$dlself"; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test dlprefiles = "$prev"; then
+	      dlself=yes
+	    elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test dlfiles = "$prev"; then
+	      func_append dlfiles " $arg"
+	    else
+	      func_append dlprefiles " $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols=$arg
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file '$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex=$arg
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) func_append deplibs " $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir=$arg
+	  prev=
+	  continue
+	  ;;
+	mllvm)
+	  # Clang does not use LLVM to link, so we can simply discard any
+	  # '-mllvm $arg' options when doing the link step.
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      func_append moreargs " $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test none = "$pic_object" &&
+		   test none = "$non_pic_object"; then
+		  func_fatal_error "cannot find name of object for '$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir=$func_dirname_result
+
+		if test none != "$pic_object"; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object=$xdir$pic_object
+
+		  if test dlfiles = "$prev"; then
+		    if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+		      func_append dlfiles " $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test dlprefiles = "$prev"; then
+		    # Preload the old-style object.
+		    func_append dlprefiles " $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg=$pic_object
+		fi
+
+		# Non-PIC object.
+		if test none != "$non_pic_object"; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object=$xdir$non_pic_object
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test none = "$pic_object"; then
+		    arg=$non_pic_object
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object=$pic_object
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir=$func_dirname_result
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "'$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file '$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	os2dllname)
+	  os2dllname=$arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex=$arg
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release=-$arg
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test rpath = "$prev"; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) func_append rpath " $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) func_append xrpath " $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds=$arg
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  func_append weak_libs " $arg"
+	  prev=
+	  continue
+	  ;;
+	xassembler)
+	  func_append compiler_flags " -Xassembler $qarg"
+	  prev=
+	  func_append compile_command " -Xassembler $qarg"
+	  func_append finalize_command " -Xassembler $qarg"
+	  continue
+	  ;;
+	xcclinker)
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  func_append compiler_flags " $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg=$arg
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "'-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test X-export-symbols = "X$arg"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname "-L" '' "$arg"
+	if test -z "$func_stripname_result"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between '-L' and '$1'"
+	  else
+	    func_fatal_error "need path for '-L' option"
+	  fi
+	fi
+	func_resolve_sysroot "$func_stripname_result"
+	dir=$func_resolve_sysroot_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of '$dir'"
+	  dir=$absdir
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "* | *" $arg "*)
+	  # Will only happen for absolute or sysroot arguments
+	  ;;
+	*)
+	  # Preserve sysroot, but never include relative directories
+	  case $dir in
+	    [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+	    *) func_append deplibs " -L$dir" ;;
+	  esac
+	  func_append lib_search_path " $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) func_append dllsearchpath ":$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) func_append dllsearchpath ":$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test X-lc = "X$arg" || test X-lm = "X$arg"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test X-lc = "X$arg" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test X-lc = "X$arg" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    func_append deplibs " System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test X-lc = "X$arg" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test X-lc = "X$arg" && continue
+	    ;;
+	  esac
+	elif test X-lc_r = "X$arg"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	func_append deplibs " $arg"
+	continue
+	;;
+
+      -mllvm)
+	prev=mllvm
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot|--sysroot)
+	func_append compiler_flags " $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+     # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199.
+     -pthread)
+	case $host in
+	  *solaris2*) ;;
+	  *)
+	    case "$new_inherited_linker_flags " in
+	        *" $arg "*) ;;
+	        * ) func_append new_inherited_linker_flags " $arg" ;;
+	    esac
+	  ;;
+	esac
+	continue
+	;;
+      -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \
+      |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	func_append compiler_flags " $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) func_append new_inherited_linker_flags " $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module=$wl-multi_module
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "'-no-install' is ignored for $host"
+	  func_warning "assuming '-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -os2dllname)
+	prev=os2dllname
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	=*)
+	  func_stripname '=' '' "$dir"
+	  dir=$lt_sysroot$func_stripname_result
+	  ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) func_append xrpath " $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs=$IFS; IFS=,
+	for flag in $args; do
+	  IFS=$save_ifs
+          func_quote_arg pretty "$flag"
+	  func_append arg " $func_quote_arg_result"
+	  func_append compiler_flags " $func_quote_arg_result"
+	done
+	IFS=$save_ifs
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs=$IFS; IFS=,
+	for flag in $args; do
+	  IFS=$save_ifs
+          func_quote_arg pretty "$flag"
+	  func_append arg " $wl$func_quote_arg_result"
+	  func_append compiler_flags " $wl$func_quote_arg_result"
+	  func_append linker_flags " $func_quote_arg_result"
+	done
+	IFS=$save_ifs
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xassembler)
+        prev=xassembler
+        continue
+        ;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
+	;;
+
+      # Flags to be passed through unchanged, with rationale:
+      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
+      # -r[0-9][0-9]*        specify processor for the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+      # +DA*, +DD*           enable 64-bit mode for the HP compiler
+      # -q*                  compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+      # -F/path              path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
+      # -fstack-protector*   stack protector flags for GCC
+      # @file                GCC response files
+      # -tp=*                Portland pgcc target processor selection
+      # --sysroot=*          for sysroot support
+      # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+      # -specs=*             GCC specs files
+      # -stdlib=*            select c++ std lib with clang
+      # -fsanitize=*         Clang/GCC memory and address sanitizer
+      # -fuse-ld=*           Linker select flags for GCC
+      # -static-*            direct GCC to link specific libraries statically
+      # -fcilkplus           Cilk Plus language extension features for C/C++
+      # -Wa,*                Pass flags directly to the assembler
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+      -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus|-Wa,*)
+        func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        func_append compiler_flags " $arg"
+        continue
+        ;;
+
+      -Z*)
+        if test os2 = "`expr $host : '.*\(os2\)'`"; then
+          # OS/2 uses -Zxxx to specify OS/2-specific options
+	  compiler_flags="$compiler_flags $arg"
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  case $arg in
+	  -Zlinker | -Zstack)
+	    prev=xcompiler
+	    ;;
+	  esac
+	  continue
+        else
+	  # Otherwise treat like 'Some other compiler flag' below
+	  func_quote_arg pretty "$arg"
+	  arg=$func_quote_arg_result
+        fi
+	;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
+	;;
+
+      *.$objext)
+	# A standard object.
+	func_append objs " $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test none = "$pic_object" &&
+	     test none = "$non_pic_object"; then
+	    func_fatal_error "cannot find name of object for '$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir=$func_dirname_result
+
+	  test none = "$pic_object" || {
+	    # Prepend the subdirectory the object is found in.
+	    pic_object=$xdir$pic_object
+
+	    if test dlfiles = "$prev"; then
+	      if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+		func_append dlfiles " $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test dlprefiles = "$prev"; then
+	      # Preload the old-style object.
+	      func_append dlprefiles " $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg=$pic_object
+	  }
+
+	  # Non-PIC object.
+	  if test none != "$non_pic_object"; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object=$xdir$non_pic_object
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test none = "$pic_object"; then
+	      arg=$non_pic_object
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object=$pic_object
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir=$func_dirname_result
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "'$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	func_append deplibs " $arg"
+	func_append old_deplibs " $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	func_resolve_sysroot "$arg"
+	if test dlfiles = "$prev"; then
+	  # This library was specified with -dlopen.
+	  func_append dlfiles " $func_resolve_sysroot_result"
+	  prev=
+	elif test dlprefiles = "$prev"; then
+	  # The library was specified with -dlpreopen.
+	  func_append dlprefiles " $func_resolve_sysroot_result"
+	  prev=
+	else
+	  func_append deplibs " $func_resolve_sysroot_result"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the '$prevarg' option requires an argument"
+
+    if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname=$func_basename_result
+    libobjs_save=$libobjs
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    # Definition is injected by LT_CONFIG during libtool generation.
+    func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
+
+    func_dirname "$output" "/" ""
+    output_objdir=$func_dirname_result$objdir
+    func_to_tool_file "$output_objdir/"
+    tool_output_objdir=$func_to_tool_file_result
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_preserve_dup_deps; then
+	case "$libs " in
+	*" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	esac
+      fi
+      func_append libs " $deplib"
+    done
+
+    if test lib = "$linkmode"; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+	  esac
+	  func_append pre_post_deps " $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=false
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test lib,link = "$linkmode,$pass"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs=$tmp_deplibs
+      fi
+
+      if test lib,link = "$linkmode,$pass" ||
+	 test prog,scan = "$linkmode,$pass"; then
+	libs=$deplibs
+	deplibs=
+      fi
+      if test prog = "$linkmode"; then
+	case $pass in
+	dlopen) libs=$dlfiles ;;
+	dlpreopen) libs=$dlprefiles ;;
+	link)
+	  libs="$deplibs %DEPLIBS%"
+	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+	  ;;
+	esac
+      fi
+      if test lib,dlpreopen = "$linkmode,$pass"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  func_resolve_sysroot "$lib"
+	  case $lib in
+	  *.la)	func_source "$func_resolve_sysroot_result" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) func_append deplibs " $deplib" ;;
+	    esac
+	  done
+	done
+	libs=$dlprefiles
+      fi
+      if test dlopen = "$pass"; then
+	# Collect dlpreopened libraries
+	save_deplibs=$deplibs
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=false
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+        |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	  if test prog,link = "$linkmode,$pass"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    func_append compiler_flags " $deplib"
+	    if test lib = "$linkmode"; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test lib != "$linkmode" && test prog != "$linkmode"; then
+	    func_warning "'-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test lib = "$linkmode"; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib=$searchdir/lib$name$search_ext
+	      if test -f "$lib"; then
+		if test .la = "$search_ext"; then
+		  found=:
+		else
+		  found=false
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if $found; then
+	    # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll=$l
+		  done
+		  if test "X$ll" = "X$old_library"; then # only static version available
+		    found=false
+		    func_dirname "$lib" "" "."
+		    ladir=$func_dirname_result
+		    lib=$ladir/$old_library
+		    if test prog,link = "$linkmode,$pass"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  else
+	    # deplib doesn't seem to be a libtool library
+	    if test prog,link = "$linkmode,$pass"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test prog,link = "$linkmode,$pass"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test lib = "$linkmode"; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test conv = "$pass" && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
+	    ;;
+	  prog)
+	    if test conv = "$pass"; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test scan = "$pass"; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
+	    ;;
+	  *)
+	    func_warning "'-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test link = "$pass"; then
+	    func_stripname '-R' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    dir=$func_resolve_sysroot_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) func_append xrpath " $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la)
+	  func_resolve_sysroot "$deplib"
+	  lib=$func_resolve_sysroot_result
+	  ;;
+	*.$libext)
+	  if test conv = "$pass"; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=false
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=:
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=:
+		;;
+	      esac
+	      if $valid_a_lib; then
+		echo
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      else
+		echo
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test link != "$pass"; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test conv = "$pass"; then
+	    deplibs="$deplib $deplibs"
+	  elif test prog = "$linkmode"; then
+	    if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      func_append newdlprefiles " $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      func_append newdlfiles " $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=:
+	  continue
+	  ;;
+	esac # case $deplib
+
+	$found || test -f "$lib" \
+	  || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "'$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir=$func_dirname_result
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test lib,link = "$linkmode,$pass" ||
+	   test prog,scan = "$linkmode,$pass" ||
+	   { test prog != "$linkmode" && test lib != "$linkmode"; }; then
+	  test -n "$dlopen" && func_append dlfiles " $dlopen"
+	  test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+	fi
+
+	if test conv = "$pass"; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for '$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    func_append convenience " $ladir/$objdir/$old_library"
+	    func_append old_convenience " $ladir/$objdir/$old_library"
+	    tmp_libs=
+	    for deplib in $dependency_libs; do
+	      deplibs="$deplib $deplibs"
+	      if $opt_preserve_dup_deps; then
+		case "$tmp_libs " in
+		*" $deplib "*) func_append specialdeplibs " $deplib" ;;
+		esac
+	      fi
+	      func_append tmp_libs " $deplib"
+	    done
+	  elif test prog != "$linkmode" && test lib != "$linkmode"; then
+	    func_fatal_error "'$lib' is not a convenience library"
+	  fi
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	if test -n "$old_library" &&
+	   { test yes = "$prefer_static_libs" ||
+	     test built,no = "$prefer_static_libs,$installed"; }; then
+	  linklib=$old_library
+	else
+	  for l in $old_library $library_names; do
+	    linklib=$l
+	  done
+	fi
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for '$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test dlopen = "$pass"; then
+	  test -z "$libdir" \
+	    && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
+	  if test -z "$dlname" ||
+	     test yes != "$dlopen_support" ||
+	     test no = "$build_libtool_libs"
+	  then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    func_append dlprefiles " $lib $dependency_libs"
+	  else
+	    func_append newdlfiles " $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of '$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir=$ladir
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname=$func_basename_result
+
+	# Find the relevant object directory and library name.
+	if test yes = "$installed"; then
+	  if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library '$lib' was moved."
+	    dir=$ladir
+	    absdir=$abs_ladir
+	    libdir=$abs_ladir
+	  else
+	    dir=$lt_sysroot$libdir
+	    absdir=$lt_sysroot$libdir
+	  fi
+	  test yes = "$hardcode_automatic" && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir=$ladir
+	    absdir=$abs_ladir
+	    # Remove this search path later
+	    func_append notinst_path " $abs_ladir"
+	  else
+	    dir=$ladir/$objdir
+	    absdir=$abs_ladir/$objdir
+	    # Remove this search path later
+	    func_append notinst_path " $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test dlpreopen = "$pass"; then
+	  if test -z "$libdir" && test prog = "$linkmode"; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
+	  fi
+	  case $host in
+	    # special handling for platforms with PE-DLLs.
+	    *cygwin* | *mingw* | *cegcc* )
+	      # Linker will automatically link against shared library if both
+	      # static and shared are present.  Therefore, ensure we extract
+	      # symbols from the import library if a shared library is present
+	      # (otherwise, the dlopen module name will be incorrect).  We do
+	      # this by putting the import library name into $newdlprefiles.
+	      # We recover the dlopen module name by 'saving' the la file
+	      # name in a special purpose variable, and (later) extracting the
+	      # dlname from the la file.
+	      if test -n "$dlname"; then
+	        func_tr_sh "$dir/$linklib"
+	        eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+	        func_append newdlprefiles " $dir/$linklib"
+	      else
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      fi
+	    ;;
+	    * )
+	      # Prefer using a static library (so that no silly _DYNAMIC symbols
+	      # are required to link).
+	      if test -n "$old_library"; then
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      # Otherwise, use the dlname, so that lt_dlopen finds it.
+	      elif test -n "$dlname"; then
+	        func_append newdlprefiles " $dir/$dlname"
+	      else
+	        func_append newdlprefiles " $dir/$linklib"
+	      fi
+	    ;;
+	  esac
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test lib = "$linkmode"; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test prog,link = "$linkmode,$pass"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test prog = "$linkmode" && test link != "$pass"; then
+	  func_append newlib_search_path " $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=false
+	  if test no != "$link_all_deplibs" || test -z "$library_names" ||
+	     test no = "$build_libtool_libs"; then
+	    linkalldeplibs=:
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         func_resolve_sysroot "$func_stripname_result"
+	         func_append newlib_search_path " $func_resolve_sysroot_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if $linkalldeplibs; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_preserve_dup_deps; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test prog,link = "$linkmode,$pass"; then
+	  if test -n "$library_names" &&
+	     { { test no = "$prefer_static_libs" ||
+	         test built,yes = "$prefer_static_libs,$installed"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
+	      # Make sure the rpath contains only unique directories.
+	      case $temp_rpath: in
+	      *"$absdir:"*) ;;
+	      *) func_append temp_rpath "$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) func_append compile_rpath " $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append finalize_rpath " $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if $alldeplibs &&
+	     { test pass_all = "$deplibs_check_method" ||
+	       { test yes = "$build_libtool_libs" &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test built = "$use_static_libs" && test yes = "$installed"; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test no = "$use_static_libs" || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc* | *os2*)
+	      # No point in relinking DLLs because paths are not encoded
+	      func_append notinst_deplibs " $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test no = "$installed"; then
+	      func_append notinst_deplibs " $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule=$dlpremoduletest
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
+	    echo
+	    if test prog = "$linkmode"; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test lib = "$linkmode" &&
+	     test yes = "$hardcode_into_libs"; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) func_append compile_rpath " $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append finalize_rpath " $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname=$1
+	    shift
+	    libname=`eval "\\$ECHO \"$libname_spec\""`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname=$dlname
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc* | *os2*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix=-$major
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname=$realname
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot=$soname
+	    func_basename "$soroot"
+	    soname=$func_basename_result
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from '$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for '$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test prog = "$linkmode" || test relink != "$opt_mode"; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test no = "$hardcode_direct"; then
+		add=$dir/$linklib
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
+		  *-*-sysv4*uw2*) add_dir=-L$dir ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir=-L$dir ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we cannot
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library"; then
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
+			else
+			  add=$dir/$old_library
+			fi
+		      elif test -n "$old_library"; then
+			add=$dir/$old_library
+		      fi
+		    fi
+		esac
+	      elif test no = "$hardcode_minus_L"; then
+		case $host in
+		*-*-sunos*) add_shlibpath=$dir ;;
+		esac
+		add_dir=-L$dir
+		add=-l$name
+	      elif test no = "$hardcode_shlibpath_var"; then
+		add_shlibpath=$dir
+		add=-l$name
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test yes = "$hardcode_direct" &&
+	         test no = "$hardcode_direct_absolute"; then
+		add=$dir/$linklib
+	      elif test yes = "$hardcode_minus_L"; then
+		add_dir=-L$absdir
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      func_append add_dir " -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add=-l$name
+	      elif test yes = "$hardcode_shlibpath_var"; then
+		add_shlibpath=$dir
+		add=-l$name
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test yes != "$lib_linked"; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) func_append compile_shlibpath "$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test prog = "$linkmode"; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test yes != "$hardcode_direct" &&
+		 test yes != "$hardcode_minus_L" &&
+		 test yes = "$hardcode_shlibpath_var"; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) func_append finalize_shlibpath "$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test prog = "$linkmode" || test relink = "$opt_mode"; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test yes = "$hardcode_direct" &&
+	       test no = "$hardcode_direct_absolute"; then
+	      add=$libdir/$linklib
+	    elif test yes = "$hardcode_minus_L"; then
+	      add_dir=-L$libdir
+	      add=-l$name
+	    elif test yes = "$hardcode_shlibpath_var"; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) func_append finalize_shlibpath "$libdir:" ;;
+	      esac
+	      add=-l$name
+	    elif test yes = "$hardcode_automatic"; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib"; then
+		add=$inst_prefix_dir$libdir/$linklib
+	      else
+		add=$libdir/$linklib
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir=-L$libdir
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    func_append add_dir " -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add=-l$name
+	    fi
+
+	    if test prog = "$linkmode"; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test prog = "$linkmode"; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test unsupported != "$hardcode_direct"; then
+	    test -n "$old_library" && linklib=$old_library
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test yes = "$build_libtool_libs"; then
+	  # Not a shared library
+	  if test pass_all != "$deplibs_check_method"; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    echo
+	    $ECHO "*** Warning: This system cannot link to static lib archive $lib."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
+	    if test yes = "$module"; then
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** 'nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test no = "$build_old_libs"; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test lib = "$linkmode"; then
+	  if test -n "$dependency_libs" &&
+	     { test yes != "$hardcode_into_libs" ||
+	       test yes = "$build_old_libs" ||
+	       test yes = "$link_static"; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) func_append xrpath " $temp_xrpath";;
+		   esac;;
+	      *) func_append temp_deplibs " $libdir";;
+	      esac
+	    done
+	    dependency_libs=$temp_deplibs
+	  fi
+
+	  func_append newlib_search_path " $absdir"
+	  # Link against this library
+	  test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    case $deplib in
+              -L*) func_stripname '-L' '' "$deplib"
+                   func_resolve_sysroot "$func_stripname_result";;
+              *) func_resolve_sysroot "$deplib" ;;
+            esac
+	    if $opt_preserve_dup_deps; then
+	      case "$tmp_libs " in
+	      *" $func_resolve_sysroot_result "*)
+                func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $func_resolve_sysroot_result"
+	  done
+
+	  if test no != "$link_all_deplibs"; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      path=
+	      case $deplib in
+	      -L*) path=$deplib ;;
+	      *.la)
+	        func_resolve_sysroot "$deplib"
+	        deplib=$func_resolve_sysroot_result
+	        func_dirname "$deplib" "" "."
+		dir=$func_dirname_result
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of '$dir'"
+		    absdir=$dir
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names"; then
+		    for tmp in $deplibrary_names; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl"; then
+		      depdepl=$absdir/$objdir/$depdepl
+		      darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`$OTOOL64 -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
+		      func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path=-L$absdir/$objdir
+		  ;;
+		esac
+		else
+		  eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "'$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "'$deplib' seems to be moved"
+
+		  path=-L$absdir
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test link = "$pass"; then
+	if test prog = "$linkmode"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs=$newdependency_libs
+      if test dlpreopen = "$pass"; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test dlopen != "$pass"; then
+	test conv = "$pass" || {
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) func_append lib_search_path " $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	}
+
+	if test prog,link = "$linkmode,$pass"; then
+	  vars="compile_deplibs finalize_deplibs"
+	else
+	  vars=deplibs
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) func_append tmp_libs " $deplib" ;;
+	      esac
+	      ;;
+	    *) func_append tmp_libs " $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+
+      # Add Sun CC postdeps if required:
+      test CXX = "$tagname" && {
+        case $host_os in
+        linux*)
+          case `$CC -V 2>&1 | $SED 5q` in
+          *Sun\ C*) # Sun C++ 5.9
+            func_suncc_cstd_abi
+
+            if test no != "$suncc_use_cstd_abi"; then
+              func_append postdeps ' -library=Cstd -library=Crun'
+            fi
+            ;;
+          esac
+          ;;
+
+        solaris*)
+          func_cc_basename "$CC"
+          case $func_cc_basename_result in
+          CC* | sunCC*)
+            func_suncc_cstd_abi
+
+            if test no != "$suncc_use_cstd_abi"; then
+              func_append postdeps ' -library=Cstd -library=Crun'
+            fi
+            ;;
+          esac
+          ;;
+        esac
+      }
+
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=
+	  ;;
+	esac
+	if test -n "$i"; then
+	  func_append tmp_libs " $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test prog = "$linkmode"; then
+      dlfiles=$newdlfiles
+    fi
+    if test prog = "$linkmode" || test lib = "$linkmode"; then
+      dlprefiles=$newdlprefiles
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+	func_warning "'-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "'-l' and '-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "'-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "'-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "'-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "'-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "'-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs=$output
+      func_append objs "$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form 'libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	test no = "$module" \
+	  && func_fatal_help "libtool library '$output' must begin with 'lib'"
+
+	if test no != "$need_lib_prefix"; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test pass_all != "$deplibs_check_method"; then
+	  func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
+	else
+	  echo
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  func_append libobjs " $objs"
+	fi
+      fi
+
+      test no = "$dlself" \
+	|| func_warning "'-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test 1 -lt "$#" \
+	&& func_warning "ignoring multiple '-rpath's for a libtool library"
+
+      install_libdir=$1
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test yes = "$build_libtool_libs"; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a '.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "'-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "'-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs=$IFS; IFS=:
+	set dummy $vinfo 0 0 0
+	shift
+	IFS=$save_ifs
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to '-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major=$1
+	  number_minor=$2
+	  number_revision=$3
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # that has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  # correct linux to gnu/linux during the next big refactor
+	  darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age=$number_minor
+	    revision=$number_revision
+	    ;;
+	  freebsd-aout|qnx|sunos)
+	    current=$number_major
+	    revision=$number_minor
+	    age=0
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age=$number_minor
+	    revision=$number_minor
+	    lt_irix_increment=no
+	    ;;
+	  *)
+	    func_fatal_configuration "$modename: unknown library version type '$version_type'"
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current=$1
+	  revision=$2
+	  age=$3
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT '$current' must be a nonnegative integer"
+	  func_fatal_error "'$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION '$revision' must be a nonnegative integer"
+	  func_fatal_error "'$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE '$age' must be a nonnegative integer"
+	  func_fatal_error "'$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE '$age' is greater than the current interface number '$current'"
+	  func_fatal_error "'$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=$major.$age.$revision
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+          # On Darwin other compilers
+          case $CC in
+              nagfor*)
+                  verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+                  ;;
+              *)
+                  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+                  ;;
+          esac
+	  ;;
+
+	freebsd-aout)
+	  major=.$current
+	  versuffix=.$current.$revision
+	  ;;
+
+	freebsd-elf | midnightbsd-elf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=$major.$age.$revision
+	  ;;
+
+	irix | nonstopux)
+	  if test no = "$lt_irix_increment"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring=$verstring_prefix$major.$revision
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test 0 -ne "$loop"; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring=$verstring_prefix$major.$iface:$verstring
+	  done
+
+	  # Before this point, $major must not contain '.'.
+	  major=.$major
+	  versuffix=$major.$revision
+	  ;;
+
+	linux) # correct to gnu/linux during the next big refactor
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=$major.$age.$revision
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=.$current.$age.$revision
+	  verstring=$current.$age.$revision
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test 0 -ne "$loop"; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring=$verstring:$iface.0
+	  done
+
+	  # Make executables depend on our current version.
+	  func_append verstring ":$current.0"
+	  ;;
+
+	qnx)
+	  major=.$current
+	  versuffix=.$current
+	  ;;
+
+	sco)
+	  major=.$current
+	  versuffix=.$current
+	  ;;
+
+	sunos)
+	  major=.$current
+	  versuffix=.$current.$revision
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 file systems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix=-$major
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type '$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring=0.0
+	    ;;
+	  esac
+	  if test no = "$need_version"; then
+	    versuffix=
+	  else
+	    versuffix=.0.0
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test yes,no = "$avoid_version,$need_version"; then
+	  major=
+	  versuffix=
+	  verstring=
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test yes = "$allow_undefined"; then
+	  if test unsupported = "$allow_undefined_flag"; then
+	    if test yes = "$build_old_libs"; then
+	      func_warning "undefined symbols not allowed in $host shared libraries; building static only"
+	      build_libtool_libs=no
+	    else
+	      func_fatal_error "can't build $host shared library unless -no-undefined is specified"
+	    fi
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag=$no_undefined_flag
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" :
+      func_append libobjs " $symfileobj"
+      test " " = "$libobjs" && libobjs=
+
+      if test relink != "$opt_mode"; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
+	       if test -n "$precious_files_regex"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       func_append removelist " $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
+	func_append oldlibs " $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  func_replace_sysroot "$libdir"
+	  func_append temp_xrpath " -R$func_replace_sysroot_result"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_rpath " $libdir" ;;
+	  esac
+	done
+	if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles=$dlfiles
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) func_append dlfiles " $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles=$dlprefiles
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) func_append dlprefiles " $lib" ;;
+	esac
+      done
+
+      if test yes = "$build_libtool_libs"; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    func_append deplibs " System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test yes = "$build_libtool_need_lc"; then
+	      func_append deplibs " -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=
+	versuffix=
+	major=
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    func_append newdeplibs " $i"
+		    i=
+		    ;;
+		  esac
+		fi
+		if test -n "$i"; then
+		  libname=`eval "\\$ECHO \"$libname_spec\""`
+		  deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+		    func_append newdeplibs " $i"
+		  else
+		    droppeddeps=yes
+		    echo
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		func_append newdeplibs " $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      func_append newdeplibs " $i"
+		      i=
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i"; then
+		    libname=`eval "\\$ECHO \"$libname_spec\""`
+		    deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+		      func_append newdeplibs " $i"
+		    else
+		      droppeddeps=yes
+		      echo
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  echo
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		func_append newdeplibs " $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  func_append newdeplibs " $a_deplib"
+		  a_deplib=
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib"; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		if test -n "$file_magic_glob"; then
+		  libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+		else
+		  libnameglob=$libname
+		fi
+		test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  if test yes = "$want_nocaseglob"; then
+		    shopt -s nocaseglob
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		    $nocaseglob
+		  else
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		  fi
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib=$potent_lib
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
+			*) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			func_append newdeplibs " $a_deplib"
+			a_deplib=
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib"; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib"; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      func_append newdeplibs " $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  func_append newdeplibs " $a_deplib"
+		  a_deplib=
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib"; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib=$potent_lib # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      func_append newdeplibs " $a_deplib"
+		      a_deplib=
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib"; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib"; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      func_append newdeplibs " $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+	  if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+	    for i in $predeps $postdeps; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
+	    done
+	  fi
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
+	    if test none = "$deplibs_check_method"; then
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	    ;;
+	  esac
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test yes = "$droppeddeps"; then
+	  if test yes = "$module"; then
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** 'nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test no = "$build_old_libs"; then
+	      oldlibs=$output_objdir/$libname.$libext
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
+
+	    if test no = "$allow_undefined"; then
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
+	      if test no = "$build_old_libs"; then
+		oldlibs=$output_objdir/$libname.$libext
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    func_append new_libs " -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) func_append new_libs " $deplib" ;;
+	  esac
+	  ;;
+	*) func_append new_libs " $deplib" ;;
+	esac
+      done
+      deplibs=$new_libs
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test yes = "$build_libtool_libs"; then
+	# Remove $wl instances when linking with ld.
+	# FIXME: should test the right _cmds variable.
+	case $archive_cmds in
+	  *\$LD\ *) wl= ;;
+        esac
+	if test yes = "$hardcode_into_libs"; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath=$finalize_rpath
+	  test relink = "$opt_mode" || rpath=$compile_rpath$rpath
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		func_replace_sysroot "$libdir"
+		libdir=$func_replace_sysroot_result
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs=$libdir
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		func_append dep_rpath " $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append perm_rpath " $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir=$hardcode_libdirs
+	    eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      func_append rpath "$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath=$finalize_shlibpath
+	test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	shift
+	realname=$1
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname=$realname
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib=$output_objdir/$realname
+	linknames=
+	for link
+	do
+	  func_append linknames " $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols=$output_objdir/$libname.uexp
+	  func_append delfiles " $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    func_dll_def_p "$export_symbols" || {
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols=$export_symbols
+	      export_symbols=
+	      always_export_symbols=yes
+	    }
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for '$libname.la'"
+	    export_symbols=$output_objdir/$libname.exp
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs=$IFS; IFS='~'
+	    for cmd1 in $cmds; do
+	      IFS=$save_ifs
+	      # Take the normal branch if the nm_file_list_spec branch
+	      # doesn't work or if tool conversion is not needed.
+	      case $nm_file_list_spec~$to_tool_file_cmd in
+		*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+		  try_normal_branch=yes
+		  eval cmd=\"$cmd1\"
+		  func_len " $cmd"
+		  len=$func_len_result
+		  ;;
+		*)
+		  try_normal_branch=no
+		  ;;
+	      esac
+	      if test yes = "$try_normal_branch" \
+		 && { test "$len" -lt "$max_cmd_len" \
+		      || test "$max_cmd_len" -le -1; }
+	      then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      elif test -n "$nm_file_list_spec"; then
+		func_basename "$output"
+		output_la=$func_basename_result
+		save_libobjs=$libobjs
+		save_output=$output
+		output=$output_objdir/$output_la.nm
+		func_to_tool_file "$output"
+		libobjs=$nm_file_list_spec$func_to_tool_file_result
+		func_append delfiles " $output"
+		func_verbose "creating $NM input file list: $output"
+		for obj in $save_libobjs; do
+		  func_to_tool_file "$obj"
+		  $ECHO "$func_to_tool_file_result"
+		done > "$output"
+		eval cmd=\"$cmd1\"
+		func_show_eval "$cmd" 'exit $?'
+		output=$save_output
+		libobjs=$save_libobjs
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS=$save_ifs
+	    if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols=$export_symbols
+	  test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+	  $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	fi
+
+	if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands, which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    func_append tmp_deplibs " $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs=$tmp_deplibs
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test yes = "$compiler_needs_object" &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop=$output_objdir/${outputname}x
+	    func_append generated " $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    func_append libobjs " $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  func_append linker_flags " $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test relink = "$opt_mode"; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test yes = "$module" && test -n "$module_cmds"; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval test_cmds=\"$archive_expsym_cmds\"
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval test_cmds=\"$archive_cmds\"
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test : != "$skipped_export" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  func_basename "$output"
+	  output_la=$func_basename_result
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
+	    output=$output_objdir/$output_la.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    echo 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    echo ')' >> $output
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$func_to_tool_file_result
+	  elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
+	    output=$output_objdir/$output_la.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test yes = "$compiler_needs_object"; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-$k.$objext
+	      eval test_cmds=\"$reload_cmds\"
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test -z "$objlist" ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test 1 -eq "$k"; then
+		    # The first file doesn't have a previous command to add.
+		    reload_objs=$objlist
+		    eval concat_cmds=\"$reload_cmds\"
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    reload_objs="$objlist $last_robj"
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+		  fi
+		  last_robj=$output_objdir/$output_la-$k.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-$k.$objext
+		  objlist=" $obj"
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      reload_objs="$objlist $last_robj"
+	      eval concat_cmds=\"\$concat_cmds$reload_cmds\"
+	      if test -n "$last_robj"; then
+	        eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	      func_append delfiles " $output"
+
+	    else
+	      output=
+	    fi
+
+	    ${skipped_export-false} && {
+	      func_verbose "generating symbol list for '$libname.la'"
+	      export_symbols=$output_objdir/$libname.exp
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+	      if test -n "$last_robj"; then
+		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	    }
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs=$IFS; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS=$save_ifs
+	      $opt_quiet || {
+		  func_quote_arg expand,pretty "$cmd"
+		  eval "func_echo $func_quote_arg_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test relink = "$opt_mode"; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS=$save_ifs
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          ${skipped_export-false} && {
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols=$export_symbols
+	      test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+	      $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands, which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  }
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test yes = "$module" && test -n "$module_cmds"; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval cmds=\"\$cmds~\$RM $delfiles\"
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop=$output_objdir/${outputname}x
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  func_append libobjs " $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs=$IFS; IFS='~'
+	for cmd in $cmds; do
+	  IFS=$sp$nl
+	  eval cmd=\"$cmd\"
+	  IFS=$save_ifs
+	  $opt_quiet || {
+	    func_quote_arg expand,pretty "$cmd"
+	    eval "func_echo $func_quote_arg_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test relink = "$opt_mode"; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS=$save_ifs
+
+	# Restore the uninstalled library and exit
+	if test relink = "$opt_mode"; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test yes = "$module" || test yes = "$export_dynamic"; then
+	  # On all known operating systems, these are identical.
+	  dlname=$soname
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+	func_warning "'-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "'-l' and '-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "'-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "'-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "'-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "'-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object '$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj=$output
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # if reload_cmds runs $LD directly, get rid of -Wl from
+      # whole_archive_flag_spec and hope we can get by with turning comma
+      # into space.
+      case $reload_cmds in
+        *\$LD[\ \$]*) wl= ;;
+      esac
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+	  test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+	  reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
+	else
+	  gentop=$output_objdir/${obj}x
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # If we're not building shared, we need to use non_pic_objs
+      test yes = "$build_libtool_libs" || libobjs=$non_pic_objects
+
+      # Create the old-style object.
+      reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs
+
+      output=$obj
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      test yes = "$build_libtool_libs" || {
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      }
+
+      if test -n "$pic_flag" || test default != "$pic_mode"; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output=$libobj
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "'-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "'-release' is ignored for programs"
+
+      $preload \
+	&& test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
+	&& func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test CXX = "$tagname"; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      func_append compile_command " $wl-bind_at_load"
+	      func_append finalize_command " $wl-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    func_append new_libs " -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) func_append new_libs " $deplib" ;;
+	  esac
+	  ;;
+	*) func_append new_libs " $deplib" ;;
+	esac
+      done
+      compile_deplibs=$new_libs
+
+
+      func_append compile_command " $compile_deplibs"
+      func_append finalize_command " $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_rpath " $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs=$libdir
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    func_append rpath " $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append perm_rpath " $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) func_append dllsearchpath ":$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) func_append dllsearchpath ":$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir=$hardcode_libdirs
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath=$rpath
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs=$libdir
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    func_append rpath " $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_perm_rpath " $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir=$hardcode_libdirs
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath=$rpath
+
+      if test -n "$libobjs" && test yes = "$build_old_libs"; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" false
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=:
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=false
+        ;;
+      *cygwin* | *mingw* )
+        test yes = "$build_libtool_libs" || wrappers_required=false
+        ;;
+      *)
+        if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
+          wrappers_required=false
+        fi
+        ;;
+      esac
+      $wrappers_required || {
+	# Replace the output file specification.
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	link_command=$compile_command$compile_rpath
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.$objext"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
+	fi
+
+	exit $exit_status
+      }
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    func_append rpath "$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    func_append rpath "$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test yes = "$no_install"; then
+	# We don't need to create a wrapper script.
+	link_command=$compile_var$compile_command$compile_rpath
+	# Replace the output file specification.
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      case $hardcode_action,$fast_install in
+        relink,*)
+	  # Fast installation is not supported
+	  link_command=$compile_var$compile_command$compile_rpath
+	  relink_command=$finalize_var$finalize_command$finalize_rpath
+
+	  func_warning "this platform does not like uninstalled shared libraries"
+	  func_warning "'$output' will be relinked during installation"
+	  ;;
+        *,yes)
+	  link_command=$finalize_var$compile_command$finalize_rpath
+	  relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+          ;;
+	*,no)
+	  link_command=$compile_var$compile_command$compile_rpath
+	  relink_command=$finalize_var$finalize_command$finalize_rpath
+          ;;
+	*,needless)
+	  link_command=$finalize_var$compile_command$finalize_rpath
+	  relink_command=
+          ;;
+      esac
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      if test -n "$postlink_cmds"; then
+	func_to_tool_file "$output_objdir/$outputname"
+	postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	func_execute_cmds "$postlink_cmds" 'exit $?'
+      fi
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_arg pretty "$var_value"
+	    relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
+	  fi
+	done
+	func_quote eval cd "`pwd`"
+	func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)"
+	relink_command=$func_quote_arg_unquoted_result
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource=$output_path/$objdir/lt-$output_name.c
+	    cwrapper=$output_path/$output_name.exe
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host"; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      case $build_libtool_libs in
+        convenience)
+	  oldobjs="$libobjs_save $symfileobj"
+	  addlibs=$convenience
+	  build_libtool_libs=no
+	  ;;
+	module)
+	  oldobjs=$libobjs_save
+	  addlibs=$old_convenience
+	  build_libtool_libs=no
+          ;;
+	*)
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  $preload && test -f "$symfileobj" \
+	    && func_append oldobjs " $symfileobj"
+	  addlibs=$old_convenience
+	  ;;
+      esac
+
+      if test -n "$addlibs"; then
+	gentop=$output_objdir/${outputname}x
+	func_append generated " $gentop"
+
+	func_extract_archives $gentop $addlibs
+	func_append oldobjs " $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop=$output_objdir/${outputname}x
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  func_append oldobjs " $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  echo "copying selected object files to avoid basename conflicts..."
+	  gentop=$output_objdir/${outputname}x
+	  func_append generated " $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase=$func_basename_result
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      func_append oldobjs " $gentop/$newobj"
+	      ;;
+	    *) func_append oldobjs " $obj" ;;
+	    esac
+	  done
+	fi
+	func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+	tool_oldlib=$func_to_tool_file_result
+	eval cmds=\"$old_archive_cmds\"
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	elif test -n "$archiver_list_spec"; then
+	  func_verbose "using command file archive linking..."
+	  for obj in $oldobjs
+	  do
+	    func_to_tool_file "$obj"
+	    $ECHO "$func_to_tool_file_result"
+	  done > $output_objdir/$libname.libcmd
+	  func_to_tool_file "$output_objdir/$libname.libcmd"
+	  oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval test_cmds=\"$old_archive_cmds\"
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj"; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test -z "$oldobjs"; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test yes = "$build_old_libs" && old_library=$libname.$libext
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_arg pretty,unquoted "$var_value"
+	  relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      func_quote eval cd "`pwd`"
+      relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      func_quote_arg pretty,unquoted "$relink_command"
+      relink_command=$func_quote_arg_unquoted_result
+      if test yes = "$hardcode_automatic"; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test yes = "$installed"; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output=$output_objdir/${outputname}i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name=$func_basename_result
+		func_resolve_sysroot "$deplib"
+		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+		test -z "$libdir" && \
+		  func_fatal_error "'$deplib' is not a valid libtool archive"
+		func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      -L*)
+		func_stripname -L '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -L$func_replace_sysroot_result"
+		;;
+	      -R*)
+		func_stripname -R '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -R$func_replace_sysroot_result"
+		;;
+	      *) func_append newdependency_libs " $deplib" ;;
+	      esac
+	    done
+	    dependency_libs=$newdependency_libs
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name=$func_basename_result
+		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "'$lib' is not a valid libtool archive"
+		func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      *) func_append newdlfiles " $lib" ;;
+	      esac
+	    done
+	    dlfiles=$newdlfiles
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name=$func_basename_result
+		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "'$lib' is not a valid libtool archive"
+		func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles=$newdlprefiles
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      func_append newdlfiles " $abs"
+	    done
+	    dlfiles=$newdlfiles
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      func_append newdlprefiles " $abs"
+	    done
+	    dlprefiles=$newdlprefiles
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test -n "$bindir"; then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result/$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that cannot go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test no,yes = "$installed,$need_relink"; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+if test link = "$opt_mode" || test relink = "$opt_mode"; then
+  func_mode_link ${1+"$@"}
+fi
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $debug_cmd
+
+    RM=$nonopt
+    files=
+    rmforce=false
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic=$magic
+
+    for arg
+    do
+      case $arg in
+      -f) func_append RM " $arg"; rmforce=: ;;
+      -*) func_append RM " $arg" ;;
+      *) func_append files " $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir=$func_dirname_result
+      if test . = "$dir"; then
+	odir=$objdir
+      else
+	odir=$dir/$objdir
+      fi
+      func_basename "$file"
+      name=$func_basename_result
+      test uninstall = "$opt_mode" && odir=$dir
+
+      # Remember odir for removal later, being careful to avoid duplicates
+      if test clean = "$opt_mode"; then
+	case " $rmdirs " in
+	  *" $odir "*) ;;
+	  *) func_append rmdirs " $odir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif $rmforce; then
+	continue
+      fi
+
+      rmfiles=$file
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    func_append rmfiles " $odir/$n"
+	  done
+	  test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+	  case $opt_mode in
+	  clean)
+	    case " $library_names " in
+	    *" $dlname "*) ;;
+	    *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" && test none != "$pic_object"; then
+	    func_append rmfiles " $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" && test none != "$non_pic_object"; then
+	    func_append rmfiles " $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test clean = "$opt_mode"; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    func_append rmfiles " $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      func_append rmfiles " $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    func_append rmfiles " $odir/$name $odir/${name}S.$objext"
+	    if test yes = "$fast_install" && test -n "$relink_command"; then
+	      func_append rmfiles " $odir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name"; then
+	      func_append rmfiles " $odir/lt-$noexename.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+
+    # Try to remove the $objdir's in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
+  func_mode_uninstall ${1+"$@"}
+fi
+
+test -z "$opt_mode" && {
+  help=$generic_help
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode '$opt_mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# where we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/mesh/README b/mesh/README
deleted file mode 100644
index f36b97c..0000000
--- a/mesh/README
+++ /dev/null
@@ -1,95 +0,0 @@
-Bluetooth Mesh Daemon
-*********************
-
-Copyright (C) 2019  Intel Corporation. All rights reserved.
-
-Compilation and installation
-============================
-
-In addition to main BlueZ requirements, MeshCtl needs the following:
-	- json-c library
-
-Configuration and options
-=========================
-
-	--enable-mesh
-
-		Build mesh daemon and other Bluetooth Mesh based tools
-
-Current implementation of the mesh daemon requires exclusive access to
-a Bluetooth controller.
-The AutoEnable option in the installed main.conf should be set to "false".
-
-Storage
-=======
-
-Default storage directory is /var/lib/bluetooth/mesh.
-
-The directory contains the provisioned nodes configurations.
-Each node has its own subdirectory, named after node's Device UUID (32-digit
-hexadecimal string) that is generated by the application that created a node.
-
-Each subdirectory contains the following files:
-	- node.json:
-		node configuration and is populated by the
-		daemon based on the configuration commands from a
-		provisioner/configuration client
-	- node.json.bak:
-		a backup that the last known good node configuration.
-	- seq_num:
-		File containing next sequence number to use
-	- seq_num.bak:
-		Backup of the sequence number. This may be larger than the
-		actual sequence number being used at runtime, to prevent re-use
-		of sequence numbers in the event of an unexpected restart.
-	- ./rpl/:
-		Directory to store the sequence numbers of remote nodes, as
-		required by Replay Protection List (RPL) parameters.
-		- xxxx:
-			Files named for remote Unicast addresses, and contain
-			last received iv_index + seq_num from each SRC address.
-	- ./dev_keys/:
-		Directory to store remote Device keys. This is only created/used
-		by Configuration Client (Network administration) nodes.
-		- xxxx:
-			Files named for remote Unicast addresses, and contains
-			16 octet key.
-	- ./net_keys/:
-		Directory to store network subnet keys. This is only
-		created/used by Configuration Client (Network administration)
-		nodes.
-		- xxx:
-			Files named for subnet index, and contains key refresh
-			phase, and old/new versions of the key.
-	- ./app_keys/:
-		Directory to store application keys. This is only created/used
-		by Configuration Client (Network administration) nodes.
-		- xxx:
-			Files named for application index, and contains bound
-			subnet index, and old/new versions of the key.
-
-The node.json and node.json.bak are in JSON format. All other files are stored
-in little endian binary format.
-
-Known Issues
-============
-
-Bluetooth Mesh makes heavy usage of AEAD-AES_CCM encryption, which is
-implemented in the Linux kernel on most platforms. Some platforms, including
-those with kernel versions including and prior to v4.8, did *not* correctly
-implement the AEAD encryption routines. If Mesh is to be ported to such a
-system, it will be the responsibility of the vendor to provide support for
-AEAD-AES_CCM encryption by some other method.
-
-Support for the required AEAD routines can be determined by running the unit
-tests provided with the ELL libraries used by Mesh. Specifically, the tests
-found in .../ell/unit/test-cipher.c
-
-Information
-===========
-
-Mailing lists:
-	linux-bluetooth@vger.kernel.org
-
-For additional information about the project visit BlueZ web site:
-	http://www.bluez.org
diff --git a/mesh/agent.c b/mesh/agent.c
index 5058d0d..2f9697a 100644
--- a/mesh/agent.c
+++ b/mesh/agent.c
@@ -61,7 +61,7 @@ struct oob_info {
 	uint16_t mask;
 };
 
-static struct prov_action cap_table[] = {
+static const struct prov_action cap_table[] = {
 	{"blink", 0x0001, 0x0000, 1},
 	{"beep", 0x0002, 0x0000, 1},
 	{"vibrate", 0x0004, 0x0000, 1},
@@ -73,7 +73,7 @@ static struct prov_action cap_table[] = {
 	{"in-alpha", 0x0000, 0x0008, 8}
 };
 
-static struct oob_info oob_table[] = {
+static const struct oob_info oob_table[] = {
 	{"other", 0x0001},
 	{"uri", 0x0002},
 	{"machine-code-2d", 0x0004},
diff --git a/mesh/bluetooth-mesh.service.in b/mesh/bluetooth-mesh.service.in
index c8afbf5..899ef10 100644
--- a/mesh/bluetooth-mesh.service.in
+++ b/mesh/bluetooth-mesh.service.in
@@ -5,7 +5,7 @@ ConditionPathIsDirectory=/sys/class/bluetooth
 [Service]
 Type=dbus
 BusName=org.bluez.mesh
-ExecStart=@pkglibexecdir@/bluetooth-meshd
+ExecStart=@PKGLIBEXECDIR@/bluetooth-meshd
 NotifyAccess=main
 LimitNPROC=1
 ProtectHome=true
diff --git a/mesh/bluetooth-meshd.rst.in b/mesh/bluetooth-meshd.rst.in
index 06cdb69..7615367 100644
--- a/mesh/bluetooth-meshd.rst.in
+++ b/mesh/bluetooth-meshd.rst.in
@@ -36,14 +36,17 @@ OPTIONS
 -i <type>, --io <type>
     Specifies I/O interface type:
 
-    *hci<index>* - Use generic HCI io on interface hci<index>,
-    or, if no idex is specified, the first available one.
+    *auto* - Use first available controller: via MGMT interface
+    if kernel supports it, otherwise, via raw HCI socket.
+
+    *generic:[hci]<index>* - Use generic HCI io on interface
+    hci<index>.
 
     *unit:<fd_path>*- Specifies open file descriptor for
     daemon testing.
 
-    By default, if no type is specified, uses generic I/O
-    on the first available HCI interface.
+    By default, if no type is specified, uses auto I/O
+    on the first available controller.
 
 -c <file>, --config <file>
     Specifies an explicit config file path instead of relying on the
diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c
index be90ef8..f64566d 100644
--- a/mesh/cfgmod-server.c
+++ b/mesh/cfgmod-server.c
@@ -30,8 +30,8 @@
 		(SET_ID(SIG_VENDOR, l_get_le16(pkt))))
 
 /* Supported composition pages, sorted high to low */
-/* Only page 0 is currently supported */
 static const uint8_t supported_pages[] = {
+	128,
 	0
 };
 
@@ -736,7 +736,7 @@ static uint16_t cfg_net_tx_msg(struct mesh_node *node, const uint8_t *pkt,
 static uint16_t get_composition(struct mesh_node *node, uint8_t page,
 								uint8_t *buf)
 {
-	const uint8_t *comp;
+	const uint8_t *comp = NULL;
 	uint16_t len = 0;
 	size_t i;
 
@@ -751,7 +751,7 @@ static uint16_t get_composition(struct mesh_node *node, uint8_t page,
 			break;
 	}
 
-	if (!len)
+	if (!len || !comp)
 		return 0;
 
 	*buf++ = page;
diff --git a/mesh/crypto.c b/mesh/crypto.c
index 668d168..b712a26 100644
--- a/mesh/crypto.c
+++ b/mesh/crypto.c
@@ -94,13 +94,6 @@ bool mesh_crypto_aes_ccm_encrypt(const uint8_t nonce[13], const uint8_t key[16],
 	result = l_aead_cipher_encrypt(cipher, msg, msg_len, aad, aad_len,
 					nonce, 13, out_msg, msg_len + mic_size);
 
-	if (result && out_mic) {
-		if (mic_size == 4)
-			*(uint32_t *)out_mic = l_get_be32(out_msg + msg_len);
-		else
-			*(uint64_t *)out_mic = l_get_be64(out_msg + msg_len);
-	}
-
 	l_aead_cipher_free(cipher);
 
 	return result;
@@ -251,9 +244,9 @@ bool mesh_crypto_nkbk(const uint8_t n[16], uint8_t beacon_key[16])
 	return crypto_128(n, "nkbk", beacon_key);
 }
 
-bool mesh_crypto_nkpk(const uint8_t n[16], uint8_t proxy_key[16])
+bool mesh_crypto_nkpk(const uint8_t n[16], uint8_t private_key[16])
 {
-	return crypto_128(n, "nkpk", proxy_key);
+	return crypto_128(n, "nkpk", private_key);
 }
 
 bool mesh_crypto_k3(const uint8_t n[16], uint8_t out64[8])
@@ -1020,7 +1013,7 @@ static const uint8_t crypto_test_result[] = {
 	0x9a, 0x2a, 0xbf, 0x96
 };
 
-bool mesh_crypto_check_avail()
+bool mesh_crypto_check_avail(void)
 {
 	void *cipher;
 	bool result;
diff --git a/mesh/crypto.h b/mesh/crypto.h
index c31abbb..5578988 100644
--- a/mesh/crypto.h
+++ b/mesh/crypto.h
@@ -26,7 +26,7 @@ bool mesh_aes_ecb_one(const uint8_t key[16],
 			const uint8_t plaintext[16], uint8_t encrypted[16]);
 bool mesh_crypto_nkik(const uint8_t network_key[16], uint8_t identity_key[16]);
 bool mesh_crypto_nkbk(const uint8_t network_key[16], uint8_t beacon_key[16]);
-bool mesh_crypto_nkpk(const uint8_t network_key[16], uint8_t proxy_key[16]);
+bool mesh_crypto_nkpk(const uint8_t network_key[16], uint8_t private_key[16]);
 bool mesh_crypto_identity(const uint8_t net_key[16], uint16_t addr,
 							uint8_t id[16]);
 bool mesh_crypto_beacon_cmac(const uint8_t encryption_key[16],
diff --git a/mesh/keyring.c b/mesh/keyring.c
index 995a4b8..1e1de3e 100644
--- a/mesh/keyring.c
+++ b/mesh/keyring.c
@@ -30,9 +30,9 @@
 #include "mesh/node.h"
 #include "mesh/keyring.h"
 
-const char *dev_key_dir = "/dev_keys";
-const char *app_key_dir = "/app_keys";
-const char *net_key_dir = "/net_keys";
+static const char *dev_key_dir = "/dev_keys";
+static const char *app_key_dir = "/app_keys";
+static const char *net_key_dir = "/net_keys";
 
 static int open_key_file(struct mesh_node *node, const char *key_dir,
 							uint16_t idx, int flags)
@@ -371,6 +371,28 @@ bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast,
 	return true;
 }
 
+bool keyring_del_remote_dev_key_all(struct mesh_node *node, uint16_t unicast)
+{
+	uint8_t dev_key[16];
+	uint8_t test_key[16];
+	uint8_t cnt = 1;
+
+	if (!keyring_get_remote_dev_key(node, unicast, dev_key))
+		return false;
+
+	while (keyring_get_remote_dev_key(node, unicast + cnt, test_key)) {
+		if (memcmp(dev_key, test_key, sizeof(dev_key)))
+			break;
+
+		cnt++;
+	}
+
+	if (cnt > 1)
+		return keyring_del_remote_dev_key(node, unicast + 1, cnt - 1);
+
+	return true;
+}
+
 static DIR *open_key_dir(const char *node_path, const char *key_dir_name)
 {
 	char dir_path[PATH_MAX];
diff --git a/mesh/keyring.h b/mesh/keyring.h
index ecf62cb..efc499a 100644
--- a/mesh/keyring.h
+++ b/mesh/keyring.h
@@ -39,5 +39,6 @@ bool keyring_put_remote_dev_key(struct mesh_node *node, uint16_t unicast,
 					uint8_t count, uint8_t dev_key[16]);
 bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast,
 								uint8_t count);
+bool keyring_del_remote_dev_key_all(struct mesh_node *node, uint16_t unicast);
 bool keyring_build_export_keys_reply(struct mesh_node *node,
 					struct l_dbus_message_builder *builder);
diff --git a/mesh/main.c b/mesh/main.c
index 3bca020..145bcfa 100644
--- a/mesh/main.c
+++ b/mesh/main.c
@@ -48,6 +48,12 @@ static const struct option main_options[] = {
 	{ }
 };
 
+static const char *io_usage =
+	       "\t(auto | generic:[hci]<index> | unit:<fd_path>)\n"
+	       "\t\tauto - Use first available controller (MGMT or raw HCI)\n"
+	       "\t\tgeneric - Use raw HCI io on interface hci<index>\n"
+	       "\t\tunit - Use test IO (for automatic testing only)\n";
+
 static void usage(void)
 {
 	fprintf(stderr,
@@ -55,18 +61,14 @@ static void usage(void)
 	       "\tbluetooth-meshd [options]\n");
 	fprintf(stderr,
 		"Options:\n"
-	       "\t--io <io>         Use specified io (default: generic)\n"
+	       "\t--io <io>         Use specified io (default: auto)\n"
 	       "\t--config          Daemon configuration directory\n"
 	       "\t--storage         Mesh node(s) configuration directory\n"
 	       "\t--nodetach        Run in foreground\n"
 	       "\t--debug           Enable debug output\n"
 	       "\t--dbus-debug      Enable D-Bus debugging\n"
 	       "\t--help            Show %s information\n", __func__);
-	fprintf(stderr,
-	       "io:\n"
-	       "\t([hci]<index> | generic[:[hci]<index>] | unit:<fd_path>)\n"
-	       "\t\tUse generic HCI io on interface hci<index>, or the first\n"
-	       "\t\tavailable one\n");
+	fprintf(stderr, "\n\t io: %s", io_usage);
 }
 
 static void do_debug(const char *str, void *user_data)
@@ -157,21 +159,8 @@ static bool parse_io(const char *optarg, enum mesh_io_type *type, void **opts)
 		*opts = index;
 
 		optarg += strlen("auto");
-		if (!*optarg) {
-			*index = MGMT_INDEX_NONE;
-			return true;
-		}
-
-		if (*optarg != ':')
-			return false;
-
-		optarg++;
-
-		if (sscanf(optarg, "hci%d", index) == 1)
-			return true;
-
-		if (sscanf(optarg, "%d", index) == 1)
-			return true;
+		*index = MGMT_INDEX_NONE;
+		return true;
 
 		return false;
 	} else if (strstr(optarg, "generic") == optarg) {
@@ -181,12 +170,7 @@ static bool parse_io(const char *optarg, enum mesh_io_type *type, void **opts)
 		*opts = index;
 
 		optarg += strlen("generic");
-		if (!*optarg) {
-			*index = MGMT_INDEX_NONE;
-			return true;
-		}
-
-		if (*optarg != ':')
+		if (!*optarg || *optarg != ':')
 			return false;
 
 		optarg++;
@@ -291,7 +275,7 @@ int main(int argc, char *argv[])
 		io = l_strdup_printf("auto");
 
 	if (!parse_io(io, &io_type, &io_opts)) {
-		l_error("Invalid io: %s", io);
+		l_error("Invalid io: %s\n%s", io, io_usage);
 		status = EXIT_FAILURE;
 		goto done;
 	}
diff --git a/mesh/manager.c b/mesh/manager.c
index e66b1a4..0c98721 100644
--- a/mesh/manager.c
+++ b/mesh/manager.c
@@ -21,75 +21,137 @@
 #include "mesh/mesh.h"
 #include "mesh/mesh-io.h"
 #include "mesh/node.h"
+#include "mesh/model.h"
 #include "mesh/net.h"
 #include "mesh/keyring.h"
 #include "mesh/agent.h"
 #include "mesh/provision.h"
+#include "mesh/prov.h"
+#include "mesh/remprv.h"
 #include "mesh/manager.h"
 
-struct add_data{
+struct prov_remote_data {
 	struct l_dbus_message *msg;
 	struct mesh_agent *agent;
 	struct mesh_node *node;
 	uint32_t disc_watch;
+	uint16_t original;
 	uint16_t primary;
 	uint16_t net_idx;
+	uint8_t transport;
 	uint8_t num_ele;
 	uint8_t uuid[16];
 };
 
-static int8_t scan_rssi;
-static uint8_t scan_uuid[16];
-static struct mesh_node *scan_node;
-static struct l_timeout *scan_timeout;
-static struct add_data *add_pending;
+struct scan_req {
+	struct mesh_node *node;
+	struct l_timeout *timeout;
+	uint16_t server;
+	uint16_t net_idx;
+	uint8_t uuid[16];
+	int8_t rssi;
+	bool ext;
+};
+
+static struct l_queue *scans;
+static struct prov_remote_data *prov_pending;
 static const uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
 
+static bool by_scan(const void *a, const void *b)
+{
+	return a == b;
+}
+
+static bool by_node(const void *a, const void *b)
+{
+	const struct scan_req *req = a;
+	const struct mesh_node *node = b;
+
+	return req->node == node;
+}
+
+static bool by_node_svr(const void *a, const void *b)
+{
+	const struct scan_req *req = a;
+	const struct scan_req *test = b;
+
+	return req->node == test->node && req->server == test->server;
+}
+
 static void scan_cancel(struct l_timeout *timeout, void *user_data)
 {
-	struct mesh_node *node = user_data;
+	struct scan_req *req = user_data;
 	struct mesh_io *io;
 	struct mesh_net *net;
+	uint8_t msg[4];
+	int n;
 
 	l_debug("");
 
-	if (scan_timeout)
-		l_timeout_remove(scan_timeout);
+	req = l_queue_remove_if(scans, by_scan, req);
+
+	if (!req)
+		return;
+
+	l_timeout_remove(req->timeout);
+
+	if (req->server) {
+		n = mesh_model_opcode_set(OP_REM_PROV_SCAN_STOP, msg);
+		mesh_model_send(req->node, 0, req->server, APP_IDX_DEV_REMOTE,
+						req->net_idx, DEFAULT_TTL,
+						true, n, msg);
+	} else {
+		net = node_get_net(req->node);
+		io = mesh_net_get_io(net);
+		mesh_io_deregister_recv_cb(io, prvb, sizeof(prvb));
+	}
 
-	net = node_get_net(node);
-	io = mesh_net_get_io(net);
-	mesh_io_deregister_recv_cb(io, prvb, sizeof(prvb));
-	scan_node = NULL;
-	scan_timeout = NULL;
+	initiator_scan_unreg(req->node);
+	l_free(req);
 }
 
-static void free_pending_add_call()
+static void free_pending_add_call(void)
 {
-	if (!add_pending)
+	if (!prov_pending)
 		return;
 
-	if (add_pending->disc_watch)
+	if (prov_pending->disc_watch)
 		l_dbus_remove_watch(dbus_get_bus(),
-						add_pending->disc_watch);
+						prov_pending->disc_watch);
 
-	if (add_pending->msg)
-		l_dbus_message_unref(add_pending->msg);
+	if (prov_pending->msg)
+		l_dbus_message_unref(prov_pending->msg);
 
-	l_free(add_pending);
-	add_pending = NULL;
+	l_free(prov_pending);
+	prov_pending = NULL;
 }
 
 static void prov_disc_cb(struct l_dbus *bus, void *user_data)
 {
-	if (!add_pending)
+	if (!prov_pending)
 		return;
 
-	initiator_cancel(add_pending);
-	add_pending->disc_watch = 0;
+	initiator_cancel(prov_pending);
+	prov_pending->disc_watch = 0;
 
 	free_pending_add_call();
 }
 
+static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
+					const char *key, const char *signature,
+					const void *data)
+{
+	if (!builder)
+		return;
+
+	l_dbus_message_builder_enter_dict(builder, "sv");
+	l_dbus_message_builder_append_basic(builder, 's', key);
+	l_dbus_message_builder_enter_variant(builder, signature);
+	l_dbus_message_builder_append_basic(builder, signature[0], data);
+	l_dbus_message_builder_leave_variant(builder);
+	l_dbus_message_builder_leave_dict(builder);
+}
+
 static void send_add_failed(const char *owner, const char *path,
 							uint8_t status)
 {
@@ -102,7 +164,7 @@ static void send_add_failed(const char *owner, const char *path,
 						"AddNodeFailed");
 
 	builder = l_dbus_message_builder_new(msg);
-	dbus_append_byte_array(builder, add_pending->uuid, 16);
+	dbus_append_byte_array(builder, prov_pending->uuid, 16);
 	l_dbus_message_builder_append_basic(builder, 's',
 						mesh_prov_status_str(status));
 	l_dbus_message_builder_finalize(builder);
@@ -115,14 +177,14 @@ static void send_add_failed(const char *owner, const char *path,
 static bool add_cmplt(void *user_data, uint8_t status,
 					struct mesh_prov_node_info *info)
 {
-	struct add_data *pending = user_data;
+	struct prov_remote_data *pending = user_data;
 	struct mesh_node *node = pending->node;
 	struct l_dbus *dbus = dbus_get_bus();
 	struct l_dbus_message_builder *builder;
 	struct l_dbus_message *msg;
 	bool result;
 
-	if (pending != add_pending)
+	if (pending != prov_pending)
 		return false;
 
 	if (status != PROV_ERR_SUCCESS) {
@@ -131,7 +193,12 @@ static bool add_cmplt(void *user_data, uint8_t status,
 		return false;
 	}
 
-	result = keyring_put_remote_dev_key(add_pending->node, info->unicast,
+	/* If Unicast address changing, delete old dev key */
+	if (pending->transport == PB_NPPI_01)
+		keyring_del_remote_dev_key_all(pending->node,
+							pending->original);
+
+	result = keyring_put_remote_dev_key(pending->node, info->unicast,
 					info->num_ele, info->device_key);
 
 	if (!result) {
@@ -140,13 +207,29 @@ static bool add_cmplt(void *user_data, uint8_t status,
 		return false;
 	}
 
-	msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
+	if (pending->transport > PB_NPPI_02)
+		msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
 						node_get_app_path(node),
 						MESH_PROVISIONER_INTERFACE,
 						"AddNodeComplete");
+	else
+		msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
+						node_get_app_path(node),
+						MESH_PROVISIONER_INTERFACE,
+						"ReprovComplete");
 
 	builder = l_dbus_message_builder_new(msg);
-	dbus_append_byte_array(builder, add_pending->uuid, 16);
+
+	if (pending->transport > PB_NPPI_02)
+		dbus_append_byte_array(builder, pending->uuid, 16);
+	else {
+		uint8_t nppi = (uint8_t) pending->transport;
+
+		l_dbus_message_builder_append_basic(builder, 'q',
+							&pending->original);
+		l_dbus_message_builder_append_basic(builder, 'y', &nppi);
+	}
+
 	l_dbus_message_builder_append_basic(builder, 'q', &info->unicast);
 	l_dbus_message_builder_append_basic(builder, 'y', &info->num_ele);
 	l_dbus_message_builder_finalize(builder);
@@ -161,47 +244,66 @@ static bool add_cmplt(void *user_data, uint8_t status,
 
 static void mgr_prov_data (struct l_dbus_message *reply, void *user_data)
 {
-	struct add_data *pending = user_data;
+	struct prov_remote_data *pending = user_data;
 	uint16_t net_idx;
 	uint16_t primary;
 
-	if (pending != add_pending)
+	if (pending != prov_pending)
 		return;
 
 	if (l_dbus_message_is_error(reply))
 		return;
 
-	if (!l_dbus_message_get_arguments(reply, "qq", &net_idx, &primary))
+	if (pending->transport == PB_NPPI_01) {
+		/* If performing NPPI, we only get new primary unicast here */
+		if (!l_dbus_message_get_arguments(reply, "q", &primary))
+			return;
+
+		net_idx = pending->net_idx;
+
+	} else if (!l_dbus_message_get_arguments(reply, "qq", &net_idx,
+								&primary))
 		return;
 
-	add_pending->primary = primary;
-	add_pending->net_idx = net_idx;
-	initiator_prov_data(net_idx, primary, add_pending);
+	pending->primary = primary;
+	pending->net_idx = net_idx;
+	initiator_prov_data(net_idx, primary, pending);
 }
 
 static bool add_data_get(void *user_data, uint8_t num_ele)
 {
-	struct add_data *pending = user_data;
+	struct prov_remote_data *pending = user_data;
 	struct l_dbus_message *msg;
 	struct l_dbus *dbus;
 	const char *app_path;
 	const char *sender;
 
-	if (pending != add_pending)
+	if (pending != prov_pending)
 		return false;
 
 	dbus = dbus_get_bus();
-	app_path = node_get_app_path(add_pending->node);
-	sender = node_get_owner(add_pending->node);
+	app_path = node_get_app_path(pending->node);
+	sender = node_get_owner(pending->node);
 
-	msg = l_dbus_message_new_method_call(dbus, sender, app_path,
+	if (pending->transport > PB_NPPI_02) {
+		msg = l_dbus_message_new_method_call(dbus, sender, app_path,
 						MESH_PROVISIONER_INTERFACE,
 						"RequestProvData");
 
-	l_dbus_message_set_arguments(msg, "y", num_ele);
-	l_dbus_send_with_reply(dbus, msg, mgr_prov_data, add_pending, NULL);
+		l_dbus_message_set_arguments(msg, "y", num_ele);
+	} else if (pending->transport == PB_NPPI_01) {
+		msg = l_dbus_message_new_method_call(dbus, sender, app_path,
+						MESH_PROVISIONER_INTERFACE,
+						"RequestReprovData");
+
+		l_dbus_message_set_arguments(msg, "qy", pending->original,
+								num_ele);
+	} else
+		return false;
 
-	add_pending->num_ele = num_ele;
+	l_dbus_send_with_reply(dbus, msg, mgr_prov_data, pending, NULL);
+
+	pending->num_ele = num_ele;
 
 	return true;
 }
@@ -213,15 +315,95 @@ static void add_start(void *user_data, int err)
 	l_debug("Start callback");
 
 	if (err == MESH_ERROR_NONE)
-		reply = l_dbus_message_new_method_return(add_pending->msg);
+		reply = l_dbus_message_new_method_return(prov_pending->msg);
 	else
-		reply = dbus_error(add_pending->msg, MESH_ERROR_FAILED,
+		reply = dbus_error(prov_pending->msg, MESH_ERROR_FAILED,
 				"Failed to start provisioning initiator");
 
 	l_dbus_send(dbus_get_bus(), reply);
-	l_dbus_message_unref(add_pending->msg);
+	l_dbus_message_unref(prov_pending->msg);
+
+	prov_pending->msg = NULL;
+}
+
+static struct l_dbus_message *reprovision_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	struct mesh_node *node = user_data;
+	struct l_dbus_message_iter options, var;
+	struct l_dbus_message *reply;
+	struct mesh_net *net = node_get_net(node);
+	const char *key;
+	uint16_t subidx;
+	uint16_t server = 0;
+	uint8_t nppi = 0;
+
+	l_debug("Reprovision request");
+
+	if (!l_dbus_message_get_arguments(msg, "qa{sv}", &server, &options))
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
+	if (!IS_UNICAST(server))
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad Unicast");
+
+	/* Default to nodes primary subnet index */
+	subidx = mesh_net_get_primary_idx(net);
+
+	/* Get Provisioning Options */
+	while (l_dbus_message_iter_next_entry(&options, &key, &var)) {
+		bool failed = true;
+
+		if (!strcmp(key, "NPPI")) {
+			if (l_dbus_message_iter_get_variant(&var, "y", &nppi)) {
+				if (nppi <= 2)
+					failed = false;
+			}
+		} else if (!strcmp(key, "Subnet")) {
+			if (l_dbus_message_iter_get_variant(&var, "q",
+								&subidx)) {
+				if (subidx <= MAX_KEY_IDX)
+					failed = false;
+			}
+		}
+
+		if (failed)
+			return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Invalid options");
+	}
+
+	/* AddNode cancels all outstanding Scanning from node */
+	manager_scan_cancel(node);
 
-	add_pending->msg = NULL;
+	/* Invoke Prov Initiator */
+	prov_pending = l_new(struct prov_remote_data, 1);
+
+	prov_pending->transport = nppi;
+	prov_pending->node = node;
+	prov_pending->original = server;
+	prov_pending->agent = node_get_agent(node);
+
+	if (!node_is_provisioner(node) || (prov_pending->agent == NULL)) {
+		reply = dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED,
+							"Missing Interfaces");
+		goto fail;
+	}
+
+	prov_pending->msg = l_dbus_message_ref(msg);
+	initiator_start(prov_pending->transport, server, subidx, NULL, 99, 60,
+					prov_pending->agent, add_start,
+					add_data_get, add_cmplt, node,
+					prov_pending);
+
+	prov_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
+						node_get_owner(node),
+						prov_disc_cb, NULL, NULL);
+
+	return NULL;
+fail:
+	l_free(prov_pending);
+	prov_pending = NULL;
+	return reply;
 }
 
 static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
@@ -229,55 +411,101 @@ static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
 						void *user_data)
 {
 	struct mesh_node *node = user_data;
-	struct l_dbus_message_iter iter_uuid, options;
+	struct l_dbus_message_iter iter_uuid, options, var;
 	struct l_dbus_message *reply;
+	struct mesh_net *net = node_get_net(node);
+	const char *key;
 	uint8_t *uuid;
-	uint32_t n = 22;
+	uint32_t n = 0;
+	uint16_t subidx;
+	uint16_t sec = 60;
+	uint16_t server = 0;
 
 	l_debug("AddNode request");
 
 	if (!l_dbus_message_get_arguments(msg, "aya{sv}", &iter_uuid, &options))
 		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
 
-	if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
-								|| n != 16)
+	if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
+									n != 16)
 		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
 							"Bad device UUID");
 
-	/* Allow AddNode to cancel Scanning if from the same node */
-	if (scan_node) {
-		if (scan_node != node)
-			return dbus_error(msg, MESH_ERROR_BUSY, NULL);
+	/* Default to nodes primary subnet index */
+	subidx = mesh_net_get_primary_idx(net);
 
-		scan_cancel(NULL, node);
+	/* Get Provisioning Options */
+	while (l_dbus_message_iter_next_entry(&options, &key, &var)) {
+		bool failed = true;
+
+		if (!strcmp(key, "Seconds")) {
+			if (l_dbus_message_iter_get_variant(&var, "q", &sec))
+				failed = false;
+		} else if (!strcmp(key, "Server")) {
+			if (l_dbus_message_iter_get_variant(&var, "q",
+								&server)) {
+				if (server < 0x8000)
+					failed = false;
+			}
+		} else if (!strcmp(key, "Subnet")) {
+			if (l_dbus_message_iter_get_variant(&var, "q",
+								&subidx)) {
+				if (subidx <= MAX_KEY_IDX)
+					failed = false;
+			}
+		}
+
+		if (failed)
+			return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Invalid options");
 	}
 
+	/* Device Key update/Composition update requires remote server */
+	if (!n && !server)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Invalid options");
+
+	/* If no server specified, use local */
+	if (!server)
+		server = node_get_primary(node);
+
+	/* AddNode cancels all outstanding Scanning from node */
+	manager_scan_cancel(node);
+
 	/* Invoke Prov Initiator */
-	add_pending = l_new(struct add_data, 1);
-	memcpy(add_pending->uuid, uuid, 16);
-	add_pending->node = node;
-	add_pending->agent = node_get_agent(node);
+	prov_pending = l_new(struct prov_remote_data, 1);
+
+	if (n)
+		memcpy(prov_pending->uuid, uuid, 16);
+	else
+		uuid = NULL;
 
-	if (!node_is_provisioner(node) || (add_pending->agent == NULL)) {
+	prov_pending->transport = PB_ADV;
+	prov_pending->node = node;
+	prov_pending->agent = node_get_agent(node);
+
+	if (!node_is_provisioner(node) || (prov_pending->agent == NULL)) {
 		l_debug("Provisioner: %d", node_is_provisioner(node));
-		l_debug("Agent: %p", add_pending->agent);
+		l_debug("Agent: %p", prov_pending->agent);
 		reply = dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED,
 							"Missing Interfaces");
 		goto fail;
 	}
 
-	add_pending->msg = l_dbus_message_ref(msg);
-	initiator_start(PB_ADV, uuid, 99, 60, add_pending->agent, add_start,
-				add_data_get, add_cmplt, node, add_pending);
+	prov_pending->msg = l_dbus_message_ref(msg);
+	initiator_start(PB_ADV, server, subidx, uuid, 99, sec,
+					prov_pending->agent, add_start,
+					add_data_get, add_cmplt, node,
+					prov_pending);
 
-	add_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
+	prov_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
 						node_get_owner(node),
 						prov_disc_cb, NULL, NULL);
 
 	return NULL;
 fail:
-	l_free(add_pending);
-	add_pending = NULL;
+	l_free(prov_pending);
+	prov_pending = NULL;
 	return reply;
 }
 
@@ -337,38 +565,50 @@ static struct l_dbus_message *delete_node_call(struct l_dbus *dbus,
 	return l_dbus_message_new_method_return(msg);
 }
 
-static void prov_beacon_recv(void *user_data, struct mesh_io_recv_info *info,
+static void manager_scan_result(void *user_data, uint16_t server, bool ext,
 					const uint8_t *data, uint16_t len)
 {
-	struct mesh_node *node = user_data;
+	struct scan_req node_svr = {
+		.node = user_data,
+		.server = server,
+	};
+	struct scan_req *req;
 	struct l_dbus_message_builder *builder;
 	struct l_dbus_message *msg;
 	struct l_dbus *dbus;
 	int16_t rssi;
 
-	if (scan_node != node || len < sizeof(scan_uuid) + 2 || data[1] != 0x00)
+	l_debug("scan_result %4.4x %p", server, user_data);
+	req = l_queue_find(scans, by_node_svr, &node_svr);
+	if (!req) {
+		l_debug("No scan_result req");
 		return;
+	}
 
-	if (!memcmp(data + 2, scan_uuid, sizeof(scan_uuid))) {
-		if (info->rssi <= scan_rssi)
+	/* Filter repeats with weaker signal */
+	if (!memcmp(data + 1, req->uuid, sizeof(req->uuid))) {
+		if (!ext && ((int8_t) data[0] <= req->rssi)) {
+			l_debug("Already Seen");
 			return;
+		}
 	}
 
-	memcpy(scan_uuid, data + 2, sizeof(scan_uuid));
-	scan_rssi = info->rssi;
-	rssi = info->rssi;
+	if (!ext && ((int8_t) data[0] > req->rssi))
+		req->rssi = (int8_t) data[0];
 
+	rssi = req->rssi;
+	memcpy(req->uuid, data + 1, sizeof(req->uuid));
 	dbus = dbus_get_bus();
-	msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
-						node_get_app_path(node),
+	msg = l_dbus_message_new_method_call(dbus, node_get_owner(req->node),
+						node_get_app_path(req->node),
 						MESH_PROVISIONER_INTERFACE,
 						"ScanResult");
 
 	builder = l_dbus_message_builder_new(msg);
 	l_dbus_message_builder_append_basic(builder, 'n', &rssi);
-	dbus_append_byte_array(builder, data + 2, len -2);
+	dbus_append_byte_array(builder, data + 1, len - 1);
 	l_dbus_message_builder_enter_array(builder, "{sv}");
-	/* TODO: populate with options when defined */
+	append_dict_entry_basic(builder, "Server", "q", &server);
 	l_dbus_message_builder_leave_array(builder);
 	l_dbus_message_builder_finalize(builder);
 	l_dbus_message_builder_destroy(builder);
@@ -380,27 +620,71 @@ static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
 {
-	struct mesh_node *node = user_data;
-	uint16_t duration = 0;
-	struct mesh_io *io;
+	struct scan_req new_req = {
+		.node = user_data,
+		.server = 0,
+		.timeout = NULL,
+		.ext = false,
+	};
+	struct scan_req *req;
 	struct mesh_net *net;
+	uint8_t *uuid, *ext = NULL;
+	uint8_t scan_req[21];
+	int n;
+	uint32_t ext_len;
+	uint32_t flen = 0;
+	uint16_t sec = 60;
 	const char *key;
 	struct l_dbus_message_iter options, var;
 	const char *sender = l_dbus_message_get_sender(msg);
 
-	if (strcmp(sender, node_get_owner(node)))
+	if (strcmp(sender, node_get_owner(new_req.node)))
 		return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
 
 	if (!l_dbus_message_get_arguments(msg, "a{sv}", &options))
 		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
 
+	if (!node_is_provisioner(new_req.node))
+		return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
+
+	net = node_get_net(new_req.node);
+	new_req.net_idx = mesh_net_get_primary_idx(net);
+	memset(new_req.uuid, 0, sizeof(new_req.uuid));
+
 	while (l_dbus_message_iter_next_entry(&options, &key, &var)) {
 		bool failed = true;
 
 		if (!strcmp(key, "Seconds")) {
-			if (l_dbus_message_iter_get_variant(&var, "q",
-							    &duration)) {
+			if (l_dbus_message_iter_get_variant(&var, "q", &sec))
 				failed = false;
+		} else if (!strcmp(key, "Subnet")) {
+			if (l_dbus_message_iter_get_variant(&var, "q",
+							&new_req.net_idx)) {
+				if (new_req.net_idx <= MAX_KEY_IDX)
+					failed = false;
+			}
+		} else if (!strcmp(key, "Server")) {
+			if (l_dbus_message_iter_get_variant(&var, "q",
+							&new_req.server)) {
+				if (new_req.server < 0x8000)
+					failed = false;
+			}
+		} else if (!strcmp(key, "Filter")) {
+			if (l_dbus_message_iter_get_variant(&var, "ay", &var)) {
+				if (l_dbus_message_iter_get_fixed_array(&var,
+								&uuid, &flen)) {
+					if (flen == 16) {
+						memcpy(new_req.uuid, uuid,
+									flen);
+						failed = false;
+					}
+				}
+			}
+		} else if (!strcmp(key, "Extended")) {
+			if (l_dbus_message_iter_get_variant(&var, "ay", &var)) {
+				if (l_dbus_message_iter_get_fixed_array(&var,
+								&ext, &ext_len))
+					failed = false;
 			}
 		}
 
@@ -409,27 +693,51 @@ static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
 							"Invalid options");
 	}
 
-	if (scan_node && scan_node != node)
-		return dbus_error(msg, MESH_ERROR_BUSY, NULL);
+	if (!scans)
+		scans = l_queue_new();
 
-	if (!node_is_provisioner(node))
-		return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
+	if (new_req.server) {
+		if (!sec || sec > 60)
+			return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Invalid options");
+	} else {
+		new_req.server = node_get_primary(new_req.node);
+		if (!sec || sec > 60)
+			sec = 60;
+	}
+
+	req = l_queue_remove_if(scans, by_node_svr, &new_req);
+
+	if (!req)
+		req = l_new(struct scan_req, 1);
+
+	if (req->timeout) {
+		l_timeout_remove(req->timeout);
+		req->timeout = NULL;
+	}
+
+	*req = new_req;
+	req->rssi = -128;
+
+	if (sec)
+		req->timeout = l_timeout_create(sec, scan_cancel, req, NULL);
 
-	if (scan_timeout)
-		l_timeout_remove(scan_timeout);
 
-	memset(scan_uuid, 0, sizeof(scan_uuid));
-	scan_rssi = -128;
-	scan_timeout = NULL;
-	net = node_get_net(node);
-	io = mesh_net_get_io(net);
-	scan_node = node;
-	mesh_io_register_recv_cb(io, prvb, sizeof(prvb),
-						prov_beacon_recv, node);
+	n = mesh_model_opcode_set(OP_REM_PROV_SCAN_START, scan_req);
+	scan_req[n++] = 5;
+	scan_req[n++] = sec;
+	if (flen) {
+		memcpy(scan_req + n, req->uuid, flen);
+		n += flen;
+	}
+
+	mesh_model_send(req->node, 0, req->server, APP_IDX_DEV_REMOTE,
+						req->net_idx, DEFAULT_TTL,
+						true, n, scan_req);
 
-	if (duration)
-		scan_timeout = l_timeout_create(duration, scan_cancel,
-								node, NULL);
+	initiator_scan_reg(manager_scan_result, req->node);
+
+	l_queue_push_tail(scans, req);
 
 	return l_dbus_message_new_method_return(msg);
 }
@@ -444,12 +752,7 @@ static struct l_dbus_message *cancel_scan_call(struct l_dbus *dbus,
 	if (strcmp(sender, node_get_owner(node)) || !node_is_provisioner(node))
 		return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
 
-	if (scan_node) {
-		if (scan_node != node)
-			return dbus_error(msg, MESH_ERROR_BUSY, NULL);
-
-		scan_cancel(NULL, node);
-	}
+	manager_scan_cancel(node);
 
 	return l_dbus_message_new_method_return(msg);
 }
@@ -814,6 +1117,8 @@ static void setup_management_interface(struct l_dbus_interface *iface)
 						"aya{sv}", "uuid", "options");
 	l_dbus_interface_method(iface, "ImportRemoteNode", 0, import_node_call,
 				"", "qyay", "primary", "count", "dev_key");
+	l_dbus_interface_method(iface, "Reprovision", 0, reprovision_call,
+					"", "qa{sv}", "unicast", "options");
 	l_dbus_interface_method(iface, "DeleteRemoteNode", 0, delete_node_call,
 						"", "qy", "primary", "count");
 	l_dbus_interface_method(iface, "UnprovisionedScan", 0, start_scan_call,
@@ -849,7 +1154,7 @@ bool manager_dbus_init(struct l_dbus *bus)
 	if (!l_dbus_register_interface(bus, MESH_MANAGEMENT_INTERFACE,
 						setup_management_interface,
 						NULL, false)) {
-		l_info("Unable to register %s interface",
+		l_debug("Unable to register %s interface",
 						MESH_MANAGEMENT_INTERFACE);
 		return false;
 	}
@@ -859,8 +1164,8 @@ bool manager_dbus_init(struct l_dbus *bus)
 
 void manager_scan_cancel(struct mesh_node *node)
 {
-	if (scan_node != node)
-		return;
+	struct scan_req *req;
 
-	scan_cancel(NULL, node);
+	while ((req = l_queue_find(scans, by_node, node)))
+		scan_cancel(NULL, req);
 }
diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
index 7f46c85..5372130 100644
--- a/mesh/mesh-config-json.c
+++ b/mesh/mesh-config-json.c
@@ -58,6 +58,33 @@ static const char *cfgnode_name = "/node.json";
 static const char *bak_ext = ".bak";
 static const char *tmp_ext = ".tmp";
 
+/* JSON key words */
+static const char *unicastAddress = "unicastAddress";
+static const char *deviceCan = "deviceCan";
+static const char *deviceKey = "deviceKey";
+static const char *defaultTTL = "defaultTTL";
+static const char *sequenceNumber = "sequenceNumber";
+static const char *netKeys = "netKeys";
+static const char *appKeys = "appKeys";
+static const char *elements = "elements";
+static const char *models = "models";
+static const char *modelId = "modelId";
+static const char *address = "address";
+static const char *bind = "bind";
+static const char *publish = "publish";
+static const char *subscribe = "subscribe";
+static const char *boundNetKey = "boundNetKey";
+static const char *keyRefresh = "keyRefresh";
+static const char *subEnabled = "subEnabled";
+static const char *pubEnabled = "pubEnabled";
+static const char *retransmit = "retransmit";
+
+/* Common JSON values */
+static const char *enabled = "enabled";
+static const char *disabled = "disabled";
+static const char *unsupported = "unsupported";
+
+
 static bool save_config(json_object *jnode, const char *fname)
 {
 	FILE *outfile;
@@ -134,14 +161,14 @@ static int get_element_index(json_object *jnode, uint16_t ele_addr)
 	uint16_t addr, num_ele;
 	char *str;
 
-	if (!json_object_object_get_ex(jnode, "unicastAddress", &jvalue))
+	if (!json_object_object_get_ex(jnode, unicastAddress, &jvalue))
 		return -1;
 
 	str = (char *)json_object_get_string(jvalue);
 	if (sscanf(str, "%04hx", &addr) != 1)
 		return -1;
 
-	if (!json_object_object_get_ex(jnode, "elements", &jelements))
+	if (!json_object_object_get_ex(jnode, elements, &jelements))
 		return -1;
 
 	num_ele = json_object_array_length(jelements);
@@ -160,14 +187,14 @@ static json_object *get_element_model(json_object *jnode, int ele_idx,
 	size_t len;
 	char buf[9];
 
-	if (!json_object_object_get_ex(jnode, "elements", &jelements))
+	if (!json_object_object_get_ex(jnode, elements, &jelements))
 		return NULL;
 
 	jelement = json_object_array_get_idx(jelements, ele_idx);
 	if (!jelement)
 		return NULL;
 
-	if (!json_object_object_get_ex(jelement, "models", &jmodels))
+	if (!json_object_object_get_ex(jelement, models, &jmodels))
 		return NULL;
 
 	num_mods = json_object_array_length(jmodels);
@@ -189,7 +216,7 @@ static json_object *get_element_model(json_object *jnode, int ele_idx,
 		char *str;
 
 		jmodel = json_object_array_get_idx(jmodels, i);
-		if (!json_object_object_get_ex(jmodel, "modelId", &jvalue))
+		if (!json_object_object_get_ex(jmodel, modelId, &jvalue))
 			return NULL;
 
 		str = (char *)json_object_get_string(jvalue);
@@ -298,7 +325,7 @@ static bool read_unicast_address(json_object *jobj, uint16_t *unicast)
 	json_object *jvalue;
 	char *str;
 
-	if (!json_object_object_get_ex(jobj, "unicastAddress", &jvalue))
+	if (!json_object_object_get_ex(jobj, unicastAddress, &jvalue))
 		return false;
 
 	str = (char *)json_object_get_string(jvalue);
@@ -314,7 +341,7 @@ static bool read_default_ttl(json_object *jobj, uint8_t *ttl)
 	int val;
 
 	/* defaultTTL is optional */
-	if (!json_object_object_get_ex(jobj, "defaultTTL", &jvalue))
+	if (!json_object_object_get_ex(jobj, defaultTTL, &jvalue))
 		return true;
 
 	val = json_object_get_int(jvalue);
@@ -336,7 +363,7 @@ static bool read_seq_number(json_object *jobj, uint32_t *seq_number)
 	int val;
 
 	/* sequenceNumber is optional */
-	if (!json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
+	if (!json_object_object_get_ex(jobj, sequenceNumber, &jvalue))
 		return true;
 
 	val = json_object_get_int(jvalue);
@@ -396,7 +423,25 @@ static bool read_device_key(json_object *jobj, uint8_t key_buf[16])
 	if (!key_buf)
 		return false;
 
-	if (!json_object_object_get_ex(jobj, "deviceKey", &jvalue))
+	if (!json_object_object_get_ex(jobj, deviceKey, &jvalue))
+		return false;
+
+	str = (char *)json_object_get_string(jvalue);
+	if (!str2hex(str, strlen(str), key_buf, 16))
+		return false;
+
+	return true;
+}
+
+static bool read_candidate(json_object *jobj, uint8_t key_buf[16])
+{
+	json_object *jvalue;
+	char *str;
+
+	if (!key_buf)
+		return false;
+
+	if (!json_object_object_get_ex(jobj, deviceCan, &jvalue))
 		return false;
 
 	str = (char *)json_object_get_string(jvalue);
@@ -460,7 +505,7 @@ static bool read_app_keys(json_object *jobj, struct mesh_config_node *node)
 	int len;
 	int i;
 
-	if (!json_object_object_get_ex(jobj, "appKeys", &jarray))
+	if (!json_object_object_get_ex(jobj, appKeys, &jarray))
 		return true;
 
 	if (json_object_get_type(jarray) != json_type_array)
@@ -484,7 +529,7 @@ static bool read_app_keys(json_object *jobj, struct mesh_config_node *node)
 		if (!get_key_index(jtemp, "index", &appkey->app_idx))
 			goto fail;
 
-		if (!get_key_index(jtemp, "boundNetKey", &appkey->net_idx))
+		if (!get_key_index(jtemp, boundNetKey, &appkey->net_idx))
 			goto fail;
 
 		if (!json_object_object_get_ex(jtemp, "key", &jvalue))
@@ -516,7 +561,7 @@ static bool read_net_keys(json_object *jobj, struct mesh_config_node *node)
 	int i;
 
 	/* At least one NetKey must be present for a provisioned node */
-	if (!json_object_object_get_ex(jobj, "netKeys", &jarray))
+	if (!json_object_object_get_ex(jobj, netKeys, &jarray))
 		return false;
 
 	if (json_object_get_type(jarray) != json_type_array)
@@ -547,7 +592,7 @@ static bool read_net_keys(json_object *jobj, struct mesh_config_node *node)
 		if (!str2hex(str, strlen(str), netkey->new_key, 16))
 			goto fail;
 
-		if (!json_object_object_get_ex(jtemp, "keyRefresh", &jvalue))
+		if (!json_object_object_get_ex(jtemp, keyRefresh, &jvalue))
 			netkey->phase = KEY_REFRESH_PHASE_NONE;
 		else
 			netkey->phase = (uint8_t) json_object_get_int(jvalue);
@@ -598,7 +643,7 @@ bool mesh_config_net_key_add(struct mesh_config *cfg, uint16_t idx,
 	jnode = cfg->jnode;
 
 	l_debug("netKey %4.4x", idx);
-	json_object_object_get_ex(jnode, "netKeys", &jarray);
+	json_object_object_get_ex(jnode, netKeys, &jarray);
 	if (jarray)
 		jentry = get_key_object(jarray, idx);
 
@@ -616,14 +661,14 @@ bool mesh_config_net_key_add(struct mesh_config *cfg, uint16_t idx,
 	if (!add_key_value(jentry, "key", key))
 		goto fail;
 
-	json_object_object_add(jentry, "keyRefresh",
+	json_object_object_add(jentry, keyRefresh,
 				json_object_new_int(KEY_REFRESH_PHASE_NONE));
 
 	if (!jarray) {
 		jarray = json_object_new_array();
 		if (!jarray)
 			goto fail;
-		json_object_object_add(jnode, "netKeys", jarray);
+		json_object_object_add(jnode, netKeys, jarray);
 	}
 
 	json_object_array_add(jarray, jentry);
@@ -648,7 +693,7 @@ bool mesh_config_net_key_update(struct mesh_config *cfg, uint16_t idx,
 
 	jnode = cfg->jnode;
 
-	if (!json_object_object_get_ex(jnode, "netKeys", &jarray))
+	if (!json_object_object_get_ex(jnode, netKeys, &jarray))
 		return false;
 
 	jentry = get_key_object(jarray, idx);
@@ -667,7 +712,7 @@ bool mesh_config_net_key_update(struct mesh_config *cfg, uint16_t idx,
 	if (!add_key_value(jentry, "key", key))
 		return false;
 
-	json_object_object_add(jentry, "keyRefresh",
+	json_object_object_add(jentry, keyRefresh,
 				json_object_new_int(KEY_REFRESH_PHASE_ONE));
 
 	return save_config(jnode, cfg->node_dir_path);
@@ -682,20 +727,55 @@ bool mesh_config_net_key_del(struct mesh_config *cfg, uint16_t idx)
 
 	jnode = cfg->jnode;
 
-	if (!json_object_object_get_ex(jnode, "netKeys", &jarray))
+	if (!json_object_object_get_ex(jnode, netKeys, &jarray))
 		return true;
 
 	jarray_key_del(jarray, idx);
 
 	if (!json_object_array_length(jarray))
-		json_object_object_del(jnode, "netKeys");
+		json_object_object_del(jnode, netKeys);
 
 	return save_config(jnode, cfg->node_dir_path);
 }
 
 bool mesh_config_write_device_key(struct mesh_config *cfg, uint8_t *key)
 {
-	if (!cfg || !add_key_value(cfg->jnode, "deviceKey", key))
+	if (!cfg || !add_key_value(cfg->jnode, deviceKey, key))
+		return false;
+
+	return save_config(cfg->jnode, cfg->node_dir_path);
+}
+
+bool mesh_config_write_candidate(struct mesh_config *cfg, uint8_t *key)
+{
+	if (!cfg || !add_key_value(cfg->jnode, deviceCan, key))
+		return false;
+
+	return save_config(cfg->jnode, cfg->node_dir_path);
+}
+
+bool mesh_config_read_candidate(struct mesh_config *cfg, uint8_t *key)
+{
+	if (!cfg)
+		return false;
+
+	return read_candidate(cfg->jnode, key);
+}
+
+bool mesh_config_finalize_candidate(struct mesh_config *cfg)
+{
+	uint8_t key[16];
+
+	if (!cfg)
+		return false;
+
+	if (!read_candidate(cfg->jnode, key))
+		return false;
+
+	json_object_object_del(cfg->jnode, deviceCan);
+	json_object_object_del(cfg->jnode, deviceKey);
+
+	if (!add_key_value(cfg->jnode, deviceKey, key))
 		return false;
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
@@ -719,7 +799,7 @@ bool mesh_config_app_key_add(struct mesh_config *cfg, uint16_t net_idx,
 
 	jnode = cfg->jnode;
 
-	json_object_object_get_ex(jnode, "appKeys", &jarray);
+	json_object_object_get_ex(jnode, appKeys, &jarray);
 	if (jarray)
 		jentry = get_key_object(jarray, app_idx);
 
@@ -734,7 +814,7 @@ bool mesh_config_app_key_add(struct mesh_config *cfg, uint16_t net_idx,
 	if (!write_int(jentry, "index", app_idx))
 		goto fail;
 
-	if (!write_int(jentry, "boundNetKey", net_idx))
+	if (!write_int(jentry, boundNetKey, net_idx))
 		goto fail;
 
 	if (!add_key_value(jentry, "key", key))
@@ -744,7 +824,7 @@ bool mesh_config_app_key_add(struct mesh_config *cfg, uint16_t net_idx,
 		jarray = json_object_new_array();
 		if (!jarray)
 			goto fail;
-		json_object_object_add(jnode, "appKeys", jarray);
+		json_object_object_add(jnode, appKeys, jarray);
 	}
 
 	json_object_array_add(jarray, jentry);
@@ -770,7 +850,7 @@ bool mesh_config_app_key_update(struct mesh_config *cfg, uint16_t app_idx,
 
 	jnode = cfg->jnode;
 
-	if (!json_object_object_get_ex(jnode, "appKeys", &jarray))
+	if (!json_object_object_get_ex(jnode, appKeys, &jarray))
 		return false;
 
 	/* The key entry should exist if the key is updated */
@@ -804,13 +884,13 @@ bool mesh_config_app_key_del(struct mesh_config *cfg, uint16_t net_idx,
 
 	jnode = cfg->jnode;
 
-	if (!json_object_object_get_ex(jnode, "appKeys", &jarray))
+	if (!json_object_object_get_ex(jnode, appKeys, &jarray))
 		return true;
 
 	jarray_key_del(jarray, idx);
 
 	if (!json_object_array_length(jarray))
-		json_object_object_del(jnode, "appKeys");
+		json_object_object_del(jnode, appKeys);
 
 	return save_config(jnode, cfg->node_dir_path);
 }
@@ -840,7 +920,7 @@ bool mesh_config_model_binding_add(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!jmodel)
 		return false;
 
-	json_object_object_get_ex(jmodel, "bind", &jarray);
+	json_object_object_get_ex(jmodel, bind, &jarray);
 	if (jarray && jarray_has_string(jarray, buf, 4))
 		return true;
 
@@ -854,7 +934,7 @@ bool mesh_config_model_binding_add(struct mesh_config *cfg, uint16_t ele_addr,
 			json_object_put(jstring);
 			return false;
 		}
-		json_object_object_add(jmodel, "bind", jarray);
+		json_object_object_add(jmodel, bind, jarray);
 	}
 
 	json_object_array_add(jarray, jstring);
@@ -887,13 +967,13 @@ bool mesh_config_model_binding_del(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!jmodel)
 		return false;
 
-	if (!json_object_object_get_ex(jmodel, "bind", &jarray))
+	if (!json_object_object_get_ex(jmodel, bind, &jarray))
 		return true;
 
 	jarray_string_del(jarray, buf, 4);
 
 	if (!json_object_array_length(jarray))
-		json_object_object_del(jmodel, "bind");
+		json_object_object_del(jmodel, bind);
 
 	return save_config(jnode, cfg->node_dir_path);
 }
@@ -963,7 +1043,7 @@ static struct mesh_config_pub *parse_model_publication(json_object *jpub)
 	int len, value;
 	char *str;
 
-	if (!json_object_object_get_ex(jpub, "address", &jvalue))
+	if (!json_object_object_get_ex(jpub, address, &jvalue))
 		return NULL;
 
 	str = (char *)json_object_get_string(jvalue);
@@ -998,9 +1078,10 @@ static struct mesh_config_pub *parse_model_publication(json_object *jpub)
 
 	if (!get_int(jpub, "credentials", &value))
 		goto fail;
+
 	pub->credential = (uint8_t) value;
 
-	if (!json_object_object_get_ex(jpub, "retransmit", &jvalue))
+	if (!json_object_object_get_ex(jpub, retransmit, &jvalue))
 		goto fail;
 
 	if (!get_int(jvalue, "count", &value))
@@ -1093,7 +1174,7 @@ static bool parse_models(json_object *jmodels, struct mesh_config_element *ele)
 
 		l_queue_push_tail(ele->models, mod);
 
-		if (!json_object_object_get_ex(jmodel, "modelId", &jvalue))
+		if (!json_object_object_get_ex(jmodel, modelId, &jvalue))
 			goto fail;
 
 		str = (char *)json_object_get_string(jvalue);
@@ -1112,29 +1193,32 @@ static bool parse_models(json_object *jmodels, struct mesh_config_element *ele)
 
 		mod->id = id;
 
-		if (json_object_object_get_ex(jmodel, "bind", &jarray)) {
+		if (len == 8)
+			mod->vendor = true;
+
+		if (json_object_object_get_ex(jmodel, bind, &jarray)) {
 			if (json_object_get_type(jarray) != json_type_array ||
 					!parse_bindings(jarray, mod))
 				goto fail;
 		}
 
-		if (json_object_object_get_ex(jmodel, "pubEnabled", &jvalue))
+		if (json_object_object_get_ex(jmodel, pubEnabled, &jvalue))
 			mod->pub_enabled = json_object_get_boolean(jvalue);
 		else
 			mod->pub_enabled = true;
 
-		if (json_object_object_get_ex(jmodel, "subEnabled", &jvalue))
+		if (json_object_object_get_ex(jmodel, subEnabled, &jvalue))
 			mod->sub_enabled = json_object_get_boolean(jvalue);
 		else
 			mod->sub_enabled = true;
 
-		if (json_object_object_get_ex(jmodel, "publish", &jvalue)) {
+		if (json_object_object_get_ex(jmodel, publish, &jvalue)) {
 			mod->pub = parse_model_publication(jvalue);
 			if (!mod->pub)
 				goto fail;
 		}
 
-		if (json_object_object_get_ex(jmodel, "subscribe", &jarray)) {
+		if (json_object_object_get_ex(jmodel, subscribe, &jarray)) {
 			if (!parse_model_subscriptions(jarray, mod))
 				goto fail;
 		}
@@ -1187,7 +1271,7 @@ static bool parse_elements(json_object *jelems, struct mesh_config_node *node)
 		if (sscanf(str, "%04hx", &(ele->location)) != 1)
 			goto fail;
 
-		if (json_object_object_get_ex(jelement, "models", &jmodels)) {
+		if (json_object_object_get_ex(jelement, models, &jmodels)) {
 			if (json_object_get_type(jmodels) != json_type_array ||
 						!parse_models(jmodels, ele))
 				goto fail;
@@ -1211,13 +1295,13 @@ static int get_mode(json_object *jvalue)
 	if (!str)
 		return 0xffffffff;
 
-	if (!strncasecmp(str, "disabled", strlen("disabled")))
+	if (!strncasecmp(str, disabled, strlen(disabled)))
 		return MESH_MODE_DISABLED;
 
-	if (!strncasecmp(str, "enabled", strlen("enabled")))
+	if (!strncasecmp(str, enabled, strlen(enabled)))
 		return MESH_MODE_ENABLED;
 
-	if (!strncasecmp(str, "unsupported", strlen("unsupported")))
+	if (!strncasecmp(str, unsupported, strlen(unsupported)))
 		return MESH_MODE_UNSUPPORTED;
 
 	return 0xffffffff;
@@ -1253,6 +1337,19 @@ static void parse_features(json_object *jconfig, struct mesh_config_node *node)
 			node->modes.beacon = mode;
 	}
 
+	if (json_object_object_get_ex(jconfig, "mpb", &jvalue)) {
+		mode = get_mode(jvalue);
+		if (mode <= MESH_MODE_UNSUPPORTED)
+			node->modes.mpb = mode;
+
+		if (node->modes.mpb == MESH_MODE_ENABLED) {
+			if (json_object_object_get_ex(jconfig, "mpbPeriod",
+								&jvalue))
+				node->modes.mpb_period =
+						json_object_get_int(jvalue);
+		}
+	}
+
 	if (!json_object_object_get_ex(jconfig, "relay", &jrelay))
 		return;
 
@@ -1323,7 +1420,7 @@ static bool read_net_transmit(json_object *jobj, struct mesh_config_node *node)
 	uint16_t interval;
 	uint8_t cnt;
 
-	if (!json_object_object_get_ex(jobj, "retransmit", &jrtx))
+	if (!json_object_object_get_ex(jobj, retransmit, &jrtx))
 		return true;
 
 	if (!json_object_object_get_ex(jrtx, "count", &jvalue))
@@ -1386,7 +1483,7 @@ static bool read_node(json_object *jnode, struct mesh_config_node *node)
 	}
 
 	/* Check for required "elements" property */
-	if (!json_object_object_get_ex(jnode, "elements", &jvalue))
+	if (!json_object_object_get_ex(jnode, elements, &jvalue))
 		return false;
 
 	if (!read_net_transmit(jnode, node)) {
@@ -1460,11 +1557,11 @@ static const char *mode_to_string(int mode)
 {
 	switch (mode) {
 	case MESH_MODE_DISABLED:
-		return "disabled";
+		return disabled;
 	case MESH_MODE_ENABLED:
-		return "enabled";
+		return enabled;
 	default:
-		return "unsupported";
+		return unsupported;
 	}
 }
 
@@ -1492,6 +1589,18 @@ bool mesh_config_write_mode(struct mesh_config *cfg, const char *keyword,
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
 
+bool mesh_config_write_mode_ex(struct mesh_config *cfg, const char *keyword,
+							int value, bool save)
+{
+	if (!cfg)
+		return false;
+
+	if (save)
+		return mesh_config_write_mode(cfg, keyword, value);
+	else
+		return write_mode(cfg->jnode, keyword, value);
+}
+
 static bool write_relay_mode(json_object *jobj, uint8_t mode,
 					uint8_t count, uint16_t interval)
 {
@@ -1522,7 +1631,7 @@ fail:
 
 bool mesh_config_write_unicast(struct mesh_config *cfg, uint16_t unicast)
 {
-	if (!cfg || !write_uint16_hex(cfg->jnode, "unicastAddress", unicast))
+	if (!cfg || !write_uint16_hex(cfg->jnode, unicastAddress, unicast))
 		return false;
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
@@ -1538,6 +1647,21 @@ bool mesh_config_write_relay_mode(struct mesh_config *cfg, uint8_t mode,
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
 
+bool mesh_config_write_mpb(struct mesh_config *cfg, uint8_t mode,
+								uint8_t period)
+{
+
+	if (!cfg || !write_mode(cfg->jnode, "mpb", mode))
+		return false;
+
+	if (mode) {
+		if (!write_int(cfg->jnode, "mpbPeriod", period))
+			return false;
+	}
+
+	return save_config(cfg->jnode, cfg->node_dir_path);
+}
+
 bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt,
 							uint16_t interval)
 {
@@ -1558,8 +1682,8 @@ bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt,
 	if (!write_int(jrtx, "interval", interval))
 		goto fail;
 
-	json_object_object_del(jnode, "retransmit");
-	json_object_object_add(jnode, "retransmit", jrtx);
+	json_object_object_del(jnode, retransmit);
+	json_object_object_add(jnode, retransmit, jrtx);
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
 
@@ -1599,8 +1723,8 @@ static void add_model(void *a, void *b)
 	if (!jmodel)
 		return;
 
-	result = (mod->vendor) ? write_uint32_hex(jmodel, "modelId", mod->id) :
-			write_uint16_hex(jmodel, "modelId", (uint16_t) mod->id);
+	result = (mod->vendor) ? write_uint32_hex(jmodel, modelId, mod->id) :
+			write_uint16_hex(jmodel, modelId, (uint16_t) mod->id);
 
 	if (!result) {
 		json_object_put(jmodel);
@@ -1608,10 +1732,10 @@ static void add_model(void *a, void *b)
 	}
 
 	jval = json_object_new_boolean(mod->sub_enabled);
-	json_object_object_add(jmodel, "subEnabled", jval);
+	json_object_object_add(jmodel, subEnabled, jval);
 
 	jval = json_object_new_boolean(mod->pub_enabled);
-	json_object_object_add(jmodel, "pubEnabled", jval);
+	json_object_object_add(jmodel, pubEnabled, jval);
 
 	json_object_array_add(jmodels, jmodel);
 }
@@ -1662,12 +1786,20 @@ static struct mesh_config *create_config(const char *cfg_path,
 	if (!write_mode(jnode, "beacon", modes->beacon))
 		return NULL;
 
+	if (!write_mode(jnode, "mpb", modes->mpb))
+		return NULL;
+
+	if (modes->mpb) {
+		if (!write_int(jnode, "mpbPeriod", modes->mpb_period))
+			return NULL;
+	}
+
 	/* Sequence number */
-	json_object_object_add(jnode, "sequenceNumber",
+	json_object_object_add(jnode, sequenceNumber,
 					json_object_new_int(node->seq_number));
 
 	/* Default TTL */
-	json_object_object_add(jnode, "defaultTTL",
+	json_object_object_add(jnode, defaultTTL,
 						json_object_new_int(node->ttl));
 
 	/* Elements */
@@ -1702,11 +1834,11 @@ static struct mesh_config *create_config(const char *cfg_path,
 		if (!jmodels)
 			goto fail;
 
-		json_object_object_add(jelement, "models", jmodels);
+		json_object_object_add(jelement, models, jmodels);
 		l_queue_foreach(ele->models, add_model, jmodels);
 	}
 
-	json_object_object_add(jnode, "elements", jelems);
+	json_object_object_add(jnode, elements, jelems);
 
 	cfg = l_new(struct mesh_config, 1);
 
@@ -1724,6 +1856,55 @@ fail:
 		return NULL;
 }
 
+void mesh_config_reset(struct mesh_config *cfg, struct mesh_config_node *node)
+{
+	json_object *jelems;
+	const struct l_queue_entry *entry;
+
+	if (!cfg || !cfg->jnode)
+		return;
+
+	/* TODO: Recreate Element Array */
+	jelems = json_object_new_array();
+	if (!jelems)
+		return;
+
+	entry = l_queue_get_entries(node->elements);
+
+	for (; entry; entry = entry->next) {
+		struct mesh_config_element *ele = entry->data;
+		json_object *jelement, *jmodels;
+
+		jelement = json_object_new_object();
+
+		if (!jelement) {
+			json_object_put(jelems);
+			return;
+		}
+
+		write_int(jelement, "elementIndex", ele->index);
+		write_uint16_hex(jelement, "location", ele->location);
+		json_object_array_add(jelems, jelement);
+
+		/* Models */
+		if (l_queue_isempty(ele->models))
+			continue;
+
+		jmodels = json_object_new_array();
+		if (!jmodels) {
+			json_object_put(jelems);
+			return;
+		}
+
+		json_object_object_add(jelement, models, jmodels);
+		l_queue_foreach(ele->models, add_model, jmodels);
+	}
+
+	/* Replace element array */
+	json_object_object_del(cfg->jnode, elements);
+	json_object_object_add(cfg->jnode, elements, jelems);
+}
+
 struct mesh_config *mesh_config_create(const char *cfgdir_name,
 		const uint8_t uuid[16], struct mesh_config_node *db_node)
 {
@@ -1768,7 +1949,7 @@ static void finish_key_refresh(json_object *jobj, uint16_t net_idx)
 	int i, len;
 
 	/* Clean up all the bound appkeys */
-	if (!json_object_object_get_ex(jobj, "appKeys", &jarray))
+	if (!json_object_object_get_ex(jobj, appKeys, &jarray))
 		return;
 
 	len = json_object_array_length(jarray);
@@ -1779,7 +1960,7 @@ static void finish_key_refresh(json_object *jobj, uint16_t net_idx)
 
 		jentry = json_object_array_get_idx(jarray, i);
 
-		if (!get_key_index(jentry, "boundNetKey", &idx))
+		if (!get_key_index(jentry, boundNetKey, &idx))
 			continue;
 
 		if (idx != net_idx)
@@ -1803,14 +1984,14 @@ bool mesh_config_net_key_set_phase(struct mesh_config *cfg, uint16_t idx,
 
 	jnode = cfg->jnode;
 
-	if (json_object_object_get_ex(jnode, "netKeys", &jarray))
+	if (json_object_object_get_ex(jnode, netKeys, &jarray))
 		jentry = get_key_object(jarray, idx);
 
 	if (!jentry)
 		return false;
 
-	json_object_object_del(jentry, "keyRefresh");
-	json_object_object_add(jentry, "keyRefresh",
+	json_object_object_del(jentry, keyRefresh);
+	json_object_object_add(jentry, keyRefresh,
 					json_object_new_int(phase));
 
 	if (phase == KEY_REFRESH_PHASE_NONE) {
@@ -1842,16 +2023,16 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!jmodel)
 		return false;
 
-	json_object_object_del(jmodel, "publish");
+	json_object_object_del(jmodel, publish);
 
 	jpub = json_object_new_object();
 	if (!jpub)
 		return false;
 
 	if (pub->virt)
-		res = add_key_value(jpub, "address", pub->virt_addr);
+		res = add_key_value(jpub, address, pub->virt_addr);
 	else
-		res = write_uint16_hex(jpub, "address", pub->addr);
+		res = write_uint16_hex(jpub, address, pub->addr);
 
 	if (!res)
 		goto fail;
@@ -1878,8 +2059,8 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!write_int(jrtx, "interval", pub->interval))
 		goto fail;
 
-	json_object_object_add(jpub, "retransmit", jrtx);
-	json_object_object_add(jmodel, "publish", jpub);
+	json_object_object_add(jpub, retransmit, jrtx);
+	json_object_object_add(jmodel, publish, jpub);
 
 	return save_config(jnode, cfg->node_dir_path);
 
@@ -1911,23 +2092,23 @@ bool mesh_config_model_pub_del(struct mesh_config *cfg, uint16_t addr,
 						uint32_t mod_id, bool vendor)
 {
 	if (!cfg || !delete_model_property(cfg->jnode, addr, mod_id, vendor,
-								"publish"))
+								publish))
 		return false;
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
 
-static void del_page(json_object *jarray, uint8_t page)
+static bool del_page(json_object *jarray, uint8_t page)
 {
 	char buf[3];
 	int i, len, ret;
 
 	if (!jarray)
-		return;
+		return false;
 
 	ret = snprintf(buf, 3, "%2.2x", page);
 	if (ret < 0)
-		return;
+		return false;
 
 	len = json_object_array_length(jarray);
 
@@ -1938,10 +2119,29 @@ static void del_page(json_object *jarray, uint8_t page)
 		jentry = json_object_array_get_idx(jarray, i);
 		str = (char *)json_object_get_string(jentry);
 
-		/* Delete matching page(s) */
-		if (!memcmp(str, buf, 2))
+		/* Delete matching page */
+		if (!memcmp(str, buf, 2)) {
 			json_object_array_del_idx(jarray, i, 1);
+			break;
+		}
 	}
+
+	return true;
+}
+
+void mesh_config_comp_page_del(struct mesh_config *cfg, uint8_t page)
+{
+	json_object *jnode, *jarray = NULL;
+
+	if (!cfg)
+		return;
+
+	jnode = cfg->jnode;
+
+	json_object_object_get_ex(jnode, "pages", &jarray);
+
+	if (del_page(jarray, page))
+		save_config(jnode, cfg->node_dir_path);
 }
 
 bool mesh_config_comp_page_add(struct mesh_config *cfg, uint8_t page,
@@ -1984,56 +2184,6 @@ bool mesh_config_comp_page_add(struct mesh_config *cfg, uint8_t page,
 	return save_config(jnode, cfg->node_dir_path);
 }
 
-bool mesh_config_comp_page_mv(struct mesh_config *cfg, uint8_t old, uint8_t nw)
-{
-	json_object *jnode, *jarray = NULL;
-	uint8_t *data;
-	char *str;
-	char old_buf[3];
-	int i, len, ret, dlen = 0;
-	bool status = true;
-
-	if (!cfg || old == nw)
-		return false;
-
-	ret = snprintf(old_buf, 3, "%2.2x", old);
-	if (ret < 0)
-		return false;
-
-	jnode = cfg->jnode;
-
-	json_object_object_get_ex(jnode, "pages", &jarray);
-
-	if (!jarray)
-		return false;
-
-	data = l_malloc(MAX_MSG_LEN);
-
-	len = json_object_array_length(jarray);
-
-	for (i = 0; i < len; i++) {
-		json_object *jentry;
-
-		jentry = json_object_array_get_idx(jarray, i);
-		str = (char *)json_object_get_string(jentry);
-
-		/* Delete matching page(s) but save data*/
-		if (!memcmp(str, old_buf, 2)) {
-			dlen = strlen(str + 2);
-			str2hex(str + 2, dlen, data, MAX_MSG_LEN);
-			dlen /= 2;
-			json_object_array_del_idx(jarray, i, 1);
-		}
-	}
-
-	if (dlen)
-		status = mesh_config_comp_page_add(cfg, nw, data, dlen);
-
-	l_free(data);
-
-	return status;
-}
-
 bool mesh_config_model_sub_add(struct mesh_config *cfg, uint16_t ele_addr,
 						uint32_t mod_id, bool vendor,
 						struct mesh_config_sub *sub)
@@ -2064,7 +2214,7 @@ bool mesh_config_model_sub_add(struct mesh_config *cfg, uint16_t ele_addr,
 		len = 32;
 	}
 
-	json_object_object_get_ex(jmodel, "subscribe", &jarray);
+	json_object_object_get_ex(jmodel, subscribe, &jarray);
 	if (jarray && jarray_has_string(jarray, buf, len))
 		return true;
 
@@ -2078,7 +2228,7 @@ bool mesh_config_model_sub_add(struct mesh_config *cfg, uint16_t ele_addr,
 			json_object_put(jstring);
 			return false;
 		}
-		json_object_object_add(jmodel, "subscribe", jarray);
+		json_object_object_add(jmodel, subscribe, jarray);
 	}
 
 	json_object_array_add(jarray, jstring);
@@ -2107,7 +2257,7 @@ bool mesh_config_model_sub_del(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!jmodel)
 		return false;
 
-	if (!json_object_object_get_ex(jmodel, "subscribe", &jarray))
+	if (!json_object_object_get_ex(jmodel, subscribe, &jarray))
 		return true;
 
 	if (!sub->virt) {
@@ -2122,7 +2272,7 @@ bool mesh_config_model_sub_del(struct mesh_config *cfg, uint16_t ele_addr,
 	jarray_string_del(jarray, buf, len);
 
 	if (!json_object_array_length(jarray))
-		json_object_object_del(jmodel, "subscribe");
+		json_object_object_del(jmodel, subscribe);
 
 	return save_config(jnode, cfg->node_dir_path);
 }
@@ -2131,7 +2281,7 @@ bool mesh_config_model_sub_del_all(struct mesh_config *cfg, uint16_t addr,
 						uint32_t mod_id, bool vendor)
 {
 	if (!cfg || !delete_model_property(cfg->jnode, addr, mod_id, vendor,
-								"subscribe"))
+								subscribe))
 		return false;
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
@@ -2161,7 +2311,7 @@ bool mesh_config_model_pub_enable(struct mesh_config *cfg, uint16_t ele_addr,
 	json_object_object_add(jmodel, "pubDisabled", jval);
 
 	if (!enable)
-		json_object_object_del(jmodel, "publish");
+		json_object_object_del(jmodel, publish);
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
@@ -2184,13 +2334,13 @@ bool mesh_config_model_sub_enable(struct mesh_config *cfg, uint16_t ele_addr,
 	if (!jmodel)
 		return false;
 
-	json_object_object_del(jmodel, "subEnabled");
+	json_object_object_del(jmodel, subEnabled);
 
 	jval = json_object_new_boolean(enable);
-	json_object_object_add(jmodel, "subEnabled", jval);
+	json_object_object_add(jmodel, subEnabled, jval);
 
 	if (!enable)
-		json_object_object_del(jmodel, "subscribe");
+		json_object_object_del(jmodel, subscribe);
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
@@ -2205,14 +2355,14 @@ bool mesh_config_write_seq_number(struct mesh_config *cfg, uint32_t seq,
 		return false;
 
 	if (!cache) {
-		if (!write_int(cfg->jnode, "sequenceNumber", seq))
+		if (!write_int(cfg->jnode, sequenceNumber, seq))
 			return false;
 
 		return mesh_config_save(cfg, true, NULL, NULL);
 	}
 
 	/* If resetting seq to Zero, make sure cached value reset as well */
-	if (seq && get_int(cfg->jnode, "sequenceNumber", &value))
+	if (seq && get_int(cfg->jnode, sequenceNumber, &value))
 		cached = (uint32_t)value;
 
 	/*
@@ -2262,8 +2412,8 @@ bool mesh_config_write_seq_number(struct mesh_config *cfg, uint32_t seq,
 
 		l_debug("Seq Cache: %d -> %d", seq, cached);
 
-		if (!write_int(cfg->jnode, "sequenceNumber", cached))
-		    return false;
+		if (!write_int(cfg->jnode, sequenceNumber, cached))
+			return false;
 
 		return mesh_config_save(cfg, false, NULL, NULL);
 	}
@@ -2273,7 +2423,7 @@ bool mesh_config_write_seq_number(struct mesh_config *cfg, uint32_t seq,
 
 bool mesh_config_write_ttl(struct mesh_config *cfg, uint8_t ttl)
 {
-	if (!cfg || !write_int(cfg->jnode, "defaultTTL", ttl))
+	if (!cfg || !write_int(cfg->jnode, defaultTTL, ttl))
 		return false;
 
 	return save_config(cfg->jnode, cfg->node_dir_path);
@@ -2544,7 +2694,8 @@ bool mesh_config_load_nodes(const char *cfgdir_name, mesh_config_node_func_t cb,
 
 void mesh_config_destroy_nvm(struct mesh_config *cfg)
 {
-	char *node_dir, *node_name;
+	char *node_dir;
+	const char *node_name;
 	char uuid[33];
 
 	if (!cfg)
@@ -2556,7 +2707,7 @@ void mesh_config_destroy_nvm(struct mesh_config *cfg)
 	if (!hex2str(cfg->uuid, 16, uuid, sizeof(uuid)))
 		return;
 
-	node_name = basename(node_dir);
+	node_name = mesh_basename(node_dir);
 
 	/* Make sure path name of node follows expected guidelines */
 	if (strcmp(node_name, uuid))
diff --git a/mesh/mesh-config.h b/mesh/mesh-config.h
index 4207758..3cb20b8 100644
--- a/mesh/mesh-config.h
+++ b/mesh/mesh-config.h
@@ -60,6 +60,8 @@ struct mesh_config_modes {
 	uint8_t friend;
 	uint8_t proxy;
 	uint8_t beacon;
+	uint8_t mpb;
+	uint8_t mpb_period;
 };
 
 struct mesh_config_netkey {
@@ -119,6 +121,7 @@ void mesh_config_release(struct mesh_config *cfg);
 void mesh_config_destroy_nvm(struct mesh_config *cfg);
 bool mesh_config_save(struct mesh_config *cfg, bool no_wait,
 				mesh_config_status_func_t cb, void *user_data);
+void mesh_config_reset(struct mesh_config *cfg, struct mesh_config_node *node);
 struct mesh_config *mesh_config_create(const char *cfgdir_name,
 						const uint8_t uuid[16],
 						struct mesh_config_node *node);
@@ -126,6 +129,9 @@ struct mesh_config *mesh_config_create(const char *cfgdir_name,
 bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt,
 							uint16_t interval);
 bool mesh_config_write_device_key(struct mesh_config *cfg, uint8_t *key);
+bool mesh_config_write_candidate(struct mesh_config *cfg, uint8_t *key);
+bool mesh_config_read_candidate(struct mesh_config *cfg, uint8_t *key);
+bool mesh_config_finalize_candidate(struct mesh_config *cfg);
 bool mesh_config_write_token(struct mesh_config *cfg, uint8_t *token);
 bool mesh_config_write_network_key(struct mesh_config *cfg, uint16_t idx,
 				uint8_t *key, uint8_t *new_key, int phase);
@@ -136,12 +142,16 @@ bool mesh_config_write_seq_number(struct mesh_config *cfg, uint32_t seq,
 bool mesh_config_write_unicast(struct mesh_config *cfg, uint16_t unicast);
 bool mesh_config_write_relay_mode(struct mesh_config *cfg, uint8_t mode,
 					uint8_t count, uint16_t interval);
+bool mesh_config_write_mpb(struct mesh_config *cfg, uint8_t mode,
+								uint8_t period);
 bool mesh_config_write_ttl(struct mesh_config *cfg, uint8_t ttl);
 bool mesh_config_write_mode(struct mesh_config *cfg, const char *keyword,
 								int value);
+bool mesh_config_write_mode_ex(struct mesh_config *cfg, const char *keyword,
+							int value, bool save);
 bool mesh_config_comp_page_add(struct mesh_config *cfg, uint8_t page,
 						uint8_t *data, uint16_t size);
-bool mesh_config_comp_page_mv(struct mesh_config *cfg, uint8_t old, uint8_t nw);
+void mesh_config_comp_page_del(struct mesh_config *cfg, uint8_t page);
 bool mesh_config_model_binding_add(struct mesh_config *cfg, uint16_t ele_addr,
 						uint32_t mod_id, bool vendor,
 							uint16_t app_idx);
diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
index 21c505c..ae51cbc 100644
--- a/mesh/mesh-io-api.h
+++ b/mesh/mesh-io-api.h
@@ -34,6 +34,13 @@ struct mesh_io_api {
 	mesh_io_tx_cancel_t	cancel;
 };
 
+struct mesh_io_reg {
+	mesh_io_recv_func_t cb;
+	void *user_data;
+	uint8_t len;
+	uint8_t filter[];
+};
+
 struct mesh_io {
 	int				index;
 	int				favored_index;
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index 827128e..13a863b 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -33,7 +33,6 @@ struct mesh_io_private {
 	struct mesh_io *io;
 	struct bt_hci *hci;
 	struct l_timeout *tx_timeout;
-	struct l_queue *rx_regs;
 	struct l_queue *tx_pkts;
 	struct tx_pkt *tx;
 	uint16_t interval;
@@ -41,13 +40,6 @@ struct mesh_io_private {
 	bool active;
 };
 
-struct pvt_rx_reg {
-	mesh_io_recv_func_t cb;
-	void *user_data;
-	uint8_t len;
-	uint8_t filter[0];
-};
-
 struct process_data {
 	struct mesh_io_private		*pvt;
 	const uint8_t			*data;
@@ -87,7 +79,7 @@ static uint32_t instant_remaining_ms(uint32_t instant)
 
 static void process_rx_callbacks(void *v_reg, void *v_rx)
 {
-	struct pvt_rx_reg *rx_reg = v_reg;
+	struct mesh_io_reg *rx_reg = v_reg;
 	struct process_data *rx = v_rx;
 
 	if (!memcmp(rx->data, rx_reg->filter, rx_reg->len))
@@ -108,7 +100,7 @@ static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
 		.info.rssi = rssi,
 	};
 
-	l_queue_foreach(pvt->rx_regs, process_rx_callbacks, &rx);
+	l_queue_foreach(pvt->io->rx_regs, process_rx_callbacks, &rx);
 }
 
 static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size)
@@ -354,7 +346,7 @@ static bool find_by_pattern(const void *a, const void *b)
 
 static bool find_active(const void *a, const void *b)
 {
-	const struct pvt_rx_reg *rx_reg = a;
+	const struct mesh_io_reg *rx_reg = a;
 
 	/* Mesh specific AD types do *not* require active scanning,
 	 * so do not turn on Active Scanning on their account.
@@ -370,10 +362,10 @@ static void restart_scan(struct mesh_io_private *pvt)
 {
 	struct bt_hci_cmd_le_set_scan_enable cmd;
 
-	if (l_queue_isempty(pvt->rx_regs))
+	if (l_queue_isempty(pvt->io->rx_regs))
 		return;
 
-	pvt->active = l_queue_find(pvt->rx_regs, find_active, NULL);
+	pvt->active = l_queue_find(pvt->io->rx_regs, find_active, NULL);
 	cmd.enable = 0x00;	/* Disable scanning */
 	cmd.filter_dup = 0x00;	/* Report duplicates */
 	bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
@@ -388,6 +380,9 @@ static void hci_init(void *user_data)
 	if (io->pvt->hci)
 		bt_hci_unref(io->pvt->hci);
 
+	/* Clear controller HCI list to suppress mgmt interface warnings */
+	mesh_mgmt_clear();
+
 	io->pvt->hci = bt_hci_new_user_channel(io->index);
 	if (!io->pvt->hci) {
 		l_error("Failed to start mesh io (hci %u): %s", io->index,
@@ -417,7 +412,6 @@ static bool dev_init(struct mesh_io *io, void *opts, void *user_data)
 
 	io->pvt = l_new(struct mesh_io_private, 1);
 
-	io->pvt->rx_regs = l_queue_new();
 	io->pvt->tx_pkts = l_queue_new();
 
 	io->pvt->io = io;
@@ -436,7 +430,6 @@ static bool dev_destroy(struct mesh_io *io)
 
 	bt_hci_unref(pvt->hci);
 	l_timeout_remove(pvt->tx_timeout);
-	l_queue_destroy(pvt->rx_regs, l_free);
 	l_queue_remove_if(pvt->tx_pkts, simple_match, pvt->tx);
 	l_queue_destroy(pvt->tx_pkts, l_free);
 	l_free(pvt->tx);
@@ -726,7 +719,7 @@ static bool send_tx(struct mesh_io *io, struct mesh_io_send_info *info,
 		l_queue_push_tail(pvt->tx_pkts, tx);
 	}
 
-    /* If not already sending, schedule the tx worker */
+	/* If not already sending, schedule the tx worker */
 	if (!pvt->tx) {
 		l_timeout_remove(pvt->tx_timeout);
 		pvt->tx_timeout = NULL;
@@ -780,46 +773,18 @@ static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
 	return true;
 }
 
-static bool find_by_filter(const void *a, const void *b)
-{
-	const struct pvt_rx_reg *rx_reg_old = a;
-	const struct pvt_rx_reg *rx_reg = b;
-
-	if (rx_reg_old->len != rx_reg->len)
-		return false;
-
-	return !memcmp(rx_reg_old->filter, rx_reg->filter, rx_reg->len);
-}
-
 static bool recv_register(struct mesh_io *io, const uint8_t *filter,
 			uint8_t len, mesh_io_recv_func_t cb, void *user_data)
 {
 	struct bt_hci_cmd_le_set_scan_enable cmd;
 	struct mesh_io_private *pvt = io->pvt;
-	struct pvt_rx_reg *rx_reg, *rx_reg_old;
 	bool already_scanning;
 	bool active = false;
 
-	if (!cb || !filter || !len)
-		return false;
-
-	rx_reg = l_malloc(sizeof(*rx_reg) + len);
-
-	memcpy(rx_reg->filter, filter, len);
-	rx_reg->len = len;
-	rx_reg->cb = cb;
-	rx_reg->user_data = user_data;
-
-	rx_reg_old = l_queue_remove_if(pvt->rx_regs, find_by_filter, rx_reg);
-
-	l_free(rx_reg_old);
-
-	already_scanning = !l_queue_isempty(pvt->rx_regs);
-
-	l_queue_push_head(pvt->rx_regs, rx_reg);
+	already_scanning = l_queue_length(io->rx_regs) > 1;
 
 	/* Look for any AD types requiring Active Scanning */
-	if (l_queue_find(pvt->rx_regs, find_active, NULL))
+	if (l_queue_find(io->rx_regs, find_active, NULL))
 		active = true;
 
 	if (!already_scanning || pvt->active != active) {
@@ -839,25 +804,13 @@ static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
 {
 	struct bt_hci_cmd_le_set_scan_enable cmd = {0, 0};
 	struct mesh_io_private *pvt = io->pvt;
-	struct pvt_rx_reg *rx_reg, *rx_reg_tmp;
 	bool active = false;
 
-	rx_reg_tmp = l_malloc(sizeof(*rx_reg_tmp) + len);
-	memcpy(&rx_reg_tmp->filter, filter, len);
-	rx_reg_tmp->len = len;
-
-	rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, rx_reg_tmp);
-
-	if (rx_reg)
-		l_free(rx_reg);
-
-	l_free(rx_reg_tmp);
-
 	/* Look for any AD types requiring Active Scanning */
-	if (l_queue_find(pvt->rx_regs, find_active, NULL))
+	if (l_queue_find(io->rx_regs, find_active, NULL))
 		active = true;
 
-	if (l_queue_isempty(pvt->rx_regs)) {
+	if (l_queue_isempty(io->rx_regs)) {
 		bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
 					&cmd, sizeof(cmd), NULL, NULL, NULL);
 
diff --git a/mesh/mesh-io-mgmt.c b/mesh/mesh-io-mgmt.c
index 9ae1af0..5f0eb20 100644
--- a/mesh/mesh-io-mgmt.c
+++ b/mesh/mesh-io-mgmt.c
@@ -35,8 +35,8 @@ struct mesh_io_private {
 	struct mesh_io *io;
 	void *user_data;
 	struct l_timeout *tx_timeout;
+	struct l_timeout *dup_timeout;
 	struct l_queue *dup_filters;
-	struct l_queue *rx_regs;
 	struct l_queue *tx_pkts;
 	struct tx_pkt *tx;
 	unsigned int tx_id;
@@ -48,13 +48,6 @@ struct mesh_io_private {
 	bool active;
 };
 
-struct pvt_rx_reg {
-	mesh_io_recv_func_t cb;
-	void *user_data;
-	uint8_t len;
-	uint8_t filter[0];
-};
-
 struct process_data {
 	struct mesh_io_private		*pvt;
 	const uint8_t			*data;
@@ -82,6 +75,8 @@ struct dup_filter {
 	uint8_t addr[6];
 } __packed;
 
+static const uint8_t zero_addr[] = {0, 0, 0, 0, 0, 0};
+
 static struct mesh_io_private *pvt;
 
 static uint32_t get_instant(void)
@@ -110,6 +105,14 @@ static bool find_by_addr(const void *a, const void *b)
 	return !memcmp(filter->addr, b, 6);
 }
 
+static bool find_by_adv(const void *a, const void *b)
+{
+	const struct dup_filter *filter = a;
+	uint64_t data = l_get_be64(b);
+
+	return !memcmp(filter->addr, zero_addr, 6) && filter->data == data;
+}
+
 static void filter_timeout(struct l_timeout *timeout, void *user_data)
 {
 	struct dup_filter *filter;
@@ -136,6 +139,7 @@ static void filter_timeout(struct l_timeout *timeout, void *user_data)
 
 done:
 	l_timeout_remove(timeout);
+	pvt->dup_timeout = NULL;
 }
 
 /* Ignore consequtive duplicate advertisements within timeout period */
@@ -146,7 +150,22 @@ static bool filter_dups(const uint8_t *addr, const uint8_t *adv,
 	uint32_t instant_delta;
 	uint64_t data = l_get_be64(adv);
 
-	filter = l_queue_remove_if(pvt->dup_filters, find_by_addr, addr);
+	if (!addr)
+		addr = zero_addr;
+
+	if (adv[1] == MESH_AD_TYPE_PROVISION) {
+		filter = l_queue_find(pvt->dup_filters, find_by_adv, adv);
+
+		if (!filter && addr != zero_addr)
+			return false;
+
+		l_queue_remove(pvt->dup_filters, filter);
+
+	} else {
+		filter = l_queue_remove_if(pvt->dup_filters, find_by_addr,
+									addr);
+	}
+
 	if (!filter) {
 		filter = l_new(struct dup_filter, 1);
 		memcpy(filter->addr, addr, 6);
@@ -154,7 +173,8 @@ static bool filter_dups(const uint8_t *addr, const uint8_t *adv,
 
 	/* Start filter expiration timer */
 	if (!l_queue_length(pvt->dup_filters))
-		l_timeout_create(1, filter_timeout, NULL, NULL);
+		pvt->dup_timeout = l_timeout_create(1, filter_timeout, NULL,
+									NULL);
 
 	l_queue_push_head(pvt->dup_filters, filter);
 	instant_delta = instant - filter->instant;
@@ -170,14 +190,14 @@ static bool filter_dups(const uint8_t *addr, const uint8_t *adv,
 
 static void process_rx_callbacks(void *v_reg, void *v_rx)
 {
-	struct pvt_rx_reg *rx_reg = v_reg;
+	struct mesh_io_reg *rx_reg = v_reg;
 	struct process_data *rx = v_rx;
 
 	if (!memcmp(rx->data, rx_reg->filter, rx_reg->len))
 		rx_reg->cb(rx_reg->user_data, &rx->info, rx->data, rx->len);
 }
 
-static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
+static void process_rx(uint16_t index, struct mesh_io_private *pvt, int8_t rssi,
 					uint32_t instant, const uint8_t *addr,
 					const uint8_t *data, uint8_t len)
 {
@@ -191,21 +211,25 @@ static void process_rx(struct mesh_io_private *pvt, int8_t rssi,
 		.info.rssi = rssi,
 	};
 
+	/* Accept all traffic except beacons from any controller */
+	if (index != pvt->send_idx && data[0] == MESH_AD_TYPE_BEACON)
+		return;
+
 	print_packet("RX", data, len);
-	l_queue_foreach(pvt->rx_regs, process_rx_callbacks, &rx);
+	l_queue_foreach(pvt->io->rx_regs, process_rx_callbacks, &rx);
 }
 
 static void send_cmplt(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
-	print_packet("Mesh Send Complete", param, length);
+	/* print_packet("Mesh Send Complete", param, length); */
 }
 
 static void event_device_found(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
 	const struct mgmt_ev_mesh_device_found *ev = param;
-	struct mesh_io *io = user_data;
+	struct mesh_io_private *pvt = user_data;
 	const uint8_t *adv;
 	const uint8_t *addr;
 	uint32_t instant;
@@ -236,9 +260,10 @@ static void event_device_found(uint16_t index, uint16_t length,
 		if (len > adv_len)
 			break;
 
-		if (adv[1] >= 0x29 && adv[1] <= 0x2B)
-			process_rx(io->pvt, ev->rssi, instant, addr, adv + 1,
-								adv[0]);
+		if (adv[1] >= MESH_AD_TYPE_PROVISION &&
+					adv[1] <= MESH_AD_TYPE_BEACON)
+			process_rx(index, pvt, ev->rssi, instant, addr,
+							adv + 1, adv[0]);
 
 		adv += field_len + 1;
 	}
@@ -270,7 +295,7 @@ static bool find_by_pattern(const void *a, const void *b)
 
 static bool find_active(const void *a, const void *b)
 {
-	const struct pvt_rx_reg *rx_reg = a;
+	const struct mesh_io_reg *rx_reg = a;
 
 	/* Mesh specific AD types do *not* require active scanning,
 	 * so do not turn on Active Scanning on their account.
@@ -320,6 +345,12 @@ static void ctl_up(uint8_t status, uint16_t length,
 	mesh->num_ad_types = sizeof(mesh_ad_types);
 	memcpy(mesh->ad_types, mesh_ad_types, sizeof(mesh_ad_types));
 
+	pvt->rx_id = mesh_mgmt_register(MGMT_EV_MESH_DEVICE_FOUND,
+				MGMT_INDEX_NONE, event_device_found, pvt,
+				NULL);
+	pvt->tx_id = mesh_mgmt_register(MGMT_EV_MESH_PACKET_CMPLT,
+					index, send_cmplt, pvt, NULL);
+
 	mesh_mgmt_send(MGMT_OP_SET_MESH_RECEIVER, index, len, mesh,
 			mesh_up, L_UINT_TO_PTR(index), NULL);
 	l_debug("done %d mesh startup", index);
@@ -407,13 +438,7 @@ static bool dev_init(struct mesh_io *io, void *opts, void *user_data)
 	mesh_mgmt_send(MGMT_OP_READ_INFO, index, 0, NULL,
 				read_info_cb, L_UINT_TO_PTR(index), NULL);
 
-	pvt->rx_id = mesh_mgmt_register(MGMT_EV_MESH_DEVICE_FOUND,
-				MGMT_INDEX_NONE, event_device_found, io, NULL);
-	pvt->tx_id = mesh_mgmt_register(MGMT_EV_MESH_PACKET_CMPLT,
-					MGMT_INDEX_NONE, send_cmplt, io, NULL);
-
 	pvt->dup_filters = l_queue_new();
-	pvt->rx_regs = l_queue_new();
 	pvt->tx_pkts = l_queue_new();
 
 	pvt->io = io;
@@ -422,14 +447,6 @@ static bool dev_init(struct mesh_io *io, void *opts, void *user_data)
 	return true;
 }
 
-static void free_rx_reg(void *user_data)
-{
-	struct pvt_rx_reg *rx_reg = user_data;
-
-	l_free(rx_reg);
-}
-
-
 static bool dev_destroy(struct mesh_io *io)
 {
 	unsigned char param[] = { 0x00 };
@@ -443,8 +460,8 @@ static bool dev_destroy(struct mesh_io *io)
 	mesh_mgmt_unregister(pvt->rx_id);
 	mesh_mgmt_unregister(pvt->tx_id);
 	l_timeout_remove(pvt->tx_timeout);
+	l_timeout_remove(pvt->dup_timeout);
 	l_queue_destroy(pvt->dup_filters, l_free);
-	l_queue_destroy(pvt->rx_regs, free_rx_reg);
 	l_queue_destroy(pvt->tx_pkts, l_free);
 	io->pvt = NULL;
 	l_free(pvt);
@@ -475,7 +492,7 @@ static void send_cancel(struct mesh_io_private *pvt)
 
 	if (pvt->handle) {
 		remove.handle = pvt->handle;
-		l_debug("Cancel TX");
+		/* l_debug("Cancel TX"); */
 		mesh_mgmt_send(MGMT_OP_MESH_SEND_CANCEL, pvt->send_idx,
 						sizeof(remove), &remove,
 						NULL, NULL, NULL);
@@ -522,9 +539,14 @@ static void send_pkt(struct mesh_io_private *pvt, struct tx_pkt *tx,
 	send->adv_data_len = tx->len + 1;
 	send->adv_data[0] = tx->len;
 	memcpy(send->adv_data + 1, tx->pkt, tx->len);
+
+	/* Filter looped back Provision packets */
+	if (tx->pkt[0] == MESH_AD_TYPE_PROVISION)
+		filter_dups(NULL, send->adv_data, get_instant());
+
 	mesh_mgmt_send(MGMT_OP_MESH_SEND, index,
 			len, send, send_queued, tx, NULL);
-	print_packet("Mesh Send Start", tx->pkt, tx->len);
+	/* print_packet("Mesh Send Start", tx->pkt, tx->len); */
 	pvt->tx = tx;
 }
 
@@ -711,37 +733,16 @@ static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
 	return true;
 }
 
-static bool find_by_filter(const void *a, const void *b)
-{
-	const struct pvt_rx_reg *rx_reg = a;
-	const uint8_t *filter = b;
-
-	return !memcmp(rx_reg->filter, filter, rx_reg->len);
-}
-
 static bool recv_register(struct mesh_io *io, const uint8_t *filter,
 			uint8_t len, mesh_io_recv_func_t cb, void *user_data)
 {
-	struct pvt_rx_reg *rx_reg;
 	bool active = false;
 
-	if (!cb || !filter || !len || io->pvt != pvt)
+	if (io->pvt != pvt)
 		return false;
 
-	rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
-
-	free_rx_reg(rx_reg);
-	rx_reg = l_malloc(sizeof(*rx_reg) + len);
-
-	memcpy(rx_reg->filter, filter, len);
-	rx_reg->len = len;
-	rx_reg->cb = cb;
-	rx_reg->user_data = user_data;
-
-	l_queue_push_head(pvt->rx_regs, rx_reg);
-
 	/* Look for any AD types requiring Active Scanning */
-	if (l_queue_find(pvt->rx_regs, find_active, NULL))
+	if (l_queue_find(io->rx_regs, find_active, NULL))
 		active = true;
 
 	if (pvt->active != active) {
@@ -755,18 +756,13 @@ static bool recv_register(struct mesh_io *io, const uint8_t *filter,
 static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
 								uint8_t len)
 {
-	struct pvt_rx_reg *rx_reg;
 	bool active = false;
 
 	if (io->pvt != pvt)
 		return false;
 
-	rx_reg = l_queue_remove_if(pvt->rx_regs, find_by_filter, filter);
-
-	free_rx_reg(rx_reg);
-
 	/* Look for any AD types requiring Active Scanning */
-	if (l_queue_find(pvt->rx_regs, find_active, NULL))
+	if (l_queue_find(io->rx_regs, find_active, NULL))
 		active = true;
 
 	if (active != pvt->active) {
diff --git a/mesh/mesh-io-unit.c b/mesh/mesh-io-unit.c
index f4f6198..a9fa533 100644
--- a/mesh/mesh-io-unit.c
+++ b/mesh/mesh-io-unit.c
@@ -485,39 +485,9 @@ static bool tx_cancel(struct mesh_io *io, const uint8_t *data, uint8_t len)
 	return true;
 }
 
-static bool find_by_filter(const void *a, const void *b)
-{
-	const struct pvt_rx_reg *rx_reg_old = a;
-	const struct pvt_rx_reg *rx_reg = b;
-
-	if (rx_reg_old->len != rx_reg->len)
-		return false;
-
-	return !memcmp(rx_reg_old->filter, rx_reg->filter, rx_reg->len);
-}
-
 static bool recv_register(struct mesh_io *io, const uint8_t *filter,
 			uint8_t len, mesh_io_recv_func_t cb, void *user_data)
 {
-	struct mesh_io_private *pvt = io->pvt;
-	struct pvt_rx_reg *rx_reg, *rx_reg_old;
-
-	if (!cb || !filter || !len)
-		return false;
-
-	rx_reg = l_malloc(sizeof(*rx_reg) + len);
-
-	memcpy(rx_reg->filter, filter, len);
-	rx_reg->len = len;
-	rx_reg->cb = cb;
-	rx_reg->user_data = user_data;
-
-	rx_reg_old = l_queue_remove_if(pvt->rx_regs, find_by_filter, rx_reg);
-
-	l_free(rx_reg_old);
-
-	l_queue_push_head(pvt->rx_regs, rx_reg);
-
 	return true;
 }
 
diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
index 233f4b3..b953bf4 100644
--- a/mesh/mesh-io.c
+++ b/mesh/mesh-io.c
@@ -28,12 +28,10 @@
 #include "mesh/mesh-io-generic.h"
 #include "mesh/mesh-io-unit.h"
 
-struct mesh_io_reg {
-	mesh_io_recv_func_t cb;
-	void *user_data;
-	uint8_t len;
-	uint8_t filter[];
-} packed;
+struct loop_data {
+	uint16_t len;
+	uint8_t data[];
+};
 
 /* List of Supported Mesh-IO Types */
 static const struct mesh_io_table table[] = {
@@ -42,7 +40,10 @@ static const struct mesh_io_table table[] = {
 	{MESH_IO_TYPE_UNIT_TEST, &mesh_io_unit},
 };
 
+static const uint8_t unprv_filter[] = { MESH_AD_TYPE_BEACON, 0 };
+
 static struct mesh_io *default_io;
+static struct l_timeout *loop_adv_to;
 
 static const struct mesh_io_api *io_api(enum mesh_io_type type)
 {
@@ -71,12 +72,20 @@ static void ctl_alert(int index, bool up, bool pwr, bool mesh, void *user_data)
 	enum mesh_io_type type = L_PTR_TO_UINT(user_data);
 	const struct mesh_io_api *api = NULL;
 
-	l_warn("up:%d pwr: %d mesh: %d", up, pwr, mesh);
+	l_warn("index %u up:%d pwr: %d mesh: %d", index, up, pwr, mesh);
 
 	/* If specific IO controller requested, honor it */
-	if (default_io->favored_index != MGMT_INDEX_NONE &&
-					default_io->favored_index != index)
-		return;
+	if (default_io->favored_index != MGMT_INDEX_NONE) {
+		if (default_io->favored_index != index)
+			return;
+
+		if (!up | pwr) {
+			l_warn("HCI%u failed to start generic IO %s",
+				index, pwr ? ": already powered on" : "");
+			if (default_io->ready)
+				default_io->ready(default_io->user_data, false);
+		}
+	}
 
 	if (!up && default_io->index == index) {
 		/* Our controller has disappeared */
@@ -96,7 +105,6 @@ static void ctl_alert(int index, bool up, bool pwr, bool mesh, void *user_data)
 
 	if (mesh && type != MESH_IO_TYPE_GENERIC)
 		api = io_api(MESH_IO_TYPE_MGMT);
-
 	else if (!pwr)
 		api = io_api(MESH_IO_TYPE_GENERIC);
 
@@ -104,7 +112,6 @@ static void ctl_alert(int index, bool up, bool pwr, bool mesh, void *user_data)
 		default_io->index = index;
 		default_io->api = api;
 		api->init(default_io, &index, default_io->user_data);
-
 		l_queue_foreach(default_io->rx_regs, refresh_rx, default_io);
 	}
 }
@@ -122,6 +129,23 @@ static void free_io(struct mesh_io *io)
 	}
 }
 
+static struct mesh_io_reg *find_by_filter(struct l_queue *rx_regs,
+					const uint8_t *filter, uint8_t len)
+{
+	const struct l_queue_entry *entry;
+
+	entry = l_queue_get_entries(rx_regs);
+
+	for (; entry; entry = entry->next) {
+		struct mesh_io_reg *rx_reg = entry->data;
+
+		if (rx_reg->len == len && !memcmp(rx_reg->filter, filter, len))
+			return rx_reg;
+	}
+
+	return NULL;
+}
+
 struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
 				mesh_io_ready_func_t cb, void *user_data)
 {
@@ -183,14 +207,23 @@ bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
 {
 	struct mesh_io_reg *rx_reg;
 
-	if (io != default_io)
+	if (io == NULL)
+		io = default_io;
+
+	if (io != default_io || !cb || !filter || !len)
 		return false;
 
+	rx_reg = find_by_filter(io->rx_regs, filter, len);
+
+	l_free(rx_reg);
+	l_queue_remove(io->rx_regs, rx_reg);
+
 	rx_reg = l_malloc(sizeof(struct mesh_io_reg) + len);
 	rx_reg->cb = cb;
 	rx_reg->len = len;
 	rx_reg->user_data = user_data;
 	memcpy(rx_reg->filter, filter, len);
+
 	l_queue_push_head(io->rx_regs, rx_reg);
 
 	if (io && io->api && io->api->reg)
@@ -199,14 +232,6 @@ bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
 	return false;
 }
 
-static bool by_filter(const void *a, const void *b)
-{
-	const struct mesh_io_reg *rx_reg = a;
-	const uint8_t *filter = b;
-
-	return rx_reg->filter[0] == filter[0];
-}
-
 bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
 								uint8_t len)
 {
@@ -215,7 +240,9 @@ bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
 	if (io != default_io)
 		return false;
 
-	rx_reg = l_queue_remove_if(io->rx_regs, by_filter, filter);
+	rx_reg = find_by_filter(io->rx_regs,  filter, len);
+
+	l_queue_remove(io->rx_regs, rx_reg);
 	l_free(rx_reg);
 
 	if (io && io->api && io->api->dereg)
@@ -224,6 +251,38 @@ bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
 	return false;
 }
 
+static void loop_foreach(void *data, void *user_data)
+{
+	struct mesh_io_reg *rx_reg = data;
+	struct loop_data *rx = user_data;
+
+	if (!memcmp(rx_reg->filter, unprv_filter, sizeof(unprv_filter)))
+		rx_reg->cb(rx_reg->user_data, NULL, rx->data, rx->len);
+}
+
+static void loop_rx(struct l_timeout *timeout, void *user_data)
+{
+	struct loop_data *rx = user_data;
+
+	l_queue_foreach(default_io->rx_regs, loop_foreach, rx);
+	l_timeout_modify_ms(loop_adv_to, 500);
+}
+
+static void loop_destroy(void *user_data)
+{
+	l_free(user_data);
+}
+
+static void loop_unprv_beacon(const uint8_t *data, uint16_t len)
+{
+	struct loop_data *pkt = l_malloc(len + sizeof(struct loop_data));
+
+	memcpy(pkt->data, data, len);
+	pkt->len = len;
+	l_timeout_remove(loop_adv_to);
+	loop_adv_to = l_timeout_create_ms(500, loop_rx, pkt, loop_destroy);
+}
+
 bool mesh_io_send(struct mesh_io *io, struct mesh_io_send_info *info,
 					const uint8_t *data, uint16_t len)
 {
@@ -233,6 +292,10 @@ bool mesh_io_send(struct mesh_io *io, struct mesh_io_send_info *info,
 	if (!io)
 		io = default_io;
 
+	/* Loop unprovisioned beacons for local clients */
+	if (!memcmp(data, unprv_filter, sizeof(unprv_filter)))
+		loop_unprv_beacon(data, len);
+
 	if (io && io->api && io->api->send)
 		return io->api->send(io, info, data, len);
 
@@ -248,6 +311,11 @@ bool mesh_io_send_cancel(struct mesh_io *io, const uint8_t *pattern,
 	if (!io)
 		io = default_io;
 
+	if (loop_adv_to && len >= 2 && !memcmp(pattern, unprv_filter, 2)) {
+		l_timeout_remove(loop_adv_to);
+		loop_adv_to = NULL;
+	}
+
 	if (io && io->api && io->api->cancel)
 		return io->api->cancel(io, pattern, len);
 
diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
index 9dd946c..f7711e7 100644
--- a/mesh/mesh-io.h
+++ b/mesh/mesh-io.h
@@ -8,8 +8,6 @@
  *
  */
 
-struct mesh_io;
-
 #define MESH_IO_TX_COUNT_UNLIMITED	0
 
 enum mesh_io_type {
diff --git a/mesh/mesh-mgmt.c b/mesh/mesh-mgmt.c
index d37aeb5..fd21a16 100644
--- a/mesh/mesh-mgmt.c
+++ b/mesh/mesh-mgmt.c
@@ -271,3 +271,8 @@ bool mesh_mgmt_unregister(unsigned int id)
 {
 	return mgmt_unregister(mgmt_mesh, id);
 }
+
+void mesh_mgmt_clear(void)
+{
+	l_queue_clear(ctl_list, l_free);
+}
diff --git a/mesh/mesh-mgmt.h b/mesh/mesh-mgmt.h
index a3cd72f..5702822 100644
--- a/mesh/mesh-mgmt.h
+++ b/mesh/mesh-mgmt.h
@@ -22,3 +22,4 @@ unsigned int mesh_mgmt_register(uint16_t event, uint16_t index,
 				void *user_data, mgmt_destroy_func_t destroy);
 bool mesh_mgmt_unregister(unsigned int id);
 void mesh_mgmt_destroy(void);
+void mesh_mgmt_clear(void);
diff --git a/mesh/model.c b/mesh/model.c
index d48e6ef..4ccafa1 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -24,6 +24,9 @@
 #include "mesh/net.h"
 #include "mesh/appkey.h"
 #include "mesh/cfgmod.h"
+#include "mesh/prov.h"
+#include "mesh/remprv.h"
+#include "mesh/prv-beacon.h"
 #include "mesh/error.h"
 #include "mesh/dbus.h"
 #include "mesh/util.h"
@@ -76,6 +79,12 @@ static bool is_internal(uint32_t id)
 	if (id == CONFIG_SRV_MODEL || id == CONFIG_CLI_MODEL)
 		return true;
 
+	if (id == REM_PROV_SRV_MODEL || id == REM_PROV_CLI_MODEL)
+		return true;
+
+	if (id == PRV_BEACON_SRV_MODEL || id == PRV_BEACON_CLI_MODEL)
+		return true;
+
 	return false;
 }
 
@@ -457,13 +466,25 @@ static int dev_packet_decrypt(struct mesh_node *node, const uint8_t *data,
 					dst, key_aid, seq, iv_idx, out, key))
 		return APP_IDX_DEV_LOCAL;
 
-	if (!keyring_get_remote_dev_key(node, src, dev_key))
+	key = dev_key;
+
+	if (keyring_get_remote_dev_key(node, src, dev_key)) {
+		if (mesh_crypto_payload_decrypt(NULL, 0, data, size, szmict,
+				src, dst, key_aid, seq, iv_idx, out, key))
+			return APP_IDX_DEV_REMOTE;
+	}
+
+	/* See if there is a local Device Key Candidate as last resort */
+	if (!node_get_device_key_candidate(node, dev_key))
 		return -1;
 
-	key = dev_key;
-	if (mesh_crypto_payload_decrypt(NULL, 0, data, size, szmict, src,
-					dst, key_aid, seq, iv_idx, out, key))
-		return APP_IDX_DEV_REMOTE;
+	if (mesh_crypto_payload_decrypt(NULL, 0, data, size, szmict,
+				src, dst, key_aid, seq, iv_idx, out, key)) {
+
+		/* If candidate dev_key worked, it is considered finalized */
+		node_finalize_candidate(node);
+		return APP_IDX_DEV_LOCAL;
+	}
 
 	return -1;
 }
@@ -630,6 +651,9 @@ static int update_binding(struct mesh_node *node, uint16_t addr, uint32_t id,
 	if (id == CONFIG_SRV_MODEL || id == CONFIG_CLI_MODEL)
 		return MESH_STATUS_INVALID_MODEL;
 
+	if (id == PRV_BEACON_SRV_MODEL || id == PRV_BEACON_CLI_MODEL)
+		return MESH_STATUS_INVALID_MODEL;
+
 	if (!appkey_have_key(node_get_net(node), app_idx))
 		return MESH_STATUS_INVALID_APPKEY;
 
@@ -1638,7 +1662,8 @@ static struct mesh_model *model_setup(struct mesh_net *net, uint8_t ele_idx,
 						SET_ID(SIG_VENDOR, db_mod->id));
 
 	/* Implicitly bind config server model to device key */
-	if (db_mod->id == CONFIG_SRV_MODEL) {
+	if (db_mod->id == CONFIG_SRV_MODEL ||
+					db_mod->id == PRV_BEACON_SRV_MODEL) {
 
 		if (ele_idx != PRIMARY_ELE_IDX) {
 			l_free(mod);
diff --git a/mesh/net-keys.c b/mesh/net-keys.c
index ee7bbf0..57a9df0 100644
--- a/mesh/net-keys.c
+++ b/mesh/net-keys.c
@@ -21,39 +21,55 @@
 #include "mesh/net.h"
 #include "mesh/net-keys.h"
 
-#define BEACON_TYPE_SNB		0x01
-#define KEY_REFRESH		0x01
-#define IV_INDEX_UPDATE		0x02
-
 #define BEACON_INTERVAL_MIN	10
 #define BEACON_INTERVAL_MAX	600
 
-struct net_beacon {
+/* This allows daemon to skip decryption on recently seen beacons */
+#define BEACON_CACHE_MAX	10
+
+struct beacon_rx {
+	uint8_t data[28];
+	uint32_t id;
+	uint32_t ivi;
+	bool kr;
+	bool ivu;
+};
+
+struct beacon_observe {
 	struct l_timeout *timeout;
 	uint32_t ts;
-	uint16_t observe_period;
-	uint16_t observed;
+	uint16_t period;
+	uint16_t seen;
 	uint16_t expected;
 	bool half_period;
-	uint8_t beacon[23];
 };
 
 struct net_key {
 	uint32_t id;
-	struct net_beacon snb;
+	struct l_timeout *mpb_to;
+	uint8_t *mpb;
+	uint8_t *snb;
+	struct beacon_observe observe;
+	uint32_t ivi;
 	uint16_t ref_cnt;
-	uint16_t beacon_enables;
+	uint16_t mpb_enables;
+	uint16_t snb_enables;
+	uint8_t mpb_refresh;
 	uint8_t friend_key;
 	uint8_t nid;
 	uint8_t flooding[16];
-	uint8_t encrypt[16];
-	uint8_t privacy[16];
-	uint8_t beacon[16];
-	uint8_t network[8];
+	uint8_t enc_key[16];
+	uint8_t prv_key[16];
+	uint8_t snb_key[16];
+	uint8_t pvt_key[16];
+	uint8_t net_id[8];
+	bool kr;
+	bool ivu;
 };
 
-static struct l_queue *keys = NULL;
-static uint32_t last_flooding_id = 0;
+static struct l_queue *beacons;
+static struct l_queue *keys;
+static uint32_t last_flooding_id;
 
 /* To avoid re-decrypting same packet for multiple nodes, cache and check */
 static uint8_t cache_pkt[29];
@@ -81,9 +97,9 @@ static bool match_id(const void *a, const void *b)
 static bool match_network(const void *a, const void *b)
 {
 	const struct net_key *key = a;
-	const uint8_t *network = b;
+	const uint8_t *net_id = b;
 
-	return memcmp(key->network, network, sizeof(key->network)) == 0;
+	return memcmp(key->net_id, net_id, sizeof(key->net_id)) == 0;
 }
 
 /* Key added from Provisioning, NetKey Add or NetKey update */
@@ -101,19 +117,27 @@ uint32_t net_key_add(const uint8_t flooding[16])
 	if (!keys)
 		keys = l_queue_new();
 
+	if (!beacons)
+		beacons = l_queue_new();
+
 	key = l_new(struct net_key, 1);
 	memcpy(key->flooding, flooding, 16);
 	key->ref_cnt++;
-	result = mesh_crypto_k2(flooding, p, sizeof(p), &key->nid, key->encrypt,
-								key->privacy);
+	key->mpb_refresh = NET_MPB_REFRESH_DEFAULT;
+	result = mesh_crypto_k2(flooding, p, sizeof(p), &key->nid, key->enc_key,
+								key->prv_key);
 	if (!result)
 		goto fail;
 
-	result = mesh_crypto_k3(flooding, key->network);
+	result = mesh_crypto_k3(flooding, key->net_id);
 	if (!result)
 		goto fail;
 
-	result = mesh_crypto_nkbk(flooding, key->beacon);
+	result = mesh_crypto_nkbk(flooding, key->snb_key);
+	if (!result)
+		goto fail;
+
+	result = mesh_crypto_nkpk(flooding, key->pvt_key);
 	if (!result)
 		goto fail;
 
@@ -146,7 +170,7 @@ uint32_t net_key_frnd_add(uint32_t flooding_id, uint16_t lpn, uint16_t frnd,
 	l_put_be16(fn_cnt, p + 7);
 
 	result = mesh_crypto_k2(key->flooding, p, sizeof(p), &frnd_key->nid,
-				frnd_key->encrypt, frnd_key->privacy);
+				frnd_key->enc_key, frnd_key->prv_key);
 
 	if (!result) {
 		l_free(frnd_key);
@@ -167,7 +191,7 @@ void net_key_unref(uint32_t id)
 
 	if (key && key->ref_cnt) {
 		if (--key->ref_cnt == 0) {
-			l_timeout_remove(key->snb.timeout);
+			l_timeout_remove(key->observe.timeout);
 			l_queue_remove(keys, key);
 			l_free(key);
 		}
@@ -206,7 +230,7 @@ static void decrypt_net_pkt(void *a, void *b)
 
 	result = mesh_crypto_packet_decode(cache_pkt, cache_len, false,
 						cache_plain, cache_iv_index,
-						key->encrypt, key->privacy);
+						key->enc_key, key->prv_key);
 
 	if (result) {
 		cache_id = key->id;
@@ -254,8 +278,8 @@ bool net_key_encrypt(uint32_t id, uint32_t iv_index, uint8_t *pkt, size_t len)
 	if (!key)
 		return false;
 
-	result = mesh_crypto_packet_encode(pkt, len, iv_index, key->encrypt,
-							key->privacy);
+	result = mesh_crypto_packet_encode(pkt, len, iv_index, key->enc_key,
+							key->prv_key);
 
 	if (!result)
 		return false;
@@ -265,9 +289,9 @@ bool net_key_encrypt(uint32_t id, uint32_t iv_index, uint8_t *pkt, size_t len)
 	return result;
 }
 
-uint32_t net_key_network_id(const uint8_t network[8])
+uint32_t net_key_network_id(const uint8_t net_id[8])
 {
-	struct net_key *key = l_queue_find(keys, match_network, network);
+	struct net_key *key = l_queue_find(keys, match_network, net_id);
 
 	if (!key)
 		return 0;
@@ -275,6 +299,55 @@ uint32_t net_key_network_id(const uint8_t network[8])
 	return key->id;
 }
 
+struct auth_check {
+	const uint8_t *data;
+	uint32_t id;
+	uint32_t ivi;
+	bool ivu;
+	bool kr;
+};
+
+static void check_auth(void *a, void *b)
+{
+	struct net_key *key = a;
+	struct auth_check *auth = b;
+	uint8_t out[5];
+
+
+	/* Stop checking if already found */
+	if (auth->id)
+		return;
+
+	if (mesh_crypto_aes_ccm_decrypt(auth->data + 1, key->pvt_key, NULL, 0,
+							auth->data + 14, 13,
+							out, NULL, 8)) {
+		auth->id = key->id;
+		auth->ivi = l_get_be32(out + 1);
+		auth->ivu = !!(out[0] & 0x02);
+		auth->kr = !!(out[0] & 0x01);
+	}
+}
+
+static uint32_t private_beacon_check(const void *beacon, uint32_t *ivi,
+							bool *ivu, bool *kr)
+{
+	struct auth_check auth = {
+		.data = beacon,
+		.id = 0,
+	};
+
+	auth.id = 0;
+	l_queue_foreach(keys, check_auth, &auth);
+
+	if (auth.id) {
+		*ivi = auth.ivi;
+		*ivu = auth.ivu;
+		*kr = auth.kr;
+	}
+
+	return auth.id;
+}
+
 bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
 								uint64_t cmac)
 {
@@ -285,7 +358,7 @@ bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
 		return false;
 
 	/* Any behavioral changes must pass CMAC test */
-	if (!mesh_crypto_beacon_cmac(key->beacon, key->network, iv_index, kr,
+	if (!mesh_crypto_beacon_cmac(key->snb_key, key->net_id, iv_index, kr,
 							ivu, &cmac_check)) {
 		l_error("mesh_crypto_beacon_cmac failed");
 		return false;
@@ -300,39 +373,142 @@ bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
 	return true;
 }
 
-bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
-								uint8_t *snb)
+static bool mpb_compose(struct net_key *key, uint32_t ivi, bool kr, bool ivu)
+{
+	uint8_t b_data[5 + 8];
+	uint8_t random[13];
+
+	if (!key)
+		return false;
+
+	b_data[0] = 0;
+	l_put_be32(ivi, b_data + 1);
+
+	if (kr)
+		b_data[0] |= KEY_REFRESH;
+
+	if (ivu)
+		b_data[0] |= IV_INDEX_UPDATE;
+
+	l_getrandom(random, sizeof(random));
+	if (!mesh_crypto_aes_ccm_encrypt(random, key->pvt_key, NULL, 0,
+						b_data, 5, b_data, NULL, 8))
+		return false;
+
+	key->mpb[0] = MESH_AD_TYPE_BEACON;
+	key->mpb[1] = BEACON_TYPE_MPB;
+	memcpy(key->mpb + 2, random, 13);
+	memcpy(key->mpb + 15, b_data, 13);
+
+	return true;
+}
+
+static bool snb_compose(struct net_key *key, uint32_t ivi, bool kr, bool ivu)
 {
-	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
 	uint64_t cmac;
 
 	if (!key)
 		return false;
 
 	/* Any behavioral changes must pass CMAC test */
-	if (!mesh_crypto_beacon_cmac(key->beacon, key->network, iv_index, kr,
+	if (!mesh_crypto_beacon_cmac(key->snb_key, key->net_id, ivi, kr,
 								ivu, &cmac)) {
 		l_error("mesh_crypto_beacon_cmac failed");
 		return false;
 	}
 
-	snb[0] = MESH_AD_TYPE_BEACON;
-	snb[1] = BEACON_TYPE_SNB;
-	snb[2] = 0;
+	key->snb[0] = MESH_AD_TYPE_BEACON;
+	key->snb[1] = BEACON_TYPE_SNB;
+	key->snb[2] = 0;
 
 	if (kr)
-		snb[2] |= KEY_REFRESH;
+		key->snb[2] |= KEY_REFRESH;
 
 	if (ivu)
-		snb[2] |= IV_INDEX_UPDATE;
+		key->snb[2] |= IV_INDEX_UPDATE;
 
-	memcpy(snb + 3, key->network, 8);
-	l_put_be32(iv_index, snb + 11);
-	l_put_be64(cmac, snb + 15);
+	memcpy(key->snb + 3, key->net_id, 8);
+	l_put_be32(ivi, key->snb + 11);
+	l_put_be64(cmac, key->snb + 15);
 
 	return true;
 }
 
+static bool match_beacon(const void *a, const void *b)
+{
+	const struct beacon_rx *cached = a;
+	const uint8_t *incoming = b;
+
+	if (incoming[0] == BEACON_TYPE_MPB)
+		return !memcmp(cached->data, incoming, 27);
+
+	if (incoming[0] == BEACON_TYPE_SNB)
+		return !memcmp(cached->data, incoming, 22);
+
+	return false;
+}
+
+uint32_t net_key_beacon(const uint8_t *data, uint16_t len, uint32_t *ivi,
+							bool *ivu, bool *kr)
+{
+	struct net_key *key;
+	struct beacon_rx *beacon;
+	uint32_t b_id, b_ivi;
+	bool b_ivu, b_kr;
+
+	if (data[1] == BEACON_TYPE_SNB && len != 23)
+		return 0;
+
+	if (data[1] == BEACON_TYPE_MPB && len != 28)
+		return 0;
+
+	beacon = l_queue_remove_if(beacons, match_beacon, data + 1);
+
+	if (beacon)
+		goto accept;
+
+	/* Validate beacon data */
+	if (data[1] == BEACON_TYPE_SNB) {
+		key = l_queue_find(keys, match_network, data + 3);
+
+		if (!key)
+			return 0;
+
+		b_id = key->id;
+		b_ivu = !!(data[2] & 0x02);
+		b_kr = !!(data[2] & 0x01);
+		b_ivi = l_get_be32(data + 11);
+
+		if (!net_key_snb_check(b_id, b_ivi, b_kr, b_ivu,
+							l_get_be64(data + 15)))
+			return 0;
+
+	} else if (data[1] == BEACON_TYPE_MPB) {
+		b_id = private_beacon_check(data + 1, &b_ivi, &b_ivu, &b_kr);
+
+		if (!b_id)
+			return 0;
+
+	} else
+		return 0;
+
+	beacon = l_new(struct beacon_rx, 1);
+	memcpy(beacon->data, data + 1, len - 1);
+	beacon->id = b_id;
+	beacon->ivi = b_ivi;
+	beacon->ivu = b_ivu;
+	beacon->kr = b_kr;
+
+accept:
+	*ivi = beacon->ivi;
+	*ivu = beacon->ivu;
+	*kr = beacon->kr;
+
+	l_queue_push_head(beacons, beacon);
+
+	return beacon->id;
+}
+
 static void send_network_beacon(struct net_key *key)
 {
 	struct mesh_io_send_info info = {
@@ -343,10 +519,26 @@ static void send_network_beacon(struct net_key *key)
 		.u.gen.max_delay = DEFAULT_MAX_DELAY
 	};
 
-	mesh_io_send(NULL, &info, key->snb.beacon, sizeof(key->snb.beacon));
+	if (key->mpb_enables) {
+		/* If Interval steps == 0, refresh key every time */
+		if (!key->mpb_refresh || !key->mpb || !key->mpb[0])
+			net_key_beacon_refresh(key->id, key->ivi, key->kr,
+								key->ivu, true);
+
+		mesh_io_send(NULL, &info, key->mpb, 28);
+	}
+
+	if (key->snb_enables) {
+		if (!key->snb || !key->snb[0]) {
+			net_key_beacon_refresh(key->id, key->ivi, key->kr,
+								key->ivu, true);
+		}
+
+		mesh_io_send(NULL, &info, key->snb, 23);
+	}
 }
 
-static void snb_timeout(struct l_timeout *timeout, void *user_data)
+static void beacon_timeout(struct l_timeout *timeout, void *user_data)
 {
 	struct net_key *key = user_data;
 	uint32_t interval, scale_factor;
@@ -355,29 +547,29 @@ static void snb_timeout(struct l_timeout *timeout, void *user_data)
 	send_network_beacon(key);
 
 	/* Count our own beacons towards the vicinity total */
-	key->snb.observed++;
+	key->observe.seen++;
 
-	if (!key->snb.half_period) {
+	if (!key->observe.half_period) {
 
 		l_debug("beacon %d for %d nodes, period %d, obs %d, exp %d",
-						key->id,
-						key->beacon_enables,
-						key->snb.observe_period,
-						key->snb.observed,
-						key->snb.expected);
+					key->id,
+					key->snb_enables + key->mpb_enables,
+					key->observe.period,
+					key->observe.seen,
+					key->observe.expected);
 
 
-		interval = (key->snb.observe_period * key->snb.observed)
-							/ key->snb.expected;
+		interval = (key->observe.period * key->observe.seen)
+							/ key->observe.expected;
 
 		/* Limit Increases and Decreases by 10 seconds Up and
 		 * 20 seconds down each step, to avoid going nearly silent
 		 * in highly populated environments.
 		 */
-		if (interval - 10 > key->snb.observe_period)
-			interval = key->snb.observe_period + 10;
-		else if (interval + 20 < key->snb.observe_period)
-			interval = key->snb.observe_period - 20;
+		if (interval - 10 > key->observe.period)
+			interval = key->observe.period + 10;
+		else if (interval + 20 < key->observe.period)
+			interval = key->observe.period - 20;
 
 		/* Beaconing must be no *slower* than once every 10 minutes,
 		 * and no *faster* than once every 10 seconds, per spec.
@@ -388,26 +580,26 @@ static void snb_timeout(struct l_timeout *timeout, void *user_data)
 		else if (interval > BEACON_INTERVAL_MAX * 2)
 			interval = BEACON_INTERVAL_MAX * 2;
 
-		key->snb.observe_period = interval;
-		key->snb.observed = 0;
+		key->observe.period = interval;
+		key->observe.seen = 0;
 
 		/* To prevent "over slowing" of the beaconing frequency,
 		 * require more significant "over observing" the slower
 		 * our own beaconing frequency.
 		 */
-		key->snb.expected = interval / 10;
+		key->observe.expected = interval / 10;
 		scale_factor = interval / 60;
-		key->snb.expected += scale_factor * 3;
+		key->observe.expected += scale_factor * 3;
 	}
 
-	interval = key->snb.observe_period / 2;
-	key->snb.half_period = !key->snb.half_period;
+	interval = key->observe.period / 2;
+	key->observe.half_period = !key->observe.half_period;
 
-	if (key->beacon_enables)
+	if (key->mpb_enables || key->snb_enables)
 		l_timeout_modify(timeout, interval);
 	else {
 		l_timeout_remove(timeout);
-		key->snb.timeout = NULL;
+		key->observe.timeout = NULL;
 	}
 }
 
@@ -416,8 +608,8 @@ void net_key_beacon_seen(uint32_t id)
 	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
 
 	if (key) {
-		key->snb.observed++;
-		key->snb.ts = get_timestamp_secs();
+		key->observe.seen++;
+		key->observe.ts = get_timestamp_secs();
 	}
 }
 
@@ -426,12 +618,87 @@ uint32_t net_key_beacon_last_seen(uint32_t id)
 	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
 
 	if (key)
-		return key->snb.ts;
+		return key->observe.ts;
 
 	return 0;
 }
 
-void net_key_beacon_enable(uint32_t id)
+bool net_key_beacon_refresh(uint32_t id, uint32_t ivi, bool kr, bool ivu,
+								bool force)
+{
+	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+	bool refresh = force;
+	uint32_t rand_ms;
+
+	if (!key)
+		return false;
+
+	if (key->snb_enables && !key->snb) {
+		key->snb = l_new(uint8_t, 23);
+		refresh = true;
+	}
+
+	if (key->mpb_enables && !key->mpb) {
+		key->mpb = l_new(uint8_t, 28);
+		refresh = true;
+	}
+
+	if (key->ivi != ivi || key->ivu != ivu || key->kr != kr)
+		refresh = true;
+
+	if (!refresh)
+		return true;
+
+	if (key->mpb) {
+		if (!mpb_compose(key, ivi, kr, ivu))
+			return false;
+
+		print_packet("Set MPB to", key->mpb, 28);
+	}
+
+	if (key->snb) {
+		if (!snb_compose(key, ivi, kr, ivu))
+			return false;
+
+		print_packet("Set SNB to", key->snb, 23);
+	}
+
+	l_debug("Set Beacon: IVI: %8.8x, IVU: %d, KR: %d", ivi, ivu, kr);
+
+	key->ivi = ivi;
+	key->ivu = ivu;
+	key->kr = kr;
+
+	/* Propagate changes to all local nodes */
+	net_local_beacon(id, ivi, ivu, kr);
+
+	/* Send one new SNB soon, after all nodes have seen it */
+	l_getrandom(&rand_ms, sizeof(rand_ms));
+	rand_ms %= 1000;
+	key->observe.expected++;
+
+	if (key->observe.timeout)
+		l_timeout_modify_ms(key->observe.timeout, 500 + rand_ms);
+	else
+		key->observe.timeout = l_timeout_create_ms(500 + rand_ms,
+						beacon_timeout, key, NULL);
+
+	return true;
+}
+
+static void mpb_timeout(struct l_timeout *timeout, void *user_data)
+{
+	struct net_key *key = user_data;
+
+	if (key->mpb_refresh) {
+		l_debug("Refresh in %d seconds", key->mpb_refresh * 10);
+		l_timeout_modify(timeout, key->mpb_refresh * 10);
+	}
+
+	net_key_beacon_refresh(key->id, key->ivi, key->kr, key->ivu, true);
+}
+
+void net_key_beacon_enable(uint32_t id, bool mpb, uint8_t refresh_count)
 {
 	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
 	bool enabled;
@@ -440,8 +707,19 @@ void net_key_beacon_enable(uint32_t id)
 	if (!key)
 		return;
 
-	enabled = !!key->beacon_enables;
-	key->beacon_enables++;
+	enabled = !!key->snb_enables || !!key->mpb_enables;
+
+	if (mpb) {
+		key->mpb_enables++;
+		key->mpb_refresh = refresh_count;
+		l_timeout_remove(key->mpb_to);
+		if (refresh_count)
+			key->mpb_to = l_timeout_create(refresh_count * 10,
+						mpb_timeout, key, NULL);
+		else
+			key->mpb_to = NULL;
+	} else
+		key->snb_enables++;
 
 	/* If already Enabled, do nothing */
 	if (enabled)
@@ -453,70 +731,68 @@ void net_key_beacon_enable(uint32_t id)
 	rand_ms++;
 
 	/* Enable Periodic Beaconing on this key */
-	key->snb.observe_period = BEACON_INTERVAL_MIN * 2;
-	key->snb.expected = 2;
-	key->snb.observed = 0;
-	key->snb.half_period = true;
-	l_timeout_remove(key->snb.timeout);
-	key->snb.timeout = l_timeout_create_ms(rand_ms, snb_timeout, key, NULL);
+	key->observe.period = BEACON_INTERVAL_MIN * 2;
+	key->observe.expected = 2;
+	key->observe.seen = 0;
+	key->observe.half_period = true;
+	l_timeout_remove(key->observe.timeout);
+	key->observe.timeout = l_timeout_create_ms(rand_ms, beacon_timeout,
+								key, NULL);
 }
 
-bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu)
+void net_key_beacon_disable(uint32_t id, bool mpb)
 {
 	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
-	uint8_t beacon[23];
-	uint32_t rand_ms;
 
 	if (!key)
-		return false;
+		return;
 
-	if (!net_key_snb_compose(id, iv_index, kr, ivu, beacon))
-		return false;
+	if (mpb) {
+		if (!key->mpb_enables)
+			return;
 
-	if (memcmp(key->snb.beacon, beacon, sizeof(beacon)))
-		memcpy(key->snb.beacon, beacon, sizeof(beacon));
-	else
-		return false;
+		key->mpb_enables--;
 
-	l_debug("Setting SNB: IVI: %8.8x, IVU: %d, KR: %d", iv_index, ivu, kr);
-	print_packet("Set SNB Beacon to", beacon, sizeof(beacon));
+		if (!key->mpb_enables) {
+			l_free(key->mpb);
+			key->mpb = NULL;
+			l_timeout_remove(key->mpb_to);
+			key->mpb_to = NULL;
+		}
+	} else {
+		if (!key->snb_enables)
+			return;
 
-	/* Propagate changes to all local nodes */
-	net_local_beacon(id, beacon);
+		key->snb_enables--;
 
-	/* Send one new SNB soon, after all nodes have seen it */
-	l_getrandom(&rand_ms, sizeof(rand_ms));
-	rand_ms %= 1000;
-	key->snb.expected++;
+		if (!key->snb_enables) {
+			l_free(key->snb);
+			key->snb = NULL;
+		}
+	}
 
-	if (key->snb.timeout)
-		l_timeout_modify_ms(key->snb.timeout, 500 + rand_ms);
-	else
-		key->snb.timeout = l_timeout_create_ms(500 + rand_ms,
-						snb_timeout, key, NULL);
+	if (key->snb_enables || key->mpb_enables)
+		return;
 
-	return true;
+	/* Disable periodic Beaconing on this key */
+	l_timeout_remove(key->observe.timeout);
+	key->observe.timeout = NULL;
 }
 
-void net_key_beacon_disable(uint32_t id)
+static void free_key(void *data)
 {
-	struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
-
-	if (!key || !key->beacon_enables)
-		return;
-
-	key->beacon_enables--;
+	struct net_key *key = data;
 
-	if (key->beacon_enables)
-		return;
-
-	/* Disable periodic Beaconing on this key */
-	l_timeout_remove(key->snb.timeout);
-	key->snb.timeout = NULL;
+	l_timeout_remove(key->mpb_to);
+	l_free(key->snb);
+	l_free(key->mpb);
+	l_free(key);
 }
 
 void net_key_cleanup(void)
 {
-	l_queue_destroy(keys, l_free);
+	l_queue_destroy(keys, free_key);
 	keys = NULL;
+	l_queue_destroy(beacons, l_free);
+	beacons = NULL;
 }
diff --git a/mesh/net-keys.h b/mesh/net-keys.h
index 420618f..e738124 100644
--- a/mesh/net-keys.h
+++ b/mesh/net-keys.h
@@ -9,8 +9,10 @@
  */
 
 #define BEACON_TYPE_SNB		0x01
+#define BEACON_TYPE_MPB		0x02
 #define KEY_REFRESH		0x01
 #define IV_INDEX_UPDATE		0x02
+#define NET_MPB_REFRESH_DEFAULT	60
 
 void net_key_cleanup(void);
 bool net_key_confirm(uint32_t id, const uint8_t flooding[16]);
@@ -23,12 +25,15 @@ uint32_t net_key_decrypt(uint32_t iv_index, const uint8_t *pkt, size_t len,
 					uint8_t **plain, size_t *plain_len);
 bool net_key_encrypt(uint32_t id, uint32_t iv_index, uint8_t *pkt, size_t len);
 uint32_t net_key_network_id(const uint8_t network[8]);
+uint32_t net_key_beacon(const uint8_t *data, uint16_t len, uint32_t *ivi,
+							bool *ivu, bool *kr);
 bool net_key_snb_check(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
 								uint64_t cmac);
 bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
 								uint8_t *snb);
 void net_key_beacon_seen(uint32_t id);
-void net_key_beacon_enable(uint32_t id);
-bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu);
-void net_key_beacon_disable(uint32_t id);
+bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
+								bool force);
+void net_key_beacon_enable(uint32_t id, bool mpb, uint8_t refresh_count);
+void net_key_beacon_disable(uint32_t id, bool mpb);
 uint32_t net_key_beacon_last_seen(uint32_t id);
diff --git a/mesh/net.c b/mesh/net.c
index 1d27289..05ca483 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -102,7 +102,8 @@ struct mesh_net {
 	unsigned int sar_id_next;
 
 	bool friend_enable;
-	bool beacon_enable;
+	bool snb_enable;
+	bool mpb_enable;
 	bool proxy_enable;
 	bool friend_seq;
 	struct l_timeout *iv_update_timeout;
@@ -119,6 +120,7 @@ struct mesh_net {
 	uint8_t chan; /* Channel of recent Rx */
 	uint8_t default_ttl;
 	uint8_t tid;
+	uint8_t mpb_period;
 
 	struct {
 		bool enable;
@@ -217,6 +219,7 @@ struct net_beacon_data {
 	bool ivu;
 	bool kr;
 	bool processed;
+	bool local;
 };
 
 static struct l_queue *fast_cache;
@@ -526,6 +529,13 @@ static void mesh_sar_free(void *data)
 static void subnet_free(void *data)
 {
 	struct mesh_subnet *subnet = data;
+	struct mesh_net *net = subnet->net;
+
+	if (net->snb_enable)
+		net_key_beacon_disable(subnet->net_key_tx, false);
+
+	if (net->mpb_enable)
+		net_key_beacon_disable(subnet->net_key_tx, true);
 
 	net_key_unref(subnet->net_key_cur);
 	net_key_unref(subnet->net_key_upd);
@@ -545,15 +555,27 @@ static struct mesh_subnet *subnet_new(struct mesh_net *net, uint16_t idx)
 	return subnet;
 }
 
-static void enable_beacon(void *a, void *b)
+static void enable_snb(void *a, void *b)
+{
+	struct mesh_subnet *subnet = a;
+	struct mesh_net *net = b;
+
+	if (net->snb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, false, 0);
+	else
+		net_key_beacon_disable(subnet->net_key_tx, false);
+}
+
+static void enable_mpb(void *a, void *b)
 {
 	struct mesh_subnet *subnet = a;
 	struct mesh_net *net = b;
 
-	if (net->beacon_enable)
-		net_key_beacon_enable(subnet->net_key_tx);
+	if (net->mpb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, true,
+							net->mpb_period);
 	else
-		net_key_beacon_disable(subnet->net_key_tx);
+		net_key_beacon_disable(subnet->net_key_tx, true);
 }
 
 static void enqueue_update(void *a, void *b);
@@ -602,7 +624,8 @@ static void refresh_beacon(void *a, void *b)
 	struct mesh_net *net = b;
 
 	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
-		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
+		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update,
+									false);
 }
 
 struct mesh_net *mesh_net_new(struct mesh_node *node)
@@ -826,7 +849,7 @@ int mesh_net_del_key(struct mesh_net *net, uint16_t idx)
 	if (idx == net->hb_pub.net_idx)
 		net->hb_pub.dst = UNASSIGNED_ADDRESS;
 
-	/* TODO: cancel beacon_enable on this subnet */
+	/* TODO: cancel snb_enable on this subnet */
 
 	l_queue_remove(net->subnets, subnet);
 	subnet_free(subnet);
@@ -853,10 +876,14 @@ static struct mesh_subnet *add_key(struct mesh_net *net, uint16_t idx,
 	}
 
 	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
-						false, net->iv_update);
+						false, net->iv_update, false);
 
-	if (net->beacon_enable)
-		net_key_beacon_enable(subnet->net_key_tx);
+	if (net->snb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, false, 0);
+
+	if (net->mpb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, true,
+							net->mpb_period);
 
 	l_queue_push_tail(net->subnets, subnet);
 
@@ -2598,6 +2625,13 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
 	if (subnet->kr_phase == KEY_REFRESH_PHASE_TWO)
 		return MESH_STATUS_SUCCESS;
 
+	/* Stop beaconing on old key */
+	if (net->snb_enable)
+		net_key_beacon_disable(subnet->net_key_tx, false);
+
+	if (net->mpb_enable)
+		net_key_beacon_disable(subnet->net_key_tx, true);
+
 	subnet->key_refresh = 1;
 	subnet->net_key_tx = subnet->net_key_upd;
 	/*
@@ -2605,6 +2639,15 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
 	 * it hears beacons from all the nodes
 	 */
 	subnet->kr_phase = KEY_REFRESH_PHASE_TWO;
+
+	/* Start beaconing on new key */
+	if (net->snb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, false, 0);
+
+	if (net->mpb_enable)
+		net_key_beacon_enable(subnet->net_key_tx, true,
+							net->mpb_period);
+
 	refresh_beacon(subnet, net);
 	queue_friend_update(net);
 
@@ -2794,83 +2837,111 @@ static void process_beacon(void *net_ptr, void *user_data)
 	beacon_data->processed = true;
 
 	/*
-	 * Ignore the beacon if it doesn't change anything, unless we're
-	 * doing IV Recovery
+	 * Ignore local beacons and beacons that don't change anything,
+	 * unless we're doing IV Recovery
 	 */
-	if (net->iv_upd_state == IV_UPD_INIT || ivi != net->iv_index ||
+	if (!beacon_data->local) {
+		if (net->iv_upd_state == IV_UPD_INIT || ivi != net->iv_index ||
 							ivu != net->iv_update)
-		updated |= update_iv_ivu_state(net, ivi, ivu);
+			updated |= update_iv_ivu_state(net, ivi, ivu);
 
-	if (kr != local_kr || beacon_data->net_key_id != subnet->net_key_cur)
-		updated |= update_kr_state(subnet, kr, beacon_data->net_key_id);
+		if (kr != local_kr)
+			updated |= update_kr_state(subnet, kr,
+						beacon_data->net_key_id);
 
-	if (updated)
-		net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
+
+		if (updated)
+			net_key_beacon_refresh(beacon_data->net_key_id,
+				net->iv_index,
 				!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO),
-								net->iv_update);
+				net->iv_update, false);
+	}
 }
 
 static void beacon_recv(void *user_data, struct mesh_io_recv_info *info,
 					const uint8_t *data, uint16_t len)
 {
 	struct net_beacon_data beacon_data = {
+		.local = false,
 		.processed = false,
 	};
 
-	if (len != 23 || data[1] != 0x01)
-		return;
+	beacon_data.net_key_id = net_key_beacon(data, len, &beacon_data.ivi,
+					&beacon_data.ivu, &beacon_data.kr);
 
-	/* Ignore Network IDs unknown to this daemon */
-	beacon_data.net_key_id = net_key_network_id(data + 3);
 	if (!beacon_data.net_key_id)
 		return;
 
-	/* Get data bits from beacon */
-	beacon_data.ivu = !!(data[2] & 0x02);
-	beacon_data.kr = !!(data[2] & 0x01);
-	beacon_data.ivi = l_get_be32(data + 11);
-
-	/* Validate beacon before accepting */
-	if (!net_key_snb_check(beacon_data.net_key_id, beacon_data.ivi,
-					beacon_data.kr, beacon_data.ivu,
-					l_get_be64(data + 15))) {
-		l_error("mesh_crypto_beacon verify failed");
-		return;
-	}
-
 	l_queue_foreach(nets, process_beacon, &beacon_data);
 
 	if (beacon_data.processed)
 		net_key_beacon_seen(beacon_data.net_key_id);
 }
 
-void net_local_beacon(uint32_t net_key_id, uint8_t *beacon)
+void net_local_beacon(uint32_t net_key_id, uint32_t ivi, bool ivu, bool kr)
 {
 	struct net_beacon_data beacon_data = {
+		.local = true,
+		.processed = false,
 		.net_key_id = net_key_id,
-		.ivu = !!(beacon[2] & 0x02),
-		.kr = !!(beacon[2] & 0x01),
-		.ivi = l_get_be32(beacon + 11),
+		.ivu = ivu,
+		.kr = kr,
+		.ivi = ivi,
 	};
 
 	/* Deliver locally generated beacons to all nodes */
 	l_queue_foreach(nets, process_beacon, &beacon_data);
 }
 
-bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
+bool mesh_net_set_snb_mode(struct mesh_net *net, bool enable)
+{
+	if (!net)
+		return false;
+
+	if (net->snb_enable == enable)
+		return true;
+
+	net->snb_enable = enable;
+
+	if (enable)
+		l_queue_foreach(net->subnets, refresh_beacon, net);
+
+	l_queue_foreach(net->subnets, enable_snb, net);
+	queue_friend_update(net);
+
+	return true;
+}
+
+bool mesh_net_set_mpb_mode(struct mesh_net *net, bool enable, uint8_t period,
+								bool initialize)
 {
+	uint8_t old_period;
+	bool old_enable;
+
 	if (!net)
 		return false;
 
-	if (net->beacon_enable == enable)
+	old_enable = net->mpb_enable;
+	old_period = net->mpb_period;
+
+	if (enable)
+		net->mpb_period = period;
+
+	if (old_enable == enable && old_period == net->mpb_period)
 		return true;
 
-	net->beacon_enable = enable;
+	if (enable && !initialize) {
+		/* If enable with different period, disable and re-enable */
+		net->mpb_enable = false;
+		l_queue_foreach(net->subnets, enable_mpb, net);
+	}
+
+	net->mpb_enable = enable;
 
 	if (enable)
 		l_queue_foreach(net->subnets, refresh_beacon, net);
 
-	l_queue_foreach(net->subnets, enable_beacon, net);
+	l_queue_foreach(net->subnets, enable_mpb, net);
 	queue_friend_update(net);
 
 	return true;
@@ -2908,17 +2979,25 @@ bool mesh_net_set_key(struct mesh_net *net, uint16_t idx, const uint8_t *key,
 		subnet->key_refresh = 1;
 		subnet->net_key_tx = subnet->net_key_upd;
 
-		if (net->beacon_enable) {
+		if (net->snb_enable) {
+			/* Switch beaconing key */
+			net_key_beacon_disable(subnet->net_key_cur, false);
+			net_key_beacon_enable(subnet->net_key_upd, false, 0);
+		}
+
+		if (net->mpb_enable) {
 			/* Switch beaconing key */
-			net_key_beacon_disable(subnet->net_key_cur);
-			net_key_beacon_enable(subnet->net_key_upd);
+			net_key_beacon_disable(subnet->net_key_cur, true);
+			net_key_beacon_enable(subnet->net_key_upd, true,
+							net->mpb_period);
 		}
 	}
 
 	subnet->kr_phase = phase;
 
 	net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
-		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
+		!!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update,
+									false);
 
 
 	return true;
@@ -2933,8 +3012,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
 
 	first = l_queue_isempty(nets);
 	if (first) {
-		uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
-		uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
+		const uint8_t snb[] = {MESH_AD_TYPE_BEACON, 1};
+		const uint8_t mpb[] = {MESH_AD_TYPE_BEACON, 2};
+		const uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
 
 		if (!nets)
 			nets = l_queue_new();
@@ -2944,6 +3024,8 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
 
 		mesh_io_register_recv_cb(io, snb, sizeof(snb),
 							beacon_recv, NULL);
+		mesh_io_register_recv_cb(io, mpb, sizeof(mpb),
+							beacon_recv, NULL);
 		mesh_io_register_recv_cb(io, pkt, sizeof(pkt),
 							net_msg_recv, NULL);
 	}
@@ -2960,8 +3042,9 @@ bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
 
 struct mesh_io *mesh_net_detach(struct mesh_net *net)
 {
-	uint8_t snb[] = {MESH_AD_TYPE_BEACON, 0x01};
-	uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
+	const uint8_t snb[] = {MESH_AD_TYPE_BEACON, 1};
+	const uint8_t mpb[] = {MESH_AD_TYPE_BEACON, 2};
+	const uint8_t pkt[] = {MESH_AD_TYPE_NETWORK};
 	struct mesh_io *io;
 	uint8_t type = 0;
 
@@ -2975,6 +3058,7 @@ struct mesh_io *mesh_net_detach(struct mesh_net *net)
 	/* Only deregister io if this is the last network detached.*/
 	if (l_queue_length(nets) < 2) {
 		mesh_io_deregister_recv_cb(io, snb, sizeof(snb));
+		mesh_io_deregister_recv_cb(io, mpb, sizeof(mpb));
 		mesh_io_deregister_recv_cb(io, pkt, sizeof(pkt));
 	}
 
diff --git a/mesh/net.h b/mesh/net.h
index 0bacbbb..d385ba1 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -236,8 +236,10 @@ void mesh_net_set_frnd_seq(struct mesh_net *net, bool seq);
 uint16_t mesh_net_get_address(struct mesh_net *net);
 bool mesh_net_register_unicast(struct mesh_net *net,
 					uint16_t unicast, uint8_t num_ele);
-void net_local_beacon(uint32_t net_key_id, uint8_t *beacon);
-bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable);
+void net_local_beacon(uint32_t key_id, uint32_t ivi, bool ivu, bool kr);
+bool mesh_net_set_snb_mode(struct mesh_net *net, bool enable);
+bool mesh_net_set_mpb_mode(struct mesh_net *net, bool enabla, uint8_t period,
+								bool init);
 bool mesh_net_set_proxy_mode(struct mesh_net *net, bool enable);
 bool mesh_net_set_relay_mode(struct mesh_net *net, bool enable, uint8_t cnt,
 							uint8_t interval);
diff --git a/mesh/node.c b/mesh/node.c
index cf4ed14..93537c5 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -27,9 +27,12 @@
 #include "mesh/appkey.h"
 #include "mesh/mesh-config.h"
 #include "mesh/provision.h"
+#include "mesh/prov.h"
 #include "mesh/keyring.h"
 #include "mesh/model.h"
 #include "mesh/cfgmod.h"
+#include "mesh/remprv.h"
+#include "mesh/prv-beacon.h"
 #include "mesh/util.h"
 #include "mesh/error.h"
 #include "mesh/dbus.h"
@@ -98,6 +101,8 @@ struct mesh_node {
 	uint8_t proxy;
 	uint8_t friend;
 	uint8_t beacon;
+	uint8_t mpb;
+	uint8_t mpb_period;
 };
 
 struct node_import {
@@ -204,6 +209,8 @@ static void set_defaults(struct mesh_node *node)
 {
 	node->lpn = MESH_MODE_UNSUPPORTED;
 	node->proxy = MESH_MODE_UNSUPPORTED;
+	node->mpb = MESH_MODE_DISABLED;
+	node->mpb_period = NET_MPB_REFRESH_DEFAULT;
 	node->friend = (mesh_friendship_supported()) ? MESH_MODE_DISABLED :
 							MESH_MODE_UNSUPPORTED;
 	node->beacon = (mesh_beacon_enabled()) ? MESH_MODE_ENABLED :
@@ -340,6 +347,7 @@ static bool add_elements_from_storage(struct mesh_node *node,
 					struct mesh_config_node *db_node)
 {
 	const struct l_queue_entry *entry;
+	struct node_element *ele;
 
 	entry = l_queue_get_entries(db_node->elements);
 
@@ -347,6 +355,20 @@ static bool add_elements_from_storage(struct mesh_node *node,
 		if (!add_element_from_storage(node, entry->data))
 			return false;
 
+	ele = l_queue_find(node->elements, match_element_idx,
+						L_UINT_TO_PTR(PRIMARY_ELE_IDX));
+	if (!ele)
+		return false;
+
+	/* Add configuration server model on the primary element */
+	mesh_model_add(node, ele->models, CONFIG_SRV_MODEL, NULL);
+
+	/* Add remote provisioning models on the primary element */
+	mesh_model_add(node, ele->models, REM_PROV_SRV_MODEL, NULL);
+
+	if (node->provisioner)
+		mesh_model_add(node, ele->models, REM_PROV_CLI_MODEL, NULL);
+
 	return true;
 }
 
@@ -392,7 +414,7 @@ static bool init_storage_dir(struct mesh_node *node)
 	return rpl_init(node->storage_dir);
 }
 
-static void update_net_settings(struct mesh_node *node)
+static void init_net_settings(struct mesh_node *node)
 {
 	struct mesh_net *net = node->net;
 
@@ -403,7 +425,9 @@ static void update_net_settings(struct mesh_node *node)
 	mesh_net_set_relay_mode(net, node->relay.mode == MESH_MODE_ENABLED,
 					node->relay.cnt, node->relay.interval);
 
-	mesh_net_set_beacon_mode(net, node->beacon == MESH_MODE_ENABLED);
+	mesh_net_set_snb_mode(net, node->beacon == MESH_MODE_ENABLED);
+	mesh_net_set_mpb_mode(net, node->mpb == MESH_MODE_ENABLED,
+							node->mpb_period, true);
 }
 
 static bool init_from_storage(struct mesh_config_node *db_node,
@@ -431,6 +455,8 @@ static bool init_from_storage(struct mesh_config_node *db_node,
 	node->relay.cnt = db_node->modes.relay.cnt;
 	node->relay.interval = db_node->modes.relay.interval;
 	node->beacon = db_node->modes.beacon;
+	node->mpb = db_node->modes.mpb;
+	node->mpb_period = db_node->modes.mpb_period;
 
 	l_debug("relay %2.2x, proxy %2.2x, lpn %2.2x, friend %2.2x",
 			node->relay.mode, node->proxy, node->lpn, node->friend);
@@ -484,11 +510,18 @@ static bool init_from_storage(struct mesh_config_node *db_node,
 	mesh_net_set_seq_num(node->net, node->seq_number);
 	mesh_net_set_default_ttl(node->net, node->ttl);
 
-	update_net_settings(node);
+	init_net_settings(node);
 
 	/* Initialize configuration server model */
 	cfgmod_server_init(node, PRIMARY_ELE_IDX);
 
+	/* Initialize remote provisioning models */
+	remote_prov_server_init(node, PRIMARY_ELE_IDX);
+	remote_prov_client_init(node, PRIMARY_ELE_IDX);
+
+	/* Initialize Private Beacon server model */
+	prv_beacon_server_init(node, PRIMARY_ELE_IDX);
+
 	node->cfg = cfg;
 
 	return true;
@@ -550,12 +583,78 @@ uint16_t node_get_primary(struct mesh_node *node)
 		return node->primary;
 }
 
+bool node_refresh(struct mesh_node *node, bool hard, void *prov_info)
+{
+	struct mesh_prov_node_info *info = prov_info;
+	bool res = true;
+
+	if (!node || !info)
+		return false;
+
+	if (!IS_UNICAST(info->unicast))
+		return false;
+
+	/* Changing Unicast addresses requires a hard node reset */
+	if (!hard && info->unicast != node->primary)
+		return false;
+
+	/*
+	 * Hard refresh results in immediate use of new Device Key.
+	 * Soft refresh saves new device key as Candidate until we
+	 * successfully receive new incoming message on that key.
+	 */
+	if (hard) {
+		if (!mesh_config_write_device_key(node->cfg, info->device_key))
+			return false;
+
+		memcpy(node->dev_key, info->device_key, sizeof(node->dev_key));
+
+	} else if (!mesh_config_write_candidate(node->cfg, info->device_key))
+		return false;
+
+	/* Replace Primary Unicast address if it has changed */
+	if (node->primary != info->unicast) {
+		res = mesh_config_write_unicast(node->cfg, info->unicast);
+		if (res) {
+			node->primary = info->unicast;
+			node->num_ele = info->num_ele;
+			mesh_net_register_unicast(node->net, node->primary,
+								node->num_ele);
+		}
+	}
+
+	/* Replace Page 0 with Page 128 if it exists */
+	if (res) {
+		if (node_replace_comp(node, 0, 128))
+			return true;
+	}
+
+	return res;
+}
+
 const uint8_t *node_get_device_key(struct mesh_node *node)
 {
 	if (!node)
 		return NULL;
-	else
-		return node->dev_key;
+
+	return node->dev_key;
+}
+
+bool node_get_device_key_candidate(struct mesh_node *node, uint8_t *key)
+{
+	if (!node)
+		return false;
+
+	return mesh_config_read_candidate(node->cfg, key);
+}
+
+void node_finalize_candidate(struct mesh_node *node)
+{
+	if (!node)
+		return;
+
+	if (mesh_config_read_candidate(node->cfg, node->dev_key))
+		mesh_config_finalize_candidate(node->cfg);
 }
 
 void node_set_token(struct mesh_node *node, uint8_t token[8])
@@ -744,7 +843,7 @@ bool node_beacon_mode_set(struct mesh_node *node, bool enable)
 
 	if (res) {
 		node->beacon = beacon;
-		mesh_net_set_beacon_mode(node->net, enable);
+		mesh_net_set_snb_mode(node->net, enable);
 	}
 
 	return res;
@@ -758,6 +857,36 @@ uint8_t node_beacon_mode_get(struct mesh_node *node)
 	return node->beacon;
 }
 
+bool node_mpb_mode_set(struct mesh_node *node, bool enable, uint8_t period)
+{
+	bool res;
+	uint8_t beacon;
+
+	if (!node)
+		return false;
+
+	beacon = enable ? MESH_MODE_ENABLED : MESH_MODE_DISABLED;
+	res = mesh_config_write_mpb(node->cfg, beacon, period);
+
+	if (res) {
+		node->mpb = beacon;
+		node->mpb_period = period;
+		mesh_net_set_mpb_mode(node->net, enable, period, false);
+	}
+
+	return res;
+}
+
+uint8_t node_mpb_mode_get(struct mesh_node *node, uint8_t *period)
+{
+	if (!node)
+		return MESH_MODE_DISABLED;
+
+	*period = node->mpb_period;
+
+	return node->mpb;
+}
+
 bool node_friend_mode_set(struct mesh_node *node, bool enable)
 {
 	bool res;
@@ -785,7 +914,7 @@ uint8_t node_friend_mode_get(struct mesh_node *node)
 	return node->friend;
 }
 
-static uint16_t generate_node_comp(struct mesh_node *node, uint8_t *buf,
+static uint16_t node_generate_comp(struct mesh_node *node, uint8_t *buf,
 								uint16_t sz)
 {
 	uint16_t n, features, num_ele = 0;
@@ -870,6 +999,8 @@ static void convert_node_to_storage(struct mesh_node *node,
 	db_node->modes.relay.cnt = node->relay.cnt;
 	db_node->modes.relay.interval = node->relay.interval;
 	db_node->modes.beacon = node->beacon;
+	db_node->modes.mpb = node->mpb;
+	db_node->modes.mpb_period = node->mpb_period;
 
 	db_node->ttl = node->ttl;
 	db_node->seq_number = node->seq_number;
@@ -895,6 +1026,21 @@ static void convert_node_to_storage(struct mesh_node *node,
 
 }
 
+static void free_db_storage(struct mesh_config_node *db_node)
+{
+	const struct l_queue_entry *entry;
+
+	/* Free temporarily allocated resources */
+	entry = l_queue_get_entries(db_node->elements);
+	for (; entry; entry = entry->next) {
+		struct mesh_config_element *db_ele = entry->data;
+
+		l_queue_destroy(db_ele->models, l_free);
+	}
+
+	l_queue_destroy(db_node->elements, l_free);
+}
+
 static bool create_node_config(struct mesh_node *node, const uint8_t uuid[16])
 {
 	struct mesh_config_node db_node;
@@ -922,7 +1068,22 @@ static bool create_node_config(struct mesh_node *node, const uint8_t uuid[16])
 	return node->cfg != NULL;
 }
 
-static bool set_node_comp(struct mesh_node *node, uint8_t page_num,
+static void node_del_comp(struct mesh_node *node, uint8_t page_num)
+{
+	struct mesh_config_comp_page *page;
+
+	if (!node)
+		return;
+
+	page = l_queue_remove_if(node->pages, match_page,
+						L_UINT_TO_PTR(page_num));
+
+	l_free(page);
+
+	mesh_config_comp_page_del(node->cfg, page_num);
+}
+
+static bool node_set_comp(struct mesh_node *node, uint8_t page_num,
 					const uint8_t *data, uint16_t len)
 {
 	struct mesh_config_comp_page *page;
@@ -944,16 +1105,6 @@ static bool set_node_comp(struct mesh_node *node, uint8_t page_num,
 	return mesh_config_comp_page_add(node->cfg, page_num, page->data, len);
 }
 
-static bool create_node_comp(struct mesh_node *node)
-{
-	uint16_t len;
-	uint8_t comp[MAX_MSG_LEN - 2];
-
-	len = generate_node_comp(node, comp, sizeof(comp));
-
-	return set_node_comp(node, 0, comp, len);
-}
-
 const uint8_t *node_get_comp(struct mesh_node *node, uint8_t page_num,
 								uint16_t *len)
 {
@@ -975,6 +1126,7 @@ const uint8_t *node_get_comp(struct mesh_node *node, uint8_t page_num,
 bool node_replace_comp(struct mesh_node *node, uint8_t retire, uint8_t with)
 {
 	struct mesh_config_comp_page *old_page, *keep;
+	bool status;
 
 	if (!node)
 		return false;
@@ -989,9 +1141,13 @@ bool node_replace_comp(struct mesh_node *node, uint8_t retire, uint8_t with)
 
 	l_free(old_page);
 	keep->page_num = retire;
-	mesh_config_comp_page_mv(node->cfg, with, retire);
+	status = mesh_config_comp_page_add(node->cfg, keep->page_num,
+							keep->data, keep->len);
 
-	return true;
+	if (with != retire)
+		mesh_config_comp_page_del(node->cfg, with);
+
+	return status;
 }
 
 static void attach_io(void *a, void *b)
@@ -1067,9 +1223,16 @@ static bool get_sig_models_from_properties(struct mesh_node *node,
 	while (l_dbus_message_iter_next_entry(&mods, &m_id, &var)) {
 		uint32_t id = SET_ID(SIG_VENDOR, m_id);
 
-		/* Allow Config Server Model only on the primary element */
-		if (ele->idx != PRIMARY_ELE_IDX && id == CONFIG_SRV_MODEL)
-			return false;
+		/*
+		 * Allow Config Server & Private Beacon Models only on
+		 * the primary element
+		 */
+		if (ele->idx != PRIMARY_ELE_IDX) {
+			if (id == CONFIG_SRV_MODEL)
+				return false;
+			if (id == PRV_BEACON_SRV_MODEL)
+				return false;
+		}
 
 		if (!mesh_model_add(node, ele->models, id, &var))
 			return false;
@@ -1170,8 +1333,14 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
 	 * daemon. If the model is present in the application properties,
 	 * the operation below will be a "no-op".
 	 */
-	if (ele->idx == PRIMARY_ELE_IDX)
+	if (ele->idx == PRIMARY_ELE_IDX) {
 		mesh_model_add(node, ele->models, CONFIG_SRV_MODEL, NULL);
+		mesh_model_add(node, ele->models, PRV_BEACON_SRV_MODEL, NULL);
+		mesh_model_add(node, ele->models, REM_PROV_SRV_MODEL, NULL);
+		if (node->provisioner)
+			mesh_model_add(node, ele->models, REM_PROV_CLI_MODEL,
+									NULL);
+	}
 
 	return true;
 fail:
@@ -1232,6 +1401,15 @@ static bool get_app_properties(struct mesh_node *node, const char *path,
 	return true;
 }
 
+static void save_pages(void *data, void *user_data)
+{
+	struct mesh_config_comp_page *page = data;
+	struct mesh_node *node = user_data;
+
+	mesh_config_comp_page_add(node->cfg, page->page_num, page->data,
+								page->len);
+}
+
 static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
 				bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
 				uint16_t net_key_idx, uint8_t net_key[16])
@@ -1275,10 +1453,17 @@ static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
 			return false;
 	}
 
-	update_net_settings(node);
+	l_queue_foreach(node->pages, save_pages, node);
 
-	/* Initialize configuration server model */
+	init_net_settings(node);
+
+	/* Initialize internal server models */
 	cfgmod_server_init(node, PRIMARY_ELE_IDX);
+	remote_prov_server_init(node, PRIMARY_ELE_IDX);
+	remote_prov_client_init(node, PRIMARY_ELE_IDX);
+
+	/* Initialize Private Beacon server model */
+	prv_beacon_server_init(node, PRIMARY_ELE_IDX);
 
 	node->busy = true;
 
@@ -1326,39 +1511,59 @@ static void update_model_options(struct mesh_node *node,
 
 static bool check_req_node(struct managed_obj_request *req)
 {
+	struct mesh_node *node;
 	const int offset = 8;
 	uint16_t node_len, len;
 	uint8_t comp[MAX_MSG_LEN - 2];
 	const uint8_t *node_comp;
 
-	len = generate_node_comp(req->node, comp, sizeof(comp));
+	if (req->type != REQUEST_TYPE_ATTACH) {
+		node = req->node;
 
-	if (len < MIN_COMP_SIZE)
-		return false;
+		if (!create_node_config(node, node->uuid))
+			return false;
+	} else
+		node = req->attach;
 
-	node_comp = node_get_comp(req->attach, 0, &node_len);
+	node_comp = node_get_comp(node, 0, &node_len);
+	len = node_generate_comp(req->node, comp, sizeof(comp));
 
-	/* If no page 0 exists, create it and accept */
-	if (!node_len || !node_comp)
-		return set_node_comp(req->attach, 0, comp, len);
+	/* If no page 0 exists, then current composition as valid */
+	if (req->type != REQUEST_TYPE_ATTACH || !node_len)
+		goto page_zero_valid;
 
-	/* Test Element/Model part of composition and reject if changed */
+	/*
+	 * If composition has materially changed, save new composition
+	 * in page 128 until next NPPI procedure. But we do allow
+	 * for CID, PID, VID and/or CRPL to freely change without
+	 * requiring a NPPI procedure.
+	 */
 	if (node_len != len || memcmp(&node_comp[offset], &comp[offset],
 							node_len - offset))
-		return false;
+		return node_set_comp(node, 128, comp, len);
 
-	/* If comp has changed, but not Element/Models, resave and accept */
-	else if (memcmp(node_comp, comp, node_len))
-		return set_node_comp(req->attach, 0, comp, len);
+page_zero_valid:
+	/* If page 0 represents current App, ensure page 128 doesn't exist */
+	node_del_comp(node, 128);
 
-	/* Nothing has changed */
-	return true;
+	if (len == node_len && !memcmp(node_comp, comp, len))
+		return true;
+
+	return node_set_comp(node, 0, comp, len);
+}
+
+static bool is_zero(const void *a, const void *b)
+{
+	const struct node_element *element = a;
+
+	return !element->idx;
 }
 
 static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 {
 	const struct l_queue_entry *attach_entry;
 	const struct l_queue_entry *node_entry;
+	bool comp_changed = false;
 
 	attach->obj_path = node->obj_path;
 	node->obj_path = NULL;
@@ -1368,6 +1573,34 @@ static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 		return false;
 	}
 
+	if (attach->num_ele != node->num_ele) {
+		struct mesh_config_node db_node;
+		struct node_element *old_ele, *new_ele;
+
+		convert_node_to_storage(node, &db_node);
+
+		/*
+		 * If composition has materially changed, we need to discard
+		 * everything we knew about elements in the old application,
+		 * and start from what they are telling us now.
+		 */
+		old_ele = l_queue_remove_if(attach->elements, is_zero, NULL);
+		new_ele = l_queue_remove_if(node->elements, is_zero, NULL);
+		element_free(new_ele);
+
+		l_queue_destroy(attach->elements, element_free);
+		attach->elements = node->elements;
+		attach->num_ele = node->num_ele;
+
+		/* Restore primary elements */
+		l_queue_push_head(attach->elements, old_ele);
+
+		comp_changed = true;
+
+		mesh_config_reset(attach->cfg, &db_node);
+		free_db_storage(&db_node);
+	}
+
 	attach_entry = l_queue_get_entries(attach->elements);
 	node_entry = l_queue_get_entries(node->elements);
 
@@ -1384,6 +1617,10 @@ static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 
 		attach_entry = attach_entry->next;
 		node_entry = node_entry->next;
+
+		/* Only need the Primary element during Composition change */
+		if (comp_changed)
+			break;
 	}
 
 	mesh_agent_remove(attach->agent);
@@ -1399,8 +1636,12 @@ static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 	node->owner = NULL;
 
 	update_composition(node, attach);
+
 	update_model_options(node, attach);
 
+	if (comp_changed)
+		node->elements = NULL;
+
 	node_remove(node);
 
 	return true;
@@ -1499,16 +1740,7 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 
 	node->num_ele = num_ele;
 
-	if (req->type != REQUEST_TYPE_ATTACH) {
-		/* Generate node configuration for a brand new node */
-		if (!create_node_config(node, node->uuid))
-			goto fail;
-
-		/* Create node composition */
-		if (!create_node_comp(node))
-			goto fail;
-	} else if (!check_req_node(req))
-		/* Check the integrity of the node composition */
+	if (!check_req_node(req))
 		goto fail;
 
 	switch (req->type) {
diff --git a/mesh/node.h b/mesh/node.h
index 2e3d898..4f31c50 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -38,6 +38,8 @@ uint16_t node_get_primary_net_idx(struct mesh_node *node);
 void node_set_token(struct mesh_node *node, uint8_t token[8]);
 const uint8_t *node_get_token(struct mesh_node *node);
 const uint8_t *node_get_device_key(struct mesh_node *node);
+bool node_get_device_key_candidate(struct mesh_node *node, uint8_t *key);
+void node_finalize_candidate(struct mesh_node *node);
 void node_set_num_elements(struct mesh_node *node, uint8_t num_ele);
 uint8_t node_get_num_elements(struct mesh_node *node);
 uint8_t node_default_ttl_get(struct mesh_node *node);
@@ -61,6 +63,8 @@ uint8_t node_relay_mode_get(struct mesh_node *node, uint8_t *cnt,
 bool node_proxy_mode_set(struct mesh_node *node, bool enable);
 uint8_t node_proxy_mode_get(struct mesh_node *node);
 bool node_beacon_mode_set(struct mesh_node *node, bool enable);
+bool node_mpb_mode_set(struct mesh_node *node, bool enable, uint8_t period);
+uint8_t node_mpb_mode_get(struct mesh_node *node, uint8_t *period);
 uint8_t node_beacon_mode_get(struct mesh_node *node);
 bool node_friend_mode_set(struct mesh_node *node, bool enable);
 uint8_t node_friend_mode_get(struct mesh_node *node);
@@ -89,3 +93,4 @@ const char *node_get_storage_dir(struct mesh_node *node);
 bool node_load_from_storage(const char *storage_dir);
 void node_finalize_new_node(struct mesh_node *node, struct mesh_io *io);
 void node_property_changed(struct mesh_node *node, const char *property);
+bool node_refresh(struct mesh_node *node, bool hard, void *prov_info);
diff --git a/mesh/pb-adv.c b/mesh/pb-adv.c
index 180b162..7a1dd87 100644
--- a/mesh/pb-adv.c
+++ b/mesh/pb-adv.c
@@ -166,7 +166,7 @@ static void send_adv_segs(struct pb_adv_session *session, const uint8_t *data,
 	consumed = init_size;
 
 	for (i = 1; i <= max_seg; i++) {
-		uint8_t seg_size; /* Amount of payload data being sent */
+		size_t seg_size; /* Amount of payload data being sent */
 
 		if (size - consumed > PB_ADV_MTU - 1)
 			seg_size = PB_ADV_MTU - 1;
@@ -219,7 +219,7 @@ static void tx_timeout(struct l_timeout *timeout, void *user_data)
 	cb(user_data, 1);
 }
 
-static void pb_adv_tx(void *user_data, void *data, uint16_t len)
+static void pb_adv_tx(void *user_data, const void *data, uint16_t len)
 {
 	struct pb_adv_session *session = user_data;
 
@@ -478,7 +478,7 @@ static void pb_adv_packet(void *user_data, const uint8_t *pkt, uint16_t len)
 bool pb_adv_reg(bool initiator, mesh_prov_open_func_t open_cb,
 		mesh_prov_close_func_t close_cb,
 		mesh_prov_receive_func_t rx_cb, mesh_prov_ack_func_t ack_cb,
-		uint8_t uuid[16], void *user_data)
+		const uint8_t *uuid, void *user_data)
 {
 	struct pb_adv_session *session, *old_session;
 
diff --git a/mesh/pb-adv.h b/mesh/pb-adv.h
index 5b1e03d..e33ba8e 100644
--- a/mesh/pb-adv.h
+++ b/mesh/pb-adv.h
@@ -11,5 +11,5 @@
 bool pb_adv_reg(bool initiator, mesh_prov_open_func_t open_cb,
 		mesh_prov_close_func_t close_cb,
 		mesh_prov_receive_func_t rx_cb, mesh_prov_ack_func_t ack_cb,
-		uint8_t uuid[16], void *user_data);
+		const uint8_t *uuid, void *user_data);
 void pb_adv_unreg(void *user_data);
diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c
index bf8c573..fd9d4cd 100644
--- a/mesh/prov-acceptor.c
+++ b/mesh/prov-acceptor.c
@@ -22,6 +22,7 @@
 #include "mesh/net.h"
 #include "mesh/prov.h"
 #include "mesh/provision.h"
+#include "mesh/remprv.h"
 #include "mesh/pb-adv.h"
 #include "mesh/mesh.h"
 #include "mesh/agent.h"
@@ -169,9 +170,6 @@ static void acp_prov_open(void *user_data, prov_trans_tx_t trans_tx,
 					prov->transport != transport)
 		return;
 
-	if (transport != PB_ADV)
-		return;
-
 	prov->trans_tx = trans_tx;
 	prov->transport = transport;
 	prov->trans_data = trans_data;
@@ -425,9 +423,10 @@ static bool prov_start_check(struct prov_start *start,
 	return true;
 }
 
-static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
+static void acp_prov_rx(void *user_data, const void *dptr, uint16_t len)
 {
 	struct mesh_prov_acceptor *rx_prov = user_data;
+	const uint8_t *data = dptr;
 	struct mesh_prov_node_info *info;
 	struct prov_fail_msg fail;
 	uint8_t type = *data++;
@@ -654,14 +653,19 @@ static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
 		info->flags = prov->rand_auth_workspace[18];
 		info->iv_index = l_get_be32(prov->rand_auth_workspace + 19);
 		info->unicast = l_get_be16(prov->rand_auth_workspace + 23);
+		info->num_ele = prov->conf_inputs.caps.num_ele;
+
+		/* Send prov complete */
+		prov->rand_auth_workspace[0] = PROV_COMPLETE;
+		prov->trans_tx(prov->trans_data,
+				prov->rand_auth_workspace, 1);
 
 		result = prov->cmplt(prov->caller_data, PROV_ERR_SUCCESS, info);
 		prov->cmplt = NULL;
 		l_free(info);
 
 		if (result) {
-			prov->rand_auth_workspace[0] = PROV_COMPLETE;
-			prov_send(prov, prov->rand_auth_workspace, 1);
+			l_debug("PROV_COMPLETE");
 			goto cleanup;
 		} else {
 			fail.reason = PROV_ERR_UNEXPECTED_ERR;
@@ -721,7 +725,7 @@ static void acp_prov_ack(void *user_data, uint8_t msg_num)
 
 
 /* This starts unprovisioned device beacon */
-bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
+bool acceptor_start(uint8_t num_ele, uint8_t *uuid,
 		uint16_t algorithms, uint32_t timeout,
 		struct mesh_agent *agent,
 		mesh_prov_acceptor_complete_func_t complete_cb,
@@ -733,8 +737,10 @@ bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
 	uint8_t len = sizeof(beacon) - sizeof(uint32_t);
 	bool result;
 
-	/* Invoked from Join() method in mesh-api.txt, to join a
-	 * remote mesh network.
+	/*
+	 * Invoked from Join() method in mesh-api.txt, to join a
+	 * remote mesh network. May also be invoked with a NULL
+	 * uuid to perform a Device Key Refresh procedure.
 	 */
 
 	if (prov)
@@ -752,37 +758,50 @@ bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
 
 	caps = mesh_agent_get_caps(agent);
 
-	/* TODO: Should we sanity check values here or elsewhere? */
 	prov->conf_inputs.caps.num_ele = num_ele;
-	prov->conf_inputs.caps.pub_type = caps->pub_type;
-	prov->conf_inputs.caps.static_type = caps->static_type;
-	prov->conf_inputs.caps.output_size = caps->output_size;
-	prov->conf_inputs.caps.input_size = caps->input_size;
-
-	/* Store UINT16 values in Over-the-Air order, in packed structure
-	 * for crypto inputs
-	 */
 	l_put_be16(algorithms, &prov->conf_inputs.caps.algorithms);
-	l_put_be16(caps->output_action, &prov->conf_inputs.caps.output_action);
-	l_put_be16(caps->input_action, &prov->conf_inputs.caps.input_action);
-
-	/* Compose Unprovisioned Beacon */
-	memcpy(beacon + 2, uuid, 16);
-	l_put_be16(caps->oob_info, beacon + 18);
-	if (caps->oob_info & OOB_INFO_URI_HASH){
-		l_put_be32(caps->uri_hash, beacon + 20);
-		len += sizeof(uint32_t);
+
+	if (caps) {
+		/* TODO: Should we sanity check values here or elsewhere? */
+		prov->conf_inputs.caps.pub_type = caps->pub_type;
+		prov->conf_inputs.caps.static_type = caps->static_type;
+		prov->conf_inputs.caps.output_size = caps->output_size;
+		prov->conf_inputs.caps.input_size = caps->input_size;
+
+		/* Store UINT16 values in Over-the-Air order, in packed
+		 * structure for crypto inputs
+		 */
+		l_put_be16(caps->output_action,
+					&prov->conf_inputs.caps.output_action);
+		l_put_be16(caps->input_action,
+					&prov->conf_inputs.caps.input_action);
+
+		/* Populate Caps fields of beacon */
+		l_put_be16(caps->oob_info, beacon + 18);
+		if (caps->oob_info & OOB_INFO_URI_HASH) {
+			l_put_be32(caps->uri_hash, beacon + 20);
+			len += sizeof(uint32_t);
+		}
 	}
 
-	/* Infinitely Beacon until Canceled, or Provisioning Starts */
-	result = mesh_send_pkt(0, 500, beacon, len);
+	if (uuid) {
+		/* Compose Unprovisioned Beacon */
+		memcpy(beacon + 2, uuid, 16);
+
+		/* Infinitely Beacon until Canceled, or Provisioning Starts */
+		result = mesh_send_pkt(0, 500, beacon, len);
 
-	if (!result)
-		goto error_fail;
+		if (!result)
+			goto error_fail;
 
-	/* Always register for PB-ADV */
-	result = pb_adv_reg(false, acp_prov_open, acp_prov_close, acp_prov_rx,
-						acp_prov_ack, uuid, prov);
+		/* Always register for PB-ADV */
+		result = pb_adv_reg(false, acp_prov_open, acp_prov_close,
+					acp_prov_rx, acp_prov_ack, uuid, prov);
+	} else {
+		/* Run Device Key Refresh Procedure */
+		result = register_nppi_acceptor(acp_prov_open, acp_prov_close,
+					acp_prov_rx, acp_prov_ack, prov);
+	}
 
 	if (result)
 		return true;
diff --git a/mesh/prov-initiator.c b/mesh/prov-initiator.c
index c625775..e353d23 100644
--- a/mesh/prov-initiator.c
+++ b/mesh/prov-initiator.c
@@ -21,10 +21,12 @@
 #include "mesh/crypto.h"
 #include "mesh/net.h"
 #include "mesh/node.h"
+#include "mesh/model.h"
 #include "mesh/keyring.h"
 #include "mesh/prov.h"
 #include "mesh/provision.h"
 #include "mesh/pb-adv.h"
+#include "mesh/remprv.h"
 #include "mesh/mesh.h"
 #include "mesh/agent.h"
 #include "mesh/error.h"
@@ -82,12 +84,16 @@ struct mesh_prov_initiator {
 	struct l_timeout *timeout;
 	uint32_t to_secs;
 	enum int_state	state;
-	enum trans_type transport;
 	uint16_t net_idx;
+	uint16_t svr_idx;
 	uint16_t unicast;
+	uint16_t server;
+	uint8_t transport;
 	uint8_t material;
 	uint8_t expected;
 	int8_t previous;
+	uint8_t out_num;
+	uint8_t rpr_state;
 	struct conf_input conf_inputs;
 	uint8_t calc_key[16];
 	uint8_t salt[16];
@@ -100,14 +106,23 @@ struct mesh_prov_initiator {
 	uint8_t uuid[16];
 };
 
+struct scan_req {
+	mesh_prov_initiator_scan_result_t scan_result;
+	struct mesh_node *node;
+	int count;
+};
+
 static struct mesh_prov_initiator *prov = NULL;
+static struct l_queue *scans;
 
 static void initiator_free(void)
 {
-	if (prov)
+	if (prov) {
 		l_timeout_remove(prov->timeout);
 
-	mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
+		if (!prov->server)
+			mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
+	}
 
 	pb_adv_unreg(prov);
 
@@ -119,6 +134,15 @@ static void int_prov_close(void *user_data, uint8_t reason)
 {
 	struct mesh_prov_initiator *prov = user_data;
 	struct mesh_prov_node_info info;
+	uint8_t msg[4];
+	int n;
+
+	if (prov->server) {
+		n = mesh_model_opcode_set(OP_REM_PROV_LINK_CLOSE, msg);
+		msg[n++] = reason == PROV_ERR_SUCCESS ? 0x00 : 0x02;
+		mesh_model_send(prov->node, 0, prov->server, APP_IDX_DEV_REMOTE,
+				prov->svr_idx, DEFAULT_TTL, true, n, msg);
+	}
 
 	if (reason != PROV_ERR_SUCCESS) {
 		prov->complete_cb(prov->caller_data, reason, NULL);
@@ -626,9 +650,10 @@ static void int_prov_start_auth(const struct mesh_agent_prov_caps *prov_caps,
 	}
 }
 
-static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
+static void int_prov_rx(void *user_data, const void *dptr, uint16_t len)
 {
 	struct mesh_prov_initiator *rx_prov = user_data;
+	const uint8_t *data = dptr;
 	uint8_t *out;
 	uint8_t type = *data++;
 	uint8_t fail_code[2];
@@ -648,10 +673,15 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
 		goto failure;
 	}
 
-	if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
-					len != expected_pdu_size[type]) {
+	if (type >= L_ARRAY_SIZE(expected_pdu_size)) {
+		l_error("Invalid PDU type %2.2x", type);
+		fail_code[1] = PROV_ERR_INVALID_FORMAT;
+		goto failure;
+	}
+
+	if (len != expected_pdu_size[type]) {
 		l_error("Expected PDU size %d, Got %d (type: %2.2x)",
-			len, expected_pdu_size[type], type);
+			expected_pdu_size[type], len, type);
 		fail_code[1] = PROV_ERR_INVALID_FORMAT;
 		goto failure;
 	}
@@ -773,7 +803,12 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
 			goto failure;
 		}
 
-		if (!prov->data_req_cb(prov->caller_data,
+		if (prov->transport == PB_NPPI_00 ||
+						prov->transport == PB_NPPI_02) {
+			/* No App data needed */
+			initiator_prov_data(prov->svr_idx, prov->server,
+							prov->caller_data);
+		} else if (!prov->data_req_cb(prov->caller_data,
 					prov->conf_inputs.caps.num_ele)) {
 			l_error("Provisioning Failed-Data Get");
 			fail_code[1] = PROV_ERR_CANT_ASSIGN_ADDR;
@@ -851,6 +886,8 @@ static void int_prov_ack(void *user_data, uint8_t msg_num)
 
 static void initiator_open_cb(void *user_data, int err)
 {
+	uint8_t msg[20];
+	int n;
 	bool result;
 
 	if (!prov)
@@ -859,18 +896,30 @@ static void initiator_open_cb(void *user_data, int err)
 	if (err != MESH_ERROR_NONE)
 		goto fail;
 
-	/* Always register for PB-ADV */
-	result = pb_adv_reg(true, int_prov_open, int_prov_close, int_prov_rx,
-						int_prov_ack, prov->uuid, prov);
+	if (prov->server) {
+		n = mesh_model_opcode_set(OP_REM_PROV_LINK_OPEN, msg);
+
+		if (prov->transport <= PB_NPPI_02) {
+			msg[n++] = prov->transport;
+		} else {
+			memcpy(msg + n, prov->uuid, 16);
+			n += 16;
+		}
+
+		result = mesh_model_send(prov->node, 0, prov->server,
+					APP_IDX_DEV_REMOTE, prov->svr_idx,
+					DEFAULT_TTL, true, n, msg);
+	} else {
+		/* Always register for PB-ADV */
+		result = pb_adv_reg(true, int_prov_open, int_prov_close,
+				int_prov_rx, int_prov_ack, prov->uuid, prov);
+	}
 
 	if (!result) {
 		err = MESH_ERROR_FAILED;
 		goto fail;
 	}
 
-	if (!prov)
-		return;
-
 	prov->start_cb(prov->caller_data, MESH_ERROR_NONE);
 	return;
 fail:
@@ -878,10 +927,20 @@ fail:
 	initiator_free();
 }
 
-bool initiator_start(enum trans_type transport,
-		uint8_t uuid[16],
-		uint16_t max_ele,
-		uint32_t timeout, /* in seconds from mesh.conf */
+static void initiate_to(struct l_timeout *timeout, void *user_data)
+{
+	struct mesh_prov_initiator *rx_prov = user_data;
+
+	if (rx_prov != prov) {
+		l_timeout_remove(timeout);
+		return;
+	}
+
+	int_prov_close(user_data, PROV_ERR_TIMEOUT);
+}
+
+bool initiator_start(uint8_t transport, uint16_t server, uint16_t svr_idx,
+		uint8_t uuid[16], uint16_t max_ele, uint32_t timeout,
 		struct mesh_agent *agent,
 		mesh_prov_initiator_start_func_t start_cb,
 		mesh_prov_initiator_data_req_func_t data_req_cb,
@@ -904,6 +963,10 @@ bool initiator_start(enum trans_type transport,
 	prov->data_req_cb = data_req_cb;
 	prov->caller_data = caller_data;
 	prov->previous = -1;
+	prov->server = server;
+	prov->svr_idx = svr_idx;
+	prov->transport = transport;
+	prov->timeout = l_timeout_create(timeout, initiate_to, prov, NULL);
 	memcpy(prov->uuid, uuid, 16);
 
 	mesh_agent_refresh(prov->agent, initiator_open_cb, prov);
@@ -915,3 +978,182 @@ void initiator_cancel(void *user_data)
 {
 	initiator_free();
 }
+
+static void rpr_tx(void *user_data, const void *data, uint16_t len)
+{
+	struct mesh_prov_initiator *prov = user_data;
+	uint8_t msg[72];
+	int n;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_PDU_SEND, msg);
+	msg[n++] = ++prov->out_num;
+	memcpy(msg + n, data, len);
+	l_debug("Send OB %2.2x, with packet type %d", msg[n], prov->out_num);
+	n += len;
+
+	prov->rpr_state = PB_REMOTE_STATE_OB_PKT_TX;
+	mesh_model_send(prov->node, 0, prov->server, APP_IDX_DEV_REMOTE,
+				prov->svr_idx, DEFAULT_TTL, true, n, msg);
+}
+
+static bool match_req_node(const void *a, const void *b)
+{
+	const struct scan_req *req = a;
+	const struct mesh_node *node = b;
+
+	return req->node == node;
+}
+
+static bool remprv_cli_pkt(uint16_t src, uint16_t unicast, uint16_t app_idx,
+					uint16_t net_idx, const uint8_t *data,
+					uint16_t size, const void *user_data)
+{
+	struct mesh_node *node = (struct mesh_node *) user_data;
+	const uint8_t *pkt = data;
+	struct scan_req *req;
+	uint32_t opcode;
+	uint16_t n;
+
+	if (mesh_model_opcode_get(pkt, size, &opcode, &n)) {
+		size -= n;
+		pkt += n;
+	} else
+		return false;
+
+	if (opcode < OP_REM_PROV_SCAN_CAP_GET ||
+					opcode > OP_REM_PROV_PDU_REPORT)
+		return false;
+
+	if (app_idx != APP_IDX_DEV_REMOTE && app_idx != APP_IDX_DEV_LOCAL)
+		return true;
+
+	/* Local Dev key only allowed for Loop-backs */
+	if (app_idx == APP_IDX_DEV_LOCAL && unicast != src)
+		return true;
+
+	if (prov && (prov->server != src || prov->node != node))
+		return true;
+
+	n = 0;
+
+	switch (opcode) {
+	default:
+		return false;
+
+	/* Provisioning Opcodes */
+	case OP_REM_PROV_LINK_STATUS:
+		if (size != 2 || !prov)
+			break;
+
+		if (pkt[0] == PB_REM_ERR_SUCCESS)
+			prov->rpr_state = pkt[1];
+
+		break;
+
+	case OP_REM_PROV_LINK_REPORT:
+		if (size != 2 || !prov)
+			return true;
+
+		if (pkt[0] != PB_REM_ERR_SUCCESS) {
+			if (pkt[0] == PB_REM_ERR_CLOSED_BY_DEVICE ||
+				pkt[0] == PB_REM_ERR_CLOSED_BY_SERVER)
+				int_prov_close(prov, pkt[1]);
+
+			break;
+		}
+
+
+		if (prov->rpr_state == PB_REMOTE_STATE_LINK_OPENING)
+			int_prov_open(prov, rpr_tx, prov, prov->transport);
+		else if (prov->rpr_state == PB_REMOTE_STATE_LINK_CLOSING) {
+			prov->rpr_state = PB_REMOTE_STATE_IDLE;
+			int_prov_close(prov, pkt[1]);
+			break;
+		}
+
+		prov->rpr_state = pkt[1];
+
+		break;
+
+	case OP_REM_PROV_PDU_REPORT:
+		int_prov_rx(prov, pkt + 1, size - 1);
+		break;
+
+	case OP_REM_PROV_PDU_OB_REPORT:
+		if (size != 1 || !prov)
+			break;
+
+		l_debug("Got Ack for OB %d", pkt[0]);
+		if (prov->rpr_state == PB_REMOTE_STATE_OB_PKT_TX &&
+							pkt[0] == prov->out_num)
+			int_prov_ack(prov, pkt[0]);
+
+		break;
+
+	/* Scan Opcodes */
+	case OP_REM_PROV_SCAN_CAP_STATUS:
+	case OP_REM_PROV_SCAN_STATUS:
+		break;
+
+	case OP_REM_PROV_SCAN_REPORT:
+	case OP_REM_PROV_EXT_SCAN_REPORT:
+		req = l_queue_find(scans, match_req_node, node);
+		if (req) {
+			req->scan_result(node, src,
+				opcode == OP_REM_PROV_EXT_SCAN_REPORT,
+				pkt, size);
+		}
+	}
+
+	return true;
+}
+
+void initiator_scan_reg(mesh_prov_initiator_scan_result_t scan_result,
+								void *user_data)
+{
+	struct scan_req *req;
+
+	if (!scans)
+		scans = l_queue_new();
+
+	req = l_queue_find(scans, match_req_node, user_data);
+	if (!req) {
+		req = l_new(struct scan_req, 1);
+		l_queue_push_head(scans, req);
+	}
+
+	req->scan_result = scan_result;
+	req->node = user_data;
+	req->count++;
+}
+
+void initiator_scan_unreg(void *user_data)
+{
+	struct scan_req *req;
+
+	req = l_queue_find(scans, match_req_node, user_data);
+	if (req) {
+		req->count--;
+		if (!req->count) {
+			l_queue_remove(scans, req);
+			l_free(req);
+		}
+	}
+}
+
+static void remprv_cli_unregister(void *user_data)
+{
+}
+
+static const struct mesh_model_ops ops = {
+	.unregister = remprv_cli_unregister,
+	.recv = remprv_cli_pkt,
+	.bind = NULL,
+	.sub = NULL,
+	.pub = NULL
+};
+
+void remote_prov_client_init(struct mesh_node *node, uint8_t ele_idx)
+{
+	mesh_model_register(node, ele_idx, REM_PROV_CLI_MODEL, &ops, node);
+}
diff --git a/mesh/prov.h b/mesh/prov.h
index 99e864c..e86668f 100644
--- a/mesh/prov.h
+++ b/mesh/prov.h
@@ -39,14 +39,14 @@ enum mesh_prov_mode {
 
 struct mesh_prov;
 
-typedef void (*prov_trans_tx_t)(void *trans_data, void *data, uint16_t len);
+typedef void (*prov_trans_tx_t)(void *tx_data, const void *data, uint16_t len);
 typedef void (*mesh_prov_open_func_t)(void *user_data, prov_trans_tx_t trans_tx,
 					void *trans_data, uint8_t trans_type);
 
 typedef void (*mesh_prov_close_func_t)(void *user_data, uint8_t reason);
 typedef void (*mesh_prov_send_func_t)(bool success, struct mesh_prov *prov);
 typedef void (*mesh_prov_ack_func_t)(void *user_data, uint8_t msg_num);
-typedef void (*mesh_prov_receive_func_t)(void *user_data, const uint8_t *data,
+typedef void (*mesh_prov_receive_func_t)(void *user_data, const void *data,
 								uint16_t size);
 
 
diff --git a/mesh/provision.h b/mesh/provision.h
index 1634c4d..cfeb6de 100644
--- a/mesh/provision.h
+++ b/mesh/provision.h
@@ -70,10 +70,11 @@ struct mesh_agent;
 #define OOB_INFO_URI_HASH	0x0002
 
 /* PB_REMOTE not supported from unprovisioned state */
-enum trans_type {
-	PB_ADV = 0,
-	PB_GATT,
-};
+#define PB_NPPI_00	0x00
+#define PB_NPPI_01	0x01
+#define PB_NPPI_02	0x02
+#define PB_ADV		0x03 /* Internal only, and may be reassigned */
+#define PB_GATT		0x04 /* Internal only, and may be reassigned */
 
 #define PROV_FLAG_KR	0x01
 #define PROV_FLAG_IVU	0x02
@@ -101,15 +102,21 @@ typedef bool (*mesh_prov_initiator_complete_func_t)(void *user_data,
 					uint8_t status,
 					struct mesh_prov_node_info *info);
 
+typedef void (*mesh_prov_initiator_scan_result_t)(void *user_data,
+					uint16_t server, bool extended,
+					const uint8_t *data, uint16_t len);
+
 /* This starts unprovisioned device beacon */
-bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
+bool acceptor_start(uint8_t num_ele, uint8_t *uuid,
 			uint16_t algorithms, uint32_t timeout,
 			struct mesh_agent *agent,
 			mesh_prov_acceptor_complete_func_t complete_cb,
 			void *caller_data);
 void acceptor_cancel(void *user_data);
 
-bool initiator_start(enum trans_type transport,
+bool initiator_start(uint8_t transport,
+		uint16_t server,
+		uint16_t svr_idx,
 		uint8_t uuid[16],
 		uint16_t max_ele,
 		uint32_t timeout, /* in seconds from mesh.conf */
@@ -120,3 +127,7 @@ bool initiator_start(enum trans_type transport,
 		void *node, void *caller_data);
 void initiator_prov_data(uint16_t net_idx, uint16_t primary, void *caller_data);
 void initiator_cancel(void *caller_data);
+
+void initiator_scan_reg(mesh_prov_initiator_scan_result_t scan_result,
+							void *user_data);
+void initiator_scan_unreg(void *caller_data);
diff --git a/mesh/prv-beacon.h b/mesh/prv-beacon.h
new file mode 100644
index 0000000..1e69e7f
--- /dev/null
+++ b/mesh/prv-beacon.h
@@ -0,0 +1,36 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  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.
+ *
+ */
+
+struct mesh_node;
+
+#define PRV_BEACON_SRV_MODEL	SET_ID(SIG_VENDOR, 0x0008)
+#define PRV_BEACON_CLI_MODEL	SET_ID(SIG_VENDOR, 0x0009)
+
+/* Private Beacon opcodes */
+#define OP_PRIVATE_BEACON_GET			0x8060
+#define OP_PRIVATE_BEACON_SET			0x8061
+#define OP_PRIVATE_BEACON_STATUS		0x8062
+#define OP_PRIVATE_GATT_PROXY_GET		0x8063
+#define OP_PRIVATE_GATT_PROXY_SET		0x8064
+#define OP_PRIVATE_GATT_PROXY_STATUS		0x8065
+#define OP_PRIVATE_NODE_ID_GET			0x8066
+#define OP_PRIVATE_NODE_ID_SET			0x8067
+#define OP_PRIVATE_NODE_ID_STATUS		0x8068
+
+void prv_beacon_server_init(struct mesh_node *node, uint8_t ele_idx);
diff --git a/mesh/prvbeac-server.c b/mesh/prvbeac-server.c
new file mode 100644
index 0000000..dd0e4cb
--- /dev/null
+++ b/mesh/prvbeac-server.c
@@ -0,0 +1,128 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/time.h>
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+#include "mesh/node.h"
+#include "mesh/net.h"
+#include "mesh/appkey.h"
+#include "mesh/model.h"
+#include "mesh/mesh-config.h"
+#include "mesh/prv-beacon.h"
+
+#define NOT_SUPPORTED 0x02
+
+static bool prvbec_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx,
+				uint16_t net_idx, const uint8_t *data,
+				uint16_t size, const void *user_data)
+{
+	struct mesh_node *node = (struct mesh_node *) user_data;
+	const uint8_t *pkt = data;
+	uint32_t opcode;
+	uint8_t msg[5];
+	uint16_t n;
+	uint8_t period;
+
+	if (app_idx != APP_IDX_DEV_LOCAL)
+		return false;
+
+	if (mesh_model_opcode_get(pkt, size, &opcode, &n)) {
+		size -= n;
+		pkt += n;
+	} else
+		return false;
+
+	l_debug("PRV-BEAC-SRV-opcode 0x%x size %u idx %3.3x", opcode, size,
+								net_idx);
+
+	n = 0;
+
+	switch (opcode) {
+	default:
+		return false;
+
+	case OP_PRIVATE_BEACON_SET:
+		if (size == 1)
+			node_mpb_mode_get(node, &period);
+		else if (size == 2)
+			period = pkt[1];
+		else
+			return true;
+
+		if (pkt[0] > 1)
+			return true;
+
+		node_mpb_mode_set(node, !!pkt[0], period);
+
+		/* fall through */
+
+	case OP_PRIVATE_BEACON_GET:
+		n = mesh_model_opcode_set(OP_PRIVATE_BEACON_STATUS, msg);
+
+		msg[n++] = node_mpb_mode_get(node, &period);
+		msg[n++] = period;
+
+		l_debug("Get/Set Private Beacon (%d)", msg[n-2]);
+		break;
+
+	case OP_PRIVATE_GATT_PROXY_SET:
+		/* fall through */
+	case OP_PRIVATE_GATT_PROXY_GET:
+		n = mesh_model_opcode_set(OP_PRIVATE_GATT_PROXY_STATUS, msg);
+		msg[n++] = NOT_SUPPORTED;
+		break;
+
+	case OP_PRIVATE_NODE_ID_SET:
+		/* fall through */
+	case OP_PRIVATE_NODE_ID_GET:
+		n = mesh_model_opcode_set(OP_PRIVATE_NODE_ID_STATUS, msg);
+		msg[n++] = NOT_SUPPORTED;
+		break;
+	}
+
+	if (n)
+		mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx,
+						DEFAULT_TTL, false, n, msg);
+
+	return true;
+}
+
+static void prvbec_srv_unregister(void *user_data)
+{
+}
+
+static const struct mesh_model_ops ops = {
+	.unregister = prvbec_srv_unregister,
+	.recv = prvbec_srv_pkt,
+	.bind = NULL,
+	.sub = NULL,
+	.pub = NULL
+};
+
+void prv_beacon_server_init(struct mesh_node *node, uint8_t ele_idx)
+{
+	l_debug("%2.2x", ele_idx);
+	mesh_model_register(node, ele_idx, PRV_BEACON_SRV_MODEL, &ops, node);
+}
diff --git a/mesh/remprv-server.c b/mesh/remprv-server.c
new file mode 100644
index 0000000..927dbab
--- /dev/null
+++ b/mesh/remprv-server.c
@@ -0,0 +1,919 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/time.h>
+#include <ell/ell.h>
+
+#include "src/shared/ad.h"
+
+#include "mesh/mesh-defs.h"
+#include "mesh/mesh-io.h"
+#include "mesh/util.h"
+#include "mesh/node.h"
+#include "mesh/net.h"
+#include "mesh/appkey.h"
+#include "mesh/model.h"
+#include "mesh/prov.h"
+#include "mesh/provision.h"
+#include "mesh/pb-adv.h"
+#include "mesh/remprv.h"
+
+#define EXT_LIST_SIZE	60
+
+#define RPR_DEV_KEY	0x00
+#define RPR_ADDR	0x01
+#define RPR_COMP	0x02
+#define RPR_ADV		0xFF	/* Internal use only*/
+
+struct rem_scan_data {
+	struct mesh_node *node;
+	struct l_timeout *timeout;
+	uint8_t *list;
+	uint16_t client;
+	uint16_t oob_info;
+	uint16_t net_idx;
+	uint8_t state;
+	uint8_t scanned_limit;
+	uint8_t addr[6];
+	uint8_t uuid[16];
+	uint8_t to_secs;
+	uint8_t rxed_ads;
+	uint8_t ext_cnt;
+	bool fltr;
+	uint8_t ext[0];
+};
+
+static struct rem_scan_data *rpb_scan;
+
+struct rem_prov_data {
+	struct mesh_node *node;
+	struct l_timeout *timeout;
+	void *trans_data;
+	uint16_t client;
+	uint16_t net_idx;
+	uint8_t svr_pdu_num;
+	uint8_t cli_pdu_num;
+	uint8_t state;
+	uint8_t nppi_proc;
+	union {
+		struct {
+			mesh_prov_open_func_t open_cb;
+			mesh_prov_close_func_t close_cb;
+			mesh_prov_receive_func_t rx_cb;
+			mesh_prov_ack_func_t ack_cb;
+			struct mesh_prov_node_info info;
+		} nppi;
+		struct {
+			uint8_t uuid[17];
+			prov_trans_tx_t tx;
+		} adv;
+	} u;
+};
+
+static struct rem_prov_data *rpb_prov;
+
+static const uint8_t prvb[2] = {BT_AD_MESH_BEACON, 0x00};
+static const uint8_t pkt_filter = BT_AD_MESH_PROV;
+static const char *name = "Test Name";
+
+static const uint8_t zero[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static void srv_open(void *user_data, prov_trans_tx_t adv_tx,
+					void *trans_data, uint8_t nppi_proc)
+{
+	struct rem_prov_data *prov = user_data;
+	uint8_t msg[5];
+	int n;
+
+	if (prov != rpb_prov || prov->state != PB_REMOTE_STATE_LINK_OPENING)
+		return;
+
+	l_debug("Remote Link open confirmed");
+	prov->u.adv.tx = adv_tx;
+	prov->trans_data = trans_data;
+	prov->state = PB_REMOTE_STATE_LINK_ACTIVE;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_LINK_REPORT, msg);
+	msg[n++] = PB_REM_ERR_SUCCESS;
+	msg[n++] = prov->state;
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, true, n, msg);
+}
+
+static void srv_rx(void *user_data, const void *dptr, uint16_t len)
+{
+	struct rem_prov_data *prov = user_data;
+	const uint8_t *data = dptr;
+	uint8_t msg[69];
+	int n;
+
+	if (prov != rpb_prov || prov->state < PB_REMOTE_STATE_LINK_ACTIVE ||
+								len > 65)
+		return;
+
+	l_debug("Remote PB IB-PDU");
+
+	prov->svr_pdu_num++;
+	n = mesh_model_opcode_set(OP_REM_PROV_PDU_REPORT, msg);
+	msg[n++] = prov->svr_pdu_num;
+	memcpy(msg + n, data, len);
+	n += len;
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, true, n, msg);
+}
+
+static void srv_ack(void *user_data, uint8_t msg_num)
+{
+	struct rem_prov_data *prov = user_data;
+	uint8_t msg[4];
+	int n;
+
+	if (prov != rpb_prov || prov->state != PB_REMOTE_STATE_OB_PKT_TX)
+		return;
+
+	l_debug("Remote PB ACK");
+
+	prov->state = PB_REMOTE_STATE_LINK_ACTIVE;
+	n = mesh_model_opcode_set(OP_REM_PROV_PDU_OB_REPORT, msg);
+	msg[n++] = prov->cli_pdu_num;
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, true, n, msg);
+}
+
+static void srv_close(void *user_data, uint8_t reason)
+{
+	struct rem_prov_data *prov = user_data;
+	uint8_t msg[4];
+	int n;
+
+	if (prov != rpb_prov || prov->state < PB_REMOTE_STATE_LINK_ACTIVE)
+		return;
+
+	l_debug("Remote PB Close");
+
+	prov->state = PB_REMOTE_STATE_LINK_CLOSING;
+	n = mesh_model_opcode_set(OP_REM_PROV_LINK_REPORT, msg);
+	msg[n++] = prov->state;
+	msg[n++] = reason;
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, true, n, msg);
+}
+
+static void send_prov_status(struct rem_prov_data *prov, uint8_t status)
+{
+	uint16_t n;
+	uint8_t msg[5];
+	bool segmented = prov->state == PB_REMOTE_STATE_LINK_CLOSING ?
+								true : false;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_LINK_STATUS, msg);
+	msg[n++] = status;
+	msg[n++] = prov->state;
+
+	l_info("RPB-Link Status(%d): dst %4.4x", prov->state, prov->client);
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, segmented, n, msg);
+}
+
+static void remprv_prov_cancel(struct l_timeout *timeout,
+						void *user_data)
+{
+	struct rem_prov_data *prov = user_data;
+
+	if (prov != rpb_prov)
+		return;
+
+	l_timeout_remove(prov->timeout);
+	l_free(prov);
+	rpb_prov = NULL;
+}
+
+static void deregister_ext_ad_type(uint8_t ad_type)
+{
+	uint8_t short_ad;
+
+	switch (ad_type) {
+	case BT_AD_MESH_BEACON:
+	case BT_AD_MESH_DATA:
+	case BT_AD_MESH_PROV:
+	case BT_AD_UUID16_SOME:
+	case BT_AD_UUID32_SOME:
+	case BT_AD_UUID128_SOME:
+	case BT_AD_NAME_SHORT:
+		return;
+
+	case BT_AD_UUID16_ALL:
+	case BT_AD_UUID32_ALL:
+	case BT_AD_UUID128_ALL:
+	case BT_AD_NAME_COMPLETE:
+		/* Automatically get short versions */
+		short_ad = ad_type - 1;
+		mesh_io_deregister_recv_cb(NULL, &short_ad, 1);
+
+		/* fall through */
+	default:
+		mesh_io_deregister_recv_cb(NULL, &ad_type, 1);
+		break;
+	}
+}
+
+static void remprv_scan_cancel(struct l_timeout *timeout,
+						void *user_data)
+{
+	struct rem_scan_data *scan = user_data;
+	uint8_t msg[22 + EXT_LIST_SIZE];
+	uint16_t i, n;
+
+	if (!scan || scan != rpb_scan)
+		return;
+
+	for (n = 0; n < scan->ext_cnt; n++)
+		deregister_ext_ad_type(scan->ext[n]);
+
+	if (scan->timeout == timeout) {
+		/* Return Extended Results */
+		if (scan->ext_cnt) {
+			/* Return Extended Result */
+			n = mesh_model_opcode_set(
+					OP_REM_PROV_EXT_SCAN_REPORT, msg);
+			msg[n++] = PB_REM_ERR_SUCCESS;
+			memcpy(msg + n, scan->uuid, 16);
+			n += 16;
+
+			if (scan->oob_info) {
+				l_put_le16(0, msg + n);
+				n += 2;
+			}
+
+			i = 0;
+			while (scan->list[i]) {
+				msg[n++] = scan->list[i];
+				memcpy(msg + n, &scan->list[i + 1],
+								scan->list[i]);
+				n += scan->list[i];
+				i += scan->list[i] + 1;
+			}
+		}
+	}
+
+	l_timeout_remove(scan->timeout);
+	l_free(scan->list);
+	l_free(scan);
+	rpb_scan = NULL;
+}
+
+static void scan_pkt(void *user_data, struct mesh_io_recv_info *info,
+					const uint8_t *data, uint16_t len)
+{
+	struct rem_scan_data *scan = user_data;
+	uint8_t msg[22 + EXT_LIST_SIZE];
+	uint8_t addr[6];
+	uint16_t i, n;
+	int8_t rssi;
+	uint8_t filled = 0;
+	bool report = false;
+
+	if (scan != rpb_scan)
+		return;
+
+	if (info) {
+		rssi = info->rssi;
+		memcpy(addr, info->addr, 6);
+	} else {
+		rssi = 0;
+		memset(addr, 0, 6);
+	}
+
+	if (scan->ext_cnt)
+		goto extended_scan;
+
+	/* RX Unprovisioned Beacon */
+	if (data[0] != BT_AD_MESH_BEACON || data[1] ||
+			(len != 18 && len != 20 && len != 24))
+		return;
+
+	data += 2;
+	len -= 2;
+
+	for (n = 0; !report && n < scan->scanned_limit; n++) {
+		if (!memcmp(&scan->list[n * 17 + 1], data, 16)) {
+
+			/* Repeat UUID, check RSSI */
+			if ((int8_t) scan->list[n * 17] < rssi) {
+				report = true;
+				scan->list[n * 17] = (uint8_t) rssi;
+			}
+
+		} else if (!memcmp(&scan->list[n * 17 + 1], zero, 16)) {
+
+			/* Found Empty slot */
+			report = true;
+			scan->list[n * 17] = (uint8_t) rssi;
+			memcpy(&scan->list[n * 17 + 1], data, 16);
+		}
+
+		filled++;
+	}
+
+	if (!report)
+		return;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_SCAN_REPORT, msg);
+	msg[n++] = (uint8_t) rssi;
+	memcpy(msg + n, data, len);
+	n += len;
+
+	/* Always return oob_info, even if it wasn't in beacon */
+	if (len == 16) {
+		l_put_le16(0, msg + n);
+		n += 2;
+	}
+
+	goto send_report;
+
+extended_scan:
+	if (data[0] == BT_AD_MESH_BEACON && !data[1]) {
+		if (len != 18 && len != 20 && len != 24)
+			return;
+
+		/* Check UUID */
+		if (memcmp(data + 2, scan->uuid, 16))
+			return;
+
+		/* Zero AD list if prior data RXed from different bd_addr */
+		if (memcmp(scan->addr, addr, 6)) {
+			scan->list[0] = 0;
+			scan->rxed_ads = 0;
+		}
+
+		memcpy(scan->addr, addr, 6);
+		scan->fltr = true;
+
+		if (len >= 20)
+			scan->oob_info = l_get_le16(data + 18);
+
+		if (scan->rxed_ads != scan->ext_cnt)
+			return;
+
+
+	} else if (data[0] != BT_AD_MESH_BEACON) {
+		if (!scan->fltr || !memcmp(scan->addr, addr, 6)) {
+			i = 0;
+			while (scan->list[i]) {
+				/* check if seen */
+				if (scan->list[i + 1] == data[0])
+					return;
+
+				i += scan->list[i] + 1;
+			}
+
+			/* Overflow Protection */
+			if (i + len + 1 > EXT_LIST_SIZE)
+				return;
+
+			scan->list[i] = len;
+			scan->list[i + len + 1] = 0;
+			memcpy(scan->list + i + 1, data, len);
+			scan->rxed_ads++;
+		}
+
+		if (scan->rxed_ads != scan->ext_cnt)
+			return;
+
+	} else
+		return;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_EXT_SCAN_REPORT, msg);
+	msg[n++] = PB_REM_ERR_SUCCESS;
+	memcpy(msg + n, scan->uuid, 16);
+	n += 16;
+	l_put_le16(scan->oob_info, msg + n);
+	n += 2;
+
+	i = 0;
+	while (scan->list[i]) {
+		msg[n++] = scan->list[i];
+		memcpy(msg + n, &scan->list[i + 1], scan->list[i]);
+		n += scan->list[i];
+		i += scan->list[i];
+	}
+
+send_report:
+	print_packet("App Tx", msg, n);
+	mesh_model_send(scan->node, 0, scan->client, APP_IDX_DEV_LOCAL,
+				scan->net_idx, DEFAULT_TTL, true, n, msg);
+
+	/* Clean-up if we are done reporting*/
+	if (filled == scan->scanned_limit || scan->ext_cnt)
+		remprv_scan_cancel(NULL, scan);
+}
+
+static bool register_ext_ad_type(uint8_t ad_type, struct rem_scan_data *scan)
+{
+	uint8_t short_ad;
+
+	switch (ad_type) {
+	case BT_AD_MESH_PROV:
+	case BT_AD_UUID16_SOME:
+	case BT_AD_UUID32_SOME:
+	case BT_AD_UUID128_SOME:
+	case BT_AD_NAME_SHORT:
+		/* Illegal Requests */
+		return false;
+
+	case BT_AD_UUID16_ALL:
+	case BT_AD_UUID32_ALL:
+	case BT_AD_UUID128_ALL:
+	case BT_AD_NAME_COMPLETE:
+		/* Automatically get short versions */
+		short_ad = ad_type - 1;
+		mesh_io_register_recv_cb(NULL, &short_ad, 1, scan_pkt, scan);
+
+		/* fall through */
+	default:
+		mesh_io_register_recv_cb(NULL, &ad_type, 1, scan_pkt, scan);
+
+		/* fall through */
+
+	case BT_AD_MESH_BEACON:
+		/* Ignored/auto request */
+		break;
+	}
+
+	return true;
+}
+
+static void link_active(void *user_data)
+{
+	struct rem_prov_data *prov = user_data;
+	uint8_t msg[5];
+	int n;
+
+	if (prov != rpb_prov || prov->state != PB_REMOTE_STATE_LINK_OPENING)
+		return;
+
+	l_debug("Remote Link open confirmed");
+	prov->state = PB_REMOTE_STATE_LINK_ACTIVE;
+
+	n = mesh_model_opcode_set(OP_REM_PROV_LINK_REPORT, msg);
+	msg[n++] = PB_REM_ERR_SUCCESS;
+	msg[n++] = PB_REMOTE_STATE_LINK_ACTIVE;
+
+	mesh_model_send(prov->node, 0, prov->client, APP_IDX_DEV_LOCAL,
+				prov->net_idx, DEFAULT_TTL, true, n, msg);
+}
+
+bool register_nppi_acceptor(mesh_prov_open_func_t open_cb,
+					mesh_prov_close_func_t close_cb,
+					mesh_prov_receive_func_t rx_cb,
+					mesh_prov_ack_func_t ack_cb,
+					void *user_data)
+{
+	struct rem_prov_data *prov = rpb_prov;
+
+	if (!prov || prov->nppi_proc == RPR_ADV)
+		return false;
+
+	prov->u.nppi.open_cb = open_cb;
+	prov->u.nppi.close_cb = close_cb;
+	prov->u.nppi.rx_cb = rx_cb;
+	prov->u.nppi.ack_cb = ack_cb;
+	prov->trans_data = user_data;
+
+	open_cb(user_data, srv_rx, prov, prov->nppi_proc);
+
+	l_idle_oneshot(link_active, prov, NULL);
+
+	return true;
+}
+
+static bool nppi_cmplt(void *user_data, uint8_t status,
+					struct mesh_prov_node_info *info)
+{
+	struct rem_prov_data *prov = user_data;
+
+	if (prov != rpb_prov)
+		return false;
+
+	/* Save new info to apply on Link Close */
+	prov->u.nppi.info = *info;
+	return true;
+}
+
+static bool start_dev_key_refresh(struct mesh_node *node, uint8_t nppi_proc,
+						struct rem_prov_data *prov)
+{
+	uint8_t num_ele = node_get_num_elements(node);
+
+	prov->nppi_proc = nppi_proc;
+	return acceptor_start(num_ele, NULL, 0x0001, 60, NULL, nppi_cmplt,
+									prov);
+}
+
+static bool remprv_srv_pkt(uint16_t src, uint16_t unicast, uint16_t app_idx,
+					uint16_t net_idx, const uint8_t *data,
+					uint16_t size, const void *user_data)
+{
+	struct rem_prov_data *prov = rpb_prov;
+	struct rem_scan_data *scan = rpb_scan;
+	struct mesh_node *node = (struct mesh_node *) user_data;
+	const uint8_t *pkt = data;
+	bool segmented = false;
+	uint32_t opcode;
+	uint8_t msg[69];
+	uint8_t old_state, status;
+	uint16_t n;
+
+	if (app_idx != APP_IDX_DEV_LOCAL)
+		return false;
+
+	if (mesh_model_opcode_get(pkt, size, &opcode, &n)) {
+		size -= n;
+		pkt += n;
+	} else
+		return false;
+
+	n = 0;
+
+	switch (opcode) {
+	default:
+		return false;
+
+	case OP_REM_PROV_SCAN_CAP_GET:
+		if (size != 0)
+			return true;
+
+		/* Compose Scan Info Status */
+		n = mesh_model_opcode_set(OP_REM_PROV_SCAN_CAP_STATUS, msg);
+		msg[n++] = PB_REMOTE_MAX_SCAN_QUEUE_SIZE;
+		msg[n++] = 1; /* Active Scanning Supported */
+		break;
+
+	case OP_REM_PROV_EXT_SCAN_START:
+		if (!size || !pkt[0])
+			return true;
+
+		/* Size check the message */
+		if (pkt[0] + 18 == size) {
+			/* Range check the Timeout */
+			if (!pkt[size - 1] || pkt[size - 1] > 5)
+				return true;
+		} else if (pkt[0] + 1 != size)
+			return true;
+
+		/* Get local device extended info */
+		if (pkt[0] + 18 != size) {
+			n = mesh_model_opcode_set(
+					OP_REM_PROV_EXT_SCAN_REPORT, msg);
+			msg[n++] = PB_REM_ERR_SUCCESS;
+			memcpy(msg + n, node_uuid_get(node), 16);
+			n += 16;
+			l_put_le16(0, msg + n);
+			n += 2;
+			size--;
+			pkt++;
+
+			while (size--) {
+				if (*pkt++ == BT_AD_NAME_COMPLETE) {
+					msg[n] = strlen(name) + 1;
+					if (msg[n] > sizeof(msg) - n - 1)
+						msg[n] = sizeof(msg) - n - 1;
+					n++;
+					msg[n++] = BT_AD_NAME_COMPLETE;
+					memcpy(&msg[n], name, msg[n - 2] - 1);
+					n += msg[n - 2] - 1;
+					goto send_pkt;
+				}
+			}
+
+			/* Send internal report */
+			l_debug("Send internal extended info %d", n);
+			goto send_pkt;
+		}
+
+		status = PB_REM_ERR_SUCCESS;
+		if (scan) {
+			if (scan->client != src || scan->node != node ||
+						scan->ext_cnt != pkt[0])
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+			else if (memcmp(scan->ext, pkt + 1, pkt[0]))
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+			else if (memcmp(scan->uuid, pkt + 2, 16))
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+		}
+
+		if (status != PB_REM_ERR_SUCCESS) {
+			n = mesh_model_opcode_set(OP_REM_PROV_EXT_SCAN_REPORT,
+									msg);
+			msg[n++] = status;
+			memset(msg + n, 0, 16);
+			n += 16;
+			segmented = true;
+			break;
+		}
+
+		/* Ignore extended requests while already scanning */
+		if (scan)
+			return true;
+
+		scan = (void *) l_new(uint8_t,
+					sizeof(struct rem_scan_data) + pkt[0]);
+
+		/* Validate and register Extended AD types */
+		for (n = 0; n < pkt[0]; n++) {
+			if (!register_ext_ad_type(pkt[1 + n], scan)) {
+				/* Invalid AD type detected -- Undo */
+				while (n--)
+					deregister_ext_ad_type(pkt[1 + n]);
+
+				l_free(scan);
+				return true;
+			}
+		}
+
+		rpb_scan = scan;
+		scan->client = src;
+		scan->net_idx = net_idx;
+		memcpy(scan->uuid, pkt + size - 17, 16);
+		scan->ext_cnt = pkt[0];
+		memcpy(scan->ext, pkt + 1, pkt[0]);
+		scan->list = l_malloc(EXT_LIST_SIZE);
+		scan->list[0] = 0;
+
+		mesh_io_register_recv_cb(NULL, prvb, sizeof(prvb),
+								scan_pkt, scan);
+
+		scan->timeout = l_timeout_create(pkt[size-1],
+						remprv_scan_cancel, scan, NULL);
+		return true;
+
+	case OP_REM_PROV_SCAN_START:
+		if (size != 2 && size != 18)
+			return true;
+
+		/* Reject Timeout of Zero */
+		if (!pkt[1])
+			return true;
+
+		status = PB_REM_ERR_SUCCESS;
+		if (scan) {
+			if (scan->ext_cnt || scan->client != src ||
+							scan->node != node)
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+			else if (!!(scan->fltr) != !!(size != 18))
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+			else if (scan->fltr && memcmp(scan->uuid, pkt + 2, 16))
+				status = PB_REM_ERR_SCANNING_CANNOT_START;
+		}
+
+		if (status != PB_REM_ERR_SUCCESS) {
+			n = mesh_model_opcode_set(OP_REM_PROV_SCAN_STATUS, msg);
+			msg[n++] = status;
+			msg[n++] = scan ? scan->state : 0;
+			msg[n++] = scan ? scan->scanned_limit :
+						PB_REMOTE_MAX_SCAN_QUEUE_SIZE;
+			msg[n++] = scan ? scan->to_secs : 0;
+			break;
+		}
+
+		if (!scan)
+			scan = l_new(struct rem_scan_data, 1);
+
+		rpb_scan = scan;
+
+		if (size == 18) {
+			memcpy(scan->uuid, pkt + 2, 16);
+			scan->fltr = true;
+			scan->state = 0x02; /* Limited */
+		} else {
+			memset(scan->uuid, 0, 16);
+			scan->fltr = false;
+			scan->state = 0x01; /* Unlimited */
+		}
+
+		scan->client = src;
+		scan->net_idx = net_idx;
+		scan->node = node;
+
+		if (!scan->list)
+			scan->list = l_new(uint8_t,
+					23 * PB_REMOTE_MAX_SCAN_QUEUE_SIZE);
+
+		mesh_io_register_recv_cb(NULL, prvb, 2, scan_pkt, scan);
+
+		scan->to_secs = pkt[1];
+
+		if (pkt[0])
+			scan->scanned_limit = pkt[0];
+		else
+			scan->scanned_limit = PB_REMOTE_MAX_SCAN_QUEUE_SIZE;
+
+		scan->timeout = l_timeout_create(pkt[1],
+					remprv_scan_cancel, scan, NULL);
+
+		/* fall through */
+
+	case OP_REM_PROV_SCAN_GET:
+		/* Compose Scan Status */
+		n = mesh_model_opcode_set(OP_REM_PROV_SCAN_STATUS, msg);
+		msg[n++] = PB_REM_ERR_SUCCESS;
+		msg[n++] = scan ? scan->state : 0;
+		msg[n++] = scan ? scan->scanned_limit :
+						PB_REMOTE_MAX_SCAN_QUEUE_SIZE;
+		msg[n++] = scan ? scan->to_secs : 0;
+		break;
+
+	case OP_REM_PROV_SCAN_STOP:
+		if (size != 0 || !scan)
+			return true;
+
+		remprv_scan_cancel(NULL, scan);
+		return true;
+
+	case OP_REM_PROV_LINK_GET:
+		if (size != 0 || !prov)
+			return true;
+
+		send_prov_status(prov, PB_REM_ERR_SUCCESS);
+		return true;
+
+	case OP_REM_PROV_LINK_OPEN:
+		/* Sanity check args */
+		if (size != 16 && size != 17 && size != 1)
+			return true;
+
+		if (size == 17 && (pkt[16] == 0 || pkt[16] > 0x3c))
+			return true;
+
+		if (size == 1 && pkt[0] > 0x02)
+			return true;
+
+		if (prov) {
+			if (prov->client != src || prov->node != node ||
+				(size == 1 && prov->nppi_proc != pkt[0]) ||
+				(size >= 16 && (prov->nppi_proc != RPR_ADV ||
+					memcmp(prov->u.adv.uuid, pkt, 16)))) {
+
+				/* Send Reject (in progress) */
+				send_prov_status(prov, PB_REM_ERR_CANNOT_OPEN);
+				n = mesh_model_opcode_set(
+						OP_REM_PROV_LINK_STATUS, msg);
+				msg[n++] = PB_REM_ERR_CANNOT_OPEN;
+				msg[n++] = PB_REMOTE_STATE_LINK_ACTIVE;
+				break;
+			}
+
+			/* Send redundant  Success */
+			send_prov_status(prov, PB_REM_ERR_SUCCESS);
+			return true;
+		}
+
+		if (scan && scan->client != src && scan->node != node) {
+			n = mesh_model_opcode_set(OP_REM_PROV_LINK_STATUS, msg);
+			msg[n++] = PB_REM_ERR_CANNOT_OPEN;
+			msg[n++] = PB_REMOTE_STATE_LINK_ACTIVE;
+			break;
+		}
+
+		print_packet("Remote Prov Link Open", pkt, size);
+
+		remprv_scan_cancel(NULL, scan);
+
+		rpb_prov = prov = l_new(struct rem_prov_data, 1);
+		prov->client = src;
+		prov->net_idx = net_idx;
+		prov->node = node;
+		prov->state = PB_REMOTE_STATE_LINK_OPENING;
+
+		if (size == 1) {
+			status = start_dev_key_refresh(node, pkt[0], prov);
+
+		} else {
+			if (size == 17)
+				prov->timeout = l_timeout_create(pkt[16],
+						remprv_prov_cancel, prov, NULL);
+
+
+			prov->nppi_proc = RPR_ADV;
+			memcpy(prov->u.adv.uuid, pkt, 16);
+			status = pb_adv_reg(true, srv_open, srv_close, srv_rx,
+							srv_ack, pkt, prov);
+		}
+
+		if (status)
+			send_prov_status(prov, PB_REM_ERR_SUCCESS);
+		else {
+			n = mesh_model_opcode_set(OP_REM_PROV_LINK_STATUS, msg);
+			msg[n++] = PB_REM_ERR_CANNOT_OPEN;
+			msg[n++] = PB_REMOTE_STATE_IDLE;
+			remprv_prov_cancel(NULL, prov);
+		}
+
+		return true;
+
+	case OP_REM_PROV_LINK_CLOSE:
+		if (size != 1)
+			return true;
+
+		if (!prov || prov->node != node || prov->client != src)
+			return true;
+
+		old_state = prov->state;
+		prov->state = PB_REMOTE_STATE_LINK_CLOSING;
+		mesh_io_send_cancel(NULL, &pkt_filter, sizeof(pkt_filter));
+		send_prov_status(prov, PB_REM_ERR_SUCCESS);
+		if (pkt[0] == 0x02 &&
+				old_state >= PB_REMOTE_STATE_LINK_ACTIVE) {
+			msg[0] = PROV_FAILED;
+			msg[1] = PROV_ERR_CANT_ASSIGN_ADDR;
+			if (prov->nppi_proc == RPR_ADV)
+				prov->u.adv.tx(prov->trans_data, msg, 2);
+			else
+				prov->u.nppi.rx_cb(prov->trans_data, msg, 2);
+		}
+
+		if (prov->nppi_proc == RPR_ADV)
+			pb_adv_unreg(prov);
+
+		else if (prov->nppi_proc <= RPR_COMP) {
+			/* Hard or Soft refresh of local node, based on NPPI */
+			node_refresh(prov->node, (prov->nppi_proc == RPR_ADDR),
+							&prov->u.nppi.info);
+		}
+
+		remprv_prov_cancel(NULL, prov);
+
+		return true;
+
+	case OP_REM_PROV_PDU_SEND:
+		if (!prov || prov->node != node || prov->client != src)
+			return true;
+
+		if (size < 2)
+			return true;
+
+
+		prov->cli_pdu_num = *pkt++;
+		size--;
+		prov->state = PB_REMOTE_STATE_OB_PKT_TX;
+
+		if (prov->nppi_proc == RPR_ADV)
+			prov->u.adv.tx(prov->trans_data, pkt, size);
+		else {
+			srv_ack(prov, prov->cli_pdu_num);
+			prov->u.nppi.rx_cb(prov->trans_data, pkt, size);
+		}
+
+		return true;
+	}
+
+send_pkt:
+	l_info("PB-SVR: src %4.4x dst %4.4x", unicast, src);
+	print_packet("App Tx", msg, n);
+	mesh_model_send(node, 0, src, APP_IDX_DEV_LOCAL,
+				net_idx, DEFAULT_TTL, segmented, n, msg);
+
+	return true;
+}
+
+static void remprv_srv_unregister(void *user_data)
+{
+}
+
+static const struct mesh_model_ops ops = {
+	.unregister = remprv_srv_unregister,
+	.recv = remprv_srv_pkt,
+	.bind = NULL,
+	.sub = NULL,
+	.pub = NULL
+};
+
+void remote_prov_server_init(struct mesh_node *node, uint8_t ele_idx)
+{
+	mesh_model_register(node, ele_idx, REM_PROV_SRV_MODEL, &ops, node);
+}
diff --git a/mesh/remprv.h b/mesh/remprv.h
new file mode 100644
index 0000000..ab7e32b
--- /dev/null
+++ b/mesh/remprv.h
@@ -0,0 +1,78 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  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.
+ *
+ */
+
+#define REM_PROV_SRV_MODEL	SET_ID(SIG_VENDOR, 0x0004)
+#define REM_PROV_CLI_MODEL	SET_ID(SIG_VENDOR, 0x0005)
+
+#define PB_REMOTE_MAX_SCAN_QUEUE_SIZE	5
+
+#define PB_REMOTE_STATE_IDLE		0x00
+#define PB_REMOTE_STATE_LINK_OPENING	0x01
+#define PB_REMOTE_STATE_LINK_ACTIVE	0x02
+#define PB_REMOTE_STATE_OB_PKT_TX	0x03
+#define PB_REMOTE_STATE_LINK_CLOSING	0x04
+
+#define PB_REMOTE_TYPE_LOCAL	0x01
+#define PB_REMOTE_TYPE_ADV	0x02
+#define PB_REMOTE_TYPE_GATT	0x04
+
+#define PB_REMOTE_SCAN_TYPE_NONE	0x00
+#define PB_REMOTE_SCAN_TYPE_UNLIMITED	0x01
+#define PB_REMOTE_SCAN_TYPE_LIMITED	0x02
+#define PB_REMOTE_SCAN_TYPE_DETAILED	0x03
+
+/* Remote Provisioning Opcode List */
+#define OP_REM_PROV_SCAN_CAP_GET	0x804F
+#define OP_REM_PROV_SCAN_CAP_STATUS	0x8050
+#define OP_REM_PROV_SCAN_GET		0x8051
+#define OP_REM_PROV_SCAN_START		0x8052
+#define OP_REM_PROV_SCAN_STOP		0x8053
+#define OP_REM_PROV_SCAN_STATUS		0x8054
+#define OP_REM_PROV_SCAN_REPORT		0x8055
+#define OP_REM_PROV_EXT_SCAN_START	0x8056
+#define OP_REM_PROV_EXT_SCAN_REPORT	0x8057
+#define OP_REM_PROV_LINK_GET		0x8058
+#define OP_REM_PROV_LINK_OPEN		0x8059
+#define OP_REM_PROV_LINK_CLOSE		0x805A
+#define OP_REM_PROV_LINK_STATUS		0x805B
+#define OP_REM_PROV_LINK_REPORT		0x805C
+#define OP_REM_PROV_PDU_SEND		0x805D
+#define OP_REM_PROV_PDU_OB_REPORT	0x805E
+#define OP_REM_PROV_PDU_REPORT		0x805F
+
+/* Remote Provisioning Errors */
+#define PB_REM_ERR_SUCCESS			0x00
+#define PB_REM_ERR_SCANNING_CANNOT_START	0x01
+#define PB_REM_ERR_INVALID_STATE		0x02
+#define PB_REM_ERR_LIMITED_RESOURCES		0x03
+#define PB_REM_ERR_CANNOT_OPEN			0x04
+#define PB_REM_ERR_OPEN_FAILED			0x05
+#define PB_REM_ERR_CLOSED_BY_DEVICE		0x06
+#define PB_REM_ERR_CLOSED_BY_SERVER		0x07
+#define PB_REM_ERR_CLOSED_BY_CLIENT		0x08
+#define PB_REM_ERR_CLOSED_CANNOT_RX_PDU		0x09
+#define PB_REM_ERR_CLOSED_CANNOT_TX_PDU		0x0A
+
+void remote_prov_server_init(struct mesh_node *node, uint8_t ele_idx);
+void remote_prov_client_init(struct mesh_node *node, uint8_t ele_idx);
+bool register_nppi_acceptor(mesh_prov_open_func_t open_cb,
+					mesh_prov_close_func_t close_cb,
+					mesh_prov_receive_func_t rx_cb,
+					mesh_prov_ack_func_t ack_cb,
+					void *user_data);
diff --git a/mesh/rpl.c b/mesh/rpl.c
index 1213ee6..69533bf 100644
--- a/mesh/rpl.c
+++ b/mesh/rpl.c
@@ -31,7 +31,7 @@
 #include "mesh/util.h"
 #include "mesh/rpl.h"
 
-const char *rpl_dir = "/rpl";
+static const char *rpl_dir = "/rpl";
 
 bool rpl_put_entry(struct mesh_node *node, uint16_t src, uint32_t iv_index,
 								uint32_t seq)
@@ -146,7 +146,7 @@ static void get_entries(const char *iv_path, struct l_queue *rpl_list)
 	if (!dir)
 		return;
 
-	iv_txt = basename(iv_path);
+	iv_txt = mesh_basename(iv_path);
 	if (sscanf(iv_txt, "%08x", &iv_index) != 1) {
 		closedir(dir);
 		return;
diff --git a/mesh/util.c b/mesh/util.c
index 82b57f6..73f13aa 100644
--- a/mesh/util.c
+++ b/mesh/util.c
@@ -161,3 +161,13 @@ void enable_debug(void)
 	debug_enabled = true;
 	l_debug_enable("*");
 }
+
+#if !HAVE_DECL_BASENAME
+#include <string.h>
+const char *mesh_basename(const char *path)
+{
+	const char *base = strrchr(path, '/');
+
+	return base ? base + 1 : path;
+}
+#endif
diff --git a/mesh/util.h b/mesh/util.h
index 085ec33..bb417dc 100644
--- a/mesh/util.h
+++ b/mesh/util.h
@@ -16,3 +16,8 @@ void print_packet(const char *label, const void *data, uint16_t size);
 int create_dir(const char *dir_name);
 void del_path(const char *path);
 void enable_debug(void);
+#if !HAVE_DECL_BASENAME
+const char *mesh_basename(const char *path);
+#else
+#define mesh_basename basename
+#endif
diff --git a/missing b/missing
new file mode 100755
index 0000000..1fe1611
--- /dev/null
+++ b/missing
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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, 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, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try '$0 --help' for more information"
+  exit 1
+fi
+
+case $1 in
+
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
+
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
+
+perl_URL=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'autom4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
+    ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/monitor/a2dp.c b/monitor/a2dp.c
index f6e99ab..ae88f56 100644
--- a/monitor/a2dp.c
+++ b/monitor/a2dp.c
@@ -47,6 +47,8 @@
 #define APTX_HD_CODEC_ID	0x0024
 #define LDAC_VENDOR_ID		0x0000012d
 #define LDAC_CODEC_ID		0x00aa
+#define OPUS_G_VENDOR_ID	0x000000e0
+#define OPUS_G_CODEC_ID		0x0001
 
 struct bit_desc {
 	uint8_t bit_num;
@@ -201,6 +203,24 @@ static const struct bit_desc faststream_source_frequency_table[] = {
 	{ }
 };
 
+static const struct bit_desc opus_g_frequency_table[] = {
+	{  7, "48000" },
+	{ }
+};
+
+static const struct bit_desc opus_g_duration_table[] = {
+	{  3, "10 ms" },
+	{  4, "20 ms" },
+	{ }
+};
+
+static const struct bit_desc opus_g_channels_table[] = {
+	{  0, "Mono" },
+	{  1, "Stereo" },
+	{  2, "Dual Mono" },
+	{ }
+};
+
 static void print_value_bits(uint8_t indent, uint32_t value,
 						const struct bit_desc *table)
 {
@@ -244,6 +264,7 @@ static bool codec_vendor_aptx_ll_cfg(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_aptx_hd_cap(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_aptx_hd_cfg(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_ldac(uint8_t losc, struct l2cap_frame *frame);
+static bool codec_vendor_opus_g(uint8_t losc, struct l2cap_frame *frame);
 
 static const struct vndcodec vndcodecs[] = {
 	{ APTX_VENDOR_ID, APTX_CODEC_ID, "aptX",
@@ -256,6 +277,8 @@ static const struct vndcodec vndcodecs[] = {
 	  codec_vendor_aptx_hd_cap, codec_vendor_aptx_hd_cfg },
 	{ LDAC_VENDOR_ID, LDAC_CODEC_ID, "LDAC",
 	  codec_vendor_ldac, codec_vendor_ldac },
+	{ OPUS_G_VENDOR_ID, OPUS_G_CODEC_ID, "Opus (Google)",
+	  codec_vendor_opus_g, codec_vendor_opus_g },
 	{ }
 };
 
@@ -685,6 +708,31 @@ static bool codec_vendor_ldac(uint8_t losc, struct l2cap_frame *frame)
 	return true;
 }
 
+static bool codec_vendor_opus_g(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint8_t cap = 0;
+
+	if (losc != 1)
+		return false;
+
+	l2cap_frame_get_u8(frame, &cap);
+
+	print_field("%*cFrequency: 0x%02x", BASE_INDENT + 2, ' ', cap & 0x80);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_frequency_table);
+
+	print_field("%*cFrame Duration: 0x%02x", BASE_INDENT + 2, ' ',
+								cap & 0x18);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_duration_table);
+
+	print_field("%*cChannel Mode: 0x%02x", BASE_INDENT + 2, ' ',
+								cap & 0x07);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_channels_table);
+
+	print_field("%*cReserved: 0x%02x", BASE_INDENT + 2, ' ', cap & 0x60);
+
+	return true;
+}
+
 static bool codec_vendor_cap(uint8_t losc, struct l2cap_frame *frame)
 {
 	uint32_t vendor_id = 0;
diff --git a/monitor/analyze.c b/monitor/analyze.c
index a20ba98..3cc482c 100644
--- a/monitor/analyze.c
+++ b/monitor/analyze.c
@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/time.h>
+#include <unistd.h>
 
 #include "lib/bluetooth.h"
 
@@ -28,6 +29,9 @@
 #include "monitor/packet.h"
 #include "monitor/analyze.h"
 
+#define TIMEVAL_MSEC(_tv) \
+	(long long)((_tv)->tv_sec * 1000 + (_tv)->tv_usec / 1000)
+
 struct hci_dev {
 	uint16_t index;
 	uint8_t type;
@@ -55,45 +59,121 @@ struct hci_dev {
 #define CONN_LE_ACL	0x04
 #define CONN_LE_ISO	0x05
 
+struct hci_stats {
+	size_t bytes;
+	size_t num;
+	size_t num_comp;
+	struct packet_latency latency;
+	struct queue *plot;
+	uint16_t min;
+	uint16_t max;
+};
+
 struct hci_conn {
 	uint16_t handle;
+	uint16_t link;
 	uint8_t type;
 	uint8_t bdaddr[6];
 	bool setup_seen;
 	bool terminated;
-	unsigned long rx_num;
-	unsigned long tx_num;
-	unsigned long tx_num_comp;
-	size_t tx_bytes;
 	struct queue *tx_queue;
-	struct timeval tx_lat_min;
-	struct timeval tx_lat_max;
-	struct timeval tx_lat_med;
-	uint16_t tx_pkt_min;
-	uint16_t tx_pkt_max;
-	uint16_t tx_pkt_med;
+	struct timeval last_rx;
 	struct queue *chan_list;
+	struct hci_stats rx;
+	struct hci_stats tx;
+};
+
+struct hci_conn_tx {
+	struct timeval tv;
+	struct l2cap_chan *chan;
+};
+
+struct plot {
+	long long x_msec;
+	size_t y_count;
 };
 
 struct l2cap_chan {
 	uint16_t cid;
 	uint16_t psm;
 	bool out;
-	unsigned long num;
+	struct timeval last_rx;
+	struct hci_stats rx;
+	struct hci_stats tx;
 };
 
 static struct queue *dev_list;
 
+static void tmp_write(void *data, void *user_data)
+{
+	struct plot *plot = data;
+	FILE *tmp = user_data;
+
+	fprintf(tmp, "%lld %zu\n", plot->x_msec, plot->y_count);
+}
+
+static void plot_draw(struct queue *queue, const char *tittle)
+{
+	FILE *gplot;
+
+	if (queue_length(queue) < 2)
+		return;
+
+	gplot = popen("gnuplot", "w");
+	if (!gplot)
+		return;
+
+	fprintf(gplot, "$data << EOD\n");
+	queue_foreach(queue, tmp_write, gplot);
+	fprintf(gplot, "EOD\n");
+
+	fprintf(gplot, "set terminal dumb enhanced ansi\n");
+	fprintf(gplot, "set xlabel 'Latency (ms)'\n");
+	fprintf(gplot, "set tics out nomirror\n");
+	fprintf(gplot, "set log y\n");
+	fprintf(gplot, "set yrange [0.5:*]\n");
+	fprintf(gplot, "plot $data using 1:2 t '%s' w impulses\n", tittle);
+	fflush(gplot);
+
+	pclose(gplot);
+}
+
+static void print_stats(struct hci_stats *stats, const char *label)
+{
+	if (!stats->num)
+		return;
+
+	print_field("%s packets: %zu/%zu", label, stats->num, stats->num_comp);
+	print_field("%s Latency: %lld-%lld msec (~%lld msec)", label,
+			TV_MSEC(stats->latency.min),
+			TV_MSEC(stats->latency.max),
+			TV_MSEC(stats->latency.med));
+	print_field("%s size: %u-%u octets (~%zd octets)", label,
+			stats->min, stats->max, stats->bytes / stats->num);
+
+	if (TV_MSEC(stats->latency.total))
+		print_field("%s speed: ~%lld Kb/s", label,
+			stats->bytes * 8 / TV_MSEC(stats->latency.total));
+
+	plot_draw(stats->plot, label);
+}
+
 static void chan_destroy(void *data)
 {
 	struct l2cap_chan *chan = data;
 
-	printf("    Found %s L2CAP channel with CID %u\n",
+	if (!chan->rx.num && !chan->tx.num)
+		goto done;
+
+	printf("  Found %s L2CAP channel with CID %u\n",
 					chan->out ? "TX" : "RX", chan->cid);
 	if (chan->psm)
-		printf("      PSM %u\n", chan->psm);
-	printf("      %lu packets\n", chan->num);
+		print_field("PSM %u", chan->psm);
 
+	print_stats(&chan->rx, "RX");
+	print_stats(&chan->tx, "TX");
+
+done:
 	free(chan);
 }
 
@@ -106,6 +186,8 @@ static struct l2cap_chan *chan_alloc(struct hci_conn *conn, uint16_t cid,
 
 	chan->cid = cid;
 	chan->out = out;
+	chan->rx.plot = queue_new();
+	chan->tx.plot = queue_new();
 
 	return chan;
 }
@@ -161,32 +243,16 @@ static void conn_destroy(void *data)
 		break;
 	}
 
-	if (conn->tx_num > 0)
-		conn->tx_pkt_med = conn->tx_bytes / conn->tx_num;
-
 	printf("  Found %s connection with handle %u\n", str, conn->handle);
 	/* TODO: Store address type */
 	packet_print_addr("Address", conn->bdaddr, 0x00);
 	if (!conn->setup_seen)
 		print_field("Connection setup missing");
-	print_field("%lu RX packets", conn->rx_num);
-	print_field("%lu TX packets", conn->tx_num);
-	print_field("%lu TX completed packets", conn->tx_num_comp);
-	print_field("%lld msec min latency",
-			(long long)
-			(conn->tx_lat_min.tv_sec * 1000 +
-			conn->tx_lat_min.tv_usec / 1000));
-	print_field("%lld msec max latency",
-			(long long)
-			(conn->tx_lat_max.tv_sec * 1000 +
-			conn->tx_lat_max.tv_usec / 1000));
-	print_field("%lld msec median latency",
-			(long long)
-			(conn->tx_lat_med.tv_sec * 1000 +
-			conn->tx_lat_med.tv_usec / 1000));
-	print_field("%u octets TX min packet size", conn->tx_pkt_min);
-	print_field("%u octets TX max packet size", conn->tx_pkt_max);
-	print_field("%u octets TX median packet size", conn->tx_pkt_med);
+	print_stats(&conn->rx, "RX");
+	print_stats(&conn->tx, "TX");
+
+	queue_destroy(conn->rx.plot, free);
+	queue_destroy(conn->tx.plot, free);
 	queue_destroy(conn->chan_list, chan_destroy);
 
 	queue_destroy(conn->tx_queue, free);
@@ -203,6 +269,8 @@ static struct hci_conn *conn_alloc(struct hci_dev *dev, uint16_t handle,
 	conn->handle = handle;
 	conn->type = type;
 	conn->tx_queue = queue_new();
+	conn->tx.plot = queue_new();
+	conn->rx.plot = queue_new();
 
 	conn->chan_list = queue_new();
 
@@ -223,6 +291,20 @@ static struct hci_conn *conn_lookup(struct hci_dev *dev, uint16_t handle)
 						UINT_TO_PTR(handle));
 }
 
+static bool link_match_handle(const void *a, const void *b)
+{
+	const struct hci_conn *conn = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return (conn->link == handle && !conn->terminated);
+}
+
+static struct hci_conn *link_lookup(struct hci_dev *dev, uint16_t handle)
+{
+	return queue_find(dev->conn_list, link_match_handle,
+						UINT_TO_PTR(handle));
+}
+
 static struct hci_conn *conn_lookup_type(struct hci_dev *dev, uint16_t handle,
 								uint8_t type)
 {
@@ -230,7 +312,7 @@ static struct hci_conn *conn_lookup_type(struct hci_dev *dev, uint16_t handle,
 
 	conn = queue_find(dev->conn_list, conn_match_handle,
 						UINT_TO_PTR(handle));
-	if (!conn || conn->type != type) {
+	if (!conn || (type && conn->type != type)) {
 		conn = conn_alloc(dev, handle, type);
 		queue_push_tail(dev->conn_list, conn);
 	}
@@ -447,6 +529,70 @@ static void evt_cmd_complete(struct hci_dev *dev, struct timeval *tv,
 	}
 }
 
+static bool match_plot_latency(const void *data, const void *user_data)
+{
+	const struct plot *plot = data;
+	const struct timeval *latency = user_data;
+
+	return TIMEVAL_MSEC(latency) == plot->x_msec;
+}
+
+static void plot_add(struct queue *queue, struct timeval *latency,
+						uint16_t count)
+{
+	struct plot *plot;
+
+	/* Use LRU ordering */
+	plot = queue_remove_if(queue, match_plot_latency, latency);
+	if (plot) {
+		plot->y_count += count;
+		queue_push_head(queue, plot);
+		return;
+	}
+
+	plot = new0(struct plot, 1);
+	plot->x_msec = TIMEVAL_MSEC(latency);
+	plot->y_count = count;
+
+	queue_push_tail(queue, plot);
+}
+
+static void evt_le_conn_complete(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_conn_complete *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->handle), CONN_LE_ACL);
+	if (!conn)
+		return;
+
+	memcpy(conn->bdaddr, evt->peer_addr, 6);
+	conn->setup_seen = true;
+}
+
+static void evt_le_enh_conn_complete(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_enhanced_conn_complete *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->handle), CONN_LE_ACL);
+	if (!conn)
+		return;
+
+	memcpy(conn->bdaddr, evt->peer_addr, 6);
+	conn->setup_seen = true;
+}
+
 static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
 					const void *data, uint16_t size)
 {
@@ -461,7 +607,8 @@ static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
 		uint16_t count = get_le16(data + 2);
 		struct hci_conn *conn;
 		struct timeval res;
-		struct timeval *last_tx;
+		struct hci_conn_tx *last_tx;
+		int j;
 
 		data += 4;
 		size -= 4;
@@ -470,48 +617,165 @@ static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
 		if (!conn)
 			continue;
 
-		conn->tx_num_comp += count;
+		conn->tx.num_comp += count;
 
-		last_tx = queue_pop_head(conn->tx_queue);
-		if (last_tx) {
-			timersub(tv, last_tx, &res);
+		for (j = 0; j < count; j++) {
+			last_tx = queue_pop_head(conn->tx_queue);
+			if (last_tx) {
+				struct l2cap_chan *chan = last_tx->chan;
 
-			if ((!timerisset(&conn->tx_lat_min) ||
-					timercmp(&res, &conn->tx_lat_min, <)) &&
-					res.tv_sec >= 0 && res.tv_usec >= 0)
-				conn->tx_lat_min = res;
+				timersub(tv, &last_tx->tv, &res);
 
-			if (!timerisset(&conn->tx_lat_max) ||
-					timercmp(&res, &conn->tx_lat_max, >))
-				conn->tx_lat_max = res;
+				packet_latency_add(&conn->tx.latency, &res);
+				plot_add(conn->tx.plot, &res, 1);
 
-			if (timerisset(&conn->tx_lat_med)) {
-				struct timeval tmp;
+				if (chan) {
+					chan->tx.num_comp += count;
+					packet_latency_add(&chan->tx.latency,
+									&res);
+					plot_add(chan->tx.plot, &res, 1);
+				}
 
-				timeradd(&conn->tx_lat_med, &res, &tmp);
+				free(last_tx);
+			}
+		}
+	}
+}
 
-				tmp.tv_sec /= 2;
-				tmp.tv_usec /= 2;
-				if (tmp.tv_sec % 2) {
-					tmp.tv_usec += 500000;
-					if (tmp.tv_usec >= 1000000) {
-						tmp.tv_sec++;
-						tmp.tv_usec -= 1000000;
-					}
-				}
+static void evt_sync_conn_complete(struct hci_dev *dev, struct timeval *tv,
+					const void *data, uint16_t size)
+{
+	const struct bt_hci_evt_sync_conn_complete *evt = data;
+	struct hci_conn *conn;
 
-				conn->tx_lat_med = tmp;
-			} else
-				conn->tx_lat_med = res;
+	if (evt->status)
+		return;
 
-			free(last_tx);
-		}
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->handle), evt->link_type);
+	if (!conn)
+		return;
+
+	memcpy(conn->bdaddr, evt->bdaddr, 6);
+	conn->setup_seen = true;
+}
+
+static void evt_le_cis_established(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_cis_established *evt;
+	struct hci_conn *conn, *link;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->conn_handle),
+						CONN_LE_ISO);
+	if (!conn)
+		return;
+
+	conn->setup_seen = true;
+
+	link = link_lookup(dev, conn->handle);
+	if (link)
+		memcpy(conn->bdaddr, link->bdaddr, 6);
+}
+
+static void evt_le_cis_req(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_cis_req *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt)
+		return;
+
+	conn = conn_lookup(dev, le16_to_cpu(evt->acl_handle));
+	if (!conn)
+		return;
+
+	conn->link = le16_to_cpu(evt->cis_handle);
+}
+
+static void evt_le_big_complete(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_big_complete *evt;
+	int i;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	for (i = 0; i < evt->num_bis; i++) {
+		struct hci_conn *conn;
+		uint16_t handle;
+
+		if (!util_iov_pull_le16(iov, &handle))
+			return;
+
+		conn = conn_lookup_type(dev, handle, CONN_LE_ISO);
+		if (conn)
+			conn->setup_seen = true;
+	}
+}
+
+static void evt_le_big_sync_established(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_big_sync_estabilished *evt;
+	int i;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	for (i = 0; i < evt->num_bis; i++) {
+		struct hci_conn *conn;
+		uint16_t handle;
+
+		if (!util_iov_pull_le16(iov, &handle))
+			return;
+
+		conn = conn_lookup_type(dev, handle, CONN_LE_ISO);
+		if (conn)
+			conn->setup_seen = true;
 	}
 }
 
 static void evt_le_meta_event(struct hci_dev *dev, struct timeval *tv,
 					const void *data, uint16_t size)
 {
+	struct iovec iov = {
+		.iov_base = (void *)data,
+		.iov_len = size,
+	};
+	uint8_t subevt;
+
+	if (!util_iov_pull_u8(&iov, &subevt))
+		return;
+
+	switch (subevt) {
+	case BT_HCI_EVT_LE_CONN_COMPLETE:
+		evt_le_conn_complete(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE:
+		evt_le_enh_conn_complete(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_CIS_ESTABLISHED:
+		evt_le_cis_established(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_CIS_REQ:
+		evt_le_cis_req(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_BIG_COMPLETE:
+		evt_le_big_complete(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED:
+		evt_le_big_sync_established(dev, tv, &iov);
+		break;
+	}
 }
 
 static void event_pkt(struct timeval *tv, uint16_t index,
@@ -543,19 +807,79 @@ static void event_pkt(struct timeval *tv, uint16_t index,
 	case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
 		evt_num_completed_packets(dev, tv, data, size);
 		break;
+	case BT_HCI_EVT_SYNC_CONN_COMPLETE:
+		evt_sync_conn_complete(dev, tv, data, size);
+		break;
 	case BT_HCI_EVT_LE_META_EVENT:
 		evt_le_meta_event(dev, tv, data, size);
 		break;
 	}
 }
 
+static void stats_add(struct hci_stats *stats, uint16_t size)
+{
+	stats->num++;
+	stats->bytes += size;
+
+	if (!stats->min || size < stats->min)
+		stats->min = size;
+	if (!stats->max || size > stats->max)
+		stats->max = size;
+}
+
+static void conn_pkt_tx(struct hci_conn *conn, struct timeval *tv,
+				uint16_t size, struct l2cap_chan *chan)
+{
+	struct hci_conn_tx *last_tx;
+
+	last_tx = new0(struct hci_conn_tx, 1);
+	memcpy(last_tx, tv, sizeof(*tv));
+	last_tx->chan = chan;
+	queue_push_tail(conn->tx_queue, last_tx);
+
+	stats_add(&conn->tx, size);
+
+	if (chan)
+		stats_add(&chan->tx, size);
+}
+
+static void conn_pkt_rx(struct hci_conn *conn, struct timeval *tv,
+				uint16_t size, struct l2cap_chan *chan)
+{
+	struct timeval res;
+
+	if (timerisset(&conn->last_rx)) {
+		timersub(tv, &conn->last_rx, &res);
+		packet_latency_add(&conn->rx.latency, &res);
+		plot_add(conn->rx.plot, &res, 1);
+	}
+
+	conn->last_rx = *tv;
+
+	stats_add(&conn->rx, size);
+	conn->rx.num_comp++;
+
+	if (chan) {
+		if (timerisset(&chan->last_rx)) {
+			timersub(tv, &chan->last_rx, &res);
+			packet_latency_add(&chan->rx.latency, &res);
+			plot_add(chan->rx.plot, &res, 1);
+		}
+
+		chan->last_rx = *tv;
+
+		stats_add(&chan->rx, size);
+		chan->rx.num_comp++;
+	}
+}
+
 static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
 					const void *data, uint16_t size)
 {
 	const struct bt_hci_acl_hdr *hdr = data;
 	struct hci_dev *dev;
 	struct hci_conn *conn;
-	struct l2cap_chan *chan;
+	struct l2cap_chan *chan = NULL;
 	uint16_t cid;
 
 	data += sizeof(*hdr);
@@ -568,8 +892,7 @@ static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
 	dev->num_hci++;
 	dev->num_acl++;
 
-	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff,
-								CONN_BR_ACL);
+	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff, 0x00);
 	if (!conn)
 		return;
 
@@ -578,35 +901,24 @@ static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
 	case 0x02:
 		cid = get_le16(data + 2);
 		chan = chan_lookup(conn, cid, out);
-		if (chan)
-			chan->num++;
 		if (cid == 1)
 			l2cap_sig(conn, out, data + 4, size - 4);
 		break;
 	}
 
 	if (out) {
-		struct timeval *last_tx;
-
-		conn->tx_num++;
-		last_tx = new0(struct timeval, 1);
-		memcpy(last_tx, tv, sizeof(*tv));
-		queue_push_tail(conn->tx_queue, last_tx);
-		conn->tx_bytes += size;
-
-		if (!conn->tx_pkt_min || size < conn->tx_pkt_min)
-			conn->tx_pkt_min = size;
-		if (!conn->tx_pkt_max || size > conn->tx_pkt_max)
-			conn->tx_pkt_max = size;
+		conn_pkt_tx(conn, tv, size, chan);
 	} else {
-		conn->rx_num++;
+		conn_pkt_rx(conn, tv, size, chan);
 	}
 }
 
-static void sco_pkt(struct timeval *tv, uint16_t index,
+static void sco_pkt(struct timeval *tv, uint16_t index, bool out,
 					const void *data, uint16_t size)
 {
+	const struct bt_hci_acl_hdr *hdr = data;
 	struct hci_dev *dev;
+	struct hci_conn *conn;
 
 	dev = dev_lookup(index);
 	if (!dev)
@@ -614,6 +926,17 @@ static void sco_pkt(struct timeval *tv, uint16_t index,
 
 	dev->num_hci++;
 	dev->num_sco++;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff,
+								CONN_BR_SCO);
+	if (!conn)
+		return;
+
+	if (out) {
+		conn_pkt_tx(conn, tv, size - sizeof(*hdr), NULL);
+	} else {
+		conn_pkt_rx(conn, tv, size - sizeof(*hdr), NULL);
+	}
 }
 
 static void info_index(struct timeval *tv, uint16_t index,
@@ -677,9 +1000,11 @@ static void ctrl_msg(struct timeval *tv, uint16_t index,
 	dev->ctrl_msg++;
 }
 
-static void iso_pkt(struct timeval *tv, uint16_t index,
+static void iso_pkt(struct timeval *tv, uint16_t index, bool out,
 					const void *data, uint16_t size)
 {
+	const struct bt_hci_iso_hdr *hdr = data;
+	struct hci_conn *conn;
 	struct hci_dev *dev;
 
 	dev = dev_lookup(index);
@@ -688,6 +1013,17 @@ static void iso_pkt(struct timeval *tv, uint16_t index,
 
 	dev->num_hci++;
 	dev->num_iso++;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff,
+								CONN_LE_ISO);
+	if (!conn)
+		return;
+
+	if (out) {
+		conn_pkt_tx(conn, tv, size - sizeof(*hdr), NULL);
+	} else {
+		conn_pkt_rx(conn, tv, size - sizeof(*hdr), NULL);
+	}
 }
 
 static void unknown_opcode(struct timeval *tv, uint16_t index,
@@ -755,8 +1091,10 @@ void analyze_trace(const char *path)
 			acl_pkt(&tv, index, false, buf, pktlen);
 			break;
 		case BTSNOOP_OPCODE_SCO_TX_PKT:
+			sco_pkt(&tv, index, true, buf, pktlen);
+			break;
 		case BTSNOOP_OPCODE_SCO_RX_PKT:
-			sco_pkt(&tv, index, buf, pktlen);
+			sco_pkt(&tv, index, false, buf, pktlen);
 			break;
 		case BTSNOOP_OPCODE_OPEN_INDEX:
 		case BTSNOOP_OPCODE_CLOSE_INDEX:
@@ -780,8 +1118,10 @@ void analyze_trace(const char *path)
 			ctrl_msg(&tv, index, buf, pktlen);
 			break;
 		case BTSNOOP_OPCODE_ISO_TX_PKT:
+			iso_pkt(&tv, index, true, buf, pktlen);
+			break;
 		case BTSNOOP_OPCODE_ISO_RX_PKT:
-			iso_pkt(&tv, index, buf, pktlen);
+			iso_pkt(&tv, index, false, buf, pktlen);
 			break;
 		default:
 			unknown_opcode(&tv, index, buf, pktlen);
diff --git a/monitor/att.c b/monitor/att.c
index efd840d..3f41c2b 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2014  Intel Corporation
  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -21,7 +22,7 @@
 #include <inttypes.h>
 #include <stdbool.h>
 #include <errno.h>
-#include <linux/limits.h>
+#include <limits.h>
 #include <sys/stat.h>
 
 #include <glib.h>
@@ -42,12 +43,15 @@
 #include "display.h"
 #include "l2cap.h"
 #include "att.h"
+#include "keys.h"
 
 struct att_read {
+	struct att_conn_data *conn;
 	struct gatt_db_attribute *attr;
 	bool in;
 	uint16_t chan;
 	void (*func)(const struct l2cap_frame *frame);
+	struct iovec *iov;
 };
 
 struct att_conn_data {
@@ -56,6 +60,7 @@ struct att_conn_data {
 	struct gatt_db *rdb;
 	struct timespec rdb_mtim;
 	struct queue *reads;
+	uint16_t mtu;
 };
 
 static void print_uuid(const char *label, const void *data, uint16_t size)
@@ -106,27 +111,127 @@ static bool match_read_frame(const void *data, const void *match_data)
 	return read->chan == frame->chan;
 }
 
-static void print_data_list(const char *label, uint8_t length,
-					const struct l2cap_frame *frame)
+static struct att_read *att_get_read(const struct l2cap_frame *frame)
 {
 	struct packet_conn_data *conn;
 	struct att_conn_data *data;
+
+	conn = packet_get_conn_data(frame->handle);
+	if (!conn)
+		return NULL;
+
+	data = conn->data;
+	if (!data)
+		return NULL;
+
+	return queue_remove_if(data->reads, match_read_frame, (void *)frame);
+}
+
+static void print_value(struct gatt_db_attribute *attr)
+{
+	uint16_t handle;
+	struct gatt_db_attribute *val;
+	const bt_uuid_t *uuid;
+	bt_uuid_t chrc = {
+		.type = BT_UUID16,
+		.value.u16 = 0x2803,
+	};
+	char label[27];
+
+	uuid = gatt_db_attribute_get_type(attr);
+	if (!uuid)
+		return;
+
+	/* Skip in case of characteristic declaration since it already prints
+	 * the value handle and properties.
+	 */
+	if (!bt_uuid_cmp(uuid, &chrc))
+		return;
+
+	val = gatt_db_attribute_get_value(attr);
+	if (!val || val == attr)
+		return;
+
+	uuid = gatt_db_attribute_get_type(val);
+	if (!uuid)
+		return;
+
+	handle = gatt_db_attribute_get_handle(val);
+	if (!handle)
+		return;
+
+	switch (uuid->type) {
+	case BT_UUID16:
+		sprintf(label, "Value Handle: 0x%4.4x Type", handle);
+		print_field("%s: %s (0x%4.4x)", label,
+				bt_uuid16_to_str(uuid->value.u16),
+				uuid->value.u16);
+		return;
+	case BT_UUID128:
+		sprintf(label, "Value Handle: 0x%4.4x Type", handle);
+		print_uuid(label, &uuid->value.u128, 16);
+		return;
+	case BT_UUID_UNSPEC:
+	case BT_UUID32:
+		break;
+	}
+}
+
+static void print_attribute(struct gatt_db_attribute *attr)
+{
+	uint16_t handle;
+	const bt_uuid_t *uuid;
+	char label[21];
+
+	handle = gatt_db_attribute_get_handle(attr);
+	if (!handle)
+		goto done;
+
+	uuid = gatt_db_attribute_get_type(attr);
+	if (!uuid)
+		goto done;
+
+	switch (uuid->type) {
+	case BT_UUID16:
+		sprintf(label, "Handle: 0x%4.4x Type", handle);
+		print_field("%s: %s (0x%4.4x)", label,
+				bt_uuid16_to_str(uuid->value.u16),
+				uuid->value.u16);
+		print_value(attr);
+		return;
+	case BT_UUID128:
+		sprintf(label, "Handle: 0x%4.4x Type", handle);
+		print_uuid(label, &uuid->value.u128, 16);
+		print_value(attr);
+		return;
+	case BT_UUID_UNSPEC:
+	case BT_UUID32:
+		break;
+	}
+
+done:
+	print_field("Handle: 0x%4.4x", handle);
+}
+
+static void att_read_free(struct att_read *read)
+{
+	if (!read)
+		return;
+
+	util_iov_free(read->iov, 1);
+	free(read);
+}
+
+static void print_data_list(const char *label, uint8_t length,
+					const struct l2cap_frame *frame)
+{
 	struct att_read *read;
 	uint8_t count;
 
 	if (length == 0)
 		return;
 
-	conn = packet_get_conn_data(frame->handle);
-	if (conn) {
-		data = conn->data;
-		if (data)
-			read = queue_remove_if(data->reads, match_read_frame,
-						(void *)frame);
-		else
-			read = NULL;
-	} else
-		read = NULL;
+	read = att_get_read(frame);
 
 	count = frame->size / length;
 
@@ -138,7 +243,7 @@ static void print_data_list(const char *label, uint8_t length,
 
 		print_hex_field("Value", frame->data, length - 2);
 
-		if (read) {
+		if (read && read->func) {
 			struct l2cap_frame f;
 
 			l2cap_frame_clone_size(&f, frame, length - 2);
@@ -151,7 +256,7 @@ static void print_data_list(const char *label, uint8_t length,
 	}
 
 	packet_hexdump(frame->data, frame->size);
-	free(read);
+	att_read_free(read);
 }
 
 static void print_attribute_info(uint16_t type, const void *data, uint16_t len)
@@ -271,6 +376,13 @@ static void att_error_response(const struct l2cap_frame *frame)
 							pdu->request);
 	print_field("Handle: 0x%4.4x", le16_to_cpu(pdu->handle));
 	print_field("Error: %s (0x%2.2x)", str, pdu->error);
+
+	/* Read/Read By Type/Read By Group Type may create a read object which
+	 * needs to be dequeued and freed in case the operation fails.
+	 */
+	if (pdu->request == 0x08 || pdu->request == 0x0a ||
+					pdu->request == 0x10)
+		att_read_free(att_get_read(frame));
 }
 
 static const struct bitfield_data chrc_prop_table[] = {
@@ -285,10 +397,203 @@ static const struct bitfield_data chrc_prop_table[] = {
 	{ }
 };
 
+static void att_conn_data_free(void *data)
+{
+	struct att_conn_data *att_data = data;
+
+	gatt_db_unref(att_data->rdb);
+	gatt_db_unref(att_data->ldb);
+	queue_destroy(att_data->reads, free);
+	free(att_data);
+}
+
+static struct att_conn_data *att_get_conn_data(struct packet_conn_data *conn)
+{
+	struct att_conn_data *data;
+
+	if (!conn)
+		return NULL;
+
+	data = conn->data;
+
+	if (data)
+		return data;
+
+	data = new0(struct att_conn_data, 1);
+	data->rdb = gatt_db_new();
+	data->ldb = gatt_db_new();
+	conn->data = data;
+	conn->destroy = att_conn_data_free;
+
+	return data;
+}
+
+static void gatt_load_db(struct gatt_db *db, const char *filename,
+						struct timespec *mtim)
+{
+	struct stat st;
+
+	if (lstat(filename, &st))
+		return;
+
+	if (!gatt_db_isempty(db)) {
+		/* Check if file has been modified since last time */
+		if (st.st_mtim.tv_sec == mtim->tv_sec &&
+				    st.st_mtim.tv_nsec == mtim->tv_nsec)
+			return;
+		/* Clear db before reloading */
+		gatt_db_clear(db);
+	}
+
+	*mtim = st.st_mtim;
+
+	btd_settings_gatt_db_load(db, filename);
+}
+
+static void load_gatt_db(struct packet_conn_data *conn)
+{
+	struct att_conn_data *data = att_get_conn_data(conn);
+	char filename[PATH_MAX];
+	char local[18];
+	char peer[18];
+	uint8_t id[6], id_type;
+
+	ba2str((bdaddr_t *)conn->src, local);
+
+	if (keys_resolve_identity(conn->dst, id, &id_type))
+		ba2str((bdaddr_t *)id, peer);
+	else
+		ba2str((bdaddr_t *)conn->dst, peer);
+
+	create_filename(filename, PATH_MAX, "/%s/attributes", local);
+	gatt_load_db(data->ldb, filename, &data->ldb_mtim);
+
+	create_filename(filename, PATH_MAX, "/%s/cache/%s", local, peer);
+	gatt_load_db(data->rdb, filename, &data->rdb_mtim);
+}
+
+static struct gatt_db *get_db(const struct l2cap_frame *frame, bool rsp)
+{
+	struct packet_conn_data *conn;
+	struct att_conn_data *data;
+	struct gatt_db *db;
+
+	conn = packet_get_conn_data(frame->handle);
+	if (!conn)
+		return NULL;
+
+	/* Try loading local and remote gatt_db if not loaded yet */
+	load_gatt_db(conn);
+
+	data = conn->data;
+	if (!data)
+		return NULL;
+
+	if (frame->in) {
+		if (rsp)
+			db = data->rdb;
+		else
+			db = data->ldb;
+	} else {
+		if (rsp)
+			db = data->ldb;
+		else
+			db = data->rdb;
+	}
+
+	return db;
+}
+
+static struct gatt_db_attribute *insert_chrc(const struct l2cap_frame *frame,
+						uint16_t handle,
+						uint16_t value_handle,
+						bt_uuid_t *uuid, uint8_t prop,
+						bool rsp)
+{
+	struct gatt_db *db;
+
+	db = get_db(frame, rsp);
+	if (!db)
+		return NULL;
+
+	return gatt_db_insert_characteristic(db, handle, value_handle, uuid, 0,
+						prop, NULL, NULL, NULL);
+}
+
+static int bt_uuid_from_data(bt_uuid_t *uuid, const void *data, uint16_t size)
+{
+	uint128_t u128;
+
+	if (!uuid)
+		return -EINVAL;
+
+	switch (size) {
+	case 2:
+		return bt_uuid16_create(uuid, get_le16(data));
+	case 4:
+		return bt_uuid32_create(uuid, get_le32(data));
+	case 16:
+		memcpy(u128.data, data, sizeof(u128.data));
+		return bt_uuid128_create(uuid, u128);
+	}
+
+	return -EINVAL;
+}
+
+static bool svc_read(const struct l2cap_frame *frame, uint16_t *start,
+			uint16_t *end, bt_uuid_t *uuid)
+{
+	if (!l2cap_frame_get_le16((void *)frame, start))
+		return false;
+
+	if (!l2cap_frame_get_le16((void *)frame, end))
+		return false;
+
+	return !bt_uuid_from_data(uuid, frame->data, frame->size);
+}
+
+static struct gatt_db_attribute *insert_svc(const struct l2cap_frame *frame,
+						uint16_t handle,
+						bt_uuid_t *uuid, bool primary,
+						bool rsp, uint16_t num_handles)
+{
+	struct gatt_db *db;
+
+	db = get_db(frame, rsp);
+	if (!db)
+		return NULL;
+
+	return gatt_db_insert_service(db, handle, uuid, primary, num_handles);
+}
+
+static void pri_svc_read(const struct l2cap_frame *frame)
+{
+	uint16_t start, end;
+	bt_uuid_t uuid;
+
+	if (!svc_read(frame, &start, &end, &uuid))
+		return;
+
+	insert_svc(frame, start, &uuid, true, true, end - start + 1);
+}
+
+static void sec_svc_read(const struct l2cap_frame *frame)
+{
+	uint16_t start, end;
+	bt_uuid_t uuid;
+
+	if (!svc_read(frame, &start, &end, &uuid))
+		return;
+
+	insert_svc(frame, start, &uuid, true, false, end - start + 1);
+}
+
 static void print_chrc(const struct l2cap_frame *frame)
 {
 	uint8_t prop;
 	uint8_t mask;
+	uint16_t handle;
+	bt_uuid_t uuid;
 
 	if (!l2cap_frame_get_u8((void *)frame, &prop)) {
 		print_text(COLOR_ERROR, "Property: invalid size");
@@ -302,10 +607,16 @@ static void print_chrc(const struct l2cap_frame *frame)
 		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
 								mask);
 
-	if (!l2cap_frame_print_le16((void *)frame, "    Value Handle"))
+	if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+		print_text(COLOR_ERROR, "    Value Handle: invalid size");
 		return;
+	}
 
+	print_field("    Value Handle: 0x%4.4x", handle);
 	print_uuid("    Value UUID", frame->data, frame->size);
+	bt_uuid_from_data(&uuid, frame->data, frame->size);
+
+	insert_chrc(frame, handle - 1, handle, &uuid, prop, true);
 }
 
 static void chrc_read(const struct l2cap_frame *frame)
@@ -377,12 +688,20 @@ static bool print_ase_codec(const struct l2cap_frame *frame)
 	return true;
 }
 
-static bool print_ase_lv(const struct l2cap_frame *frame, const char *label,
-			struct packet_ltv_decoder *decoder, size_t decoder_len)
+static void print_ltv(const char *str, void *user_data)
 {
-	struct bt_hci_lv_data *lv;
+	const char *label = user_data;
 
-	lv = l2cap_frame_pull((void *)frame, frame, sizeof(*lv));
+	print_field("%s: %s", label, str);
+}
+
+static bool print_ase_lv(const struct l2cap_frame *frame, const char *label,
+			const struct util_ltv_debugger *decoder,
+			size_t decoder_len)
+{
+	struct bt_hci_lv_data *lv;
+
+	lv = l2cap_frame_pull((void *)frame, frame, sizeof(*lv));
 	if (!lv) {
 		print_text(COLOR_ERROR, "%s: invalid size", label);
 		return false;
@@ -393,13 +712,15 @@ static bool print_ase_lv(const struct l2cap_frame *frame, const char *label,
 		return false;
 	}
 
-	packet_print_ltv(label, lv->data, lv->len, decoder, decoder_len);
+	util_debug_ltv(lv->data, lv->len, decoder, decoder_len, print_ltv,
+			(void *) label);
 
 	return true;
 }
 
 static bool print_ase_cc(const struct l2cap_frame *frame, const char *label,
-			struct packet_ltv_decoder *decoder, size_t decoder_len)
+			const struct util_ltv_debugger *decoder,
+			size_t decoder_len)
 {
 	return print_ase_lv(frame, label, decoder, decoder_len);
 }
@@ -446,7 +767,8 @@ done:
 		print_hex_field("    Data", frame->data, frame->size);
 }
 
-static void ase_decode_preferred_context(const uint8_t *data, uint8_t len)
+static void ase_debug_preferred_context(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 
@@ -455,7 +777,8 @@ static void ase_decode_preferred_context(const uint8_t *data, uint8_t len)
 	print_context(&frame, "      Preferred Context");
 }
 
-static void ase_decode_context(const uint8_t *data, uint8_t len)
+static void ase_debug_context(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 
@@ -464,7 +787,8 @@ static void ase_decode_context(const uint8_t *data, uint8_t len)
 	print_context(&frame, "      Context");
 }
 
-static void ase_decode_program_info(const uint8_t *data, uint8_t len)
+static void ase_debug_program_info(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	const char *str;
@@ -484,7 +808,8 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-static void ase_decode_language(const uint8_t *data, uint8_t len)
+static void ase_debug_language(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint32_t value;
@@ -503,16 +828,17 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-struct packet_ltv_decoder ase_metadata_table[] = {
-	LTV_DEC(0x01, ase_decode_preferred_context),
-	LTV_DEC(0x02, ase_decode_context),
-	LTV_DEC(0x03, ase_decode_program_info),
-	LTV_DEC(0x04, ase_decode_language)
+static const struct util_ltv_debugger ase_metadata_table[] = {
+	UTIL_LTV_DEBUG(0x01, ase_debug_preferred_context),
+	UTIL_LTV_DEBUG(0x02, ase_debug_context),
+	UTIL_LTV_DEBUG(0x03, ase_debug_program_info),
+	UTIL_LTV_DEBUG(0x04, ase_debug_language)
 };
 
 static bool print_ase_metadata(const struct l2cap_frame *frame)
 {
-	return print_ase_lv(frame, "    Metadata", NULL, 0);
+	return print_ase_lv(frame, "    Metadata", ase_metadata_table,
+					ARRAY_SIZE(ase_metadata_table));
 }
 
 static const struct bitfield_data pac_freq_table[] = {
@@ -535,7 +861,8 @@ static const struct bitfield_data pac_freq_table[] = {
 	{ }
 };
 
-static void pac_decode_freq(const uint8_t *data, uint8_t len)
+static void pac_decode_freq(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint16_t value;
@@ -572,7 +899,8 @@ static const struct bitfield_data pac_duration_table[] = {
 	{ }
 };
 
-static void pac_decode_duration(const uint8_t *data, uint8_t len)
+static void pac_decode_duration(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -609,7 +937,8 @@ static const struct bitfield_data pac_channel_table[] = {
 	{ }
 };
 
-static void pac_decode_channels(const uint8_t *data, uint8_t len)
+static void pac_decode_channels(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -634,7 +963,8 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-static void pac_decode_frame_length(const uint8_t *data, uint8_t len)
+static void pac_decode_frame_length(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint16_t min, max;
@@ -659,7 +989,8 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-static void pac_decode_sdu(const uint8_t *data, uint8_t len)
+static void pac_decode_sdu(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -678,12 +1009,12 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-struct packet_ltv_decoder pac_cap_table[] = {
-	LTV_DEC(0x01, pac_decode_freq),
-	LTV_DEC(0x02, pac_decode_duration),
-	LTV_DEC(0x03, pac_decode_channels),
-	LTV_DEC(0x04, pac_decode_frame_length),
-	LTV_DEC(0x05, pac_decode_sdu)
+static const struct util_ltv_debugger pac_cap_table[] = {
+	UTIL_LTV_DEBUG(0x01, pac_decode_freq),
+	UTIL_LTV_DEBUG(0x02, pac_decode_duration),
+	UTIL_LTV_DEBUG(0x03, pac_decode_channels),
+	UTIL_LTV_DEBUG(0x04, pac_decode_frame_length),
+	UTIL_LTV_DEBUG(0x05, pac_decode_sdu)
 };
 
 static void print_pac(const struct l2cap_frame *frame)
@@ -819,7 +1150,8 @@ static bool print_ase_pd(const struct l2cap_frame *frame, const char *label)
 	return true;
 }
 
-static void ase_decode_freq(const uint8_t *data, uint8_t len)
+static void ase_debug_freq(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -845,31 +1177,31 @@ static void ase_decode_freq(const uint8_t *data, uint8_t len)
 		print_field("      Sampling Frequency: 22.05 Khz (0x04)");
 		break;
 	case 0x05:
-		print_field("      Sampling Frequency: 24 Khz (0x04)");
+		print_field("      Sampling Frequency: 24 Khz (0x05)");
 		break;
 	case 0x06:
-		print_field("      Sampling Frequency: 32 Khz (0x04)");
+		print_field("      Sampling Frequency: 32 Khz (0x06)");
 		break;
 	case 0x07:
-		print_field("      Sampling Frequency: 44.1 Khz (0x04)");
+		print_field("      Sampling Frequency: 44.1 Khz (0x07)");
 		break;
 	case 0x08:
-		print_field("      Sampling Frequency: 48 Khz (0x04)");
+		print_field("      Sampling Frequency: 48 Khz (0x08)");
 		break;
 	case 0x09:
-		print_field("      Sampling Frequency: 88.2 Khz (0x04)");
+		print_field("      Sampling Frequency: 88.2 Khz (0x09)");
 		break;
 	case 0x0a:
-		print_field("      Sampling Frequency: 96 Khz (0x04)");
+		print_field("      Sampling Frequency: 96 Khz (0x0a)");
 		break;
 	case 0x0b:
-		print_field("      Sampling Frequency: 176.4 Khz (0x04)");
+		print_field("      Sampling Frequency: 176.4 Khz (0x0b)");
 		break;
 	case 0x0c:
-		print_field("      Sampling Frequency: 192 Khz (0x04)");
+		print_field("      Sampling Frequency: 192 Khz (0x0c)");
 		break;
 	case 0x0d:
-		print_field("      Sampling Frequency: 384 Khz (0x04)");
+		print_field("      Sampling Frequency: 384 Khz (0x0d)");
 		break;
 	default:
 		print_field("      Sampling Frequency: RFU (0x%2.2x)", value);
@@ -881,7 +1213,8 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-static void ase_decode_duration(const uint8_t *data, uint8_t len)
+static void ase_debug_duration(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -968,7 +1301,8 @@ done:
 		print_hex_field("  Data", frame->data, frame->size);
 }
 
-static void ase_decode_location(const uint8_t *data, uint8_t len)
+static void ase_debug_location(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 
@@ -977,7 +1311,8 @@ static void ase_decode_location(const uint8_t *data, uint8_t len)
 	print_location(&frame);
 }
 
-static void ase_decode_frame_length(const uint8_t *data, uint8_t len)
+static void ase_debug_frame_length(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint16_t value;
@@ -996,7 +1331,8 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-static void ase_decode_blocks(const uint8_t *data, uint8_t len)
+static void ase_debug_blocks(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
 {
 	struct l2cap_frame frame;
 	uint8_t value;
@@ -1015,12 +1351,12 @@ done:
 		print_hex_field("    Data", frame.data, frame.size);
 }
 
-struct packet_ltv_decoder ase_cc_table[] = {
-	LTV_DEC(0x01, ase_decode_freq),
-	LTV_DEC(0x02, ase_decode_duration),
-	LTV_DEC(0x03, ase_decode_location),
-	LTV_DEC(0x04, ase_decode_frame_length),
-	LTV_DEC(0x05, ase_decode_blocks)
+static const struct util_ltv_debugger ase_cc_table[] = {
+	UTIL_LTV_DEBUG(0x01, ase_debug_freq),
+	UTIL_LTV_DEBUG(0x02, ase_debug_duration),
+	UTIL_LTV_DEBUG(0x03, ase_debug_location),
+	UTIL_LTV_DEBUG(0x04, ase_debug_frame_length),
+	UTIL_LTV_DEBUG(0x05, ase_debug_blocks)
 };
 
 static void print_ase_config(const struct l2cap_frame *frame)
@@ -1389,7 +1725,7 @@ static bool ase_release_cmd(const struct l2cap_frame *frame)
 	.func = _func, \
 }
 
-struct ase_cmd {
+static const struct ase_cmd {
 	const char *desc;
 	bool (*func)(const struct l2cap_frame *frame);
 } ase_cmd_table[] = {
@@ -1411,7 +1747,7 @@ struct ase_cmd {
 	ASE_CMD(0x08, "Release", ase_release_cmd),
 };
 
-static struct ase_cmd *ase_get_cmd(uint8_t op)
+static const struct ase_cmd *ase_get_cmd(uint8_t op)
 {
 	if (op > ARRAY_SIZE(ase_cmd_table))
 		return NULL;
@@ -1422,7 +1758,7 @@ static struct ase_cmd *ase_get_cmd(uint8_t op)
 static void print_ase_cmd(const struct l2cap_frame *frame)
 {
 	uint8_t op, num, i;
-	struct ase_cmd *cmd;
+	const struct ase_cmd *cmd;
 
 	if (!l2cap_frame_get_u8((void *)frame, &op)) {
 		print_text(COLOR_ERROR, "opcode: invalid size");
@@ -1590,7 +1926,7 @@ static bool print_ase_cp_rsp_reason(const struct l2cap_frame *frame)
 static void print_ase_cp_rsp(const struct l2cap_frame *frame)
 {
 	uint8_t op, num, i;
-	struct ase_cmd *cmd;
+	const struct ase_cmd *cmd;
 
 	if (!l2cap_frame_get_u8((void *)frame, &op)) {
 		print_text(COLOR_ERROR, "    opcode: invalid size");
@@ -1688,6 +2024,85 @@ static void pac_context_notify(const struct l2cap_frame *frame)
 	print_pac_context(frame);
 }
 
+static void csip_rank_read(const struct l2cap_frame *frame)
+{
+	uint8_t rank;
+
+	if (!l2cap_frame_get_u8((void *)frame, &rank)) {
+		print_text(COLOR_ERROR, "Rank: invalid size");
+		goto done;
+	}
+
+	print_field("    Rank: 0x%02x", rank);
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void csip_lock_read(const struct l2cap_frame *frame)
+{
+	uint8_t lock;
+
+	if (!l2cap_frame_get_u8((void *)frame, &lock)) {
+		print_text(COLOR_ERROR, "Lock: invalid size");
+		goto done;
+	}
+
+	switch (lock) {
+	case 0x01:
+		print_field("    Unlocked (0x%02x)", lock);
+		break;
+	case 0x02:
+		print_field("    Locked (0x%02x)", lock);
+		break;
+	default:
+		print_field("    RFU (0x%02x)", lock);
+		break;
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void print_csip_size(const struct l2cap_frame *frame)
+{
+	uint8_t size;
+
+	if (!l2cap_frame_get_u8((void *)frame, &size)) {
+		print_text(COLOR_ERROR, "Size: invalid size");
+		goto done;
+	}
+	print_field("    Size: 0x%02x", size);
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void csip_size_read(const struct l2cap_frame *frame)
+{
+	print_csip_size(frame);
+}
+
+static void csip_size_notify(const struct l2cap_frame *frame)
+{
+	print_csip_size(frame);
+}
+
+static void csip_sirk_read(const struct l2cap_frame *frame)
+{
+	if (frame->size)
+		print_hex_field("  SIRK", frame->data, frame->size);
+}
+
+static void csip_sirk_notify(const struct l2cap_frame *frame)
+{
+	if (frame->size)
+		print_hex_field("  SIRK", frame->data, frame->size);
+}
+
 static void print_vcs_state(const struct l2cap_frame *frame)
 {
 	uint8_t vol_set, mute, chng_ctr;
@@ -1761,7 +2176,7 @@ static bool vcs_absolute_cmd(const struct l2cap_frame *frame)
 	.func = _func, \
 }
 
-struct vcs_cmd {
+static const struct vcs_cmd {
 	const char *desc;
 	bool (*func)(const struct l2cap_frame *frame);
 } vcs_cmd_table[] = {
@@ -1781,7 +2196,7 @@ struct vcs_cmd {
 	VCS_CMD(0x06, "Mute", vcs_config_cmd),
 };
 
-static struct vcs_cmd *vcs_get_cmd(uint8_t op)
+static const struct vcs_cmd *vcs_get_cmd(uint8_t op)
 {
 	if (op > ARRAY_SIZE(vcs_cmd_table))
 		return NULL;
@@ -1792,7 +2207,7 @@ static struct vcs_cmd *vcs_get_cmd(uint8_t op)
 static void print_vcs_cmd(const struct l2cap_frame *frame)
 {
 	uint8_t op;
-	struct vcs_cmd *cmd;
+	const struct vcs_cmd *cmd;
 
 	if (!l2cap_frame_get_u8((void *)frame, &op)) {
 		print_text(COLOR_ERROR, "opcode: invalid size");
@@ -1876,6 +2291,8 @@ static void print_mp_name(const struct l2cap_frame *frame)
 	name = name2utf8((uint8_t *)frame->data, frame->size);
 
 	print_field("  Media Player Name: %s", name);
+
+	g_free(name);
 }
 
 static void mp_name_read(const struct l2cap_frame *frame)
@@ -1905,6 +2322,8 @@ static void print_track_title(const struct l2cap_frame *frame)
 	name = name2utf8((uint8_t *)frame->data, frame->size);
 
 	print_field("  Track Title: %s", name);
+
+	g_free(name);
 }
 
 static void track_title_read(const struct l2cap_frame *frame)
@@ -2031,227 +2450,889 @@ static void seeking_speed_notify(const struct l2cap_frame *frame)
 	print_seeking_speed(frame);
 }
 
-static const char *play_order_str(uint8_t order)
+static void print_bearer_name(const struct l2cap_frame *frame)
 {
-	switch (order) {
+	char *name;
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  Bearer Name: %s", name);
+
+	g_free(name);
+}
+
+static void bearer_name_read(const struct l2cap_frame *frame)
+{
+	print_bearer_name(frame);
+}
+
+static void bearer_name_notify(const struct l2cap_frame *frame)
+{
+	print_bearer_name(frame);
+}
+
+static void bearer_uci_read(const struct l2cap_frame *frame)
+{
+	char *name;
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  Bearer Uci Name: %s", name);
+
+	g_free(name);
+}
+
+static void print_technology_name(const struct l2cap_frame *frame)
+{
+	int8_t tech_id;
+	const char *str;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&tech_id)) {
+		print_text(COLOR_ERROR, "  Technology id:: invalid size");
+		goto done;
+	}
+
+	switch (tech_id) {
 	case 0x01:
-		return "Single once";
+		str = "3G";
+		break;
 	case 0x02:
-		return "Single repeat";
+		str = "4G";
+		break;
 	case 0x03:
-		return "In order once";
+		str = "LTE";
+		break;
 	case 0x04:
-		return "In order repeat";
+		str = "WiFi";
+		break;
 	case 0x05:
-		return "Oldest once";
+		str = "5G";
+		break;
 	case 0x06:
-		return "Oldest repeat";
+		str = "GSM";
+		break;
 	case 0x07:
-		return "Newest once";
+		str = "CDMA";
+		break;
 	case 0x08:
-		return "Newest repeat";
+		str = "2G";
+		break;
 	case 0x09:
-		return "Shuffle once";
-	case 0x0A:
-		return "Shuffle repeat";
+		str = "WCDMA";
+		break;
 	default:
-		return "RFU";
-	}
-}
-
-static void print_playing_order(const struct l2cap_frame *frame)
-{
-	int8_t playing_order;
-
-	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&playing_order)) {
-		print_text(COLOR_ERROR, "  Playing Order: invalid size");
-		goto done;
+		str = "Reserved";
+		break;
 	}
 
-	print_field("  Playing Order: %s", play_order_str(playing_order));
+	print_field("Technology: %s  (0x%2.2x)", str, tech_id);
 
 done:
 	if (frame->size)
 		print_hex_field("  Data", frame->data, frame->size);
 }
 
-static void playing_order_read(const struct l2cap_frame *frame)
+static void bearer_technology_read(const struct l2cap_frame *frame)
 {
-	print_playing_order(frame);
+	print_technology_name(frame);
 }
 
-static void playing_order_write(const struct l2cap_frame *frame)
+static void bearer_technology_notify(const struct l2cap_frame *frame)
 {
-	print_playing_order(frame);
+	print_technology_name(frame);
 }
 
-static void playing_order_notify(const struct l2cap_frame *frame)
+static void print_uri_scheme_list(const struct l2cap_frame *frame)
 {
-	print_playing_order(frame);
+	char *name;
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  Uri scheme Name: %s", name);
+
+	g_free(name);
 }
 
-static const struct bitfield_data playing_orders_table[] = {
-	{  0, "Single once (0x0001)"	    },
-	{  1, "Single repeat (0x0002)"		},
-	{  2, "In order once (0x0004)"		},
-	{  3, "In Order Repeat (0x0008)"	},
-	{  4, "Oldest once (0x0010)"		},
-	{  5, "Oldest repeat (0x0020)"		},
-	{  6, "Newest once (0x0040)"		},
-	{  7, "Newest repeat (0x0080)"	    },
-	{  8, "Shuffle once (0x0100)"		},
-	{  9, "Shuffle repeat (0x0200)"		},
-	{  10, "RFU (0x0400)"			    },
-	{  11, "RFU (0x0800)"		        },
-	{  12, "RFU (0x1000)"				},
-	{  13, "RFU (0x2000)"				},
-	{  14, "RFU (0x4000)"				},
-	{  15, "RFU (0x8000)"				},
-	{ }
-};
+static void bearer_uri_schemes_list_read(const struct l2cap_frame *frame)
+{
+	print_uri_scheme_list(frame);
+}
 
-static void print_playing_orders_supported(const struct l2cap_frame *frame)
+static void print_signal_strength(const struct l2cap_frame *frame)
 {
-	uint16_t supported_orders;
-	uint16_t mask;
+	uint8_t signal_strength;
 
-	if (!l2cap_frame_get_le16((void *)frame, &supported_orders)) {
-		print_text(COLOR_ERROR,
-				"    Supported Playing Orders: invalid size");
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&signal_strength)) {
+		print_text(COLOR_ERROR, " signal_strength:: invalid size");
 		goto done;
 	}
 
-	print_field("      Supported Playing Orders: 0x%4.4x",
-				supported_orders);
+	print_field("  signal_strength: %x", signal_strength);
 
-	mask = print_bitfield(8, supported_orders, playing_orders_table);
-	if (mask)
-		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%4.4x)",
-								mask);
+	if (signal_strength == 0)
+		print_field("  No Service");
+	else if (signal_strength == 0x64)
+		print_field("  Maximum signal strength");
+	else if ((signal_strength > 0) && (signal_strength < 0x64))
+		print_field("  Implementation specific");
+	else if (signal_strength == 0xFF)
+		print_field("  Signal strength is unavailable");
+	else
+		print_field("  RFU");
 
 done:
 	if (frame->size)
-		print_hex_field("    Data", frame->data, frame->size);
+		print_hex_field("  Data", frame->data, frame->size);
 }
 
-static void playing_orders_supported_read(const struct l2cap_frame *frame)
+static void bearer_signal_strength_read(const struct l2cap_frame *frame)
 {
-	print_playing_orders_supported(frame);
+	print_signal_strength(frame);
 }
 
-static const char *media_state_str(uint8_t state)
+static void bearer_signal_strength_notify(const struct l2cap_frame *frame)
 {
-	switch (state) {
-	case 0x00:
-		return "Inactive";
-	case 0x01:
-		return "Playing";
-	case 0x02:
-		return "Paused";
-	case 0x03:
-		return "Seeking";
-	default:
-		return "RFU";
-	}
+	print_signal_strength(frame);
 }
 
-static void print_media_state(const struct l2cap_frame *frame)
+static void
+print_signal_strength_rep_intrvl(const struct l2cap_frame *frame)
 {
-	int8_t state;
+	int8_t reporting_intrvl;
 
-	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&state)) {
-		print_text(COLOR_ERROR, "  Media State: invalid size");
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&reporting_intrvl)) {
+		print_text(COLOR_ERROR, "Reporting_interval:: invalid size");
 		goto done;
 	}
 
-	print_field("  Media State: %s", media_state_str(state));
+	print_field("  Reporting_interval: 0x%x", reporting_intrvl);
 
 done:
 	if (frame->size)
 		print_hex_field("  Data", frame->data, frame->size);
 }
 
-static void media_state_read(const struct l2cap_frame *frame)
+static void
+bearer_signal_strength_rep_intrvl_read(const struct l2cap_frame *frame)
 {
-	print_media_state(frame);
+	print_signal_strength_rep_intrvl(frame);
 }
 
-static void media_state_notify(const struct l2cap_frame *frame)
+static void
+bearer_signal_strength_rep_intrvl_write(const struct l2cap_frame *frame)
 {
-	print_media_state(frame);
+	print_signal_strength_rep_intrvl(frame);
 }
 
-struct media_cp_opcode {
-	uint8_t opcode;
-	const char *opcode_str;
-} media_cp_opcode_table[] = {
-	{0x01,	"Play"},
-	{0x02,	"Pause"},
-	{0x03,	"Fast Rewind"},
-	{0x04,	"Fast Forward"},
-	{0x05,	"Stop"},
-	{0x10,	"Move Relative"},
-	{0x20,	"Previous Segment"},
-	{0x21,	"Next Segment"},
-	{0x22,	"First Segment"},
-	{0x23,	"Last Segment"},
-	{0x24,	"Goto Segment"},
-	{0x30,	"Previous Track"},
-	{0x31,	"Next Track"},
-	{0x32,	"First Track"},
-	{0x33,	"Last Track"},
-	{0x34,	"Goto Track"},
-	{0x40,	"Previous Group"},
-	{0x41,	"Next Group"},
-	{0x42,	"First Group"},
-	{0x43,	"Last Group"},
-	{0x44,	"Goto Group"},
-};
-
-static const char *cp_opcode_str(uint8_t opcode)
+static void print_call_list(const struct l2cap_frame *frame)
 {
-	size_t i;
+	uint8_t list_item_length;
+	uint8_t call_index;
+	uint8_t call_state;
+	uint8_t call_flag;
+	char *call_uri;
 
-	for (i = 0; i < ARRAY_SIZE(media_cp_opcode_table); i++) {
-		const char *str = media_cp_opcode_table[i].opcode_str;
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&list_item_length)) {
+		print_text(COLOR_ERROR, "    list_item_length:: invalid size");
+		goto done;
+	}
 
-		if (opcode == media_cp_opcode_table[i].opcode)
-			return str;
+	print_field("  list_item_length: 0x%x", list_item_length);
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_index)) {
+		print_text(COLOR_ERROR, "  call_index:: invalid size");
+		goto done;
 	}
 
-	return "RFU";
-}
+	print_field("  call_index: 0x%x", call_index);
 
-static void print_media_cp(const struct l2cap_frame *frame)
-{
-	int8_t opcode;
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_state)) {
+		print_text(COLOR_ERROR, "  call_state:: invalid size");
+		goto done;
+	}
 
-	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&opcode)) {
-		print_text(COLOR_ERROR, "  Media Control Point: invalid size");
+	print_field("  call_state: 0x%x", call_state);
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_flag)) {
+		print_text(COLOR_ERROR, "  call_flag:: invalid size");
 		goto done;
 	}
 
-	print_field("  Media Control Point: %s", cp_opcode_str(opcode));
+	print_field("  call_flag: 0x%x", call_flag);
+
+	call_uri = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  call_uri: %s", call_uri);
+
+	g_free(call_uri);
 
 done:
 	if (frame->size)
-		print_hex_field("  Data", frame->data, frame->size);
+		print_hex_field("  call_list Data", frame->data, frame->size);
 }
 
-static void media_cp_write(const struct l2cap_frame *frame)
+static void bearer_current_call_list_read(const struct l2cap_frame *frame)
 {
-	print_media_cp(frame);
+	print_call_list(frame);
 }
 
-static void media_cp_notify(const struct l2cap_frame *frame)
+static void bearer_current_call_list_notify(const struct l2cap_frame *frame)
 {
-	print_media_cp(frame);
+	print_call_list(frame);
 }
 
-static const struct bitfield_data supported_opcodes_table[] = {
-	{0, "Play (0x00000001)"				},
-	{1, "Pause (0x00000002)"			},
-	{2, "Fast Rewind	(0x00000004)"	},
+static void print_ccid(const struct l2cap_frame *frame)
+{
+	int8_t ccid;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&ccid)) {
+		print_text(COLOR_ERROR, "  ccid:: invalid size");
+		goto done;
+	}
+
+	print_field("  ccid: %x", ccid);
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void call_content_control_id_read(const struct l2cap_frame *frame)
+{
+	print_ccid(frame);
+}
+
+static void print_status_flag(const struct l2cap_frame *frame)
+{
+	int16_t flag;
+
+	if (!l2cap_frame_get_le16((void *)frame, (uint16_t *)&flag)) {
+		print_text(COLOR_ERROR, "  status flag:: invalid size");
+		goto done;
+	}
+
+	print_field("  status flag:");
+
+	if (flag & 0x1)
+		print_field("  Inband Ringtone Enabled:");
+	else
+		print_field("  Inband Ringtone Disabled:");
+
+	if (flag & 0x2)
+		print_field("  Server in silent Mode");
+	else
+		print_field("  Server Not in silent Mode");
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void status_flag_read(const struct l2cap_frame *frame)
+{
+	print_status_flag(frame);
+}
+
+static void status_flag_notify(const struct l2cap_frame *frame)
+{
+	print_status_flag(frame);
+}
+
+static void print_target_uri(const struct l2cap_frame *frame)
+{
+	char *name;
+	uint8_t call_idx;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_idx)) {
+		print_text(COLOR_ERROR, "  call_idx:: invalid size");
+		goto done;
+	}
+
+	print_field("  call_idx: %x", call_idx);
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  Uri: %s", name);
+
+	g_free(name);
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void incom_target_bearer_uri_read(const struct l2cap_frame *frame)
+{
+	print_target_uri(frame);
+}
+
+static void incom_target_bearer_uri_notify(const struct l2cap_frame *frame)
+{
+	print_target_uri(frame);
+}
+
+static void print_call_state(const struct l2cap_frame *frame)
+{
+	uint8_t call_Index;
+	uint8_t call_state;
+	uint8_t call_flag;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_Index)) {
+		print_text(COLOR_ERROR, "  call_Index:: invalid index");
+		goto done;
+	}
+
+	print_field("  call_Index: 0x%2.2x", call_Index);
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_state)) {
+		print_text(COLOR_ERROR, "  call_state:: invalid state");
+		goto done;
+	}
+
+	print_field("  call_state: 0x%2.2x", call_state);
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&call_flag)) {
+		print_text(COLOR_ERROR, "  call_flag:: invalid flag");
+		goto done;
+	}
+
+	print_field("  call_flag: 0x%2.2x", call_flag);
+
+done:
+	if (frame->size)
+		print_hex_field("   call_state Data", frame->data, frame->size);
+}
+
+static void call_state_read(const struct l2cap_frame *frame)
+{
+	print_call_state(frame);
+}
+
+static void call_state_notify(const struct l2cap_frame *frame)
+{
+	print_call_state(frame);
+}
+
+static void print_call_cp(const struct l2cap_frame *frame)
+{
+	uint8_t opcode;
+	uint8_t parameter;
+	const char *str;
+	char *name;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&opcode)) {
+		print_text(COLOR_ERROR, "  opcode:: invalid size");
+		goto done;
+	}
+
+	print_field("  opcode: 0x%2.2x", opcode);
+
+	switch (opcode) {
+	case 0x00:
+		str = "Accept";
+		if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&parameter)) {
+			print_text(COLOR_ERROR, "  parameter:: invalid size");
+			goto done;
+		}
+		print_field("  Operation: %s  (0x%2.2x)", str, parameter);
+		break;
+	case 0x01:
+		str = "Terminate";
+		if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&parameter)) {
+			print_text(COLOR_ERROR, "  parameter:: invalid size");
+			goto done;
+		}
+		print_field("  Operation: %s  (0x%2.2x)", str, parameter);
+		break;
+	case 0x02:
+		str = "Local Hold";
+		if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&parameter)) {
+			print_text(COLOR_ERROR, "  parameter:: invalid size");
+			goto done;
+		}
+		print_field("  Operation: %s  (0x%2.2x)", str, parameter);
+		break;
+	case 0x03:
+		str = "Local Retrieve";
+		if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&parameter)) {
+			print_text(COLOR_ERROR, "  parameter:: invalid size");
+			goto done;
+		}
+		print_field("  Operation: %s  (0x%2.2x)", str, parameter);
+		break;
+	case 0x04:
+		str = "Originate";
+		name = name2utf8((uint8_t *)frame->data, frame->size);
+		print_field("  Operation: %s  Uri: %s", str, name);
+		g_free(name);
+		break;
+	case 0x05:
+		str = "Join";
+		if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&parameter)) {
+			print_text(COLOR_ERROR, "  parameter:: invalid size");
+			goto done;
+		}
+		print_field("  Operation: %s  (0x%2.2x)", str, parameter);
+		break;
+	default:
+		str = "RFU";
+		print_field("  Operation: %s", str);
+		break;
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("call_cp Data", frame->data, frame->size);
+}
+
+static void print_call_cp_notification(const struct l2cap_frame *frame)
+{
+	uint8_t opcode;
+	uint8_t result_code;
+	const char *str;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&opcode)) {
+		print_text(COLOR_ERROR, "  result_code:: invalid opcode");
+		goto done;
+	}
+
+	print_field("  opcode: 0x%2.2x", opcode);
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&result_code)) {
+		print_text(COLOR_ERROR, "  result_code:: invalid result_code");
+		goto done;
+	}
+
+	print_field("  result_code: 0x%2.2x", result_code);
+
+	switch (result_code) {
+	case 0x00:
+		str = "SUCCESS";
+		break;
+	case 0x01:
+		str = "OPCODE NOT SUPPORTED";
+		break;
+	case 0x02:
+		str = "OPERATION NOT POSSIBLE";
+		break;
+	case 0x03:
+		str = "INVALID CALL INDEX";
+		break;
+	case 0x04:
+		str = "STATE MISMATCH";
+		break;
+	case 0x05:
+		str = "LACK OF RESOURCES";
+		break;
+	case 0x06:
+		str = "INVALID OUTGOING URI";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("  Status: %s", str);
+
+done:
+	if (frame->size)
+		print_hex_field("  call_cp Data", frame->data, frame->size);
+}
+
+static void call_cp_write(const struct l2cap_frame *frame)
+{
+	print_call_cp(frame);
+}
+
+static void call_cp_notify(const struct l2cap_frame *frame)
+{
+	print_call_cp_notification(frame);
+}
+
+static void print_call_cp_opt(const struct l2cap_frame *frame)
+{
+	uint16_t operation;
+
+	if (!l2cap_frame_get_le16((void *)frame, (uint16_t *)&operation)) {
+		print_text(COLOR_ERROR, "  status operation:: invalid size");
+		goto done;
+	}
+
+	print_field("  operation: 0x%2x", operation);
+
+	if (operation & 0x1) {
+		print_field("  Local Hold and Local Retrieve "
+								"Call Control Point Opcodes supported");
+	} else {
+		print_field("  Local Hold and Local Retrieve "
+								"Call Control Point Opcodes not supported");
+	}
+
+	if (operation & 0x2)
+		print_field("  Join Call Control Point Opcode supported");
+	else
+		print_field("  Join Call Control Point Opcode not supported");
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void call_cp_opt_opcodes_read(const struct l2cap_frame *frame)
+{
+	print_call_cp_opt(frame);
+}
+
+static void print_term_reason(const struct l2cap_frame *frame)
+{
+	uint8_t call_id, reason;
+
+	if (!l2cap_frame_get_u8((void *)frame, &call_id)) {
+		print_text(COLOR_ERROR, "Call Index: invalid size");
+		goto done;
+	}
+	print_field("  call Index: %u", call_id);
+
+	if (!l2cap_frame_get_u8((void *)frame, &reason)) {
+		print_text(COLOR_ERROR, "Reason: invalid size");
+		goto done;
+	}
+
+	print_field("  Reason:");
+
+	switch (reason) {
+	case 0x00:
+		print_field("  Improper URI");
+		break;
+	case 0x01:
+		print_field("  Call Failed");
+		break;
+	case 0x02:
+		print_field("  Remote party ended the call");
+		break;
+	case 0x03:
+		print_field("  Server  ended the call");
+		break;
+	case 0x04:
+		print_field("  Line was Busy");
+		break;
+	case 0x05:
+		print_field("  Network Congestion");
+		break;
+	case 0x06:
+		print_field("  Client terminated the call");
+		break;
+	case 0x07:
+		print_field("  No service");
+		break;
+	case 0x08:
+		print_field("  No answer");
+		break;
+	case 0x09:
+		print_field("  Unspecified");
+		break;
+	default:
+		print_field("  RFU");
+		break;
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void call_termination_reason_notify(const struct l2cap_frame *frame)
+{
+	print_term_reason(frame);
+}
+
+static void print_incom_call(const struct l2cap_frame *frame)
+{
+	char *name;
+	uint8_t call_id;
+
+	if (!l2cap_frame_get_u8((void *)frame, &call_id)) {
+		print_text(COLOR_ERROR, "Call Index: invalid size");
+		goto done;
+	}
+
+	print_field("  Call Index: %u", call_id);
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  call_string: %s", name);
+
+	g_free(name);
+
+done:
+	if (frame->size)
+		print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void incoming_call_read(const struct l2cap_frame *frame)
+{
+	print_incom_call(frame);
+}
+
+static void incoming_call_notify(const struct l2cap_frame *frame)
+{
+	print_incom_call(frame);
+}
+
+static void print_call_friendly_name(const struct l2cap_frame *frame)
+{
+	char *name;
+	uint8_t call_id;
+
+	if (!l2cap_frame_get_u8((void *)frame, &call_id)) {
+		print_text(COLOR_ERROR, "Call Index: invalid size");
+		goto done;
+	}
+
+	print_field("  Call Index: %u", call_id);
+
+	name = name2utf8((uint8_t *)frame->data, frame->size);
+
+	print_field("  Friendly Name: %s", name);
+
+	g_free(name);
+
+done:
+	if (frame->size)
+		print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void call_friendly_name_read(const struct l2cap_frame *frame)
+{
+	print_call_friendly_name(frame);
+}
+
+static void call_friendly_name_notify(const struct l2cap_frame *frame)
+{
+	print_call_friendly_name(frame);
+}
+
+static const char *play_order_str(uint8_t order)
+{
+	switch (order) {
+	case 0x01:
+		return "Single once";
+	case 0x02:
+		return "Single repeat";
+	case 0x03:
+		return "In order once";
+	case 0x04:
+		return "In order repeat";
+	case 0x05:
+		return "Oldest once";
+	case 0x06:
+		return "Oldest repeat";
+	case 0x07:
+		return "Newest once";
+	case 0x08:
+		return "Newest repeat";
+	case 0x09:
+		return "Shuffle once";
+	case 0x0A:
+		return "Shuffle repeat";
+	default:
+		return "RFU";
+	}
+}
+
+static void print_playing_order(const struct l2cap_frame *frame)
+{
+	int8_t playing_order;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&playing_order)) {
+		print_text(COLOR_ERROR, "  Playing Order: invalid size");
+		goto done;
+	}
+
+	print_field("  Playing Order: %s", play_order_str(playing_order));
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void playing_order_read(const struct l2cap_frame *frame)
+{
+	print_playing_order(frame);
+}
+
+static void playing_order_write(const struct l2cap_frame *frame)
+{
+	print_playing_order(frame);
+}
+
+static void playing_order_notify(const struct l2cap_frame *frame)
+{
+	print_playing_order(frame);
+}
+
+static const struct bitfield_data playing_orders_table[] = {
+	{  0, "Single once (0x0001)"	    },
+	{  1, "Single repeat (0x0002)"		},
+	{  2, "In order once (0x0004)"		},
+	{  3, "In Order Repeat (0x0008)"	},
+	{  4, "Oldest once (0x0010)"		},
+	{  5, "Oldest repeat (0x0020)"		},
+	{  6, "Newest once (0x0040)"		},
+	{  7, "Newest repeat (0x0080)"	    },
+	{  8, "Shuffle once (0x0100)"		},
+	{  9, "Shuffle repeat (0x0200)"		},
+	{  10, "RFU (0x0400)"			    },
+	{  11, "RFU (0x0800)"		        },
+	{  12, "RFU (0x1000)"				},
+	{  13, "RFU (0x2000)"				},
+	{  14, "RFU (0x4000)"				},
+	{  15, "RFU (0x8000)"				},
+	{ }
+};
+
+static void print_playing_orders_supported(const struct l2cap_frame *frame)
+{
+	uint16_t supported_orders;
+	uint16_t mask;
+
+	if (!l2cap_frame_get_le16((void *)frame, &supported_orders)) {
+		print_text(COLOR_ERROR,
+				"    Supported Playing Orders: invalid size");
+		goto done;
+	}
+
+	print_field("      Supported Playing Orders: 0x%4.4x",
+				supported_orders);
+
+	mask = print_bitfield(8, supported_orders, playing_orders_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%4.4x)",
+								mask);
+
+done:
+	if (frame->size)
+		print_hex_field("    Data", frame->data, frame->size);
+}
+
+static void playing_orders_supported_read(const struct l2cap_frame *frame)
+{
+	print_playing_orders_supported(frame);
+}
+
+static const char *media_state_str(uint8_t state)
+{
+	switch (state) {
+	case 0x00:
+		return "Inactive";
+	case 0x01:
+		return "Playing";
+	case 0x02:
+		return "Paused";
+	case 0x03:
+		return "Seeking";
+	default:
+		return "RFU";
+	}
+}
+
+static void print_media_state(const struct l2cap_frame *frame)
+{
+	int8_t state;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&state)) {
+		print_text(COLOR_ERROR, "  Media State: invalid size");
+		goto done;
+	}
+
+	print_field("  Media State: %s", media_state_str(state));
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void media_state_read(const struct l2cap_frame *frame)
+{
+	print_media_state(frame);
+}
+
+static void media_state_notify(const struct l2cap_frame *frame)
+{
+	print_media_state(frame);
+}
+
+static const struct media_cp_opcode {
+	uint8_t opcode;
+	const char *opcode_str;
+} media_cp_opcode_table[] = {
+	{0x01,	"Play"},
+	{0x02,	"Pause"},
+	{0x03,	"Fast Rewind"},
+	{0x04,	"Fast Forward"},
+	{0x05,	"Stop"},
+	{0x10,	"Move Relative"},
+	{0x20,	"Previous Segment"},
+	{0x21,	"Next Segment"},
+	{0x22,	"First Segment"},
+	{0x23,	"Last Segment"},
+	{0x24,	"Goto Segment"},
+	{0x30,	"Previous Track"},
+	{0x31,	"Next Track"},
+	{0x32,	"First Track"},
+	{0x33,	"Last Track"},
+	{0x34,	"Goto Track"},
+	{0x40,	"Previous Group"},
+	{0x41,	"Next Group"},
+	{0x42,	"First Group"},
+	{0x43,	"Last Group"},
+	{0x44,	"Goto Group"},
+};
+
+static const char *cp_opcode_str(uint8_t opcode)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(media_cp_opcode_table); i++) {
+		const char *str = media_cp_opcode_table[i].opcode_str;
+
+		if (opcode == media_cp_opcode_table[i].opcode)
+			return str;
+	}
+
+	return "RFU";
+}
+
+static void print_media_cp(const struct l2cap_frame *frame)
+{
+	int8_t opcode;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&opcode)) {
+		print_text(COLOR_ERROR, "  Media Control Point: invalid size");
+		goto done;
+	}
+
+	print_field("  Media Control Point: %s", cp_opcode_str(opcode));
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void media_cp_write(const struct l2cap_frame *frame)
+{
+	print_media_cp(frame);
+}
+
+static void media_cp_notify(const struct l2cap_frame *frame)
+{
+	print_media_cp(frame);
+}
+
+static const struct bitfield_data supported_opcodes_table[] = {
+	{0, "Play (0x00000001)"				},
+	{1, "Pause (0x00000002)"			},
+	{2, "Fast Rewind	(0x00000004)"	},
 	{3, "Fast Forward (0x00000008)"		},
 	{4, "Stop (0x00000010)"				},
 	{5, "Move Relative (0x00000020)"	},
@@ -2284,59 +3365,652 @@ static const struct bitfield_data supported_opcodes_table[] = {
 	{ }
 };
 
-static void print_media_cp_op_supported(const struct l2cap_frame *frame)
+static void print_media_cp_op_supported(const struct l2cap_frame *frame)
+{
+	uint32_t supported_opcodes;
+	uint32_t mask;
+
+	if (!l2cap_frame_get_le32((void *)frame, &supported_opcodes)) {
+		print_text(COLOR_ERROR, "    value: invalid size");
+		goto done;
+	}
+
+	print_field("      Supported Opcodes: 0x%8.8x", supported_opcodes);
+
+	mask = print_bitfield(8, supported_opcodes, supported_opcodes_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%4.4x)",
+								mask);
+
+done:
+	if (frame->size)
+		print_hex_field("    Data", frame->data, frame->size);
+}
+
+static void media_cp_op_supported_read(const struct l2cap_frame *frame)
+{
+	print_media_cp_op_supported(frame);
+}
+
+static void media_cp_op_supported_notify(const struct l2cap_frame *frame)
+{
+	print_media_cp_op_supported(frame);
+}
+
+static void print_content_control_id(const struct l2cap_frame *frame)
+{
+	int8_t ccid;
+
+	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&ccid)) {
+		print_text(COLOR_ERROR, "  Content Control ID: invalid size");
+		goto done;
+	}
+
+	print_field("  Content Control ID: 0x%2.2x", ccid);
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void content_control_id_read(const struct l2cap_frame *frame)
+{
+	print_content_control_id(frame);
+}
+
+static const struct pa_sync_state_decoder {
+	uint8_t code;
+	const char *value;
+} pa_sync_state_decoders[] = {
+	{ 0x00, "Not synchronized to PA" },
+	{ 0x01, "SyncInfo Request" },
+	{ 0x02, "Synchronized to PA" },
+	{ 0x03, "Failed to synchronize to PA" },
+	{ 0x04, "No PAST" },
+};
+
+static const struct cp_pa_sync_state_decoder {
+	uint8_t code;
+	const char *value;
+} cp_pa_sync_state_decoders[] = {
+	{ 0x00, "Do not synchronize to PA" },
+	{ 0x01, "Synchronize to PA - PAST available" },
+	{ 0x02, "Synchronize to PA - PAST not available" },
+};
+
+static const struct big_enc_decoder {
+	uint8_t code;
+	const char *value;
+} big_enc_decoders[] = {
+	{ 0x00, "Not encrypted" },
+	{ 0x01, "Broadcast_Code required" },
+	{ 0x02, "Decrypting" },
+	{ 0x03, "Bad_Code (incorrect encryption key)" },
+};
+
+static bool print_subgroup_lv(const struct l2cap_frame *frame,
+				const char *label,
+				const struct util_ltv_debugger *debugger,
+				size_t debugger_len)
+{
+	struct bt_hci_lv_data *lv;
+
+	lv = l2cap_frame_pull((void *)frame, frame, sizeof(*lv));
+	if (!lv) {
+		print_text(COLOR_ERROR, "%s: invalid size", label);
+		return false;
+	}
+
+	if (!l2cap_frame_pull((void *)frame, frame, lv->len)) {
+		print_text(COLOR_ERROR, "%s: invalid size", label);
+		return false;
+	}
+
+	util_debug_ltv(lv->data, lv->len, debugger, debugger_len,
+			       print_ltv, (void *)label);
+
+	return true;
+}
+
+static bool print_subgroup_metadata(const char *label,
+				const struct l2cap_frame *frame)
+{
+	return print_subgroup_lv(frame, label, NULL, 0);
+}
+
+static void print_bcast_recv_state(const struct l2cap_frame *frame)
+{
+	uint8_t i;
+	uint8_t id;
+	uint8_t addr_type;
+	uint8_t *addr;
+	uint8_t sid;
+	uint32_t bid;
+	uint8_t pa_sync_state;
+	uint8_t enc;
+	uint8_t *bad_code;
+	uint8_t num_subgroups = 0;
+	uint32_t bis_sync_state;
+
+	if (frame->size == 0) {
+		print_field("  Empty characteristic");
+		goto done;
+	}
+
+	if (!l2cap_frame_get_u8((void *)frame, &id)) {
+		print_text(COLOR_ERROR, "Source_ID: invalid size");
+		goto done;
+	}
+
+	print_field("  Source_ID: %u", id);
+
+	if (!l2cap_frame_get_u8((void *)frame, &addr_type)) {
+		print_text(COLOR_ERROR, "Source_Address_Type: invalid size");
+		goto done;
+	}
+
+	print_field("  Source_Address_Type: %u", addr_type);
+
+	addr = l2cap_frame_pull((void *)frame, frame, sizeof(bdaddr_t));
+	if (!addr) {
+		print_text(COLOR_ERROR, "Source_Address: invalid size");
+		goto done;
+	}
+
+	print_field("  Source_Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+					addr[5], addr[4],
+					addr[3], addr[2],
+					addr[1], addr[0]);
+
+	if (!l2cap_frame_get_u8((void *)frame, &sid)) {
+		print_text(COLOR_ERROR, "Source_Adv_SID: invalid size");
+		goto done;
+	}
+
+	print_field("  Source_Adv_SID: %u", sid);
+
+	if (!l2cap_frame_get_le24((void *)frame, &bid)) {
+		print_text(COLOR_ERROR, "Broadcast_ID: invalid size");
+		goto done;
+	}
+
+	print_field("  Broadcast_ID: 0x%06x", bid);
+
+	if (!l2cap_frame_get_u8((void *)frame, &pa_sync_state)) {
+		print_text(COLOR_ERROR, "PA_Sync_State: invalid size");
+		goto done;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pa_sync_state_decoders); i++) {
+		const struct pa_sync_state_decoder *decoder;
+
+		decoder = &pa_sync_state_decoders[i];
+
+		if (decoder->code == pa_sync_state) {
+			print_field("  PA_Sync_State: %s", decoder->value);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(pa_sync_state_decoders))
+		print_field("  PA_Sync_State: %s", "Invalid value");
+
+	if (!l2cap_frame_get_u8((void *)frame, &enc)) {
+		print_text(COLOR_ERROR, "BIG_Encryption: invalid size");
+		goto done;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(big_enc_decoders); i++) {
+		const struct big_enc_decoder *decoder;
+
+		decoder = &big_enc_decoders[i];
+
+		if (decoder->code == enc) {
+			print_field("  BIG_Encryption: %s", decoder->value);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(big_enc_decoders))
+		print_field("  BIG_Encryption: %s", "Invalid value");
+
+	if (enc == 0x03) {
+		bad_code = l2cap_frame_pull((void *)frame, frame, 16);
+		if (!bad_code) {
+			print_text(COLOR_ERROR, "Bad_Code: invalid size");
+			goto done;
+		}
+
+		print_hex_field("  Bad_Code", bad_code, 16);
+	}
+
+	if (!l2cap_frame_get_u8((void *)frame, &num_subgroups)) {
+		print_text(COLOR_ERROR, "Num_Subgroups: invalid size");
+		goto done;
+	}
+
+	print_field("  Num_Subgroups: %u", num_subgroups);
+
+	for (i = 0; i < num_subgroups; i++) {
+		print_field("  Subgroup #%u:", i);
+
+		if (!l2cap_frame_get_le32((void *)frame, &bis_sync_state)) {
+			print_text(COLOR_ERROR, "BIS_Sync State: invalid size");
+			goto done;
+		}
+
+		print_field("    BIS_Sync State: 0x%8.8x", bis_sync_state);
+
+		if (!print_subgroup_metadata("    Metadata", frame))
+			goto done;
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void bcast_recv_state_read(const struct l2cap_frame *frame)
+{
+	print_bcast_recv_state(frame);
+}
+
+static void bcast_recv_state_notify(const struct l2cap_frame *frame)
+{
+	print_bcast_recv_state(frame);
+}
+
+#define BCAST_AUDIO_SCAN_CP_CMD(_op, _desc, _func) \
+[_op] = { \
+	.desc = _desc, \
+	.func = _func, \
+}
+
+static void bcast_audio_scan_cp_add_src_cmd(const struct l2cap_frame *frame)
+{
+	uint8_t i;
+	uint8_t addr_type;
+	uint8_t *addr;
+	uint8_t sid;
+	uint32_t bid;
+	uint8_t pa_sync_state;
+	uint16_t pa_interval;
+	uint8_t num_subgroups = 0;
+	uint32_t bis_sync_state;
+
+	if (!l2cap_frame_get_u8((void *)frame, &addr_type)) {
+		print_text(COLOR_ERROR, "Source_Address_Type: invalid size");
+		return;
+	}
+
+	print_field("    Source_Address_Type: %u", addr_type);
+
+	addr = l2cap_frame_pull((void *)frame, frame, sizeof(bdaddr_t));
+	if (!addr) {
+		print_text(COLOR_ERROR, "Source_Address: invalid size");
+		return;
+	}
+
+	print_field("    Source_Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+					addr[5], addr[4],
+					addr[3], addr[2],
+					addr[1], addr[0]);
+
+	if (!l2cap_frame_get_u8((void *)frame, &sid)) {
+		print_text(COLOR_ERROR, "Source_Adv_SID: invalid size");
+		return;
+	}
+
+	print_field("    Source_Adv_SID: %u", sid);
+
+	if (!l2cap_frame_get_le24((void *)frame, &bid)) {
+		print_text(COLOR_ERROR, "Broadcast_ID: invalid size");
+		return;
+	}
+
+	print_field("    Broadcast_ID: 0x%06x", bid);
+
+	if (!l2cap_frame_get_u8((void *)frame, &pa_sync_state)) {
+		print_text(COLOR_ERROR, "PA_Sync_State: invalid size");
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cp_pa_sync_state_decoders); i++) {
+		const struct cp_pa_sync_state_decoder *decoder;
+
+		decoder = &cp_pa_sync_state_decoders[i];
+
+		if (decoder->code == pa_sync_state) {
+			print_field("    PA_Sync_State: %s", decoder->value);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(cp_pa_sync_state_decoders))
+		print_field("    PA_Sync_State: %s", "Invalid value");
+
+	if (!l2cap_frame_get_le16((void *)frame, &pa_interval)) {
+		print_text(COLOR_ERROR, "PA_Interval: invalid size");
+		return;
+	}
+
+	print_field("    PA_Interval: 0x%04x", pa_interval);
+
+	if (!l2cap_frame_get_u8((void *)frame, &num_subgroups)) {
+		print_text(COLOR_ERROR, "Num_Subgroups: invalid size");
+		return;
+	}
+
+	print_field("    Num_Subgroups: %u", num_subgroups);
+
+	for (i = 0; i < num_subgroups; i++) {
+		print_field("    Subgroup #%u:", i);
+
+		if (!l2cap_frame_get_le32((void *)frame, &bis_sync_state)) {
+			print_text(COLOR_ERROR, "BIS_Sync State: invalid size");
+			return;
+		}
+
+		print_field("      BIS_Sync State: 0x%8.8x", bis_sync_state);
+
+		if (!print_subgroup_metadata("      Metadata", frame))
+			return;
+	}
+}
+
+static void bcast_audio_scan_cp_mod_src_cmd(const struct l2cap_frame *frame)
 {
-	uint32_t supported_opcodes;
-	uint32_t mask;
+	uint8_t i;
+	uint8_t id;
+	uint8_t pa_sync_state;
+	uint16_t pa_interval;
+	uint8_t num_subgroups = 0;
+	uint32_t bis_sync_state;
 
-	if (!l2cap_frame_get_le32((void *)frame, &supported_opcodes)) {
-		print_text(COLOR_ERROR, "    value: invalid size");
-		goto done;
+	if (!l2cap_frame_get_u8((void *)frame, &id)) {
+		print_text(COLOR_ERROR, "Source_ID: invalid size");
+		return;
 	}
 
-	print_field("      Supported Opcodes: 0x%8.8x", supported_opcodes);
+	print_field("    Source_ID: %u", id);
 
-	mask = print_bitfield(8, supported_opcodes, supported_opcodes_table);
-	if (mask)
-		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%4.4x)",
-								mask);
+	if (!l2cap_frame_get_u8((void *)frame, &pa_sync_state)) {
+		print_text(COLOR_ERROR, "PA_Sync_State: invalid size");
+		return;
+	}
 
-done:
-	if (frame->size)
-		print_hex_field("    Data", frame->data, frame->size);
+	for (i = 0; i < ARRAY_SIZE(cp_pa_sync_state_decoders); i++) {
+		const struct cp_pa_sync_state_decoder *decoder;
+
+		decoder = &cp_pa_sync_state_decoders[i];
+
+		if (decoder->code == pa_sync_state) {
+			print_field("    PA_Sync_State: %s", decoder->value);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(cp_pa_sync_state_decoders))
+		print_field("    PA_Sync_State: %s", "Invalid value");
+
+	if (!l2cap_frame_get_le16((void *)frame, &pa_interval)) {
+		print_text(COLOR_ERROR, "PA_Interval: invalid size");
+		return;
+	}
+
+	print_field("    PA_Interval: 0x%04x", pa_interval);
+
+	if (!l2cap_frame_get_u8((void *)frame, &num_subgroups)) {
+		print_text(COLOR_ERROR, "Num_Subgroups: invalid size");
+		return;
+	}
+
+	print_field("    Num_Subgroups: %u", num_subgroups);
+
+	for (i = 0; i < num_subgroups; i++) {
+		print_field("    Subgroup #%u:", i);
+
+		if (!l2cap_frame_get_le32((void *)frame, &bis_sync_state)) {
+			print_text(COLOR_ERROR, "BIS_Sync State: invalid size");
+			return;
+		}
+
+		print_field("      BIS_Sync State: 0x%8.8x", bis_sync_state);
+
+		if (!print_subgroup_metadata("      Metadata", frame))
+			return;
+	}
 }
 
-static void media_cp_op_supported_read(const struct l2cap_frame *frame)
+static void bcast_audio_scan_cp_set_bcode_cmd(const struct l2cap_frame *frame)
 {
-	print_media_cp_op_supported(frame);
+	uint8_t id;
+	uint8_t *bcast_code;
+
+	if (!l2cap_frame_get_u8((void *)frame, &id)) {
+		print_text(COLOR_ERROR, "Source_ID: invalid size");
+		return;
+	}
+
+	print_field("    Source_ID: %u", id);
+
+	bcast_code = l2cap_frame_pull((void *)frame, frame, 16);
+	if (!bcast_code) {
+		print_text(COLOR_ERROR, "Broadcast_Code: invalid size");
+		return;
+	}
+
+	print_hex_field("    Broadcast_Code", bcast_code, 16);
+
 }
 
-static void media_cp_op_supported_notify(const struct l2cap_frame *frame)
+static void bcast_audio_scan_cp_remove_src_cmd(const struct l2cap_frame *frame)
 {
-	print_media_cp_op_supported(frame);
+	uint8_t id;
+
+	if (!l2cap_frame_get_u8((void *)frame, &id)) {
+		print_text(COLOR_ERROR, "Source_ID: invalid size");
+		return;
+	}
+
+	print_field("    Source_ID: %u", id);
 }
 
-static void print_content_control_id(const struct l2cap_frame *frame)
+static const struct bcast_audio_scan_cp_cmd {
+	const char *desc;
+	void (*func)(const struct l2cap_frame *frame);
+} bcast_audio_scan_cp_cmd_table[] = {
+	/* Opcode = 0x00 (Remote Scan Stopped) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x00, "Remote Scan Stopped", NULL),
+	/* Opcode = 0x01 (Remote Scan Started) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x01, "Remote Scan Started", NULL),
+	/* Opcode = 0x02 (Add Source) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x02, "Add Source",
+					bcast_audio_scan_cp_add_src_cmd),
+	/* Opcode = 0x03 (Modify Source) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x03, "Modify Source",
+					bcast_audio_scan_cp_mod_src_cmd),
+	/* Opcode = 0x04 (Set Broadcast_Code) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x04, "Set Broadcast_Code",
+					bcast_audio_scan_cp_set_bcode_cmd),
+	/* Opcode = 0x05 (Remove Source) */
+	BCAST_AUDIO_SCAN_CP_CMD(0x05, "Remove Source",
+					bcast_audio_scan_cp_remove_src_cmd),
+};
+
+static const struct bcast_audio_scan_cp_cmd *
+bcast_audio_scan_cp_get_cmd(uint8_t op)
 {
-	int8_t ccid;
+	if (op > ARRAY_SIZE(bcast_audio_scan_cp_cmd_table))
+		return NULL;
 
-	if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&ccid)) {
-		print_text(COLOR_ERROR, "  Content Control ID: invalid size");
+	return &bcast_audio_scan_cp_cmd_table[op];
+}
+
+static void print_bcast_audio_scan_cp_cmd(const struct l2cap_frame *frame)
+{
+	uint8_t op;
+	const struct bcast_audio_scan_cp_cmd *cmd;
+
+	if (!l2cap_frame_get_u8((void *)frame, &op)) {
+		print_text(COLOR_ERROR, "Opcode: invalid size");
 		goto done;
 	}
 
-	print_field("  Content Control ID: 0x%2.2x", ccid);
+	cmd = bcast_audio_scan_cp_get_cmd(op);
+	if (!cmd) {
+		print_field("    Opcode: Reserved (0x%2.2x)", op);
+		goto done;
+	}
+
+	print_field("    Opcode: %s (0x%2.2x)", cmd->desc, op);
+	if (cmd->func)
+		cmd->func(frame);
 
 done:
 	if (frame->size)
 		print_hex_field("  Data", frame->data, frame->size);
 }
 
-static void content_control_id_read(const struct l2cap_frame *frame)
+static void bcast_audio_scan_cp_write(const struct l2cap_frame *frame)
 {
-	print_content_control_id(frame);
+	print_bcast_audio_scan_cp_cmd(frame);
+}
+
+static const struct bitfield_data gmap_role_table[] = {
+	{  0, "Unicast Game Gateway (UGG) (0x0001)"	},
+	{  1, "Unicast Game Terminal (UGT) (0x0002)"	},
+	{  2, "Broadcast Game Sender (BGS) (0x0004)"	},
+	{  3, "Broadcast Game Receiver (BGR) (0x0008)"	},
+	{ }
+};
+
+static void gmap_role_read(const struct l2cap_frame *frame)
+{
+	uint8_t role;
+	uint8_t mask;
+
+	if (!l2cap_frame_get_u8((void *)frame, &role)) {
+		print_text(COLOR_ERROR, "    invalid size");
+		return;
+	}
+
+	print_field("    Role: 0x%2.2x", role);
+
+	mask = print_bitfield(6, role, gmap_role_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
+								mask);
 }
 
+static const struct bitfield_data ugg_features_table[] = {
+	{  0, "UGG Multiplex (0x0001)"	},
+	{  1, "UGG 96 kbps Source (0x0002)"	},
+	{  2, "UGG Multilink (0x0004)"	},
+	{ }
+};
+
+static void ugg_features_read(const struct l2cap_frame *frame)
+{
+	uint8_t value;
+	uint8_t mask;
+
+	if (!l2cap_frame_get_u8((void *)frame, &value)) {
+		print_text(COLOR_ERROR, "    invalid size");
+		return;
+	}
+
+	print_field("    Value: 0x%2.2x", value);
+
+	mask = print_bitfield(6, value, ugg_features_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
+								mask);
+}
+
+static const struct bitfield_data ugt_features_table[] = {
+	{  0, "UGT Source (0x0001)"		},
+	{  1, "UGT 80 kbps Source (0x0002)"	},
+	{  2, "UGT Sink (0x0004)"		},
+	{  3, "UGT 64 kbps Sink (0x0008)"	},
+	{  4, "UGT Multiplex (0x0010)"		},
+	{  5, "UGT Multisink (0x0020)"		},
+	{  6, "UGT Multisource (0x0040)"	},
+	{ }
+};
+
+static void ugt_features_read(const struct l2cap_frame *frame)
+{
+	uint8_t value;
+	uint8_t mask;
+
+	if (!l2cap_frame_get_u8((void *)frame, &value)) {
+		print_text(COLOR_ERROR, "    invalid size");
+		return;
+	}
+
+	print_field("    Value: 0x%2.2x", value);
+
+	mask = print_bitfield(6, value, ugt_features_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
+								mask);
+}
+
+static const struct bitfield_data bgs_features_table[] = {
+	{  0, "BGS 96 kbps (0x0001)"		},
+	{ }
+};
+
+static void bgs_features_read(const struct l2cap_frame *frame)
+{
+	uint8_t value;
+	uint8_t mask;
+
+	if (!l2cap_frame_get_u8((void *)frame, &value)) {
+		print_text(COLOR_ERROR, "    invalid size");
+		return;
+	}
+
+	print_field("    Value: 0x%2.2x", value);
+
+	mask = print_bitfield(6, value, bgs_features_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
+								mask);
+}
+
+static const struct bitfield_data bgr_features_table[] = {
+	{  0, "BGR Multisink (0x0001)"		},
+	{  1, "BGR Multiplex (0x0002)"		},
+	{ }
+};
+
+static void bgr_features_read(const struct l2cap_frame *frame)
+{
+	uint8_t value;
+	uint8_t mask;
+
+	if (!l2cap_frame_get_u8((void *)frame, &value)) {
+		print_text(COLOR_ERROR, "    invalid size");
+		return;
+	}
+
+	print_field("    Value: 0x%2.2x", value);
+
+	mask = print_bitfield(6, value, bgr_features_table);
+	if (mask)
+		print_text(COLOR_WHITE_BG, "    Unknown fields (0x%2.2x)",
+								mask);
+}
+
+#define GMAS \
+	GATT_HANDLER(0x2c00, gmap_role_read, NULL, NULL), \
+	GATT_HANDLER(0x2c01, ugg_features_read, NULL, NULL), \
+	GATT_HANDLER(0x2c02, ugt_features_read, NULL, NULL), \
+	GATT_HANDLER(0x2c02, bgs_features_read, NULL, NULL), \
+	GATT_HANDLER(0x2c03, bgr_features_read, NULL, NULL)
+
 #define GATT_HANDLER(_uuid, _read, _write, _notify) \
 { \
 	.uuid = { \
@@ -2348,12 +4022,14 @@ static void content_control_id_read(const struct l2cap_frame *frame)
 	.notify = _notify \
 }
 
-struct gatt_handler {
+static const struct gatt_handler {
 	bt_uuid_t uuid;
 	void (*read)(const struct l2cap_frame *frame);
 	void (*write)(const struct l2cap_frame *frame);
 	void (*notify)(const struct l2cap_frame *frame);
 } gatt_handlers[] = {
+	GATT_HANDLER(0x2800, pri_svc_read, NULL, NULL),
+	GATT_HANDLER(0x2801, sec_svc_read, NULL, NULL),
 	GATT_HANDLER(0x2803, chrc_read, NULL, NULL),
 	GATT_HANDLER(0x2902, ccc_read, ccc_write, NULL),
 	GATT_HANDLER(0x2bc4, ase_read, NULL, ase_notify),
@@ -2368,6 +4044,12 @@ struct gatt_handler {
 	GATT_HANDLER(0x2b7d, vol_state_read, NULL, vol_state_notify),
 	GATT_HANDLER(0x2b7e, NULL, vol_cp_write, NULL),
 	GATT_HANDLER(0x2b7f, vol_flag_read, NULL, vol_flag_notify),
+
+	GATT_HANDLER(0x2b84, csip_sirk_read, NULL, csip_sirk_notify),
+	GATT_HANDLER(0x2b85, csip_size_read, NULL, csip_size_notify),
+	GATT_HANDLER(0x2b86, csip_lock_read, NULL, NULL),
+	GATT_HANDLER(0x2b87, csip_rank_read, NULL, NULL),
+
 	GATT_HANDLER(0x2b93, mp_name_read, NULL, mp_name_notify),
 	GATT_HANDLER(0x2b96, NULL, NULL, track_changed_notify),
 	GATT_HANDLER(0x2b97, track_title_read, NULL, track_title_notify),
@@ -2385,14 +4067,44 @@ struct gatt_handler {
 	GATT_HANDLER(0x2ba5, media_cp_op_supported_read, NULL,
 					media_cp_op_supported_notify),
 	GATT_HANDLER(0x2bba, content_control_id_read, NULL, NULL),
+
+	GATT_HANDLER(0x2bc7, NULL, bcast_audio_scan_cp_write, NULL),
+	GATT_HANDLER(0x2bc8, bcast_recv_state_read, NULL,
+					bcast_recv_state_notify),
+	GATT_HANDLER(0x2bb3, bearer_name_read, NULL, bearer_name_notify),
+	GATT_HANDLER(0x2bb4, bearer_uci_read, NULL, NULL),
+	GATT_HANDLER(0x2bb5, bearer_technology_read, NULL,
+					bearer_technology_notify),
+	GATT_HANDLER(0x2bb6, bearer_uri_schemes_list_read, NULL, NULL),
+	GATT_HANDLER(0x2bb7, bearer_signal_strength_read, NULL,
+					bearer_signal_strength_notify),
+	GATT_HANDLER(0x2bb8, bearer_signal_strength_rep_intrvl_read,
+			bearer_signal_strength_rep_intrvl_write, NULL),
+	GATT_HANDLER(0x2bb9, bearer_current_call_list_read, NULL,
+					bearer_current_call_list_notify),
+	GATT_HANDLER(0x2bba, call_content_control_id_read, NULL, NULL),
+	GATT_HANDLER(0x2bbb, status_flag_read, NULL, status_flag_notify),
+	GATT_HANDLER(0x2bbc, incom_target_bearer_uri_read, NULL,
+					incom_target_bearer_uri_notify),
+	GATT_HANDLER(0x2bbd, call_state_read, NULL, call_state_notify),
+	GATT_HANDLER(0x2bbe, NULL, call_cp_write, call_cp_notify),
+	GATT_HANDLER(0x2bbf, call_cp_opt_opcodes_read, NULL, NULL),
+	GATT_HANDLER(0x2bc0, NULL, NULL, call_termination_reason_notify),
+	GATT_HANDLER(0x2bc1, incoming_call_read, NULL, incoming_call_notify),
+	GATT_HANDLER(0x2bc2, call_friendly_name_read, NULL,
+					call_friendly_name_notify),
+	GMAS
 };
 
-static struct gatt_handler *get_handler_uuid(const bt_uuid_t *uuid)
+static const struct gatt_handler *get_handler_uuid(const bt_uuid_t *uuid)
 {
 	size_t i;
 
+	if (!uuid)
+		return NULL;
+
 	for (i = 0; i < ARRAY_SIZE(gatt_handlers); i++) {
-		struct gatt_handler *handler = &gatt_handlers[i];
+		const struct gatt_handler *handler = &gatt_handlers[i];
 
 		if (!bt_uuid_cmp(&handler->uuid, uuid))
 			return handler;
@@ -2401,7 +4113,7 @@ static struct gatt_handler *get_handler_uuid(const bt_uuid_t *uuid)
 	return NULL;
 }
 
-static struct gatt_handler *get_handler(struct gatt_db_attribute *attr)
+static const struct gatt_handler *get_handler(struct gatt_db_attribute *attr)
 {
 	return get_handler_uuid(gatt_db_attribute_get_type(attr));
 }
@@ -2415,9 +4127,23 @@ static void att_exchange_mtu_req(const struct l2cap_frame *frame)
 
 static void att_exchange_mtu_rsp(const struct l2cap_frame *frame)
 {
-	const struct bt_l2cap_att_exchange_mtu_rsp *pdu = frame->data;
+	struct packet_conn_data *conn;
+	struct att_conn_data *data;
+	uint16_t mtu;
+
+	if (!l2cap_frame_get_le16((void *)frame, &mtu)) {
+		print_text(COLOR_ERROR, "  invalid size");
+		return;
+	}
 
-	print_field("Server RX MTU: %d", le16_to_cpu(pdu->mtu));
+	print_field("Server RX MTU: %d", mtu);
+
+	conn = packet_get_conn_data(frame->handle);
+	data = att_get_conn_data(conn);
+	if (!data)
+		return;
+
+	data->mtu = mtu;
 }
 
 static void att_find_info_req(const struct l2cap_frame *frame)
@@ -2437,45 +4163,96 @@ static const char *att_format_str(uint8_t format)
 	}
 }
 
-static uint16_t print_info_data_16(const void *data, uint16_t len)
+static struct gatt_db_attribute *insert_desc(const struct l2cap_frame *frame,
+						uint16_t handle,
+						bt_uuid_t *uuid, bool rsp)
 {
-	while (len >= 4) {
-		print_field("Handle: 0x%4.4x", get_le16(data));
-		print_uuid("UUID", data + 2, 2);
-		data += 4;
-		len -= 4;
-	}
+	struct gatt_db *db;
+
+	db = get_db(frame, rsp);
+	if (!db)
+		return NULL;
 
-	return len;
+	return gatt_db_insert_descriptor(db, handle, uuid, 0, NULL, NULL, NULL);
 }
 
-static uint16_t print_info_data_128(const void *data, uint16_t len)
+static void att_find_info_rsp_16(const struct l2cap_frame *frame)
 {
-	while (len >= 18) {
-		print_field("Handle: 0x%4.4x", get_le16(data));
-		print_uuid("UUID", data + 2, 16);
-		data += 18;
-		len -= 18;
+	while (frame->size >= 4) {
+		uint16_t handle;
+		uint16_t u16;
+		bt_uuid_t uuid;
+
+		if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+			print_text(COLOR_ERROR, "    Handle: invalid size");
+			return;
+		}
+
+		if (!l2cap_frame_get_le16((void *)frame, &u16)) {
+			print_text(COLOR_ERROR, "    UUID: invalid size");
+			return;
+		}
+
+		print_field("Handle: 0x%4.4x", handle);
+		print_uuid("UUID", &u16, 2);
+
+		bt_uuid16_create(&uuid, u16);
+
+		insert_desc(frame, handle, &uuid, true);
 	}
+}
+
+static void att_find_info_rsp_128(const struct l2cap_frame *frame)
+{
+	while (frame->size >= 18) {
+		uint16_t handle;
+		bt_uuid_t uuid;
+
+		if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+			print_text(COLOR_ERROR, "    Handle: invalid size");
+			return;
+		}
+
+		if (frame->size < 16) {
+			print_text(COLOR_ERROR, "    UUID: invalid size");
+			return;
+		}
+
+		print_field("Handle: 0x%4.4x", handle);
+		print_uuid("UUID", frame->data, 16);
+
+		bt_uuid_from_data(&uuid, frame->data, 16);
 
-	return len;
+		if (!l2cap_frame_pull((void *)frame, frame, 16))
+			return;
+
+		insert_desc(frame, handle, &uuid, true);
+	}
 }
 
 static void att_find_info_rsp(const struct l2cap_frame *frame)
 {
-	const uint8_t *format = frame->data;
-	uint16_t len;
+	uint8_t format;
+
+	if (!l2cap_frame_get_u8((void *)frame, &format)) {
+		print_text(COLOR_ERROR, "    Format: invalid size");
+		goto done;
+	}
 
-	print_field("Format: %s (0x%2.2x)", att_format_str(*format), *format);
+	print_field("Format: %s (0x%2.2x)", att_format_str(format), format);
 
-	if (*format == 0x01)
-		len = print_info_data_16(frame->data + 1, frame->size - 1);
-	else if (*format == 0x02)
-		len = print_info_data_128(frame->data + 1, frame->size - 1);
-	else
-		len = frame->size - 1;
+	switch (format) {
+	case 0x01:
+		att_find_info_rsp_16(frame);
+		break;
+	case 0x02:
+		att_find_info_rsp_128(frame);
+		break;
+	}
 
-	packet_hexdump(frame->data + (frame->size - len), len);
+done:
+	if (frame->size)
+		packet_hexdump(frame->data, frame->size);
 }
 
 static void att_find_by_type_val_req(const struct l2cap_frame *frame)
@@ -2502,194 +4279,77 @@ static void att_find_by_type_val_rsp(const struct l2cap_frame *frame)
 	packet_hexdump(ptr, len);
 }
 
-static int bt_uuid_from_data(bt_uuid_t *uuid, const void *data, uint16_t size)
-{
-	uint128_t u128;
-
-	switch (size) {
-	case 2:
-		return bt_uuid16_create(uuid, get_le16(data));
-	case 4:
-		return bt_uuid32_create(uuid, get_le32(data));
-	case 16:
-		memcpy(u128.data, data, sizeof(u128.data));
-		return bt_uuid128_create(uuid, u128);
-	}
-
-	return -EINVAL;
-}
-
-static void att_conn_data_free(void *data)
-{
-	struct att_conn_data *att_data = data;
-
-	gatt_db_unref(att_data->rdb);
-	gatt_db_unref(att_data->ldb);
-	queue_destroy(att_data->reads, free);
-	free(att_data);
-}
-
-static struct att_conn_data *att_get_conn_data(struct packet_conn_data *conn)
+static struct gatt_db_attribute *get_attribute(const struct l2cap_frame *frame,
+						uint16_t handle, bool rsp)
 {
-	struct att_conn_data *data = conn->data;
-
-	if (data)
-		return data;
+	struct gatt_db *db;
 
-	data = new0(struct att_conn_data, 1);
-	data->rdb = gatt_db_new();
-	data->ldb = gatt_db_new();
-	conn->data = data;
-	conn->destroy = att_conn_data_free;
+	db = get_db(frame, rsp);
+	if (!db)
+		return NULL;
 
-	return data;
+	return gatt_db_get_attribute(db, handle);
 }
 
-static void att_read_type_req(const struct l2cap_frame *frame)
+static void queue_read(const struct l2cap_frame *frame, bt_uuid_t *uuid,
+					uint16_t handle)
 {
-	bt_uuid_t uuid;
 	struct packet_conn_data *conn;
 	struct att_conn_data *data;
 	struct att_read *read;
-	struct gatt_handler *handler;
-
-	print_handle_range("Handle range", frame->data);
-	print_uuid("Attribute type", frame->data + 4, frame->size - 4);
+	struct gatt_db_attribute *attr = NULL;
+	const struct gatt_handler *handler;
 
-	if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
-		return;
+	if (handle) {
+		attr = get_attribute(frame, handle, false);
+		if (!attr)
+			return;
+	}
 
-	handler = get_handler_uuid(&uuid);
-	if (!handler || !handler->read)
-		return;
+	handler = attr ? get_handler(attr) : get_handler_uuid(uuid);
 
 	conn = packet_get_conn_data(frame->handle);
 	data = att_get_conn_data(conn);
+	if (!data)
+		return;
 
 	if (!data->reads)
 		data->reads = queue_new();
 
 	read = new0(struct att_read, 1);
+	read->conn = data;
+	read->attr = attr;
 	read->in = frame->in;
 	read->chan = frame->chan;
-	read->func = handler->read;
+	read->func = handler ? handler->read : NULL;
 
 	queue_push_tail(data->reads, read);
 }
 
-static void att_read_type_rsp(const struct l2cap_frame *frame)
+static void att_read_type_req(const struct l2cap_frame *frame)
 {
-	uint8_t len;
-
-	if (!l2cap_frame_get_u8((void *)frame, &len)) {
-		print_text(COLOR_ERROR, "invalid size");
-		return;
-	}
-
-	print_field("Attribute data length: %d", len);
-	print_data_list("Attribute data list", len, frame);
-}
+	bt_uuid_t uuid;
 
-static void gatt_load_db(struct gatt_db *db, const char *filename,
-						struct timespec *mtim)
-{
-	struct stat st;
+	print_handle_range("Handle range", frame->data);
+	print_uuid("Attribute type", frame->data + 4, frame->size - 4);
 
-	if (lstat(filename, &st))
+	if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
 		return;
 
-	if (!gatt_db_isempty(db)) {
-		/* Check if file has been modified since last time */
-		if (st.st_mtim.tv_sec == mtim->tv_sec &&
-				    st.st_mtim.tv_nsec == mtim->tv_nsec)
-			return;
-		/* Clear db before reloading */
-		gatt_db_clear(db);
-	}
-
-	*mtim = st.st_mtim;
-
-	btd_settings_gatt_db_load(db, filename);
-}
-
-static void load_gatt_db(struct packet_conn_data *conn)
-{
-	struct att_conn_data *data = att_get_conn_data(conn);
-	char filename[PATH_MAX];
-	char local[18];
-	char peer[18];
-
-	ba2str((bdaddr_t *)conn->src, local);
-	ba2str((bdaddr_t *)conn->dst, peer);
-
-	create_filename(filename, PATH_MAX, "/%s/attributes", local);
-	gatt_load_db(data->ldb, filename, &data->ldb_mtim);
-
-	create_filename(filename, PATH_MAX, "/%s/cache/%s", local, peer);
-	gatt_load_db(data->rdb, filename, &data->rdb_mtim);
-}
-
-static struct gatt_db_attribute *get_attribute(const struct l2cap_frame *frame,
-						uint16_t handle, bool rsp)
-{
-	struct packet_conn_data *conn;
-	struct att_conn_data *data;
-	struct gatt_db *db;
-
-	conn = packet_get_conn_data(frame->handle);
-	if (!conn)
-		return NULL;
-
-	/* Try loading local and remote gatt_db if not loaded yet */
-	load_gatt_db(conn);
-
-	data = conn->data;
-	if (!data)
-		return NULL;
-
-	if (frame->in) {
-		if (rsp)
-			db = data->rdb;
-		else
-			db = data->ldb;
-	} else {
-		if (rsp)
-			db = data->ldb;
-		else
-			db = data->rdb;
-	}
-
-	return gatt_db_get_attribute(db, handle);
+	queue_read(frame, &uuid, 0x0000);
 }
 
-static void print_attribute(struct gatt_db_attribute *attr)
+static void att_read_type_rsp(const struct l2cap_frame *frame)
 {
-	uint16_t handle = gatt_db_attribute_get_handle(attr);
-	const bt_uuid_t *uuid;
-	char label[21];
-
-	uuid = gatt_db_attribute_get_type(attr);
-	if (!uuid)
-		goto done;
+	uint8_t len;
 
-	switch (uuid->type) {
-	case BT_UUID16:
-		sprintf(label, "Handle: 0x%4.4x Type", handle);
-		print_field("%s: %s (0x%4.4x)", label,
-				bt_uuid16_to_str(uuid->value.u16),
-				uuid->value.u16);
-		return;
-	case BT_UUID128:
-		sprintf(label, "Handle: 0x%4.4x Type", handle);
-		print_uuid(label, &uuid->value.u128, 16);
+	if (!l2cap_frame_get_u8((void *)frame, &len)) {
+		print_text(COLOR_ERROR, "invalid size");
 		return;
-	case BT_UUID_UNSPEC:
-	case BT_UUID32:
-		break;
 	}
 
-done:
-	print_field("Handle: 0x%4.4x", handle);
+	print_field("Attribute data length: %d", len);
+	print_data_list("Attribute data list", len, frame);
 }
 
 static void print_handle(const struct l2cap_frame *frame, uint16_t handle,
@@ -2710,74 +4370,104 @@ static void att_read_req(const struct l2cap_frame *frame)
 {
 	const struct bt_l2cap_att_read_req *pdu = frame->data;
 	uint16_t handle;
-	struct packet_conn_data *conn;
-	struct att_conn_data *data;
-	struct att_read *read;
-	struct gatt_db_attribute *attr;
-	struct gatt_handler *handler;
 
 	l2cap_frame_pull((void *)frame, frame, sizeof(*pdu));
 
 	handle = le16_to_cpu(pdu->handle);
 	print_handle(frame, handle, false);
 
-	attr = get_attribute(frame, handle, false);
-	if (!attr)
-		return;
+	queue_read(frame, NULL, handle);
+}
 
-	handler = get_handler(attr);
-	if (!handler || !handler->read)
-		return;
+static void att_read_append(struct att_read *read,
+				const struct l2cap_frame *frame)
+{
+	if (!read->iov)
+		read->iov = new0(struct iovec, 1);
+	util_iov_append(read->iov, frame->data, frame->size);
+}
 
-	conn = packet_get_conn_data(frame->handle);
-	data = conn->data;
+static void att_read_func(struct att_read *read,
+				const struct l2cap_frame *frame)
+{
+	att_read_append(read, frame);
 
-	if (!data->reads)
-		data->reads = queue_new();
+	print_attribute(read->attr);
+	print_hex_field("Value", read->iov->iov_base, read->iov->iov_len);
 
-	read = new0(struct att_read, 1);
-	read->attr = attr;
-	read->in = frame->in;
-	read->chan = frame->chan;
-	read->func = handler->read;
+	if (read->func) {
+		struct l2cap_frame f = *frame;
 
-	queue_push_tail(data->reads, read);
+		f.data = read->iov->iov_base;
+		f.size = read->iov->iov_len;
+
+		read->func(&f);
+	}
+
+	att_read_free(read);
 }
 
 static void att_read_rsp(const struct l2cap_frame *frame)
 {
-	struct packet_conn_data *conn;
-	struct att_conn_data *data;
 	struct att_read *read;
 
 	print_hex_field("Value", frame->data, frame->size);
 
-	conn = packet_get_conn_data(frame->handle);
-	if (!conn)
-		return;
-
-	data = conn->data;
-
-	read = queue_remove_if(data->reads, match_read_frame, (void *)frame);
+	read = att_get_read(frame);
 	if (!read)
 		return;
 
-	print_attribute(read->attr);
-
-	read->func(frame);
+	/* Check if the data size is equal to the MTU then read long procedure
+	 * maybe used.
+	 */
+	if (frame->size == read->conn->mtu - 1) {
+		att_read_append(read, frame);
+		print_hex_field("Long Value", read->iov->iov_base,
+					read->iov->iov_len);
+		queue_push_head(read->conn->reads, read);
+		return;
+	}
 
-	free(read);
+	att_read_func(read, frame);
 }
 
 static void att_read_blob_req(const struct l2cap_frame *frame)
 {
-	print_handle(frame, get_le16(frame->data), false);
-	print_field("Offset: 0x%4.4x", get_le16(frame->data + 2));
+	uint16_t handle, offset;
+	struct att_read *read;
+
+	if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+		print_text(COLOR_ERROR, "invalid size");
+		return;
+	}
+
+	if (!l2cap_frame_get_le16((void *)frame, &offset)) {
+		print_text(COLOR_ERROR, "invalid size");
+		return;
+	}
+
+	print_handle(frame, handle, false);
+	print_field("Offset: 0x%4.4x", offset);
+
+	read = att_get_read(frame);
+	if (!read)
+		return;
+
+	/* Check if attribute handle and offset match so the read object shall
+	 * be keeped.
+	 */
+	if (gatt_db_attribute_get_handle(read->attr) == handle &&
+				offset == read->iov->iov_len) {
+		queue_push_head(read->conn->reads, read);
+		return;
+	}
+
+	att_read_func(read, frame);
 }
 
 static void att_read_blob_rsp(const struct l2cap_frame *frame)
 {
-	packet_hexdump(frame->data, frame->size);
+	att_read_rsp(frame);
 }
 
 static void att_read_multiple_req(const struct l2cap_frame *frame)
@@ -2792,62 +4482,83 @@ static void att_read_multiple_req(const struct l2cap_frame *frame)
 
 static void att_read_group_type_req(const struct l2cap_frame *frame)
 {
+	bt_uuid_t uuid;
+
 	print_handle_range("Handle range", frame->data);
 	print_uuid("Attribute group type", frame->data + 4, frame->size - 4);
+
+	if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
+		return;
+
+	queue_read(frame, &uuid, 0x0000);
 }
 
 static void print_group_list(const char *label, uint8_t length,
-					const void *data, uint16_t size)
+					const struct l2cap_frame *frame)
 {
+	struct att_read *read;
 	uint8_t count;
 
 	if (length == 0)
 		return;
 
-	count = size / length;
+	read = att_get_read(frame);
+
+	count = frame->size / length;
 
 	print_field("%s: %u entr%s", label, count, count == 1 ? "y" : "ies");
 
-	while (size >= length) {
-		print_handle_range("Handle range", data);
-		print_uuid("UUID", data + 4, length - 4);
+	while (frame->size >= length) {
+		print_handle_range("Handle range", frame->data);
+		print_uuid("UUID", frame->data + 4, length - 4);
+
+		if (read && read->func) {
+			struct l2cap_frame f;
+
+			l2cap_frame_clone_size(&f, frame, length);
+
+			read->func(&f);
+		}
 
-		data += length;
-		size -= length;
+		if (!l2cap_frame_pull((void *)frame, frame, length))
+			break;
 	}
 
-	packet_hexdump(data, size);
+	packet_hexdump(frame->data, frame->size);
+	att_read_free(read);
 }
 
 static void att_read_group_type_rsp(const struct l2cap_frame *frame)
 {
 	const struct bt_l2cap_att_read_group_type_rsp *pdu = frame->data;
 
+	l2cap_frame_pull((void *)frame, frame, sizeof(*pdu));
+
 	print_field("Attribute data length: %d", pdu->length);
-	print_group_list("Attribute group list", pdu->length,
-					frame->data + 1, frame->size - 1);
+	print_group_list("Attribute group list", pdu->length, frame);
 }
 
 static void print_write(const struct l2cap_frame *frame, uint16_t handle,
 							size_t len)
 {
 	struct gatt_db_attribute *attr;
-	struct gatt_handler *handler;
+	const struct gatt_handler *handler;
 
 	print_handle(frame, handle, false);
-	print_hex_field("  Data", frame->data, frame->size);
 
 	if (len > frame->size) {
 		print_text(COLOR_ERROR, "invalid size");
 		return;
 	}
 
+	print_hex_field("  Data", frame->data, len);
+
 	attr = get_attribute(frame, handle, false);
 	if (!attr)
 		return;
 
 	handler = get_handler(attr);
-	if (!handler)
+	if (!handler || !handler->write)
 		return;
 
 	handler->write(frame);
@@ -2907,7 +4618,7 @@ static void print_notify(const struct l2cap_frame *frame, uint16_t handle,
 								size_t len)
 {
 	struct gatt_db_attribute *attr;
-	struct gatt_handler *handler;
+	const struct gatt_handler *handler;
 	struct l2cap_frame clone;
 
 	print_handle(frame, handle, true);
@@ -2935,7 +4646,8 @@ static void print_notify(const struct l2cap_frame *frame, uint16_t handle,
 		frame = &clone;
 	}
 
-	handler->notify(frame);
+	if (handler->notify)
+		handler->notify(frame);
 }
 
 static void att_handle_value_notify(const struct l2cap_frame *frame)
@@ -3006,7 +4718,6 @@ static void att_signed_write_command(const struct l2cap_frame *frame)
 	}
 
 	print_write(frame, handle, frame->size - 12);
-	print_hex_field("  Data", frame->data, frame->size - 12);
 	print_hex_field("  Signature", frame->data + frame->size - 12, 12);
 }
 
diff --git a/monitor/avctp.c b/monitor/avctp.c
index fb26282..4da4487 100644
--- a/monitor/avctp.c
+++ b/monitor/avctp.c
@@ -156,6 +156,7 @@
 #define AVRCP_MEDIA_ATTRIBUTE_TOTAL	0x05
 #define AVRCP_MEDIA_ATTRIBUTE_GENRE	0x06
 #define AVRCP_MEDIA_ATTRIBUTE_DURATION	0x07
+#define AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE	0x08
 
 /* play status */
 #define AVRCP_PLAY_STATUS_STOPPED	0x00
@@ -582,6 +583,8 @@ static const char *mediattr2str(uint32_t attr)
 		return "Genre";
 	case AVRCP_MEDIA_ATTRIBUTE_DURATION:
 		return "Track duration";
+	case AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE:
+		return "Imaging handle";
 	default:
 		return "Reserved";
 	}
@@ -1802,7 +1805,7 @@ response:
 }
 
 
-static struct {
+static const struct {
 	const char *str;
 	bool reserved;
 } features_table[] = {
diff --git a/monitor/broadcom.c b/monitor/broadcom.c
index 72da56d..80c95e9 100644
--- a/monitor/broadcom.c
+++ b/monitor/broadcom.c
@@ -706,7 +706,8 @@ void broadcom_lm_diag(const void *data, uint8_t size)
 	}
 }
 
-static void lm_diag_evt(uint16_t index, const void *data, uint8_t size)
+static void lm_diag_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	broadcom_lm_diag(data, 63);
 }
diff --git a/monitor/bt.h b/monitor/bt.h
index 7aa016a..6fb81ab 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2014  Intel Corporation
  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -94,8 +95,36 @@ struct bt_ll_peripheral_feature_req {
 } __attribute__ ((packed));
 
 #define BT_LL_CONN_PARAM_REQ	0x0f
+struct bt_ll_conn_param_req {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint8_t pref_period;
+	uint16_t pref_conn_evt_count;
+	uint8_t offset_0;
+	uint8_t offset_1;
+	uint8_t offset_2;
+	uint8_t offset_3;
+	uint8_t offset_4;
+	uint8_t offset_5;
+} __attribute__ ((packed));
 
 #define BT_LL_CONN_PARAM_RSP	0x10
+struct bt_ll_conn_param_rsp {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint8_t pref_period;
+	uint16_t pref_conn_evt_count;
+	uint8_t offset_0;
+	uint8_t offset_1;
+	uint8_t offset_2;
+	uint8_t offset_3;
+	uint8_t offset_4;
+	uint8_t offset_5;
+} __attribute__ ((packed));
 
 #define BT_LL_REJECT_IND_EXT	0x11
 struct bt_ll_reject_ind_ext {
@@ -561,6 +590,10 @@ struct bt_hci_cmd_add_sco_conn {
 struct bt_hci_cmd_create_conn_cancel {
 	uint8_t  bdaddr[6];
 } __attribute__ ((packed));
+struct bt_hci_rsp_create_conn_cancel {
+	uint8_t  status;
+	uint8_t  bdaddr[6];
+} __attribute__ ((packed));
 
 #define BT_HCI_CMD_ACCEPT_CONN_REQUEST		0x0409
 struct bt_hci_cmd_accept_conn_request {
@@ -1787,6 +1820,12 @@ struct bt_hci_rsp_read_local_pairing_options {
 #define BT_HCI_LOCAL_CODEC_LE_CIS		BIT(2)
 #define BT_HCI_LOCAL_CODEC_LE_BIS		BIT(3)
 
+struct bt_hci_vnd_codec_v2 {
+	uint16_t cid;
+	uint16_t vid;
+	uint8_t  transport;
+} __attribute__ ((packed));
+
 struct bt_hci_vnd_codec {
 	uint8_t  id;
 	uint16_t cid;
@@ -2601,7 +2640,7 @@ struct bt_hci_cmd_periodic_sync_trans {
 struct bt_hci_cmd_pa_set_info_trans {
 	uint16_t handle;
 	uint16_t service_data;
-	uint16_t adv_handle;
+	uint8_t adv_handle;
 } __attribute__ ((packed));
 
 #define BT_HCI_CMD_PA_SYNC_TRANS_PARAMS		0x205c
@@ -2770,20 +2809,19 @@ struct bt_hci_bis_test {
 	uint16_t iso_interval;
 	uint8_t  nse;
 	uint16_t sdu;
-	uint8_t  pdu;
+	uint16_t  pdu;
 	uint8_t  phy;
 	uint8_t  packing;
 	uint8_t  framing;
 	uint8_t  bn;
 	uint8_t  irc;
 	uint8_t  pto;
-	uint8_t  adv_handle;
 	uint8_t  encryption;
 	uint8_t  bcode[16];
 } __attribute__ ((packed));
 
 struct bt_hci_cmd_le_create_big_test {
-	uint8_t  big_id;
+	uint8_t  big_handle;
 	uint8_t  adv_handle;
 	uint8_t  num_bis;
 	struct bt_hci_bis_test bis[0];
@@ -2856,6 +2894,11 @@ struct bt_hci_cmd_le_remove_iso_path {
 	uint8_t  direction;
 } __attribute__ ((packed));
 
+struct bt_hci_rsp_le_remove_iso_path {
+	uint8_t  status;
+	uint16_t handle;
+} __attribute__ ((packed));
+
 #define BT_HCI_CMD_LE_ISO_TX_TEST		0x2070
 #define BT_HCI_BIT_LE_ISO_TX_TEST		BT_HCI_CMD_BIT(43, 5)
 
@@ -2875,6 +2918,24 @@ struct bt_hci_cmd_le_set_host_feature {
 	uint8_t  bit_value;
 } __attribute__ ((packed));
 
+#define BT_HCI_CMD_LE_READ_ISO_LINK_QUALITY	0x2075
+#define BT_HCI_BIT_LE_READ_ISO_LINK_QUALITY	BT_HCI_CMD_BIT(45, 1)
+struct bt_hci_cmd_le_read_iso_link_quality {
+	uint16_t handle;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_read_iso_link_quality {
+	uint8_t  status;
+	uint16_t handle;
+	uint32_t tx_unacked_packets;
+	uint32_t tx_flushed_packets;
+	uint32_t tx_last_subevent_packets;
+	uint32_t retransmitted_packets;
+	uint32_t crc_error_packets;
+	uint32_t rx_unreceived_packets;
+	uint32_t duplicated_packets;
+} __attribute__ ((packed));
+
 #define BT_HCI_EVT_INQUIRY_COMPLETE		0x01
 struct bt_hci_evt_inquiry_complete {
 	uint8_t  status;
@@ -3670,7 +3731,7 @@ struct bt_hci_evt_le_big_sync_estabilished {
 
 #define BT_HCI_EVT_LE_BIG_SYNC_LOST		0x1e
 struct bt_hci_evt_le_big_sync_lost {
-	uint8_t  big_id;
+	uint8_t  big_handle;
 	uint8_t  reason;
 } __attribute__ ((packed));
 
@@ -3706,14 +3767,17 @@ struct bt_hci_evt_le_big_info_adv_report {
 #define BT_HCI_ERR_AUTH_FAILURE			0x05
 #define BT_HCI_ERR_PIN_OR_KEY_MISSING		0x06
 #define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED	0x07
+#define BT_HCI_ERR_CONN_ALREADY_EXISTS		0x0b
 #define BT_HCI_ERR_COMMAND_DISALLOWED		0x0c
 #define BT_HCI_ERR_UNSUPPORTED_FEATURE		0x11
 #define BT_HCI_ERR_INVALID_PARAMETERS		0x12
+#define BT_HCI_ERR_LOCAL_HOST_TERM		0x16
 #define BT_HCI_ERR_UNSPECIFIED_ERROR		0x1f
 #define BT_HCI_ERR_ADV_TIMEOUT			0x3c
 #define BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH	0x3e
 #define BT_HCI_ERR_UNKNOWN_ADVERTISING_ID	0x42
 #define BT_HCI_ERR_CANCELLED			0x44
+#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE	0x25
 
 struct bt_l2cap_hdr {
 	uint16_t len;
diff --git a/monitor/btmon.1 b/monitor/btmon.1
new file mode 100644
index 0000000..80254f6
--- /dev/null
+++ b/monitor/btmon.1
@@ -0,0 +1,258 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BTMON" "1" "April 2021" "BlueZ" "Linux System Administration"
+.SH NAME
+btmon \- Bluetooth monitor
+.SH SYNOPSYS
+.sp
+\fBbtmon\fP [\fIOPTIONS\fP ...]
+.SH DESCRIPTION
+.sp
+The  btmon(1) command  provides  access  to the Bluetooth subsystem monitor
+infrastructure for reading HCI traces.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-r \ FILE\fR,\fB \ \-\-read \ FILE
+Read traces in btsnoop format from \fIFILE\fP\&.
+.TP
+.BI \-w \ FILE\fR,\fB \ \-\-write \ FILE
+Save traces in btsnoop format to \fIFILE\fP\&.
+.TP
+.BI \-a \ FILE\fR,\fB \ \-\-analyze \ FILE
+Analyze traces in btsnoop format from \fIFILE\fP\&.
+It displays the devices found in the \fIFILE\fP with
+its packets by type. If gnuplot is installed on
+the system it also attempts to plot packet latency
+graph.
+.TP
+.BI \-s \ SOCKET\fR,\fB \ \-\-server \ SOCKET
+Start monitor server socket.
+.TP
+.BI \-p \ PRIORITY\fR,\fB \ \-\-priority \ PRIORITY
+Show only priority or lower for user log.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIPRIORITY\fP
+T}	T{
+NAME
+T}
+_
+T{
+\fB3\fP
+T}	T{
+Error
+T}
+_
+T{
+\fB4\fP
+T}	T{
+Warning
+T}
+_
+T{
+\fB6\fP
+T}	T{
+Information (Default)
+T}
+_
+T{
+\fB7\fP
+T}	T{
+Debug. \fBdebug\fP can be used.
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-i \ NUM\fR,\fB \ \-\-index \ NUM
+Show only specified controller. \fIhciNUM\fP is also
+acceptable. This is useful to capture the traces
+from the specific controller when the multiple
+controllers are presented.
+.TP
+.BI \-d \ TTY\fR,\fB \ \-\-tty \ TTY
+Read data from \fITTY\fP\&.
+.TP
+.BI \-B \ SPEED\fR,\fB \ \-\-rate \ SPEED
+Set TTY speed. The default \fISPEED\fP is 115300
+.TP
+.BI \-V \ COMPID\fR,\fB \ \-\-vendor \ COMPID
+Set the default company identifier. The \fICOMPID\fP is
+a unique number assigned by the Bluetooth SIG to
+a member company and can be found/searched from the
+Bluetooth SIG webpage.
+.sp
+For example, Intel is 2 and Realtek is 93.
+.TP
+.B  \-M\fP,\fB  \-\-mgmt
+Open channel for mgmt events.
+.TP
+.B  \-t\fP,\fB  \-\-time
+Show a time instead of time offset.
+.TP
+.B  \-T\fP,\fB  \-\-date
+Show a time and date information instead of
+time offset.
+.TP
+.B  \-S\fP,\fB  \-\-sco
+Dump SCO traffic in raw hex format.
+.TP
+.B  \-A\fP,\fB  \-\-a2dp
+Dump A2DP stream traffic in a raw hex format.
+.TP
+.BI \-E \ IP\fR,\fB \ \-\-ellisys \ IP
+Send Ellisys HCI Injection.
+.TP
+.B  \-P\fP,\fB  \-\-no\-pager
+Disable pager usage while reading the log file.
+.TP
+.BI \-J \ OPTIONS\fR,\fB \ \-\-jlink \ OPTIONS
+Read data from RTT.  Each options are comma(,)
+seprated without spaces.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIOPTIONS\fP
+T}	T{
+Description
+T}
+_
+T{
+\fBDEVICE\fP
+T}	T{
+Required. Set the target device.
+T}
+_
+T{
+\fBSERIALNO\fP
+T}	T{
+(Optional) Set the USB serial number. Default is \fB0\fP\&.
+T}
+_
+T{
+\fBINTERFACE\fP
+T}	T{
+(Optional) Target interface. Default is \fBswd\fP\&.
+T}
+_
+T{
+\fBSPEED\fP
+T}	T{
+(Optional) Set target interface speed in kHz. Default is \fB1000\fP\&.
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-R \ OPTIONS\fR,\fB \ \-\-rtt \ OPTIONS
+RTT control block parameters. Each options are
+comma(,) seprated without spaces.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIOPTIONS\fP
+T}	T{
+Description
+T}
+_
+T{
+\fBADDRESS\fP
+T}	T{
+(Optional) Address of RTT buffer. Default is \fB0x00\fP
+T}
+_
+T{
+\fBAREA\fP
+T}	T{
+(Optional) Size of range to search in RTT buffer. Default is \fB0\fP
+T}
+_
+T{
+\fBNAME\fP
+T}	T{
+(Optional) Buffer name. Default is \fBbtmonitor\fP
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-C \ WIDTH\fR,\fB \ \-\-columns \ WIDTH
+Output width if not a terminal
+.TP
+.BI \-c \ MODE\fR,\fB \ \-\-color \ MODE
+Set output color. The possible \fIMODE\fP values are:
+\fBauto|always|never\fP\&.
+.sp
+Default value is \fBauto\fP
+.TP
+.B  \-v\fP,\fB  \-\-version
+Show version
+.TP
+.B  \-h\fP,\fB  \-\-help
+Show help options
+.UNINDENT
+.SH EXAMPLES
+.SS Capture the traces from hci0 to hcidump.log file
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ btmon \-i hci0 \-w hcidump.log
+.EE
+.UNINDENT
+.UNINDENT
+.SS Open the trace file
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ btmon \-r hcidump.log
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann <marcel@holtmann.org>, Tedd Ho-Jeong An <tedd.an@intel.com>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/monitor/btmon.rst b/monitor/btmon.rst
index 0ab13eb..82f9381 100644
--- a/monitor/btmon.rst
+++ b/monitor/btmon.rst
@@ -33,7 +33,9 @@ OPTIONS
 -w FILE, --write FILE       Save traces in btsnoop format to *FILE*.
 -a FILE, --analyze FILE     Analyze traces in btsnoop format from *FILE*.
                             It displays the devices found in the *FILE* with
-                            its packets by type.
+			    its packets by type. If gnuplot is installed on
+			    the system it also attempts to plot packet latency
+			    graph.
 -s SOCKET, --server SOCKET  Start monitor server socket.
 -p PRIORITY, --priority PRIORITY  Show only priority or lower for user log.
 
diff --git a/monitor/display.h b/monitor/display.h
index 5a82f8e..ee07644 100644
--- a/monitor/display.h
+++ b/monitor/display.h
@@ -87,7 +87,7 @@ static inline void print_hex_field(const char *label, const uint8_t *data,
 	for (i = 0; i < len; i++)
 		sprintf(str + (i * 2), "%2.2x", data[i]);
 
-	print_field("%s: %s", label, str);
+	print_field("%s[%u]: %s", label, len, str);
 }
 
 void set_default_pager_num_columns(int num_columns);
diff --git a/monitor/hwdb.c b/monitor/hwdb.c
index 22de9ed..6c0d052 100644
--- a/monitor/hwdb.c
+++ b/monitor/hwdb.c
@@ -19,7 +19,7 @@
 
 #include "hwdb.h"
 
-#ifdef HAVE_UDEV_HWDB_NEW
+#ifdef HAVE_UDEV
 #include <libudev.h>
 
 bool hwdb_get_vendor_model(const char *modalias, char **vendor, char **model)
diff --git a/monitor/intel.c b/monitor/intel.c
index f5e9f59..0de864d 100644
--- a/monitor/intel.c
+++ b/monitor/intel.c
@@ -171,25 +171,25 @@ struct intel_version_tlv {
 };
 
 static void print_version_tlv_u32(const struct intel_version_tlv *tlv,
-				  char *type_str)
+				  const char *type_str)
 {
 	print_field("%s(%u): 0x%8.8x", type_str, tlv->type, get_le32(tlv->val));
 }
 
 static void print_version_tlv_u16(const struct intel_version_tlv *tlv,
-				  char *type_str)
+				  const char *type_str)
 {
 	print_field("%s(%u): 0x%4.4x", type_str, tlv->type, get_le16(tlv->val));
 }
 
 static void print_version_tlv_u8(const struct intel_version_tlv *tlv,
-				 char *type_str)
+				 const char *type_str)
 {
 	print_field("%s(%u): 0x%2.2x", type_str, tlv->type, get_u8(tlv->val));
 }
 
 static void print_version_tlv_enabled(const struct intel_version_tlv *tlv,
-				      char *type_str)
+				      const char *type_str)
 {
 	print_field("%s(%u): %s(%u)", type_str, tlv->type,
 					tlv->val[0] ? "Enabled" : "Disabled",
@@ -197,7 +197,7 @@ static void print_version_tlv_enabled(const struct intel_version_tlv *tlv,
 }
 
 static void print_version_tlv_img_type(const struct intel_version_tlv *tlv,
-				       char *type_str)
+				       const char *type_str)
 {
 	const char *str;
 
@@ -217,34 +217,34 @@ static void print_version_tlv_img_type(const struct intel_version_tlv *tlv,
 }
 
 static void print_version_tlv_timestamp(const struct intel_version_tlv *tlv,
-					char *type_str)
+					const char *type_str)
 {
 	print_field("%s(%u): %u-%u", type_str, tlv->type,
 				tlv->val[1], tlv->val[0]);
 }
 
 static void print_version_tlv_min_fw(const struct intel_version_tlv *tlv,
-				     char *type_str)
+				     const char *type_str)
 {
 	print_field("%s(%u): %u-%u.%u", type_str, tlv->type,
 				tlv->val[0], tlv->val[1], 2000 + tlv->val[2]);
 }
 
 static void print_version_tlv_otp_bdaddr(const struct intel_version_tlv *tlv,
-					 char *type_str)
+					 const char *type_str)
 {
 	packet_print_addr(type_str, tlv->val, 0x00);
 }
 
 static void print_version_tlv_unknown(const struct intel_version_tlv *tlv,
-				      char *type_str)
+				      const char *type_str)
 {
 	print_field("%s(%u): ", type_str, tlv->type);
 	packet_hexdump(tlv->val, tlv->len);
 }
 
 static void print_version_tlv_mfg(const struct intel_version_tlv *tlv,
-					 char *type_str)
+					 const char *type_str)
 {
 	uint16_t mfg_id = get_le16(tlv->val);
 
@@ -254,8 +254,8 @@ static void print_version_tlv_mfg(const struct intel_version_tlv *tlv,
 
 static const struct intel_version_tlv_desc {
 	uint8_t type;
-	char *type_str;
-	void (*func)(const struct intel_version_tlv *tlv, char *type_str);
+	const char *type_str;
+	void (*func)(const struct intel_version_tlv *tlv, const char *type_str);
 } intel_version_tlv_table[] = {
 	{ 16, "CNVi TOP", print_version_tlv_u32 },
 	{ 17, "CNVr TOP", print_version_tlv_u32 },
@@ -365,7 +365,7 @@ static void read_version_rsp(uint16_t index, const void *data, uint8_t size)
 
 static void read_version_cmd(uint16_t index, const void *data, uint8_t size)
 {
-	char *str;
+	const char *str;
 	uint8_t type;
 
 	/* This is the legacy read version command format and no further action
@@ -712,6 +712,29 @@ static void read_supported_features_rsp(uint16_t index, const void *data,
 	packet_hexdump(data + 3, size - 3);
 }
 
+static void ppag_enable(uint16_t index, const void *data, uint8_t size)
+{
+	uint32_t enable = get_le32(data);
+	char *ppag_enable_flags;
+
+	switch (enable) {
+	case 0x01:
+		ppag_enable_flags = "EU";
+		break;
+	case 0x02:
+		ppag_enable_flags = "China";
+		break;
+	case 0x03:
+		ppag_enable_flags = "EU and China";
+		break;
+	default:
+		ppag_enable_flags = "Unknown";
+		break;
+	}
+
+	print_field("Enable: %s (0x%8.8x)", ppag_enable_flags, enable);
+}
+
 static const struct vendor_ocf vendor_ocf_table[] = {
 	{ 0x001, "Reset",
 			reset_cmd, 8, true,
@@ -777,7 +800,9 @@ static const struct vendor_ocf vendor_ocf_table[] = {
 	{ 0x0a6, "Read Supported Features",
 			read_supported_features_cmd, 1, true,
 			read_supported_features_rsp, 19, true },
-
+	{ 0x20b, "PPAG Enable",
+			ppag_enable, 4, true,
+			status_rsp, 1, true },
 	{ }
 };
 
@@ -793,11 +818,13 @@ const struct vendor_ocf *intel_vendor_ocf(uint16_t ocf)
 	return NULL;
 }
 
-static void startup_evt(uint16_t index, const void *data, uint8_t size)
+static void startup_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 }
 
-static void fatal_exception_evt(uint16_t index, const void *data, uint8_t size)
+static void fatal_exception_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	uint16_t line = get_le16(data);
 	uint8_t module = get_u8(data + 2);
@@ -808,7 +835,8 @@ static void fatal_exception_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("Reason: 0x%2.2x", reason);
 }
 
-static void bootup_evt(uint16_t index, const void *data, uint8_t size)
+static void bootup_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	uint8_t zero = get_u8(data);
 	uint8_t num_packets = get_u8(data + 1);
@@ -911,7 +939,8 @@ static void bootup_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("DDC status: %s (0x%2.2x)", str, ddc_status);
 }
 
-static void default_bd_data_evt(uint16_t index, const void *data, uint8_t size)
+static void default_bd_data_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t mem_status = get_u8(data);
 	const char *str;
@@ -928,8 +957,8 @@ static void default_bd_data_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("Memory status: %s (0x%2.2x)", str, mem_status);
 }
 
-static void secure_send_commands_result_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void secure_send_commands_result_evt(struct timeval *tv, uint16_t index,
+						const void *data, uint8_t size)
 {
 	uint8_t result = get_u8(data);
 	uint16_t opcode = get_le16(data + 1);
@@ -973,7 +1002,8 @@ static void secure_send_commands_result_evt(uint16_t index, const void *data,
 	print_status(status);
 }
 
-static void debug_exception_evt(uint16_t index, const void *data, uint8_t size)
+static void debug_exception_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint16_t line = get_le16(data);
 	uint8_t module = get_u8(data + 2);
@@ -984,8 +1014,8 @@ static void debug_exception_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("Reason: 0x%2.2x", reason);
 }
 
-static void le_link_established_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_link_established_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint16_t handle = get_le16(data);
 	uint32_t access_addr = get_le32(data + 10);
@@ -999,7 +1029,8 @@ static void le_link_established_evt(uint16_t index, const void *data,
 	packet_hexdump(data + 14, size - 14);
 }
 
-static void scan_status_evt(uint16_t index, const void *data, uint8_t size)
+static void scan_status_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t enable = get_u8(data);
 
@@ -1014,15 +1045,16 @@ static void scan_status_evt(uint16_t index, const void *data, uint8_t size)
 
 }
 
-static void act_deact_traces_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void act_deact_traces_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t status = get_u8(data);
 
 	print_status(status);
 }
 
-static void lmp_pdu_trace_evt(uint16_t index, const void *data, uint8_t size)
+static void lmp_pdu_trace_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t type, len, id;
 	uint16_t handle, count;
@@ -1116,16 +1148,16 @@ static void lmp_pdu_trace_evt(uint16_t index, const void *data, uint8_t size)
 	}
 }
 
-static void write_bd_data_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void write_bd_data_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t status = get_u8(data);
 
 	print_status(status);
 }
 
-static void sco_rejected_via_lmp_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void sco_rejected_via_lmp_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t reason = get_u8(data + 6);
 
@@ -1133,8 +1165,8 @@ static void sco_rejected_via_lmp_evt(uint16_t index, const void *data,
 	packet_print_error("Reason", reason);
 }
 
-static void ptt_switch_notification_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void ptt_switch_notification_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint16_t handle = get_le16(data);
 	uint8_t table = get_u8(data + 2);
@@ -1157,7 +1189,8 @@ static void ptt_switch_notification_evt(uint16_t index, const void *data,
 	print_field("Packet type table: %s (0x%2.2x)", str, table);
 }
 
-static void system_exception_evt(uint16_t index, const void *data, uint8_t size)
+static void system_exception_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	uint8_t type = get_u8(data);
 	const char *str;
@@ -1257,11 +1290,9 @@ static void ext_evt_type(const struct intel_tlv *tlv)
 		str = "Disconnection Event";
 		break;
 	case 0x05:
-		str = "Audio Link Quality Report Type";
-		break;
-	case 0x06:
-		str = "Stats for BR/EDR Link Type";
+		str = "Performance Stats";
 		break;
+
 	default:
 		print_text(COLOR_UNKNOWN_EXT_EVENT,
 			"Unknown extended telemetry event type (0x%2.2x)",
@@ -1287,6 +1318,10 @@ static void ext_acl_evt_hec_errors(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Rx HEC errors (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1294,6 +1329,10 @@ static void ext_acl_evt_crc_errors(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Rx CRC errors (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1301,6 +1340,10 @@ static void ext_acl_evt_num_pkt_from_host(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Packets from host (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
@@ -1309,6 +1352,10 @@ static void ext_acl_evt_num_tx_pkt_to_air(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Tx packets (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1317,6 +1364,10 @@ static void ext_acl_evt_num_tx_pkt_retry(const struct intel_tlv *tlv)
 	char *subevent_str;
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	switch (tlv->subevent_id) {
 	case 0x4f:
 		subevent_str = "Tx packets 0 retries";
@@ -1346,6 +1397,10 @@ static void ext_acl_evt_num_tx_pkt_type(const struct intel_tlv *tlv)
 	char *packet_type_str;
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	switch (tlv->subevent_id) {
 	case 0x54:
 		packet_type_str = "DH1";
@@ -1387,6 +1442,10 @@ static void ext_acl_evt_num_rx_pkt_from_air(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Rx packets (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
@@ -1395,7 +1454,11 @@ static void ext_acl_evt_link_throughput(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
-	print_field("ACL link throughput (KBps) (0x%2.2x): %d",
+	/* Skip if 0 */
+	if (!num)
+		return;
+
+	print_field("ACL link throughput (bps) (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
 
@@ -1403,7 +1466,11 @@ static void ext_acl_evt_max_packet_latency(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
-	print_field("ACL max packet latency (ms) (0x%2.2x): %d",
+	/* Skip if 0 */
+	if (!num)
+		return;
+
+	print_field("ACL max packet latency (us) (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
 
@@ -1411,10 +1478,55 @@ static void ext_acl_evt_avg_packet_latency(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
-	print_field("ACL avg packet latency (ms) (0x%2.2x): %d",
+	/* Skip if 0 */
+	if (!num)
+		return;
+
+	print_field("ACL avg packet latency (us) (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
 
+static void ext_acl_evt_rssi_moving_avg(const struct intel_tlv *tlv)
+{
+	uint32_t num = get_le16(tlv->value);
+
+	/* Skip if 0 */
+	if (!num)
+		return;
+
+	print_field("ACL RX RSSI moving avg (0x%2.2x): %d",
+			tlv->subevent_id, num);
+}
+
+static void ext_acl_evt_bad_cnt(const char *prefix, const struct intel_tlv *tlv)
+{
+	uint32_t c_1m = get_le32(tlv->value);
+	uint32_t c_2m = get_le32(tlv->value + 4);
+	uint32_t c_3m = get_le32(tlv->value + 8);
+
+	/* Skip if all 0 */
+	if (!c_1m && !c_2m && !c_3m)
+		return;
+
+	print_field("%s (0x%2.2x): 1M %d 2M %d 3M %d",
+			prefix, tlv->subevent_id, c_1m, c_2m, c_3m);
+}
+
+static void ext_acl_evt_snr_bad_cnt(const struct intel_tlv *tlv)
+{
+	ext_acl_evt_bad_cnt("ACL RX SNR Bad Margin Counter", tlv);
+}
+
+static void ext_acl_evt_rx_rssi_bad_cnt(const struct intel_tlv *tlv)
+{
+	ext_acl_evt_bad_cnt("ACL RX RSSI Bad Counter", tlv);
+}
+
+static void ext_acl_evt_tx_rssi_bad_cnt(const struct intel_tlv *tlv)
+{
+	ext_acl_evt_bad_cnt("ACL TX RSSI Bad Counter", tlv);
+}
+
 static void ext_sco_evt_conn_handle(const struct intel_tlv *tlv)
 {
 	uint16_t conn_handle = get_le16(tlv->value);
@@ -1427,6 +1539,10 @@ static void ext_sco_evt_num_rx_pkt_from_air(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Packets from host (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1434,6 +1550,10 @@ static void ext_sco_evt_num_tx_pkt_to_air(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Tx packets (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1441,6 +1561,10 @@ static void ext_sco_evt_num_rx_payloads_lost(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Rx payload lost (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1449,6 +1573,10 @@ static void ext_sco_evt_num_tx_payloads_lost(const struct intel_tlv *tlv)
 
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Tx payload lost (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1508,6 +1636,10 @@ static void ext_sco_evt_samples_inserted(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Late samples inserted based on CDC (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
@@ -1516,6 +1648,10 @@ static void ext_sco_evt_samples_dropped(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Samples dropped (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1523,6 +1659,10 @@ static void ext_sco_evt_mute_samples(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("Mute samples sent at initial connection (0x%2.2x): %d",
 			tlv->subevent_id, num);
 }
@@ -1531,6 +1671,10 @@ static void ext_sco_evt_plc_injection_data(const struct intel_tlv *tlv)
 {
 	uint32_t num = get_le32(tlv->value);
 
+	/* Skip if 0 */
+	if (!num)
+		return;
+
 	print_field("PLC injection data (0x%2.2x): %d", tlv->subevent_id, num);
 }
 
@@ -1565,6 +1709,10 @@ static const struct intel_ext_subevent {
 	{ 0x5e, 4, ext_acl_evt_link_throughput },
 	{ 0x5f, 4, ext_acl_evt_max_packet_latency },
 	{ 0x60, 4, ext_acl_evt_avg_packet_latency },
+	{ 0x61, 2, ext_acl_evt_rssi_moving_avg },
+	{ 0x62, 12, ext_acl_evt_snr_bad_cnt },
+	{ 0x63, 12, ext_acl_evt_rx_rssi_bad_cnt },
+	{ 0x64, 12, ext_acl_evt_tx_rssi_bad_cnt },
 
 	/* SCO/eSCO audio link quality subevents */
 	{ 0x6a, 2, ext_sco_evt_conn_handle },
@@ -1606,7 +1754,8 @@ static const struct intel_tlv *process_ext_subevent(const struct intel_tlv *tlv,
 		print_text(COLOR_UNKNOWN_EXT_EVENT,
 				"Unknown extended subevent 0x%2.2x",
 				tlv->subevent_id);
-		return NULL;
+		packet_hexdump(tlv->value, tlv->length);
+		return next_tlv;
 	}
 
 	if (tlv->length != subevent->length) {
@@ -1625,7 +1774,8 @@ static const struct intel_tlv *process_ext_subevent(const struct intel_tlv *tlv,
 	return next_tlv;
 }
 
-static void intel_vendor_ext_evt(uint16_t index, const void *data, uint8_t size)
+static void intel_vendor_ext_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	/* The data pointer points to a number of tlv.*/
 	const struct intel_tlv *tlv = data;
@@ -1648,7 +1798,7 @@ static const struct vendor_evt vendor_prefix_evt_table[] = {
 	{ }
 };
 
-const uint8_t intel_vendor_prefix[] = {0x87, 0x80};
+static const uint8_t intel_vendor_prefix[] = {0x87, 0x80};
 #define INTEL_VENDOR_PREFIX_SIZE sizeof(intel_vendor_prefix)
 
 /*
diff --git a/monitor/jlink.c b/monitor/jlink.c
index f9d4037..e08cc87 100644
--- a/monitor/jlink.c
+++ b/monitor/jlink.c
@@ -47,6 +47,7 @@ struct rtt_desc {
 };
 
 static struct rtt_desc rtt_desc;
+static void *so = NULL;
 
 typedef int (*jlink_emu_selectbyusbsn_func) (unsigned int sn);
 typedef int (*jlink_open_func) (void);
@@ -80,7 +81,6 @@ static struct jlink jlink;
 
 int jlink_init(void)
 {
-	void *so;
 	unsigned int i;
 
 	for (i = 0; i < NELEM(jlink_so_name); i++) {
@@ -109,6 +109,7 @@ int jlink_init(void)
 			!jlink.emu_getproductname ||
 			!jlink.rtterminal_control || !jlink.rtterminal_read) {
 		dlclose(so);
+		so = NULL;
 		return -EIO;
 	}
 
diff --git a/monitor/keys.c b/monitor/keys.c
index d2fa3b2..c1eebae 100644
--- a/monitor/keys.c
+++ b/monitor/keys.c
@@ -112,3 +112,29 @@ bool keys_resolve_identity(const uint8_t addr[6], uint8_t ident[6],
 
 	return false;
 }
+
+static bool match_key(const void *data, const void *match_data)
+{
+	const struct irk_data *irk = data;
+	const uint8_t *key = match_data;
+
+	return !memcmp(irk->key, key, 16);
+}
+
+bool keys_add_identity(const uint8_t addr[6], uint8_t addr_type,
+					const uint8_t key[16])
+{
+	struct irk_data *irk;
+
+	irk = queue_find(irk_list, match_key, key);
+	if (!irk) {
+		irk = new0(struct irk_data, 1);
+		memcpy(irk->key, key, 16);
+		queue_push_tail(irk_list, irk);
+	}
+
+	memcpy(irk->addr, addr, 6);
+	irk->addr_type = addr_type;
+
+	return true;
+}
diff --git a/monitor/keys.h b/monitor/keys.h
index e40c90f..f44d332 100644
--- a/monitor/keys.h
+++ b/monitor/keys.h
@@ -20,3 +20,5 @@ void keys_update_identity_addr(const uint8_t addr[6], uint8_t addr_type);
 
 bool keys_resolve_identity(const uint8_t addr[6], uint8_t ident[6],
 							uint8_t *ident_type);
+bool keys_add_identity(const uint8_t addr[6], uint8_t addr_type,
+					const uint8_t key[16]);
diff --git a/monitor/l2cap.c b/monitor/l2cap.c
index 3f5554e..dff183b 100644
--- a/monitor/l2cap.c
+++ b/monitor/l2cap.c
@@ -23,6 +23,7 @@
 #include "lib/uuid.h"
 
 #include "src/shared/util.h"
+#include "src/shared/queue.h"
 #include "bt.h"
 #include "packet.h"
 #include "display.h"
@@ -99,6 +100,7 @@ struct chan_data {
 	uint8_t  ext_ctrl;
 	uint8_t  seq_num;
 	uint16_t sdu;
+	struct packet_latency tx_l;
 };
 
 static struct chan_data chan_list[MAX_CHAN];
@@ -716,7 +718,7 @@ static void print_config_result(uint16_t result)
 	print_field("Result: %s (0x%4.4x)", str, le16_to_cpu(result));
 }
 
-static struct {
+static const struct {
 	uint8_t type;
 	uint8_t len;
 	const char *str;
@@ -1538,6 +1540,23 @@ static const struct sig_opcode_data le_sig_opcode_table[] = {
 	{ },
 };
 
+static void l2cap_queue_frame(struct l2cap_frame *frame)
+{
+	struct packet_conn_data *conn;
+	struct l2cap_frame *tx;
+
+	conn = packet_get_conn_data(frame->handle);
+	if (!conn)
+		return;
+
+	if (!conn->chan_q)
+		conn->chan_q = queue_new();
+
+	tx = new0(struct l2cap_frame, 1);
+	memcpy(tx, frame, sizeof(*frame));
+	queue_push_tail(conn->chan_q, tx);
+}
+
 void l2cap_frame_init(struct l2cap_frame *frame, uint16_t index, bool in,
 				uint16_t handle, uint8_t ident,
 				uint16_t cid, uint16_t psm,
@@ -1554,6 +1573,9 @@ void l2cap_frame_init(struct l2cap_frame *frame, uint16_t index, bool in,
 	frame->psm     = psm ? psm : get_psm(frame);
 	frame->mode    = get_mode(frame);
 	frame->seq_num = psm ? 1 : get_seq_num(frame);
+
+	if (!in)
+		l2cap_queue_frame(frame);
 }
 
 static void bredr_sig_packet(uint16_t index, bool in, uint16_t handle,
@@ -2773,3 +2795,29 @@ void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags,
 		return;
 	}
 }
+
+void l2cap_dequeue_frame(struct timeval *delta, struct packet_conn_data *conn)
+{
+	struct l2cap_frame *frame;
+	struct chan_data *chan;
+
+	frame = queue_pop_head(conn->chan_q);
+	if (!frame)
+		return;
+
+	chan = get_chan(frame);
+	if (!chan)
+		return;
+
+	packet_latency_add(&chan->tx_l, delta);
+
+	print_field("Channel: %d [PSM %d mode %s (0x%02x)] {chan %d}",
+			frame->cid, frame->psm, mode2str(frame->mode),
+			frame->mode, frame->chan);
+
+	print_field("Channel Latency: %lld msec (%lld-%lld msec ~%lld msec)",
+			TV_MSEC(*delta), TV_MSEC(chan->tx_l.min),
+			TV_MSEC(chan->tx_l.max), TV_MSEC(chan->tx_l.med));
+
+	free(frame);
+}
diff --git a/monitor/l2cap.h b/monitor/l2cap.h
index 935066e..b545bf6 100644
--- a/monitor/l2cap.h
+++ b/monitor/l2cap.h
@@ -355,3 +355,5 @@ void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags,
 					const void *data, uint16_t size);
 
 void rfcomm_packet(const struct l2cap_frame *frame);
+
+void l2cap_dequeue_frame(struct timeval *delta, struct packet_conn_data *conn);
diff --git a/monitor/ll.c b/monitor/ll.c
index f588d5e..feeb13e 100644
--- a/monitor/ll.c
+++ b/monitor/ll.c
@@ -458,6 +458,64 @@ static void peripheral_feature_req(const void *data, uint8_t size)
 	packet_print_features_ll(pdu->features);
 }
 
+static void conn_param_req(const void *data, uint8_t size)
+{
+	const struct bt_ll_conn_param_req *pdu = data;
+
+	print_field("Interval min: %.2f msec (0x%4.4x)",
+				pdu->interval_min * 1.25, pdu->interval_min);
+	print_field("Interval max: %.2f msec (0x%4.4x)",
+				pdu->interval_max * 1.25, pdu->interval_max);
+	print_field("Latency: %d (0x%4.4x)", pdu->latency, pdu->latency);
+	print_field("Timeout: %d msec (0x%4.4x)", pdu->timeout * 10,
+								pdu->timeout);
+	print_field("Preffered periodicity: %.2f (0x%2.2x)",
+				pdu->pref_period * 1.25, pdu->pref_period);
+	print_field("Reference connection event count: %d (0x%2.2x)",
+			pdu->pref_conn_evt_count, pdu->pref_conn_evt_count);
+	print_field("Offset 0: %.2f msec (0x%2.2x)", pdu->offset_0 * 1.25,
+								pdu->offset_0);
+	print_field("Offset 1: %.2f msec (0x%2.2x)", pdu->offset_1 * 1.25,
+								pdu->offset_1);
+	print_field("Offset 2: %.2f msec (0x%2.2x)", pdu->offset_2 * 1.25,
+								pdu->offset_2);
+	print_field("Offset 3: %.2f msec (0x%2.2x)", pdu->offset_3 * 1.25,
+								pdu->offset_3);
+	print_field("Offset 4: %.2f msec (0x%2.2x)", pdu->offset_4 * 1.25,
+								pdu->offset_4);
+	print_field("Offset 5: %.2f msec (0x%2.2x)", pdu->offset_5 * 1.25,
+								pdu->offset_5);
+}
+
+static void conn_param_rsp(const void *data, uint8_t size)
+{
+	const struct bt_ll_conn_param_rsp *pdu = data;
+
+	print_field("Interval min: %.2f msec (0x%4.4x)",
+				pdu->interval_min * 1.25, pdu->interval_min);
+	print_field("Interval max: %.2f msec (0x%4.4x)",
+				pdu->interval_max * 1.25, pdu->interval_max);
+	print_field("Latency: %d (0x%4.4x)", pdu->latency, pdu->latency);
+	print_field("Timeout: %d msec (0x%4.4x)", pdu->timeout * 10,
+								pdu->timeout);
+	print_field("Preffered periodicity: %.2f (0x%2.2x)",
+				pdu->pref_period * 1.25, pdu->pref_period);
+	print_field("Reference connection event count: %d (0x%2.2x)",
+			pdu->pref_conn_evt_count, pdu->pref_conn_evt_count);
+	print_field("Offset 0: %.2f msec (0x%2.2x)", pdu->offset_0 * 1.25,
+								pdu->offset_0);
+	print_field("Offset 1: %.2f msec (0x%2.2x)", pdu->offset_1 * 1.25,
+								pdu->offset_1);
+	print_field("Offset 2: %.2f msec (0x%2.2x)", pdu->offset_2 * 1.25,
+								pdu->offset_2);
+	print_field("Offset 3: %.2f msec (0x%2.2x)", pdu->offset_3 * 1.25,
+								pdu->offset_3);
+	print_field("Offset 4: %.2f msec (0x%2.2x)", pdu->offset_4 * 1.25,
+								pdu->offset_4);
+	print_field("Offset 5: %.2f msec (0x%2.2x)", pdu->offset_5 * 1.25,
+								pdu->offset_5);
+}
+
 static void reject_ind_ext(const void *data, uint8_t size)
 {
 	const struct bt_ll_reject_ind_ext *pdu = data;
@@ -707,8 +765,8 @@ static const struct llcp_data llcp_table[] = {
 	{ 0x0c, "LL_VERSION_IND",           version_ind,        5, true },
 	{ 0x0d, "LL_REJECT_IND",            reject_ind,         1, true },
 	{ 0x0e, "LL_PERIPHERAL_FEATURE_REQ", peripheral_feature_req, 8, true },
-	{ 0x0f, "LL_CONNECTION_PARAM_REQ",  NULL,              23, true },
-	{ 0x10, "LL_CONNECTION_PARAM_RSP",  NULL,              23, true },
+	{ 0x0f, "LL_CONNECTION_PARAM_REQ",  conn_param_req,    23, true },
+	{ 0x10, "LL_CONNECTION_PARAM_RSP",  conn_param_rsp,    23, true },
 	{ 0x11, "LL_REJECT_IND_EXT",        reject_ind_ext,     2, true },
 	{ 0x12, "LL_PING_REQ",              null_pdu,           0, true },
 	{ 0x13, "LL_PING_RSP",              null_pdu,           0, true },
diff --git a/monitor/main.c b/monitor/main.c
index 3ec3a5f..fa56fcb 100644
--- a/monitor/main.c
+++ b/monitor/main.c
@@ -51,6 +51,9 @@ static void usage(void)
 		"\t-r, --read <file>      Read traces in btsnoop format\n"
 		"\t-w, --write <file>     Save traces in btsnoop format\n"
 		"\t-a, --analyze <file>   Analyze traces in btsnoop format\n"
+		"\t                       If gnuplot is installed on the\n"
+                "\t                       system it will also attempt to plot\n"
+		"\t                       packet latency graph.\n"
 		"\t-s, --server <socket>  Start monitor server socket\n"
 		"\t-p, --priority <level> Show only priority or lower\n"
 		"\t-i, --index <num>      Show only specified controller\n"
@@ -62,6 +65,7 @@ static void usage(void)
 		"\t-T, --date             Show time and date information\n"
 		"\t-S, --sco              Dump SCO traffic\n"
 		"\t-A, --a2dp             Dump A2DP stream traffic\n"
+		"\t-I, --iso              Dump ISO traffic\n"
 		"\t-E, --ellisys [ip]     Send Ellisys HCI Injection\n"
 		"\t-P, --no-pager         Disable pager usage\n"
 		"\t-J  --jlink <device>,[<serialno>],[<interface>],[<speed>]\n"
@@ -89,6 +93,7 @@ static const struct option main_options[] = {
 	{ "date",      no_argument,       NULL, 'T' },
 	{ "sco",       no_argument,       NULL, 'S' },
 	{ "a2dp",      no_argument,       NULL, 'A' },
+	{ "iso",       no_argument,       NULL, 'I' },
 	{ "ellisys",   required_argument, NULL, 'E' },
 	{ "no-pager",  no_argument,       NULL, 'P' },
 	{ "jlink",     required_argument, NULL, 'J' },
@@ -126,8 +131,8 @@ int main(int argc, char *argv[])
 		struct sockaddr_un addr;
 
 		opt = getopt_long(argc, argv,
-					"r:w:a:s:p:i:d:B:V:MNtTSAE:PJ:R:C:c:vh",
-					main_options, NULL);
+				"r:w:a:s:p:i:d:B:V:MNtTSAIE:PJ:R:C:c:vh",
+				main_options, NULL);
 		if (opt < 0)
 			break;
 
@@ -197,6 +202,9 @@ int main(int argc, char *argv[])
 		case 'A':
 			filter_mask |= PACKET_FILTER_SHOW_A2DP_STREAM;
 			break;
+		case 'I':
+			filter_mask |= PACKET_FILTER_SHOW_ISO_DATA;
+			break;
 		case 'E':
 			ellisys_server = optarg;
 			ellisys_port = 24352;
diff --git a/monitor/msft.c b/monitor/msft.c
index 38af672..096fedd 100644
--- a/monitor/msft.c
+++ b/monitor/msft.c
@@ -299,7 +299,8 @@ const struct vendor_ocf *msft_vendor_ocf(void)
 	return &vendor_ocf_entry;
 }
 
-static void msft_evt(uint16_t index, const void *data, uint8_t size)
+static void msft_evt(struct timeval *tv, uint16_t index,
+			const void *data, uint8_t size)
 {
 	packet_hexdump(data, size);
 }
diff --git a/monitor/packet.c b/monitor/packet.c
index dae763e..32a440b 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2011-2014  Intel Corporation
  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -25,6 +26,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <sys/socket.h>
+#include <limits.h>
 
 #include "lib/bluetooth.h"
 #include "lib/uuid.h"
@@ -33,18 +35,20 @@
 
 #include "src/shared/util.h"
 #include "src/shared/btsnoop.h"
+#include "src/shared/queue.h"
+#include "src/shared/bap-debug.h"
 #include "display.h"
 #include "bt.h"
 #include "ll.h"
 #include "hwdb.h"
 #include "keys.h"
+#include "packet.h"
 #include "l2cap.h"
 #include "control.h"
 #include "vendor.h"
 #include "msft.h"
 #include "intel.h"
 #include "broadcom.h"
-#include "packet.h"
 
 #define COLOR_CHANNEL_LABEL		COLOR_WHITE
 #define COLOR_FRAME_LABEL		COLOR_WHITE
@@ -65,6 +69,7 @@
 #define COLOR_HCI_EVENT_UNKNOWN		COLOR_WHITE_BG
 #define COLOR_HCI_ACLDATA		COLOR_CYAN
 #define COLOR_HCI_SCODATA		COLOR_YELLOW
+#define COLOR_HCI_ISODATA		COLOR_YELLOW
 
 #define COLOR_UNKNOWN_ERROR		COLOR_WHITE_BG
 #define COLOR_UNKNOWN_FEATURE_BIT	COLOR_WHITE_BG
@@ -169,44 +174,82 @@ static uint16_t get_format(uint32_t cookie)
 
 #define MAX_CONN 16
 
-static struct packet_conn_data conn_list[MAX_CONN];
+static struct packet_conn_data conn_list[MAX_CONN] = {
+	 [0 ... MAX_CONN - 1].handle = 0xffff
+};
 
-static void assign_handle(uint16_t index, uint16_t handle, uint8_t type,
-					uint8_t *dst, uint8_t dst_type)
+static struct packet_conn_data *lookup_parent(uint16_t handle)
 {
 	int i;
 
 	for (i = 0; i < MAX_CONN; i++) {
-		if (conn_list[i].handle == 0x0000) {
-			if (hci_devba(index, (bdaddr_t *)conn_list[i].src) < 0)
-				return;
+		if (conn_list[i].link == handle)
+			return &conn_list[i];
+	}
 
-			conn_list[i].index = index;
-			conn_list[i].handle = handle;
-			conn_list[i].type = type;
+	return NULL;
+}
 
-			if (!dst)
-				break;
+static struct packet_conn_data *release_handle(uint16_t handle)
+{
+	int i;
 
-			memcpy(conn_list[i].dst, dst, sizeof(conn_list[i].dst));
-			conn_list[i].dst_type = dst_type;
-			break;
+	for (i = 0; i < MAX_CONN; i++) {
+		struct packet_conn_data *conn = &conn_list[i];
+
+		if (conn->handle == handle) {
+			if (conn->destroy)
+				conn->destroy(conn->data);
+
+			queue_destroy(conn->tx_q, free);
+			queue_destroy(conn->chan_q, free);
+			memset(conn, 0, sizeof(*conn));
+			conn->handle = 0xffff;
+			return conn;
 		}
 	}
+
+	return NULL;
 }
 
-static void release_handle(uint16_t handle)
+static void assign_handle(uint16_t index, uint16_t handle, uint8_t type,
+					uint8_t *dst, uint8_t dst_type)
 {
+	struct packet_conn_data *conn = release_handle(handle);
 	int i;
 
-	for (i = 0; i < MAX_CONN; i++) {
-		if (conn_list[i].handle == handle) {
-			if (conn_list[i].destroy)
-				conn_list[i].destroy(conn_list[i].data);
+	if (!conn) {
+		for (i = 0; i < MAX_CONN; i++) {
+			if (conn_list[i].handle == 0xffff) {
+				conn = &conn_list[i];
+				break;
+			}
+		}
+	}
 
-			memset(&conn_list[i], 0, sizeof(conn_list[i]));
-			break;
+	if (!conn)
+		return;
+
+	hci_devba(index, (bdaddr_t *)conn->src);
+
+	conn->index = index;
+	conn->handle = handle;
+	conn->type = type;
+
+	if (!dst) {
+		struct packet_conn_data *p;
+
+		/* If destination is not set attempt to use the parent one if
+		 * that exists.
+		 */
+		p = lookup_parent(handle);
+		if (p) {
+			memcpy(conn->dst, p->dst, sizeof(conn->dst));
+			conn->dst_type = p->dst_type;
 		}
+	} else {
+		memcpy(conn->dst, dst, sizeof(conn->dst));
+		conn->dst_type = dst_type;
 	}
 }
 
@@ -308,13 +351,33 @@ void packet_set_msft_evt_prefix(const uint8_t *prefix, uint8_t len)
 		memcpy(index_list[index_current].msft_evt_prefix, prefix, len);
 }
 
+static void cred_pid(struct ucred *cred, char *str, size_t len)
+{
+	char *path = alloca(24);
+	char line[128];
+	FILE *fp;
+
+	snprintf(path, 23, "/proc/%u/comm", cred->pid);
+
+	fp = fopen(path, "re");
+	if (fp) {
+		if (fgets(line, sizeof(line), fp)) {
+			line[strcspn(line, "\r\n")] = '\0';
+			snprintf(str, len, "%s[%u]", line, cred->pid);
+		} else
+			snprintf(str, len, "[%u]", cred->pid);
+		fclose(fp);
+	} else
+		snprintf(str, len, "[%u]", cred->pid);
+}
+
 static void print_packet(struct timeval *tv, struct ucred *cred, char ident,
 					uint16_t index, const char *channel,
 					const char *color, const char *label,
 					const char *text, const char *extra)
 {
 	int col = num_columns();
-	char line[256], ts_str[96];
+	char line[LINE_MAX], ts_str[96], pid_str[140];
 	int n, ts_len = 0, ts_pos = 0, len = 0, pos = 0;
 	static size_t last_frame;
 
@@ -411,7 +474,13 @@ static void print_packet(struct timeval *tv, struct ucred *cred, char ident,
 			pos += n;
 	}
 
-	n = sprintf(line + pos, "%c %s", ident, label ? label : "");
+	if (cred && cred->pid) {
+		cred_pid(cred, pid_str, sizeof(pid_str));
+		n = sprintf(line + pos, "%s: %c %s", pid_str, ident,
+						label ? label : "");
+	} else
+		n = sprintf(line + pos, "%c %s", ident, label ? label : "");
+
 	if (n > 0) {
 		pos += n;
 		len += n;
@@ -2391,6 +2460,9 @@ void packet_print_version(const char *label, uint8_t version,
 	case 0x0c:
 		str = "Bluetooth 5.3";
 		break;
+	case 0x0d:
+		str = "Bluetooth 5.4";
+		break;
 	default:
 		str = "Reserved";
 		break;
@@ -2663,7 +2735,7 @@ static const struct bitfield_data features_le[] = {
 	{ 29, "Connected Isochronous Stream - Peripheral"	},
 	{ 30, "Isochronous Broadcaster"				},
 	{ 31, "Synchronized Receiver"				},
-	{ 32, "Isochronous Channels (Host Support)"		},
+	{ 32, "Connected Isochronous Stream (Host Support)"	},
 	{ 33, "LE Power Control Request"			},
 	{ 34, "LE Power Control Request"			},
 	{ 35, "LE Path Loss Monitoring"				},
@@ -3054,12 +3126,21 @@ static const struct bitfield_data events_le_table[] = {
 	{ 17, "LE Extended Advertising Set Terminated"	},
 	{ 18, "LE Scan Request Received"		},
 	{ 19, "LE Channel Selection Algorithm"		},
+	{ 20, "LE Connectionless IQ Report"		},
+	{ 21, "LE Connection IQ Report"			},
+	{ 22, "LE CTE Request Failed"			},
+	{ 23, "LE Periodic Advertising Sync Transfer Rvc"},
 	{ 24, "LE CIS Established"			},
 	{ 25, "LE CIS Request"				},
 	{ 26, "LE Create BIG Complete"			},
 	{ 27, "LE Terminate BIG Complete"		},
 	{ 28, "LE BIG Sync Estabilished Complete"	},
 	{ 29, "LE BIG Sync Lost"			},
+	{ 30, "LE Request Peer SCA Complete"},
+	{ 31, "LE Path Loss Threshold"		},
+	{ 32, "LE Transmit Power Reporting"	},
+	{ 33, "LE BIG Info Advertising Report"	},
+	{ 34, "LE Subrate Change"			},
 	{ }
 };
 
@@ -3123,6 +3204,7 @@ static void print_fec(uint8_t fec)
 #define BT_EIR_MESH_PROV		0x29
 #define BT_EIR_MESH_DATA		0x2a
 #define BT_EIR_MESH_BEACON		0x2b
+#define BT_EIR_CSIP_RSI			0x2e
 #define BT_EIR_3D_INFO_DATA		0x3d
 #define BT_EIR_MANUFACTURER_DATA	0xff
 
@@ -3332,86 +3414,11 @@ static void print_uuid128_list(const char *label, const void *data,
 	}
 }
 
-static void *iov_pull(struct iovec *iov, size_t len)
+static void print_ltv(const char *str, void *user_data)
 {
-	void *data;
-
-	if (iov->iov_len < len)
-		return NULL;
-
-	data = iov->iov_base;
-	iov->iov_base += len;
-	iov->iov_len -= len;
+	const char *label = user_data;
 
-	return data;
-}
-
-static struct packet_ltv_decoder*
-get_ltv_decoder(struct packet_ltv_decoder *decoder, size_t num, uint8_t type)
-{
-	size_t i;
-
-	if (!decoder || !num)
-		return NULL;
-
-	for (i = 0; i < num; i++) {
-		struct packet_ltv_decoder *dec = &decoder[i];
-
-		if (dec->type == type)
-			return dec;
-	}
-
-	return NULL;
-}
-
-static void print_ltv(const char *label, const uint8_t *data, uint8_t len,
-			struct packet_ltv_decoder *decoder, size_t num)
-{
-	struct iovec iov;
-	int i;
-
-	iov.iov_base = (void *) data;
-	iov.iov_len = len;
-
-	for (i = 0; iov.iov_len; i++) {
-		uint8_t l, t, *v;
-		struct packet_ltv_decoder *dec;
-
-		l = get_u8(iov_pull(&iov, sizeof(l)));
-		if (!l) {
-			print_field("%s #%d: len 0x%02x", label, i, l);
-			break;
-		}
-
-		v = iov_pull(&iov, sizeof(*v));
-		if (!v)
-			break;
-
-		t = get_u8(v);
-
-		print_field("%s #%d: len 0x%02x type 0x%02x", label, i, l, t);
-
-		l -= 1;
-
-		v = iov_pull(&iov, l);
-		if (!v)
-			break;
-
-		dec = get_ltv_decoder(decoder, num, t);
-		if (dec)
-			dec->func(v, l);
-		else
-			print_hex_field(label, v, l);
-	}
-
-	if (iov.iov_len)
-		print_hex_field(label, iov.iov_base, iov.iov_len);
-}
-
-void packet_print_ltv(const char *label, const uint8_t *data, uint8_t len,
-			struct packet_ltv_decoder *decoder, size_t decoder_len)
-{
-	print_ltv(label, data, len, decoder, decoder_len);
+	print_field("%s: %s", label, str);
 }
 
 static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
@@ -3423,7 +3430,7 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
 	iov.iov_base = (void *) data;
 	iov.iov_len = data_len;
 
-	base_data = iov_pull(&iov, sizeof(*base_data));
+	base_data = util_iov_pull_mem(&iov, sizeof(*base_data));
 	if (!base_data)
 		goto done;
 
@@ -3437,10 +3444,11 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
 		struct bt_hci_lv_data *codec_cfg;
 		struct bt_hci_lv_data *metadata;
 		uint8_t j;
+		const char *label;
 
 		print_field("    Subgroup #%u:", i);
 
-		subgroup = iov_pull(&iov, sizeof(*subgroup));
+		subgroup = util_iov_pull_mem(&iov, sizeof(*subgroup));
 		if (!subgroup)
 			goto done;
 
@@ -3457,26 +3465,31 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
 						subgroup->codec.vid);
 		}
 
-		codec_cfg = iov_pull(&iov, sizeof(*codec_cfg));
+		codec_cfg = util_iov_pull_mem(&iov, sizeof(*codec_cfg));
 		if (!codec_cfg)
 			goto done;
 
-		if (!iov_pull(&iov, codec_cfg->len))
+		if (!util_iov_pull_mem(&iov, codec_cfg->len))
 			goto done;
 
-		print_ltv("    Codec Specific Configuration",
-					codec_cfg->data, codec_cfg->len,
-					NULL, 0);
+		label = "    Codec Specific Configuration";
 
-		metadata = iov_pull(&iov, sizeof(*metadata));
+		bt_bap_debug_config(codec_cfg->data, codec_cfg->len,
+					print_ltv, (void *)label);
+
+		metadata = util_iov_pull_mem(&iov, sizeof(*metadata));
 		if (!metadata)
 			goto done;
 
-		if (!iov_pull(&iov, metadata->len))
+		if (!util_iov_pull(&iov, metadata->len))
 			goto done;
 
-		print_ltv("    Metadata", metadata->data, metadata->len,
-					NULL, 0);
+		label = "    Metadata";
+
+		bt_bap_debug_metadata(metadata->data, metadata->len,
+					print_ltv, (void *)label);
+
+		label = "      Codec Specific Configuration";
 
 		/* Level 3 - BIS(s)*/
 		for (j = 0; j < subgroup->num_bis; j++) {
@@ -3484,21 +3497,21 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
 
 			print_field("      BIS #%u:", j);
 
-			bis = iov_pull(&iov, sizeof(*bis));
+			bis = util_iov_pull_mem(&iov, sizeof(*bis));
 			if (!bis)
 				goto done;
 
 			print_field("      Index: %u", bis->index);
 
-			codec_cfg = iov_pull(&iov, sizeof(*codec_cfg));
+			codec_cfg = util_iov_pull_mem(&iov, sizeof(*codec_cfg));
 			if (!codec_cfg)
 				goto done;
 
-			if (!iov_pull(&iov, codec_cfg->len))
+			if (!util_iov_pull(&iov, codec_cfg->len))
 				goto done;
 
-			print_hex_field("      Codec Specific Configuration",
-					codec_cfg->data, codec_cfg->len);
+			bt_bap_debug_config(codec_cfg->data, codec_cfg->len,
+					print_ltv, (void *)label);
 		}
 	}
 
@@ -3767,7 +3780,7 @@ static void print_transport_data(const uint8_t *data, uint8_t len)
 		print_field("      Provider Only");
 		break;
 	case 0x03:
-		print_field("      Both Seeker an Provider");
+		print_field("      Both Seeker and Provider");
 		break;
 	}
 
@@ -3954,6 +3967,18 @@ static void print_eir(const uint8_t *eir, uint8_t eir_len, bool le)
 			print_service_data(data, data_len);
 			break;
 
+		case BT_EIR_SERVICE_DATA128:
+			if (data_len <= 16)
+				break;
+
+			print_field("Service Data UUID 128: %s ",
+						bt_uuid128_to_str(&data[0]));
+
+			if (data_len > 16)
+				print_hex_field("  Data", &data[16],
+								data_len - 16);
+
+			break;
 		case BT_EIR_RANDOM_ADDRESS:
 			if (data_len < 6)
 				break;
@@ -4017,6 +4042,14 @@ static void print_eir(const uint8_t *eir, uint8_t eir_len, bool le)
 			print_mesh_beacon(data, data_len);
 			break;
 
+		case BT_EIR_CSIP_RSI:
+			if (data_len < 6)
+				break;
+			print_addr("Resolvable Set Identifier", data, 0xff);
+			print_field("  Hash: 0x%6x", get_le24(data));
+			print_field("  Random: 0x%6x", get_le24(data + 3));
+			break;
+
 		case BT_EIR_MANUFACTURER_DATA:
 			if (data_len < 2)
 				break;
@@ -4261,10 +4294,26 @@ void packet_monitor(struct timeval *tv, struct ucred *cred,
 				 */
 				index_list[index].msft_opcode = 0xFC1E;
 				break;
+			case 29:
+				/*
+				 * Qualcomm controllers that support the
+				 * Microsoft vendor extensions are using
+				 * 0xFD70 for VsMsftOpCode.
+				 */
+				index_list[index].msft_opcode = 0xFD70;
+				break;
+			case 70:
+				/*
+				 * Mediatek controllers that support the
+				 * Microsoft vendor extensions are using
+				 * 0xFD30 for VsMsftOpCode.
+				 */
+				index_list[index].msft_opcode = 0xFD30;
+				break;
 			case 93:
 				/*
 				 * Realtek controllers that support the
-				 * Microsoft vendor extenions are using
+				 * Microsoft vendor extensions are using
 				 * 0xFCF0 for VsMsftOpCode.
 				 */
 				index_list[index].msft_opcode = 0xFCF0;
@@ -4273,7 +4322,7 @@ void packet_monitor(struct timeval *tv, struct ucred *cred,
 				/*
 				 * Emulator controllers use Linux Foundation as
 				 * manufacturer and support the
-				 * Microsoft vendor extenions using
+				 * Microsoft vendor extensions using
 				 * 0xFC1E for VsMsftOpCode.
 				 */
 				index_list[index].msft_opcode = 0xFC1E;
@@ -4797,6 +4846,50 @@ static void flow_spec_modify_cmd(uint16_t index, const void *data, uint8_t size)
 	print_flow_spec("RX", cmd->rx_flow_spec);
 }
 
+static void print_coding_format(const char *label,
+						const uint8_t coding_format[5])
+{
+	print_field("%s:", label);
+	packet_print_codec_id("  Codec", coding_format[0]);
+	if (coding_format[0] == 0xff) {
+		print_field("  Company: %s",
+				bt_compidtostr(get_le16(coding_format + 1)));
+		print_field("  Vendor Specific Codec: 0x%4.4x",
+						get_le16(coding_format + 3));
+	}
+}
+
+static void print_pcm_data_format(const char *label, uint8_t pcm)
+{
+	switch (pcm) {
+	case 0:
+		print_field("%s: NA", label);
+		break;
+	case 1:
+		print_field("%s: 1's complement", label);
+		break;
+	case 2:
+		print_field("%s: 2's complement", label);
+		break;
+	case 3:
+		print_field("%s: Sign-magnitude", label);
+		break;
+	case 4:
+		print_field("%s: Unsigned", label);
+		break;
+	default:
+		print_field("%s: Unknown (0x%2.2x)", label, pcm);
+	}
+}
+
+static void print_data_path(const char *label, uint8_t data_path)
+{
+	if (data_path == 0)
+		print_field("%s: HCI", label);
+	else
+		print_field("%s: Vendor Specific (0x%2.2x)", label, data_path);
+}
+
 static void enhanced_setup_sync_conn_cmd(uint16_t index, const void *data,
 							uint8_t size)
 {
@@ -4805,9 +4898,30 @@ static void enhanced_setup_sync_conn_cmd(uint16_t index, const void *data,
 	print_handle(cmd->handle);
 	print_field("Transmit bandwidth: %d", le32_to_cpu(cmd->tx_bandwidth));
 	print_field("Receive bandwidth: %d", le32_to_cpu(cmd->rx_bandwidth));
-
-	/* TODO */
-
+	print_coding_format("Transmit Coding Format", cmd->tx_coding_format);
+	print_coding_format("Receive Coding Format", cmd->rx_coding_format);
+	print_field("Transmit Codec Frame Size: %d",
+					le16_to_cpu(cmd->tx_codec_frame_size));
+	print_field("Receive Codec Frame Size: %d",
+					le16_to_cpu(cmd->rx_codec_frame_size));
+	print_coding_format("Input Coding Format", cmd->input_coding_format);
+	print_coding_format("Output Coding Format", cmd->output_coding_format);
+	print_field("Input Coded Data Size: %d",
+				le16_to_cpu(cmd->input_coded_data_size));
+	print_field("Output Coded Data Size: %d",
+				le16_to_cpu(cmd->output_coded_data_size));
+	print_pcm_data_format("Input PCM Data Format",
+						cmd->input_pcm_data_format);
+	print_pcm_data_format("Output PCM Data Format",
+						cmd->output_pcm_data_format);
+	print_field("Input PCM Sample Payload MSB Position: %d",
+						cmd->input_pcm_msb_position);
+	print_field("Output PCM Sample Payload MSB Position: %d",
+						cmd->output_pcm_msb_position);
+	print_data_path("Input Data Path", cmd->input_data_path);
+	print_data_path("Output Data Path", cmd->output_data_path);
+	print_field("Input Transport Unit Size: %d", cmd->input_unit_size);
+	print_field("Output Transport Unit Size: %d", cmd->output_unit_size);
 	print_field("Max latency: %d", le16_to_cpu(cmd->max_latency));
 	print_pkt_type_sco(cmd->pkt_type);
 	print_retransmission_effort(cmd->retrans_effort);
@@ -4822,9 +4936,30 @@ static void enhanced_accept_sync_conn_request_cmd(uint16_t index,
 	print_bdaddr(cmd->bdaddr);
 	print_field("Transmit bandwidth: %d", le32_to_cpu(cmd->tx_bandwidth));
 	print_field("Receive bandwidth: %d", le32_to_cpu(cmd->rx_bandwidth));
-
-	/* TODO */
-
+	print_coding_format("Transmit Coding Format", cmd->tx_coding_format);
+	print_coding_format("Receive Coding Format", cmd->rx_coding_format);
+	print_field("Transmit Codec Frame Size: %d",
+					le16_to_cpu(cmd->tx_codec_frame_size));
+	print_field("Receive Codec Frame Size: %d",
+					le16_to_cpu(cmd->rx_codec_frame_size));
+	print_coding_format("Input Coding Format", cmd->input_coding_format);
+	print_coding_format("Output Coding Format", cmd->output_coding_format);
+	print_field("Input Coded Data Size: %d",
+				le16_to_cpu(cmd->input_coded_data_size));
+	print_field("Output Coded Data Size: %d",
+				le16_to_cpu(cmd->output_coded_data_size));
+	print_pcm_data_format("Input PCM Data Format",
+						cmd->input_pcm_data_format);
+	print_pcm_data_format("Output PCM Data Format",
+						cmd->output_pcm_data_format);
+	print_field("Input PCM Sample Payload MSB Position: %d",
+						cmd->input_pcm_msb_position);
+	print_field("Output PCM Sample Payload MSB Position: %d",
+						cmd->output_pcm_msb_position);
+	print_data_path("Input Data Path", cmd->input_data_path);
+	print_data_path("Output Data Path", cmd->output_data_path);
+	print_field("Input Transport Unit Size: %d", cmd->input_unit_size);
+	print_field("Output Transport Unit Size: %d", cmd->output_unit_size);
 	print_field("Max latency: %d", le16_to_cpu(cmd->max_latency));
 	print_pkt_type_sco(cmd->pkt_type);
 	print_retransmission_effort(cmd->retrans_effort);
@@ -6384,6 +6519,20 @@ static void print_list(const void *data, uint8_t size, int num_items,
 		print_hex_field("", data, size);
 }
 
+static void print_vnd_codecs_v2(const void *data, int i)
+{
+	const struct bt_hci_vnd_codec_v2 *codec = data;
+	uint8_t mask;
+
+	packet_print_company("  Company ID", le16_to_cpu(codec->cid));
+	print_field("  Vendor Codec ID: 0x%4.4x", le16_to_cpu(codec->vid));
+	print_field("  Logical Transport Type: 0x%02x", codec->transport);
+	mask = print_bitfield(4, codec->transport, codec_transport_table);
+	if (mask)
+		print_text(COLOR_UNKNOWN_SERVICE_CLASS,
+				"  Unknown transport (0x%2.2x)", mask);
+}
+
 static void read_local_codecs_rsp_v2(uint16_t index, const void *data,
 							uint8_t size)
 {
@@ -6417,7 +6566,18 @@ static void read_local_codecs_rsp_v2(uint16_t index, const void *data,
 
 	num_vnd_codecs = rsp->codec[rsp->num_codecs].id;
 
+	size -= 1;
+
 	print_field("Number of vendor codecs: %d", num_vnd_codecs);
+
+	if (size < num_vnd_codecs * sizeof(*rsp->codec)) {
+		print_field("Invalid number of vendor codecs.");
+		return;
+	}
+
+	print_list(&rsp->codec[rsp->num_codecs] + 1, size, num_vnd_codecs,
+			sizeof(struct bt_hci_vnd_codec_v2),
+			print_vnd_codecs_v2);
 }
 
 static void print_path_direction(const char *prefix, uint8_t dir)
@@ -6520,11 +6680,9 @@ static void config_data_path_cmd(uint16_t index, const void *data, uint8_t size)
 
 static void print_usec_interval(const char *prefix, const uint8_t interval[3])
 {
-	uint32_t u24 = 0;
+	uint32_t value = get_le24(interval);
 
-	memcpy(&u24, interval, 3);
-	print_field("%s: %u us (0x%6.6x)", prefix, le32_to_cpu(u24),
-						le32_to_cpu(u24));
+	print_field("%s: %u us (0x%6.6x)", prefix, value, value);
 }
 
 static void read_local_ctrl_delay_rsp(uint16_t index, const void *data,
@@ -8639,9 +8797,14 @@ static void le_set_cig_params_rsp(uint16_t index, const void *data,
 static void print_cis(const void *data, int i)
 {
 	const struct bt_hci_cis *cis = data;
+	struct packet_conn_data *conn;
 
 	print_field("CIS Handle: %d", cis->cis_handle);
 	print_field("ACL Handle: %d", cis->acl_handle);
+
+	conn = packet_get_conn_data(cis->acl_handle);
+	if (conn)
+		conn->link = cis->cis_handle;
 }
 
 static void le_create_cis_cmd(uint16_t index, const void *data, uint8_t size)
@@ -8741,7 +8904,7 @@ static void le_create_big_cmd_test_cmd(uint16_t index, const void *data,
 {
 	const struct bt_hci_cmd_le_create_big_test *cmd = data;
 
-	print_field("BIG ID: 0x%2.2x", cmd->big_id);
+	print_field("BIG Handle: 0x%2.2x", cmd->big_handle);
 	print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
 	print_field("Number of BIS: %u", cmd->num_bis);
 
@@ -8774,7 +8937,7 @@ static void le_big_create_sync_cmd(uint16_t index, const void *data,
 	print_field("BIG Handle: 0x%2.2x", cmd->handle);
 	print_field("BIG Sync Handle: 0x%4.4x", le16_to_cpu(cmd->sync_handle));
 	print_field("Encryption: %s (0x%2.2x)",
-			cmd->encryption ? "Unencrypted" : "Encrypted",
+			cmd->encryption ? "Encrypted" : "Unencrypted",
 			cmd->encryption);
 	print_hex_field("Broadcast Code", cmd->bcode, 16);
 	print_field("Maximum Number Subevents: 0x%2.2x", cmd->mse);
@@ -8872,6 +9035,37 @@ static void le_set_host_feature_cmd(uint16_t index, const void *data,
 	print_field("Bit Value: %u", cmd->bit_value);
 }
 
+static void le_read_iso_link_quality_cmd(uint16_t index, const void *data,
+							uint8_t size)
+{
+	const struct bt_hci_cmd_le_read_iso_link_quality *cmd = data;
+
+	print_field("Handle: %d", le16_to_cpu(cmd->handle));
+}
+
+static void status_le_read_iso_link_quality_rsp(uint16_t index,
+							const void *data,
+							uint8_t size)
+{
+	const struct bt_hci_rsp_le_read_iso_link_quality *rsp = data;
+
+	print_status(rsp->status);
+
+	if (size == 1)
+		return;
+
+	print_field("Handle: %d", le16_to_cpu(rsp->handle));
+	print_field("TX unacked packets %d", rsp->tx_unacked_packets);
+	print_field("TX flushed packets %d", rsp->tx_flushed_packets);
+	print_field("TX last subevent packets %d",
+					rsp->tx_last_subevent_packets);
+	print_field("TX retransmitted packets %d",
+						rsp->retransmitted_packets);
+	print_field("TX crc error packets %d", rsp->crc_error_packets);
+	print_field("RX unreceived packets %d", rsp->rx_unreceived_packets);
+	print_field("Duplicated packets %d", rsp->duplicated_packets);
+}
+
 struct opcode_data {
 	uint16_t opcode;
 	int bit;
@@ -9801,7 +9995,9 @@ static const struct opcode_data opcode_table[] = {
 				"LE Remove Isochronous Data Path",
 				le_remove_iso_path_cmd,
 				sizeof(struct bt_hci_cmd_le_remove_iso_path),
-				true, status_rsp, 1, true },
+				true, status_handle_rsp,
+				sizeof(struct bt_hci_rsp_le_remove_iso_path),
+				true },
 	{ BT_HCI_CMD_LE_ISO_TX_TEST, BT_HCI_BIT_LE_ISO_TX_TEST,
 				"LE Isochronous Transmit Test", NULL, 0,
 				false },
@@ -9819,6 +10015,16 @@ static const struct opcode_data opcode_table[] = {
 				"LE Set Host Feature", le_set_host_feature_cmd,
 				sizeof(struct bt_hci_cmd_le_set_host_feature),
 				true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_READ_ISO_LINK_QUALITY,
+				BT_HCI_BIT_LE_READ_ISO_LINK_QUALITY,
+				"LE Read ISO link quality",
+				le_read_iso_link_quality_cmd,
+				sizeof(
+				struct bt_hci_cmd_le_read_iso_link_quality),
+				true, status_le_read_iso_link_quality_rsp,
+				sizeof(
+				struct bt_hci_rsp_le_read_iso_link_quality),
+				true },
 	{ }
 };
 
@@ -9933,14 +10139,16 @@ static const char *current_vendor_evt_str(void)
 	return NULL;
 }
 
-static void inquiry_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void inquiry_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_inquiry_complete *evt = data;
 
 	print_status(evt->status);
 }
 
-static void inquiry_result_evt(uint16_t index, const void *data, uint8_t size)
+static void inquiry_result_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_inquiry_result *evt = data;
 
@@ -9956,12 +10164,13 @@ static void inquiry_result_evt(uint16_t index, const void *data, uint8_t size)
 		packet_hexdump(data + sizeof(*evt), size - sizeof(*evt));
 }
 
-static void conn_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void conn_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_conn_complete *evt = data;
 
 	print_status(evt->status);
-	print_handle(evt->handle);
+	print_field("Handle: %d", le16_to_cpu(evt->handle));
 	print_bdaddr(evt->bdaddr);
 	print_link_type(evt->link_type);
 	print_enable("Encryption", evt->encr_mode);
@@ -9971,7 +10180,8 @@ static void conn_complete_evt(uint16_t index, const void *data, uint8_t size)
 					(void *)evt->bdaddr, BDADDR_BREDR);
 }
 
-static void conn_request_evt(uint16_t index, const void *data, uint8_t size)
+static void conn_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_conn_request *evt = data;
 
@@ -9980,8 +10190,8 @@ static void conn_request_evt(uint16_t index, const void *data, uint8_t size)
 	print_link_type(evt->link_type);
 }
 
-static void disconnect_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void disconnect_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_disconnect_complete *evt = data;
 
@@ -9993,7 +10203,8 @@ static void disconnect_complete_evt(uint16_t index, const void *data,
 		release_handle(le16_to_cpu(evt->handle));
 }
 
-static void auth_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void auth_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_auth_complete *evt = data;
 
@@ -10001,8 +10212,8 @@ static void auth_complete_evt(uint16_t index, const void *data, uint8_t size)
 	print_handle(evt->handle);
 }
 
-static void remote_name_request_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_name_request_complete_evt(struct timeval *tv, uint16_t index,
+						const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_name_request_complete *evt = data;
 
@@ -10011,7 +10222,8 @@ static void remote_name_request_complete_evt(uint16_t index, const void *data,
 	print_name(evt->name);
 }
 
-static void encrypt_change_evt(uint16_t index, const void *data, uint8_t size)
+static void encrypt_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_encrypt_change *evt = data;
 
@@ -10020,8 +10232,9 @@ static void encrypt_change_evt(uint16_t index, const void *data, uint8_t size)
 	print_encr_mode_change(evt->encr_mode, evt->handle);
 }
 
-static void change_conn_link_key_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void change_conn_link_key_complete_evt(struct timeval *tv,
+						uint16_t index,
+						const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_change_conn_link_key_complete *evt = data;
 
@@ -10029,8 +10242,8 @@ static void change_conn_link_key_complete_evt(uint16_t index, const void *data,
 	print_handle(evt->handle);
 }
 
-static void link_key_type_changed_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void link_key_type_changed_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_link_key_type_changed *evt = data;
 
@@ -10039,8 +10252,8 @@ static void link_key_type_changed_evt(uint16_t index, const void *data,
 	print_key_flag(evt->key_flag);
 }
 
-static void remote_features_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_features_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_features_complete *evt = data;
 
@@ -10049,8 +10262,8 @@ static void remote_features_complete_evt(uint16_t index, const void *data,
 	print_features(0, evt->features, 0x00);
 }
 
-static void remote_version_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_version_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_version_complete *evt = data;
 
@@ -10066,8 +10279,8 @@ static void remote_version_complete_evt(uint16_t index, const void *data,
 	}
 }
 
-static void qos_setup_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void qos_setup_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_qos_setup_complete *evt = data;
 
@@ -10083,7 +10296,8 @@ static void qos_setup_complete_evt(uint16_t index, const void *data,
 	print_field("Delay variation: %d", le32_to_cpu(evt->delay_variation));
 }
 
-static void cmd_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void cmd_complete_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_cmd_complete *evt = data;
 	uint16_t opcode = le16_to_cpu(evt->opcode);
@@ -10179,7 +10393,8 @@ static void cmd_complete_evt(uint16_t index, const void *data, uint8_t size)
 	opcode_data->rsp_func(index, data + 3, size - 3);
 }
 
-static void cmd_status_evt(uint16_t index, const void *data, uint8_t size)
+static void cmd_status_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_cmd_status *evt = data;
 	uint16_t opcode = le16_to_cpu(evt->opcode);
@@ -10231,21 +10446,24 @@ static void cmd_status_evt(uint16_t index, const void *data, uint8_t size)
 	print_status(evt->status);
 }
 
-static void hardware_error_evt(uint16_t index, const void *data, uint8_t size)
+static void hardware_error_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_hardware_error *evt = data;
 
 	print_field("Code: 0x%2.2x", evt->code);
 }
 
-static void flush_occurred_evt(uint16_t index, const void *data, uint8_t size)
+static void flush_occurred_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_flush_occurred *evt = data;
 
 	print_handle(evt->handle);
 }
 
-static void role_change_evt(uint16_t index, const void *data, uint8_t size)
+static void role_change_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_role_change *evt = data;
 
@@ -10254,20 +10472,105 @@ static void role_change_evt(uint16_t index, const void *data, uint8_t size)
 	print_role(evt->role);
 }
 
-static void num_completed_packets_evt(uint16_t index, const void *data,
-							uint8_t size)
+void packet_latency_add(struct packet_latency *latency, struct timeval *delta)
+{
+	timeradd(&latency->total, delta, &latency->total);
+
+	if ((!timerisset(&latency->min) || timercmp(delta, &latency->min, <))
+				&& delta->tv_sec >= 0 && delta->tv_usec >= 0)
+		latency->min = *delta;
+
+	if (!timerisset(&latency->max) || timercmp(delta, &latency->max, >))
+		latency->max = *delta;
+
+	if (timerisset(&latency->med)) {
+		struct timeval tmp;
+
+		timeradd(&latency->med, delta, &tmp);
+
+		tmp.tv_sec /= 2;
+		tmp.tv_usec /= 2;
+		if (tmp.tv_sec % 2) {
+			tmp.tv_usec += 500000;
+			if (tmp.tv_usec >= 1000000) {
+				tmp.tv_sec++;
+				tmp.tv_usec -= 1000000;
+			}
+		}
+
+		latency->med = tmp;
+	} else
+		latency->med = *delta;
+}
+
+static void packet_dequeue_tx(struct timeval *tv, uint16_t handle)
+{
+	struct packet_conn_data *conn;
+	struct packet_frame *frame;
+	struct timeval delta;
+
+	conn = packet_get_conn_data(handle);
+	if (!conn)
+		return;
+
+	frame = queue_pop_head(conn->tx_q);
+	if (!frame)
+		return;
+
+	timersub(tv, &frame->tv, &delta);
+
+	packet_latency_add(&conn->tx_l, &delta);
+
+	if (TV_MSEC(delta)) {
+		print_field("#%zu: len %zu (%lld Kb/s)", frame->num, frame->len,
+				frame->len * 8 / TV_MSEC(delta));
+		print_field("Latency: %lld msec (%lld-%lld msec ~%lld msec)",
+				TV_MSEC(delta), TV_MSEC(conn->tx_l.min),
+				TV_MSEC(conn->tx_l.max),
+				TV_MSEC(conn->tx_l.med));
+	}
+
+	l2cap_dequeue_frame(&delta, conn);
+
+	free(frame);
+}
+
+static void num_completed_packets_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
+	struct iovec iov = { (void *)data, size};
 	const struct bt_hci_evt_num_completed_packets *evt = data;
+	int i;
+
+	util_iov_pull(&iov, 1);
 
 	print_field("Num handles: %d", evt->num_handles);
-	print_handle(evt->handle);
-	print_field("Count: %d", le16_to_cpu(evt->count));
 
-	if (size > sizeof(*evt))
-		packet_hexdump(data + sizeof(*evt), size - sizeof(*evt));
+	for (i = 0; i < evt->num_handles; i++) {
+		uint16_t handle;
+		uint16_t count;
+		int j;
+
+		if (!util_iov_pull_le16(&iov, &handle))
+			break;
+
+		print_handle_native(handle);
+
+		if (!util_iov_pull_le16(&iov, &count))
+			break;
+
+		print_field("Count: %d", count);
+
+		for (j = 0; j < count; j++)
+			packet_dequeue_tx(tv, handle);
+	}
+
+	if (iov.iov_len)
+		packet_hexdump(iov.iov_base, iov.iov_len);
 }
 
-static void mode_change_evt(uint16_t index, const void *data, uint8_t size)
+static void mode_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_mode_change *evt = data;
 
@@ -10277,7 +10580,8 @@ static void mode_change_evt(uint16_t index, const void *data, uint8_t size)
 	print_interval(evt->interval);
 }
 
-static void return_link_keys_evt(uint16_t index, const void *data, uint8_t size)
+static void return_link_keys_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_return_link_keys *evt = data;
 	uint8_t i;
@@ -10290,21 +10594,24 @@ static void return_link_keys_evt(uint16_t index, const void *data, uint8_t size)
 	}
 }
 
-static void pin_code_request_evt(uint16_t index, const void *data, uint8_t size)
+static void pin_code_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_pin_code_request *evt = data;
 
 	print_bdaddr(evt->bdaddr);
 }
 
-static void link_key_request_evt(uint16_t index, const void *data, uint8_t size)
+static void link_key_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_link_key_request *evt = data;
 
 	print_bdaddr(evt->bdaddr);
 }
 
-static void link_key_notify_evt(uint16_t index, const void *data, uint8_t size)
+static void link_key_notify_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_link_key_notify *evt = data;
 
@@ -10313,20 +10620,22 @@ static void link_key_notify_evt(uint16_t index, const void *data, uint8_t size)
 	print_key_type(evt->key_type);
 }
 
-static void loopback_command_evt(uint16_t index, const void *data, uint8_t size)
+static void loopback_command_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	packet_hexdump(data, size);
 }
 
-static void data_buffer_overflow_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void data_buffer_overflow_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_data_buffer_overflow *evt = data;
 
 	print_link_type(evt->link_type);
 }
 
-static void max_slots_change_evt(uint16_t index, const void *data, uint8_t size)
+static void max_slots_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_max_slots_change *evt = data;
 
@@ -10334,8 +10643,8 @@ static void max_slots_change_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("Max slots: %d", evt->max_slots);
 }
 
-static void clock_offset_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void clock_offset_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_clock_offset_complete *evt = data;
 
@@ -10344,8 +10653,8 @@ static void clock_offset_complete_evt(uint16_t index, const void *data,
 	print_clock_offset(evt->clock_offset);
 }
 
-static void conn_pkt_type_changed_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void conn_pkt_type_changed_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_conn_pkt_type_changed *evt = data;
 
@@ -10354,15 +10663,16 @@ static void conn_pkt_type_changed_evt(uint16_t index, const void *data,
 	print_pkt_type(evt->pkt_type);
 }
 
-static void qos_violation_evt(uint16_t index, const void *data, uint8_t size)
+static void qos_violation_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_qos_violation *evt = data;
 
 	print_handle(evt->handle);
 }
 
-static void pscan_mode_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void pscan_mode_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_pscan_mode_change *evt = data;
 
@@ -10370,8 +10680,8 @@ static void pscan_mode_change_evt(uint16_t index, const void *data,
 	print_pscan_mode(evt->pscan_mode);
 }
 
-static void pscan_rep_mode_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void pscan_rep_mode_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_pscan_rep_mode_change *evt = data;
 
@@ -10379,8 +10689,8 @@ static void pscan_rep_mode_change_evt(uint16_t index, const void *data,
 	print_pscan_rep_mode(evt->pscan_rep_mode);
 }
 
-static void flow_spec_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void flow_spec_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_flow_spec_complete *evt = data;
 
@@ -10398,8 +10708,8 @@ static void flow_spec_complete_evt(uint16_t index, const void *data,
 	print_field("Access latency: %d", le32_to_cpu(evt->access_latency));
 }
 
-static void inquiry_result_with_rssi_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void inquiry_result_with_rssi_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_inquiry_result_with_rssi *evt = data;
 
@@ -10415,8 +10725,8 @@ static void inquiry_result_with_rssi_evt(uint16_t index, const void *data,
 		packet_hexdump(data + sizeof(*evt), size - sizeof(*evt));
 }
 
-static void remote_ext_features_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_ext_features_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_ext_features_complete *evt = data;
 
@@ -10426,13 +10736,13 @@ static void remote_ext_features_complete_evt(uint16_t index, const void *data,
 	print_features(evt->page, evt->features, 0x00);
 }
 
-static void sync_conn_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void sync_conn_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_sync_conn_complete *evt = data;
 
 	print_status(evt->status);
-	print_handle(evt->handle);
+	print_field("Handle: %d", le16_to_cpu(evt->handle));
 	print_bdaddr(evt->bdaddr);
 	print_link_type(evt->link_type);
 	print_field("Transmission interval: 0x%2.2x", evt->tx_interval);
@@ -10440,10 +10750,14 @@ static void sync_conn_complete_evt(uint16_t index, const void *data,
 	print_field("RX packet length: %d", le16_to_cpu(evt->rx_pkt_len));
 	print_field("TX packet length: %d", le16_to_cpu(evt->tx_pkt_len));
 	print_air_mode(evt->air_mode);
+
+	if (evt->status == 0x00)
+		assign_handle(index, le16_to_cpu(evt->handle), evt->link_type,
+					(void *)evt->bdaddr, BDADDR_BREDR);
 }
 
-static void sync_conn_changed_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void sync_conn_changed_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_sync_conn_changed *evt = data;
 
@@ -10455,7 +10769,8 @@ static void sync_conn_changed_evt(uint16_t index, const void *data,
 	print_field("TX packet length: %d", le16_to_cpu(evt->tx_pkt_len));
 }
 
-static void sniff_subrating_evt(uint16_t index, const void *data, uint8_t size)
+static void sniff_subrating_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_sniff_subrating *evt = data;
 
@@ -10467,8 +10782,8 @@ static void sniff_subrating_evt(uint16_t index, const void *data, uint8_t size)
 	print_slot_625("Min local timeout", evt->min_local_timeout);
 }
 
-static void ext_inquiry_result_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void ext_inquiry_result_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_ext_inquiry_result *evt = data;
 
@@ -10482,8 +10797,8 @@ static void ext_inquiry_result_evt(uint16_t index, const void *data,
 	print_eir(evt->data, sizeof(evt->data), false);
 }
 
-static void encrypt_key_refresh_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void encrypt_key_refresh_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_encrypt_key_refresh_complete *evt = data;
 
@@ -10491,16 +10806,16 @@ static void encrypt_key_refresh_complete_evt(uint16_t index, const void *data,
 	print_handle(evt->handle);
 }
 
-static void io_capability_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void io_capability_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_io_capability_request *evt = data;
 
 	print_bdaddr(evt->bdaddr);
 }
 
-static void io_capability_response_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void io_capability_response_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_io_capability_response *evt = data;
 
@@ -10510,8 +10825,8 @@ static void io_capability_response_evt(uint16_t index, const void *data,
 	print_authentication(evt->authentication);
 }
 
-static void user_confirm_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void user_confirm_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_user_confirm_request *evt = data;
 
@@ -10519,24 +10834,24 @@ static void user_confirm_request_evt(uint16_t index, const void *data,
 	print_passkey(evt->passkey);
 }
 
-static void user_passkey_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void user_passkey_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_user_passkey_request *evt = data;
 
 	print_bdaddr(evt->bdaddr);
 }
 
-static void remote_oob_data_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_oob_data_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_oob_data_request *evt = data;
 
 	print_bdaddr(evt->bdaddr);
 }
 
-static void simple_pairing_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void simple_pairing_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_simple_pairing_complete *evt = data;
 
@@ -10544,8 +10859,8 @@ static void simple_pairing_complete_evt(uint16_t index, const void *data,
 	print_bdaddr(evt->bdaddr);
 }
 
-static void link_supv_timeout_changed_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void link_supv_timeout_changed_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_link_supv_timeout_changed *evt = data;
 
@@ -10553,16 +10868,16 @@ static void link_supv_timeout_changed_evt(uint16_t index, const void *data,
 	print_timeout(evt->timeout);
 }
 
-static void enhanced_flush_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void enhanced_flush_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_enhanced_flush_complete *evt = data;
 
 	print_handle(evt->handle);
 }
 
-static void user_passkey_notify_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void user_passkey_notify_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_user_passkey_notify *evt = data;
 
@@ -10570,7 +10885,8 @@ static void user_passkey_notify_evt(uint16_t index, const void *data,
 	print_passkey(evt->passkey);
 }
 
-static void keypress_notify_evt(uint16_t index, const void *data, uint8_t size)
+static void keypress_notify_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_keypress_notify *evt = data;
 	const char *str;
@@ -10601,8 +10917,8 @@ static void keypress_notify_evt(uint16_t index, const void *data, uint8_t size)
 	print_field("Notification type: %s (0x%2.2x)", str, evt->type);
 }
 
-static void remote_host_features_notify_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void remote_host_features_notify_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_remote_host_features_notify *evt = data;
 
@@ -10610,8 +10926,8 @@ static void remote_host_features_notify_evt(uint16_t index, const void *data,
 	print_features(1, evt->features, 0x00);
 }
 
-static void phy_link_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void phy_link_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_phy_link_complete *evt = data;
 
@@ -10619,15 +10935,16 @@ static void phy_link_complete_evt(uint16_t index, const void *data,
 	print_phy_handle(evt->phy_handle);
 }
 
-static void channel_selected_evt(uint16_t index, const void *data, uint8_t size)
+static void channel_selected_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_channel_selected *evt = data;
 
 	print_phy_handle(evt->phy_handle);
 }
 
-static void disconn_phy_link_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void disconn_phy_link_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_disconn_phy_link_complete *evt = data;
 
@@ -10636,8 +10953,8 @@ static void disconn_phy_link_complete_evt(uint16_t index, const void *data,
 	print_reason(evt->reason);
 }
 
-static void phy_link_loss_early_warning_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void phy_link_loss_early_warning_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_phy_link_loss_early_warning *evt = data;
 	const char *str;
@@ -10668,16 +10985,16 @@ static void phy_link_loss_early_warning_evt(uint16_t index, const void *data,
 	print_field("Reason: %s (0x%2.2x)", str, evt->reason);
 }
 
-static void phy_link_recovery_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void phy_link_recovery_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_phy_link_recovery *evt = data;
 
 	print_phy_handle(evt->phy_handle);
 }
 
-static void logic_link_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void logic_link_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_logic_link_complete *evt = data;
 
@@ -10687,8 +11004,8 @@ static void logic_link_complete_evt(uint16_t index, const void *data,
 	print_field("TX flow spec: 0x%2.2x", evt->flow_spec);
 }
 
-static void disconn_logic_link_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void disconn_logic_link_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_disconn_logic_link_complete *evt = data;
 
@@ -10697,8 +11014,8 @@ static void disconn_logic_link_complete_evt(uint16_t index, const void *data,
 	print_reason(evt->reason);
 }
 
-static void flow_spec_modify_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void flow_spec_modify_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_flow_spec_modify_complete *evt = data;
 
@@ -10706,8 +11023,8 @@ static void flow_spec_modify_complete_evt(uint16_t index, const void *data,
 	print_handle(evt->handle);
 }
 
-static void num_completed_data_blocks_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void num_completed_data_blocks_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_num_completed_data_blocks *evt = data;
 
@@ -10722,8 +11039,8 @@ static void num_completed_data_blocks_evt(uint16_t index, const void *data,
 		packet_hexdump(data + sizeof(*evt), size - sizeof(*evt));
 }
 
-static void short_range_mode_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void short_range_mode_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_short_range_mode_change *evt = data;
 
@@ -10732,8 +11049,8 @@ static void short_range_mode_change_evt(uint16_t index, const void *data,
 	print_enable("Short range mode", evt->mode);
 }
 
-static void amp_status_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void amp_status_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_amp_status_change *evt = data;
 
@@ -10741,8 +11058,8 @@ static void amp_status_change_evt(uint16_t index, const void *data,
 	print_amp_status(evt->amp_status);
 }
 
-static void triggered_clock_capture_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void triggered_clock_capture_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_triggered_clock_capture *evt = data;
 
@@ -10752,16 +11069,16 @@ static void triggered_clock_capture_evt(uint16_t index, const void *data,
 	print_clock_offset(evt->clock_offset);
 }
 
-static void sync_train_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void sync_train_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_sync_train_complete *evt = data;
 
 	print_status(evt->status);
 }
 
-static void sync_train_received_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void sync_train_received_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_sync_train_received *evt = data;
 
@@ -10776,8 +11093,8 @@ static void sync_train_received_evt(uint16_t index, const void *data,
 	print_field("Service Data: 0x%2.2x", evt->service_data);
 }
 
-static void peripheral_broadcast_receive_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void peripheral_broadcast_receive_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_peripheral_broadcast_receive *evt = data;
 
@@ -10799,8 +11116,8 @@ static void peripheral_broadcast_receive_evt(uint16_t index, const void *data,
 		packet_hexdump(data + 18, size - 18);
 }
 
-static void peripheral_broadcast_timeout_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void peripheral_broadcast_timeout_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_peripheral_broadcast_timeout *evt = data;
 
@@ -10808,8 +11125,8 @@ static void peripheral_broadcast_timeout_evt(uint16_t index, const void *data,
 	print_lt_addr(evt->lt_addr);
 }
 
-static void truncated_page_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void truncated_page_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_truncated_page_complete *evt = data;
 
@@ -10817,21 +11134,22 @@ static void truncated_page_complete_evt(uint16_t index, const void *data,
 	print_bdaddr(evt->bdaddr);
 }
 
-static void peripheral_page_response_timeout_evt(uint16_t index,
-						const void *data, uint8_t size)
+static void peripheral_page_response_timeout_evt(struct timeval *tv,
+					uint16_t index, const void *data,
+					uint8_t size)
 {
 }
 
-static void channel_map_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void channel_map_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_channel_map_change *evt = data;
 
 	print_channel_map(evt->map);
 }
 
-static void inquiry_response_notify_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void inquiry_response_notify_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_inquiry_response_notify *evt = data;
 
@@ -10839,20 +11157,21 @@ static void inquiry_response_notify_evt(uint16_t index, const void *data,
 	print_rssi(evt->rssi);
 }
 
-static void auth_payload_timeout_expired_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void auth_payload_timeout_expired_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_auth_payload_timeout_expired *evt = data;
 
 	print_handle(evt->handle);
 }
 
-static void le_conn_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void le_conn_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_conn_complete *evt = data;
 
 	print_status(evt->status);
-	print_handle(evt->handle);
+	print_field("Handle: %d", le16_to_cpu(evt->handle));
 	print_role(evt->role);
 	print_peer_addr_type("Peer address type", evt->peer_addr_type);
 	print_addr("Peer address", evt->peer_addr, evt->peer_addr_type);
@@ -10868,7 +11187,8 @@ static void le_conn_complete_evt(uint16_t index, const void *data, uint8_t size)
 				(void *)evt->peer_addr, evt->peer_addr_type);
 }
 
-static void le_adv_report_evt(uint16_t index, const void *data, uint8_t size)
+static void le_adv_report_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_adv_report *evt = data;
 	uint8_t evt_len;
@@ -10896,8 +11216,8 @@ report:
 	}
 }
 
-static void le_conn_update_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_conn_update_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_conn_update_complete *evt = data;
 
@@ -10910,8 +11230,8 @@ static void le_conn_update_complete_evt(uint16_t index, const void *data,
 					le16_to_cpu(evt->supv_timeout));
 }
 
-static void le_remote_features_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_remote_features_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_remote_features_complete *evt = data;
 
@@ -10920,8 +11240,8 @@ static void le_remote_features_complete_evt(uint16_t index, const void *data,
 	print_features(0, evt->features, 0x01);
 }
 
-static void le_long_term_key_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_long_term_key_request_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_long_term_key_request *evt = data;
 
@@ -10930,8 +11250,8 @@ static void le_long_term_key_request_evt(uint16_t index, const void *data,
 	print_encrypted_diversifier(evt->ediv);
 }
 
-static void le_conn_param_request_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_conn_param_request_evt(struct timeval *tv, uint16_t index,
+				      const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_conn_param_request *evt = data;
 
@@ -10944,8 +11264,8 @@ static void le_conn_param_request_evt(uint16_t index, const void *data,
 					le16_to_cpu(evt->supv_timeout));
 }
 
-static void le_data_length_change_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_data_length_change_evt(struct timeval *tv, uint16_t index,
+				      const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_data_length_change *evt = data;
 
@@ -10956,8 +11276,8 @@ static void le_data_length_change_evt(uint16_t index, const void *data,
 	print_field("Max RX time: %d", le16_to_cpu(evt->max_rx_time));
 }
 
-static void le_read_local_pk256_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_read_local_pk256_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_read_local_pk256_complete *evt = data;
 
@@ -10965,8 +11285,8 @@ static void le_read_local_pk256_complete_evt(uint16_t index, const void *data,
 	print_pk256("Local P-256 public key", evt->local_pk256);
 }
 
-static void le_generate_dhkey_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_generate_dhkey_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_generate_dhkey_complete *evt = data;
 
@@ -10974,13 +11294,13 @@ static void le_generate_dhkey_complete_evt(uint16_t index, const void *data,
 	print_dhkey(evt->dhkey);
 }
 
-static void le_enhanced_conn_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_enhanced_conn_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_enhanced_conn_complete *evt = data;
 
 	print_status(evt->status);
-	print_handle(evt->handle);
+	print_field("Handle: %d", le16_to_cpu(evt->handle));
 	print_role(evt->role);
 	print_peer_addr_type("Peer address type", evt->peer_addr_type);
 	print_addr("Peer address", evt->peer_addr, evt->peer_addr_type);
@@ -10998,8 +11318,8 @@ static void le_enhanced_conn_complete_evt(uint16_t index, const void *data,
 				(void *)evt->peer_addr, evt->peer_addr_type);
 }
 
-static void le_direct_adv_report_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_direct_adv_report_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_direct_adv_report *evt = data;
 
@@ -11016,8 +11336,8 @@ static void le_direct_adv_report_evt(uint16_t index, const void *data,
 		packet_hexdump(data + sizeof(*evt), size - sizeof(*evt));
 }
 
-static void le_phy_update_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_phy_update_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_phy_update_complete *evt = data;
 
@@ -11120,8 +11440,8 @@ static void print_legacy_adv_report_pdu(uint16_t flags)
 	print_field("  Legacy PDU Type: %s (0x%4.4x)", str, flags);
 }
 
-static void le_ext_adv_report_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_ext_adv_report_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_ext_adv_report *evt = data;
 	const struct bt_hci_le_ext_adv_report *report;
@@ -11208,7 +11528,8 @@ static void le_ext_adv_report_evt(uint16_t index, const void *data,
 	}
 }
 
-static void le_pa_sync(uint16_t index, const void *data, uint8_t size)
+static void le_pa_sync_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_per_sync_established *evt = data;
 
@@ -11226,7 +11547,8 @@ static void le_pa_sync(uint16_t index, const void *data, uint8_t size)
 	print_field("Advertiser clock accuracy: 0x%2.2x", evt->clock_accuracy);
 }
 
-static void le_pa_report_evt(uint16_t index, const void *data, uint8_t size)
+static void le_pa_report_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	const struct bt_hci_le_pa_report *evt = data;
 	const char *color_on;
@@ -11285,17 +11607,19 @@ static void le_pa_report_evt(uint16_t index, const void *data, uint8_t size)
 
 	print_field("Data status: %s%s%s", color_on, str, COLOR_OFF);
 	print_field("Data length: 0x%2.2x", evt->data_len);
-	packet_hexdump(evt->data, evt->data_len);
+	print_eir(evt->data, evt->data_len, true);
 }
 
-static void le_pa_sync_lost(uint16_t index, const void *data, uint8_t size)
+static void le_pa_sync_lost_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_per_sync_lost *evt = data;
 
 	print_field("Sync handle: %d", evt->handle);
 }
 
-static void le_adv_set_term_evt(uint16_t index, const void *data, uint8_t size)
+static void le_adv_set_term_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_adv_set_term *evt = data;
 
@@ -11306,8 +11630,8 @@ static void le_adv_set_term_evt(uint16_t index, const void *data, uint8_t size)
 			evt->num_evts);
 }
 
-static void le_scan_req_received_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_scan_req_received_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_scan_req_received *evt = data;
 
@@ -11317,8 +11641,8 @@ static void le_scan_req_received_evt(uint16_t index, const void *data,
 							evt->scanner_addr_type);
 }
 
-static void le_chan_select_alg_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_chan_select_alg_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_chan_select_alg *evt = data;
 	const char *str;
@@ -11340,8 +11664,8 @@ static void le_chan_select_alg_evt(uint16_t index, const void *data,
 	print_field("Algorithm: %s (0x%2.2x)", str, evt->algorithm);
 }
 
-static void le_cte_request_failed_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_cte_request_failed_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_cte_request_failed *evt = data;
 
@@ -11349,8 +11673,8 @@ static void le_cte_request_failed_evt(uint16_t index, const void *data,
 	print_field("Connection handle: %d", evt->handle);
 }
 
-static void le_pa_sync_trans_rec_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_pa_sync_trans_rec_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_pa_sync_trans_rec *evt = data;
 
@@ -11368,8 +11692,8 @@ static void le_pa_sync_trans_rec_evt(uint16_t index, const void *data,
 	print_clock_accuracy(evt->clock_accuracy);
 }
 
-static void le_cis_established_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_cis_established_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_cis_established *evt = data;
 
@@ -11388,17 +11712,27 @@ static void le_cis_established_evt(uint16_t index, const void *data,
 	print_field("Peripheral to Central Flush Timeout: %u", evt->p_ft);
 	print_field("Central to Peripheral MTU: %u", le16_to_cpu(evt->c_mtu));
 	print_field("Peripheral to Central MTU: %u", le16_to_cpu(evt->p_mtu));
-	print_field("ISO Interval: %u", le16_to_cpu(evt->interval));
+	print_slot_125("ISO Interval", evt->interval);
+
+	if (!evt->status)
+		assign_handle(index, le16_to_cpu(evt->conn_handle), 0x05,
+					NULL, BDADDR_LE_PUBLIC);
 }
 
-static void le_req_cis_evt(uint16_t index, const void *data, uint8_t size)
+static void le_req_cis_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_cis_req *evt = data;
+	struct packet_conn_data *conn;
 
 	print_field("ACL Handle: %d", le16_to_cpu(evt->acl_handle));
 	print_field("CIS Handle: %d", le16_to_cpu(evt->cis_handle));
 	print_field("CIG ID: 0x%2.2x", evt->cig_id);
 	print_field("CIS ID: 0x%2.2x", evt->cis_id);
+
+	conn = packet_get_conn_data(evt->acl_handle);
+	if (conn)
+		conn->link = evt->cis_handle;
 }
 
 static void print_bis_handle(const void *data, int i)
@@ -11408,7 +11742,8 @@ static void print_bis_handle(const void *data, int i)
 	print_field("Connection Handle #%d: %d", i, handle);
 }
 
-static void le_big_complete_evt(uint16_t index, const void *data, uint8_t size)
+static void le_big_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_big_complete *evt = data;
 
@@ -11419,15 +11754,24 @@ static void le_big_complete_evt(uint16_t index, const void *data, uint8_t size)
 	print_le_phy("PHY", evt->phy);
 	print_field("NSE: %u", evt->nse);
 	print_field("BN: %u", evt->bn);
-	print_field("PTO: %u", evt->bn);
+	print_field("PTO: %u", evt->pto);
 	print_field("IRC: %u", evt->irc);
 	print_field("Maximum PDU: %u", evt->max_pdu);
 	print_slot_125("ISO Interval", evt->interval);
 	print_list(evt->bis_handle, size, evt->num_bis,
 				sizeof(*evt->bis_handle), print_bis_handle);
+
+	if (!evt->status) {
+		int i;
+
+		for (i = 0; i < evt->num_bis; i++)
+			assign_handle(index, le16_to_cpu(evt->bis_handle[i]),
+					0x05, NULL, BDADDR_LE_PUBLIC);
+	}
 }
 
-static void le_big_terminate_evt(uint16_t index, const void *data, uint8_t size)
+static void le_big_terminate_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_big_terminate *evt = data;
 
@@ -11435,8 +11779,8 @@ static void le_big_terminate_evt(uint16_t index, const void *data, uint8_t size)
 	print_reason(evt->reason);
 }
 
-static void le_big_sync_estabilished_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_big_sync_estabilished_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_big_sync_estabilished *evt = data;
 
@@ -11451,18 +11795,27 @@ static void le_big_sync_estabilished_evt(uint16_t index, const void *data,
 	print_slot_125("ISO Interval", evt->interval);
 	print_list(evt->bis, size, evt->num_bis, sizeof(*evt->bis),
 						print_bis_handle);
+
+	if (!evt->status) {
+		int i;
+
+		for (i = 0; i < evt->num_bis; i++)
+			assign_handle(index, le16_to_cpu(evt->bis[i]),
+					0x05, NULL, BDADDR_LE_PUBLIC);
+	}
 }
 
-static void le_big_sync_lost_evt(uint16_t index, const void *data, uint8_t size)
+static void le_big_sync_lost_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_big_sync_lost *evt = data;
 
-	print_field("BIG ID: 0x%2.2x", evt->big_id);
+	print_field("BIG Handle: 0x%2.2x", evt->big_handle);
 	print_reason(evt->reason);
 }
 
-static void le_req_sca_complete_evt(uint16_t index, const void *data,
-							uint8_t size)
+static void le_req_sca_complete_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_req_peer_sca_complete *evt = data;
 
@@ -11471,7 +11824,8 @@ static void le_req_sca_complete_evt(uint16_t index, const void *data,
 	print_sca(evt->sca);
 }
 
-static void le_big_info_evt(uint16_t index, const void *data, uint8_t size)
+static void le_big_info_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
 {
 	const struct bt_hci_evt_le_big_info_adv_report *evt = data;
 
@@ -11493,12 +11847,13 @@ static void le_big_info_evt(uint16_t index, const void *data, uint8_t size)
 struct subevent_data {
 	uint8_t subevent;
 	const char *str;
-	void (*func) (uint16_t index, const void *data, uint8_t size);
+	void (*func) (struct timeval *tv, uint16_t index, const void *data,
+							uint8_t size);
 	uint8_t size;
 	bool fixed;
 };
 
-static void print_subevent(uint16_t index,
+static void print_subevent(struct timeval *tv, uint16_t index,
 				const struct subevent_data *subevent_data,
 				const void *data, uint8_t size)
 {
@@ -11531,7 +11886,7 @@ static void print_subevent(uint16_t index,
 		}
 	}
 
-	subevent_data->func(index, data, size);
+	subevent_data->func(tv, index, data, size);
 }
 
 static const struct subevent_data le_meta_event_table[] = {
@@ -11562,11 +11917,11 @@ static const struct subevent_data le_meta_event_table[] = {
 	{ 0x0d, "LE Extended Advertising Report",
 				le_ext_adv_report_evt, 1, false},
 	{ 0x0e, "LE Periodic Advertising Sync Established",
-				le_pa_sync, 15, true },
+				le_pa_sync_evt, 15, true },
 	{ 0x0f, "LE Periodic Advertising Report",
 				le_pa_report_evt, 7, false},
 	{ 0x10, "LE Periodic Advertising Sync Lost",
-				le_pa_sync_lost, 2, true},
+				le_pa_sync_lost_evt, 2, true},
 	{ 0x11, "LE Scan Timeout" },
 	{ 0x12, "LE Advertising Set Terminated",
 				le_adv_set_term_evt, 5, true},
@@ -11616,7 +11971,8 @@ static const struct subevent_data le_meta_event_table[] = {
 	{ }
 };
 
-static void le_meta_event_evt(uint16_t index, const void *data, uint8_t size)
+static void le_meta_event_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	uint8_t subevent = *((const uint8_t *) data);
 	struct subevent_data unknown;
@@ -11636,10 +11992,11 @@ static void le_meta_event_evt(uint16_t index, const void *data, uint8_t size)
 		}
 	}
 
-	print_subevent(index, subevent_data, data + 1, size - 1);
+	print_subevent(tv, index, subevent_data, data + 1, size - 1);
 }
 
-static void vendor_evt(uint16_t index, const void *data, uint8_t size)
+static void vendor_evt(struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size)
 {
 	struct subevent_data vendor_data;
 	char vendor_str[150];
@@ -11660,7 +12017,7 @@ static void vendor_evt(uint16_t index, const void *data, uint8_t size)
 		vendor_data.size = vnd->evt_size;
 		vendor_data.fixed = vnd->evt_fixed;
 
-		print_subevent(index, &vendor_data, data + consumed_size,
+		print_subevent(tv, index, &vendor_data, data + consumed_size,
 							size - consumed_size);
 	} else {
 		uint16_t manufacturer;
@@ -11677,7 +12034,8 @@ static void vendor_evt(uint16_t index, const void *data, uint8_t size)
 struct event_data {
 	uint8_t event;
 	const char *str;
-	void (*func) (uint16_t index, const void *data, uint8_t size);
+	void (*func) (struct timeval *tv, uint16_t index, const void *data,
+							uint8_t size);
 	uint8_t size;
 	bool fixed;
 };
@@ -11910,7 +12268,7 @@ void packet_system_note(struct timeval *tv, struct ucred *cred,
 struct monitor_l2cap_hdr {
 	uint16_t cid;
 	uint16_t psm;
-};
+} __attribute__((packed));
 
 static void packet_decode(struct timeval *tv, struct ucred *cred, char dir,
 				uint16_t index, const char *color,
@@ -11929,7 +12287,8 @@ static void packet_decode(struct timeval *tv, struct ucred *cred, char dir,
 				NULL);
 
 	/* Discard last byte since it just a filler */
-	l2cap_frame(index, dir == '>', 0, hdr->cid, hdr->psm,
+	l2cap_frame(index, dir == '>', 0,
+			le16_to_cpu(hdr->cid), le16_to_cpu(hdr->psm),
 			data + sizeof(*hdr), size - (sizeof(*hdr) + 1));
 }
 
@@ -11938,7 +12297,6 @@ void packet_user_logging(struct timeval *tv, struct ucred *cred,
 					const char *ident, const void *data,
 					uint16_t size)
 {
-	char pid_str[140];
 	const char *label;
 	const char *color;
 
@@ -11964,26 +12322,7 @@ void packet_user_logging(struct timeval *tv, struct ucred *cred,
 	}
 
 	if (cred) {
-		char *path = alloca(24);
-		char line[128];
-		FILE *fp;
-
-		snprintf(path, 23, "/proc/%u/comm", cred->pid);
-
-		fp = fopen(path, "re");
-		if (fp) {
-			if (fgets(line, sizeof(line), fp)) {
-				line[strcspn(line, "\r\n")] = '\0';
-				snprintf(pid_str, sizeof(pid_str), "%s[%u]",
-							line, cred->pid);
-			} else
-				snprintf(pid_str, sizeof(pid_str), "%u",
-								cred->pid);
-			fclose(fp);
-		} else
-			snprintf(pid_str, sizeof(pid_str), "%u", cred->pid);
-
-		label = pid_str;
+		label = NULL;
         } else {
 		if (ident)
 			label = ident;
@@ -11993,8 +12332,8 @@ void packet_user_logging(struct timeval *tv, struct ucred *cred,
 
 	if (ident && (ident[0] == '<' || ident[0] == '>')) {
 		packet_decode(tv, cred, ident[0], index, color,
-				label == ident ? &ident[2] : label,
-				data, size);
+			      label == ident ? &ident[2] : label,
+			      data, size);
 		return;
 	}
 
@@ -12189,7 +12528,28 @@ void packet_hci_event(struct timeval *tv, struct ucred *cred, uint16_t index,
 		}
 	}
 
-	event_data->func(index, data, hdr->plen);
+	event_data->func(tv, index, data, hdr->plen);
+}
+
+static void packet_enqueue_tx(struct timeval *tv, uint16_t handle,
+				size_t num, uint16_t len)
+{
+	struct packet_conn_data *conn;
+	struct packet_frame *frame;
+
+	conn = packet_get_conn_data(handle);
+	if (!conn)
+		return;
+
+	if (!conn->tx_q)
+		conn->tx_q = queue_new();
+
+	frame = new0(struct packet_frame, 1);
+	if (tv)
+		memcpy(&frame->tv, tv, sizeof(*tv));
+	frame->num = num;
+	frame->len = len;
+	queue_push_tail(conn->tx_q, frame);
 }
 
 void packet_hci_acldata(struct timeval *tv, struct ucred *cred, uint16_t index,
@@ -12229,6 +12589,10 @@ void packet_hci_acldata(struct timeval *tv, struct ucred *cred, uint16_t index,
 				in ? "ACL Data RX" : "ACL Data TX",
 						handle_str, extra_str);
 
+	if (!in)
+		packet_enqueue_tx(tv, acl_handle(handle),
+					index_list[index].frame, dlen);
+
 	if (size != dlen) {
 		print_text(COLOR_ERROR, "invalid packet size (%d != %d)",
 								size, dlen);
@@ -12278,6 +12642,10 @@ void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index,
 				in ? "SCO Data RX" : "SCO Data TX",
 						handle_str, extra_str);
 
+	if (!in)
+		packet_enqueue_tx(tv, acl_handle(handle),
+					index_list[index].frame, hdr->dlen);
+
 	if (size != hdr->dlen) {
 		print_text(COLOR_ERROR, "invalid packet size (%d != %d)",
 							size, hdr->dlen);
@@ -12321,10 +12689,14 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
 	sprintf(handle_str, "Handle %d", acl_handle(handle));
 	sprintf(extra_str, "flags 0x%2.2x dlen %d", flags, hdr->dlen);
 
-	print_packet(tv, cred, in ? '>' : '<', index, NULL, COLOR_HCI_SCODATA,
+	print_packet(tv, cred, in ? '>' : '<', index, NULL, COLOR_HCI_ISODATA,
 				in ? "ISO Data RX" : "ISO Data TX",
 						handle_str, extra_str);
 
+	if (!in)
+		packet_enqueue_tx(tv, acl_handle(handle),
+					index_list[index].frame, hdr->dlen);
+
 	if (size != hdr->dlen) {
 		print_text(COLOR_ERROR, "invalid packet size (%d != %d)",
 							size, hdr->dlen);
@@ -12332,7 +12704,7 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
 		return;
 	}
 
-	if (filter_mask & PACKET_FILTER_SHOW_SCO_DATA)
+	if (filter_mask & PACKET_FILTER_SHOW_ISO_DATA)
 		packet_hexdump(data, size);
 }
 
@@ -12615,7 +12987,11 @@ static const struct bitfield_data mgmt_settings_table[] = {
 	{ 15, "Static Address"		},
 	{ 16, "PHY Configuration"	},
 	{ 17, "Wideband Speech"		},
-	{ }
+	{ 18, "CIS Central"		},
+	{ 19, "CIS Peripheral"		},
+	{ 20, "ISO Broadcaster"		},
+	{ 21, "Sync Receiver"		},
+	{}
 };
 
 static void mgmt_print_settings(const char *label, uint32_t settings)
@@ -12669,6 +13045,8 @@ static const struct bitfield_data mgmt_device_flags_table[] = {
 	{  1, "Legacy Pairing"			},
 	{  2, "Not Connectable"			},
 	{  3, "Connection Locally Initiated"	},
+	{  4, "Name Request Failed"		},
+	{  5, "Scan Response"			},
 	{ }
 };
 
@@ -12834,6 +13212,7 @@ static void mgmt_print_identity_resolving_key(const void *data)
 
 	mgmt_print_address(data, address_type);
 	print_hex_field("Key", data + 7, 16);
+	keys_add_identity(data, address_type, data + 7);
 }
 
 static void mgmt_print_signature_resolving_key(const void *data)
@@ -13046,6 +13425,57 @@ static void mgmt_set_low_energy_cmd(const void *data, uint16_t size)
 	print_enable("Low Energy", enable);
 }
 
+static void mgmt_set_blocked_keys_cmd(const void *data, uint16_t size)
+{
+	struct iovec frame = { (void *)data, size };
+	uint16_t num_keys;
+	int i;
+
+	if (!util_iov_pull_le16(&frame, &num_keys)) {
+		print_field("Keys: invalid size");
+		return;
+	}
+
+	print_field("Keys: %u", num_keys);
+
+	for (i = 0; i < num_keys; i++) {
+		uint8_t type;
+		uint8_t *key;
+
+		if (!util_iov_pull_u8(&frame, &type)) {
+			print_field("Key type[%u]: invalid size", i);
+			return;
+		}
+
+		switch (type) {
+		case 0x00:
+			print_field("type: Link Key (0x00)");
+			break;
+		case 0x01:
+			print_field("type: Long Term Key (0x01)");
+			break;
+		case 0x02:
+			print_field("type: Identity Resolving Key (0x02)");
+			break;
+		}
+
+		key = util_iov_pull_mem(&frame, 16);
+		if (!key) {
+			print_field("Key[%u]: invalid size", i);
+			return;
+		}
+
+		print_link_key(key);
+	}
+}
+
+static void mgmt_set_wbs_cmd(const void *data, uint16_t size)
+{
+	uint8_t enable = get_u8(data);
+
+	print_enable("Wideband Speech", enable);
+}
+
 static void mgmt_new_settings_rsp(const void *data, uint16_t size)
 {
 	uint32_t current_settings = get_le32(data);
@@ -14501,8 +14931,12 @@ static const struct mgmt_data mgmt_command_table[] = {
 	{ 0x0045, "Set PHY Configuration",
 				mgmt_set_phy_cmd, 4, true,
 				mgmt_null_rsp, 0, true },
-	{ 0x0046, "Load Blocked Keys" },
-	{ 0x0047, "Set Wideband Speech" },
+	{ 0x0046, "Set Blocked Keys",
+				mgmt_set_blocked_keys_cmd, 2, false,
+				mgmt_null_rsp, 0, true },
+	{ 0x0047, "Set Wideband Speech",
+				mgmt_set_wbs_cmd, 1, true,
+				mgmt_new_settings_rsp, 4, true },
 	{ 0x0048, "Read Controller Capabilities" },
 	{ 0x0049, "Read Experimental Features Information",
 				mgmt_null_cmd, 0, true,
diff --git a/monitor/packet.h b/monitor/packet.h
index b07d5d1..856f74f 100644
--- a/monitor/packet.h
+++ b/monitor/packet.h
@@ -22,19 +22,39 @@
 #define PACKET_FILTER_SHOW_SCO_DATA	(1 << 5)
 #define PACKET_FILTER_SHOW_A2DP_STREAM	(1 << 6)
 #define PACKET_FILTER_SHOW_MGMT_SOCKET	(1 << 7)
+#define PACKET_FILTER_SHOW_ISO_DATA	(1 << 8)
+#define TV_MSEC(_tv) (long long)((_tv).tv_sec * 1000 + (_tv).tv_usec / 1000)
+
+struct packet_latency {
+	struct timeval total;
+	struct timeval min;
+	struct timeval max;
+	struct timeval med;
+};
+
+struct packet_frame {
+	struct timeval tv;
+	size_t num;
+	size_t len;
+};
 
 struct packet_conn_data {
 	uint16_t index;
 	uint8_t  src[6];
 	uint16_t handle;
+	uint16_t link;
 	uint8_t  type;
 	uint8_t  dst[6];
 	uint8_t  dst_type;
+	struct queue *tx_q;
+	struct queue *chan_q;
+	struct packet_latency tx_l;
 	void     *data;
 	void     (*destroy)(void *data);
 };
 
 struct packet_conn_data *packet_get_conn_data(uint16_t handle);
+void packet_latency_add(struct packet_latency *latency, struct timeval *delta);
 
 bool packet_has_filter(unsigned long filter);
 void packet_set_filter(unsigned long filter);
@@ -64,20 +84,6 @@ void packet_print_io_capability(uint8_t capability);
 void packet_print_io_authentication(uint8_t authentication);
 void packet_print_codec_id(const char *label, uint8_t codec);
 
-#define LTV_DEC(_type, _func) \
-{ \
-	.type = _type, \
-	.func = _func, \
-}
-
-struct packet_ltv_decoder {
-	uint8_t  type;
-	void (*func)(const uint8_t *data, uint8_t len);
-};
-
-void packet_print_ltv(const char *label, const uint8_t *data, uint8_t len,
-			struct packet_ltv_decoder *decoder, size_t num);
-
 void packet_control(struct timeval *tv, struct ucred *cred,
 					uint16_t index, uint16_t opcode,
 					const void *data, uint16_t size);
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index 02300a8..a855152 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -32,7 +32,7 @@
 #include "sdp.h"
 #include "rfcomm.h"
 
-static char *cr_str[] = {
+static const char *cr_str[] = {
 	"RSP",
 	"CMD"
 };
diff --git a/monitor/sdp.c b/monitor/sdp.c
index daf9a9d..5fe4f29 100644
--- a/monitor/sdp.c
+++ b/monitor/sdp.c
@@ -148,9 +148,9 @@ static void print_boolean(uint8_t indent, const uint8_t *data, uint32_t size)
 
 #define SIZES(args...) ((uint8_t[]) { args, 0xff } )
 
-static struct {
+static const struct {
 	uint8_t value;
-	uint8_t *sizes;
+	const uint8_t *sizes;
 	bool recurse;
 	const char *str;
 	void (*print) (uint8_t indent, const uint8_t *data, uint32_t size);
@@ -167,7 +167,7 @@ static struct {
 	{ }
 };
 
-static struct {
+static const struct {
 	uint8_t index;
 	uint8_t bits;
 	uint8_t size;
@@ -184,7 +184,7 @@ static struct {
 	{ }
 };
 
-static bool valid_size(uint8_t size, uint8_t *sizes)
+static bool valid_size(uint8_t size, const uint8_t *sizes)
 {
 	int i;
 
@@ -322,7 +322,7 @@ static uint32_t get_bytes(const uint8_t *data, uint32_t size)
 	return 0;
 }
 
-static struct {
+static const struct {
 	uint16_t id;
 	const char *str;
 } attribute_table[] = {
diff --git a/monitor/vendor.h b/monitor/vendor.h
index 9430f37..996ed44 100644
--- a/monitor/vendor.h
+++ b/monitor/vendor.h
@@ -25,7 +25,8 @@ struct vendor_ocf {
 struct vendor_evt {
 	uint8_t evt;
 	const char *str;
-	void (*evt_func) (uint16_t index, const void *data, uint8_t size);
+	void (*evt_func) (struct timeval *tv, uint16_t index,
+				const void *data, uint8_t size);
 	uint8_t evt_size;
 	bool evt_fixed;
 };
diff --git a/obexd/client/bip-common.c b/obexd/client/bip-common.c
new file mode 100644
index 0000000..613b52c
--- /dev/null
+++ b/obexd/client/bip-common.c
@@ -0,0 +1,800 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2024  Collabora Ltd.
+ *  Based on previous work done by Jakub Adamek for GSoC 2011
+ *
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <regex.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gobex/gobex.h"
+
+#include "obexd/src/log.h"
+#include "bip-common.h"
+
+#define HANDLE_LEN 7
+#define HANDLE_LIMIT 10000000
+
+struct encconv_pair {
+	gchar *bip, *im;
+};
+
+struct encconv_pair encconv_table[] = {
+	{ "JPEG", "JPEG" },
+	{ "GIF", "GIF" },
+	{ "WBMP", "WBMP" },
+	{ "PNG", "PNG" },
+	{ "JPEG2000", "JP2" },
+	{ "BMP", "BMP" },
+	{ }
+};
+
+static const gchar *convBIP2IM(const gchar *encoding)
+{
+	struct encconv_pair *et = encconv_table;
+
+	while (et->bip) {
+		if (g_strcmp0(encoding, et->bip) == 0)
+			return et->im;
+		et++;
+	}
+	return NULL;
+}
+
+gboolean parse_pixel_range(const gchar *dim, unsigned int *lower_ret,
+						unsigned int *upper_ret,
+						gboolean *fixed_ratio_ret)
+{
+	static regex_t no_range;
+	static regex_t range;
+	static regex_t range_fixed;
+	static int regex_initialized;
+	unsigned int lower[2], upper[2];
+	gboolean fixed_ratio = FALSE;
+
+	if (!regex_initialized) {
+		regcomp(&no_range, "^([[:digit:]]{1,5})\\*([[:digit:]]{1,5})$",
+							REG_EXTENDED);
+		regcomp(&range, "^([[:digit:]]{1,5})\\*([[:digit:]]{1,5})"
+				"-([[:digit:]]{1,5})\\*([[:digit:]]{1,5})$",
+							REG_EXTENDED);
+		regcomp(&range_fixed, "^([[:digit:]]{1,5})\\*\\*"
+				"-([[:digit:]]{1,5})\\*([[:digit:]]{1,5})$",
+							REG_EXTENDED);
+		regex_initialized = 1;
+	}
+	if (dim == NULL)
+		return FALSE;
+	if (regexec(&no_range, dim, 0, NULL, 0) == 0) {
+		if (sscanf(dim, "%u*%u", &lower[0], &lower[1]) != 2)
+			return FALSE;
+		upper[0] = lower[0];
+		upper[1] = lower[1];
+		fixed_ratio = FALSE;
+	} else if (regexec(&range, dim, 0, NULL, 0) == 0) {
+		if (sscanf(dim, "%u*%u-%u*%u", &lower[0], &lower[1],
+				&upper[0], &upper[1]) != 4)
+			return FALSE;
+		fixed_ratio = FALSE;
+	} else if (regexec(&range_fixed, dim, 0, NULL, 0) == 0) {
+		if (sscanf(dim, "%u**-%u*%u", &lower[0], &upper[0],
+				&upper[1]) != 3)
+			return FALSE;
+		lower[1] = 0;
+		fixed_ratio = TRUE;
+	} else {
+		return FALSE;
+	}
+	if (lower[0] > 65535 || lower[1] > 65535 ||
+			upper[0] > 65535 || upper[1] > 65535)
+		return FALSE;
+	if (lower_ret == NULL || upper_ret == NULL || fixed_ratio_ret == NULL)
+		return TRUE;
+	if (upper[0] < lower[0] || upper[1] < lower[1])
+		return FALSE;
+	lower_ret[0] = lower[0];
+	lower_ret[1] = lower[1];
+	upper_ret[0] = upper[0];
+	upper_ret[1] = upper[1];
+	*fixed_ratio_ret = fixed_ratio;
+
+	return TRUE;
+}
+
+static gboolean verify_unsignednumber(const char *size)
+{
+	static regex_t unumber;
+	static int regex_initialized;
+
+	if (!regex_initialized) {
+		regcomp(&unumber, "^[[:digit:]]+$", REG_EXTENDED);
+		regex_initialized = 1;
+	}
+	if (regexec(&unumber, size, 0, NULL, 0) != 0)
+		return FALSE;
+
+	return TRUE;
+}
+
+static uint64_t parse_unsignednumber(const char *size)
+{
+	if (!verify_unsignednumber(size))
+		return 0;
+
+	return g_ascii_strtoll(size, NULL, 10);
+}
+
+char *transforms[] = {
+	"crop",
+	"stretch",
+	"fill",
+	NULL
+};
+
+gboolean verify_encoding(const char *encoding)
+{
+	struct encconv_pair *et = encconv_table;
+
+	while (et->bip) {
+		if (g_strcmp0(encoding, et->bip) == 0)
+			return TRUE;
+		et++;
+	}
+	return FALSE;
+}
+
+static gboolean verify_transform(const char *transform)
+{
+	char **str = transforms;
+
+	while (*str != NULL) {
+		if (g_str_equal(transform, *str))
+			return TRUE;
+		str++;
+	}
+	return FALSE;
+}
+
+char *parse_transform(const char *transform)
+{
+	if (!verify_transform(transform))
+		return NULL;
+	return g_strdup(transform);
+}
+
+static char *parse_transform_list(const char *transform)
+{
+	char **args = NULL, **arg = NULL;
+	gboolean used[3] = { FALSE, FALSE, FALSE };
+
+	if (transform == NULL)
+		return NULL;
+	if (strlen(transform) == 0)
+		return NULL;
+	args = g_strsplit(transform, " ", 0);
+	for (arg = args; *arg != NULL; arg++) {
+		char *t = *arg;
+
+		if (!verify_transform(t)) {
+			g_strfreev(args);
+			return NULL;
+		}
+		switch (t[0]) {
+		case 's':
+			if (used[0])
+				goto failure;
+			used[0] = TRUE;
+			break;
+		case 'c':
+			if (used[1])
+				goto failure;
+			used[1] = TRUE;
+			break;
+		case 'f':
+			if (used[2])
+				goto failure;
+			used[2] = TRUE;
+			break;
+		}
+	}
+	g_strfreev(args);
+	return g_strdup(transform);
+failure:
+	g_strfreev(args);
+	return NULL;
+}
+
+static time_t parse_iso8601_bip(const gchar *str, int len)
+{
+	gchar    *tstr;
+	struct tm tm;
+	gint      nr;
+	gchar     tz;
+	time_t    time;
+	time_t    tz_offset = 0;
+
+	if (str == NULL)
+		return -1;
+
+	memset(&tm, 0, sizeof(struct tm));
+
+	/* According to spec the time doesn't have to be null terminated */
+	if (str[len - 1] != '\0') {
+		tstr = g_malloc(len + 1);
+		strncpy(tstr, str, len);
+		tstr[len] = '\0';
+	} else
+		tstr = g_strdup(str);
+
+	nr = sscanf(tstr, "%04u%02u%02uT%02u%02u%02u%c",
+			&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+			&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
+			&tz);
+
+	g_free(tstr);
+
+	/* Fixup the tm values */
+	tm.tm_year -= 1900;       /* Year since 1900 */
+	tm.tm_mon--;              /* Months since January, values 0-11 */
+	tm.tm_isdst = -1;         /* Daylight savings information not avail */
+
+	if (nr < 6) {
+		/* Invalid time format */
+		return -1;
+	}
+
+	time = mktime(&tm);
+
+#if defined(HAVE_TM_GMTOFF)
+	tz_offset = tm.tm_gmtoff;
+#elif defined(HAVE_TIMEZONE)
+	tz_offset = -timezone;
+	if (tm.tm_isdst > 0)
+		tz_offset += 3600;
+#endif
+
+	if (nr == 7) { /* Date/Time was in localtime (to remote device)
+			* already. Since we don't know anything about the
+			* timezone on that one we won't try to apply UTC offset
+			*/
+		time += tz_offset;
+	}
+
+	return time;
+}
+
+static int parse_handle(const char *data)
+{
+	int handle;
+	char *ptr;
+
+	if (data == NULL)
+		return -1;
+	if (strlen(data) != HANDLE_LEN)
+		return -1;
+	handle = strtol(data, &ptr, 10);
+	if (ptr != data + HANDLE_LEN)
+		return -1;
+	if (handle < 0 || handle >= HANDLE_LIMIT)
+		return -1;
+	return handle;
+}
+
+struct native_prop {
+	char *encoding, *pixel;
+	uint64_t size;
+};
+
+struct variant_prop {
+	char *encoding, *pixel, *transform;
+	uint64_t maxsize;
+};
+
+struct att_prop {
+	char *content_type, *charset, *name;
+	uint64_t size;
+	time_t ctime, mtime;
+};
+
+struct prop_object {
+	char *handle, *name;
+	GSList *native, *variant, *att;
+};
+
+static void free_native_prop(struct native_prop *prop)
+{
+	DBG("");
+
+	if (prop == NULL)
+		return;
+	g_free(prop->encoding);
+	g_free(prop->pixel);
+	g_free(prop);
+}
+
+static void free_variant_prop(struct variant_prop *prop)
+{
+	DBG("");
+
+	if (prop == NULL)
+		return;
+	g_free(prop->encoding);
+	g_free(prop->pixel);
+	g_free(prop->transform);
+	g_free(prop);
+}
+
+static void free_att_prop(struct att_prop *prop)
+{
+	DBG("");
+
+	if (prop == NULL)
+		return;
+	g_free(prop->content_type);
+	g_free(prop->charset);
+	g_free(prop->name);
+	g_free(prop);
+}
+
+static void free_prop_object(struct prop_object *object)
+{
+	GSList *list;
+
+	DBG("");
+
+	if (object == NULL)
+		return;
+	for (list = object->native; list != NULL; list = g_slist_next(list))
+		free_native_prop(list->data);
+	for (list = object->variant; list != NULL; list = g_slist_next(list))
+		free_variant_prop(list->data);
+	for (list = object->att; list != NULL; list = g_slist_next(list))
+		free_att_prop(list->data);
+	g_slist_free(object->native);
+	g_slist_free(object->variant);
+	g_slist_free(object->att);
+	g_free(object->handle);
+	g_free(object->name);
+	g_free(object);
+}
+
+static gboolean parse_attrib_native(struct native_prop *prop, const gchar *key,
+					const gchar *value, GError **gerr)
+{
+	DBG("");
+
+	if (g_str_equal(key, "encoding")) {
+		if (convBIP2IM(value) == NULL)
+			goto invalid;
+		prop->encoding = g_strdup(value);
+	} else if (g_str_equal(key, "pixel")) {
+		if (!parse_pixel_range(value, NULL, NULL, NULL))
+			goto invalid;
+		prop->pixel = g_strdup(value);
+	} else if (g_str_equal(key, "size")) {
+		prop->size = parse_unsignednumber(value);
+		if (prop->size == 0)
+			goto invalid;
+	} else {
+		g_set_error(gerr, G_MARKUP_ERROR,
+				G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+invalid:
+	g_set_error(gerr, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			NULL);
+	return FALSE;
+}
+
+static gboolean parse_attrib_variant(struct variant_prop *prop,
+					const gchar *key,
+					const gchar *value, GError **gerr)
+{
+	DBG("");
+
+	if (g_str_equal(key, "encoding")) {
+		if (convBIP2IM(value) == NULL)
+			goto invalid;
+		prop->encoding = g_strdup(value);
+	} else if (g_str_equal(key, "pixel")) {
+		if (!parse_pixel_range(value, NULL, NULL, NULL))
+			goto invalid;
+		prop->pixel = g_strdup(value);
+	} else if (g_str_equal(key, "maxsize")) {
+		prop->maxsize = parse_unsignednumber(value);
+		if (prop->maxsize == 0)
+			goto invalid;
+	} else if (g_str_equal(key, "transform")) {
+		prop->transform = parse_transform_list(value);
+		if (prop->transform == NULL)
+			goto invalid;
+	} else {
+		g_set_error(gerr, G_MARKUP_ERROR,
+				G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+invalid:
+	g_set_error(gerr, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			NULL);
+	return FALSE;
+}
+
+static gboolean parse_attrib_att(struct att_prop *prop, const gchar *key,
+					const gchar *value, GError **gerr)
+{
+	DBG("");
+
+	if (g_str_equal(key, "content-type")) {
+		prop->content_type = g_strdup(value);
+	} else if (g_str_equal(key, "charset")) {
+		prop->charset = g_strdup(value);
+	} else if (g_str_equal(key, "name")) {
+		prop->name = g_strdup(value);
+	} else if (g_str_equal(key, "size")) {
+		prop->size = parse_unsignednumber(value);
+		if (prop->size == 0)
+			goto invalid;
+	} else if (g_str_equal(key, "created")) {
+		prop->ctime = parse_iso8601_bip(value, strlen(value));
+		if (prop->ctime == -1)
+			goto invalid;
+	} else if (g_str_equal(key, "modified")) {
+		prop->mtime = parse_iso8601_bip(value, strlen(value));
+		if (prop->mtime == -1)
+			goto invalid;
+	} else {
+		g_set_error(gerr, G_MARKUP_ERROR,
+				G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+invalid:
+	g_set_error(gerr, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			NULL);
+	return FALSE;
+}
+
+static struct att_prop *parse_elem_att(const gchar **names,
+					const gchar **values, GError **gerr)
+{
+	gchar **key;
+	struct att_prop *prop = g_new0(struct att_prop, 1);
+
+	DBG("");
+
+	for (key = (gchar **) names; *key; key++, values++) {
+		if (!parse_attrib_att(prop, *key, *values, gerr)) {
+			free_att_prop(prop);
+			return NULL;
+		}
+	}
+	return prop;
+}
+
+static struct variant_prop *parse_elem_variant(const gchar **names,
+					const gchar **values, GError **gerr)
+{
+	gchar **key;
+	struct variant_prop *prop = g_new0(struct variant_prop, 1);
+
+	DBG("");
+
+	for (key = (gchar **) names; *key; key++, values++) {
+		if (!parse_attrib_variant(prop, *key, *values, gerr)) {
+			free_variant_prop(prop);
+			return NULL;
+		}
+	}
+	if (prop->transform == NULL)
+		prop->transform = g_strdup("stretch crop fill");
+	return prop;
+}
+
+static struct native_prop *parse_elem_native(const gchar **names,
+					const gchar **values, GError **gerr)
+{
+	gchar **key;
+	struct native_prop *prop = g_new0(struct native_prop, 1);
+
+	DBG("");
+
+	for (key = (gchar **) names; *key; key++, values++) {
+		if (!parse_attrib_native(prop, *key, *values, gerr)) {
+			free_native_prop(prop);
+			return NULL;
+		}
+	}
+	return prop;
+}
+
+static gboolean parse_attrib_prop(struct prop_object *prop, const gchar *key,
+					const gchar *value, GError **gerr)
+{
+	DBG("");
+
+	if (g_str_equal(key, "handle")) {
+		if (parse_handle(value) < 0)
+			goto invalid;
+		prop->handle = g_strdup(value);
+	} else if (g_str_equal(key, "friendly-name")) {
+		prop->name = g_strdup(value);
+	} else if (g_str_equal(key, "version")) {
+		// pass;
+	} else {
+		g_set_error(gerr, G_MARKUP_ERROR,
+				G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+invalid:
+	g_set_error(gerr, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			NULL);
+	return FALSE;
+}
+
+static struct prop_object *parse_elem_prop(const gchar **names,
+					const gchar **values, GError **gerr)
+{
+	gchar **key;
+	struct prop_object *prop = g_new0(struct prop_object, 1);
+
+	DBG("");
+
+	for (key = (gchar **) names; *key; key++, values++) {
+		if (!parse_attrib_prop(prop, *key, *values, gerr)) {
+			free_prop_object(prop);
+			return NULL;
+		}
+	}
+	return prop;
+}
+
+static void prop_element(GMarkupParseContext *ctxt,
+		const gchar *element,
+		const gchar **names,
+		const gchar **values,
+		gpointer user_data,
+		GError **gerr)
+{
+	struct prop_object **obj = user_data;
+
+	DBG("");
+
+	if (g_str_equal(element, "image-properties")) {
+		if (*obj != NULL) {
+			free_prop_object(*obj);
+			*obj = NULL;
+			goto invalid;
+		}
+		*obj = parse_elem_prop(names, values, gerr);
+	} else if (g_str_equal(element, "native")) {
+		struct native_prop *prop;
+
+		if (*obj == NULL)
+			goto invalid;
+		prop = parse_elem_native(names, values, gerr);
+		(*obj)->native = g_slist_append((*obj)->native, prop);
+	} else if (g_str_equal(element, "variant")) {
+		struct variant_prop *prop;
+
+		if (*obj == NULL)
+			goto invalid;
+		prop = parse_elem_variant(names, values, gerr);
+		(*obj)->variant = g_slist_append((*obj)->variant, prop);
+	} else if (g_str_equal(element, "attachment")) {
+		struct att_prop *prop;
+
+		if (*obj == NULL)
+			goto invalid;
+		prop = parse_elem_att(names, values, gerr);
+		(*obj)->att = g_slist_append((*obj)->att, prop);
+	} else {
+		if (*obj != NULL) {
+			free_prop_object(*obj);
+			*obj = NULL;
+		}
+		goto invalid;
+	}
+
+	return;
+invalid:
+	g_set_error(gerr, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			NULL);
+}
+
+static const GMarkupParser properties_parser = {
+	prop_element,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct prop_object *parse_properties(char *data, unsigned int length,
+							int *err)
+{
+	struct prop_object *prop = NULL;
+	gboolean status;
+	GError *gerr = NULL;
+	GMarkupParseContext *ctxt = g_markup_parse_context_new(
+					&properties_parser, 0, &prop, NULL);
+
+	DBG("");
+
+	if (err != NULL)
+		*err = 0;
+	status = g_markup_parse_context_parse(ctxt, data, length, &gerr);
+	g_markup_parse_context_free(ctxt);
+	if (!status) {
+		if (err != NULL)
+			*err = -EINVAL;
+		free_prop_object(prop);
+		prop = NULL;
+	}
+	return prop;
+}
+
+gboolean verify_properties(struct prop_object *obj)
+{
+	GSList *list;
+
+	if (obj->handle == NULL)
+		return FALSE;
+
+	for (list = obj->native; list != NULL; list = g_slist_next(list)) {
+		struct native_prop *prop = list->data;
+
+		if (prop->encoding == NULL || prop->pixel == NULL)
+			return FALSE;
+	}
+
+	for (list = obj->variant; list != NULL; list = g_slist_next(list)) {
+		struct variant_prop *prop = list->data;
+
+		if (prop->encoding == NULL || prop->pixel == NULL)
+			return FALSE;
+	}
+
+	for (list = obj->att; list != NULL; list = g_slist_next(list)) {
+		struct att_prop *prop = list->data;
+
+		if (prop->content_type == NULL || prop->name == NULL)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+void append_properties(DBusMessageIter *args, struct prop_object *obj)
+{
+	DBusMessageIter dict, iter;
+	GSList *list;
+
+	dbus_message_iter_open_container(args, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_ARRAY_AS_STRING
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	dbus_message_iter_open_container(&dict, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&iter);
+	g_dbus_dict_append_entry(&iter, "handle", DBUS_TYPE_STRING,
+					&obj->handle);
+	g_dbus_dict_append_entry(&iter, "name", DBUS_TYPE_STRING, &obj->name);
+	dbus_message_iter_close_container(&dict, &iter);
+
+	for (list = obj->native; list != NULL; list = g_slist_next(list)) {
+		struct native_prop *prop = list->data;
+		static char *native_str = "native";
+
+		dbus_message_iter_open_container(&dict, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&iter);
+		g_dbus_dict_append_entry(&iter, "type", DBUS_TYPE_STRING,
+						&native_str);
+		if (prop->encoding)
+			g_dbus_dict_append_entry(&iter, "encoding",
+							DBUS_TYPE_STRING,
+							&prop->encoding);
+		if (prop->pixel)
+			g_dbus_dict_append_entry(&iter, "pixel",
+							DBUS_TYPE_STRING,
+							&prop->pixel);
+		if (prop->size)
+			g_dbus_dict_append_entry(&iter, "size",
+							DBUS_TYPE_UINT64,
+							&prop->size);
+		dbus_message_iter_close_container(&dict, &iter);
+	}
+
+	for (list = obj->variant; list != NULL; list = g_slist_next(list)) {
+		struct variant_prop *prop = list->data;
+		static char *variant_str = "variant";
+
+		dbus_message_iter_open_container(&dict, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&iter);
+		g_dbus_dict_append_entry(&iter, "type", DBUS_TYPE_STRING,
+						&variant_str);
+		if (prop->encoding)
+			g_dbus_dict_append_entry(&iter, "encoding",
+							DBUS_TYPE_STRING,
+							&prop->encoding);
+		if (prop->pixel)
+			g_dbus_dict_append_entry(&iter, "pixel",
+							DBUS_TYPE_STRING,
+							&prop->pixel);
+		if (prop->maxsize)
+			g_dbus_dict_append_entry(&iter, "maxsize",
+							DBUS_TYPE_UINT64,
+							&prop->maxsize);
+		if (prop->transform)
+			g_dbus_dict_append_entry(&iter, "transformation",
+							DBUS_TYPE_STRING,
+							&prop->transform);
+		dbus_message_iter_close_container(&dict, &iter);
+	}
+
+	for (list = obj->att; list != NULL; list = g_slist_next(list)) {
+		struct att_prop *prop = list->data;
+		static char *attachment_str = "attachment";
+
+		dbus_message_iter_open_container(&dict, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&iter);
+		g_dbus_dict_append_entry(&iter, "type", DBUS_TYPE_STRING,
+						&attachment_str);
+		if (prop->content_type)
+			g_dbus_dict_append_entry(&iter, "content-type",
+							DBUS_TYPE_STRING,
+							&prop->content_type);
+		if (prop->charset)
+			g_dbus_dict_append_entry(&iter, "charset",
+							DBUS_TYPE_STRING,
+							&prop->charset);
+		if (prop->name)
+			g_dbus_dict_append_entry(&iter, "name",
+							DBUS_TYPE_STRING,
+							&prop->name);
+		if (prop->size)
+			g_dbus_dict_append_entry(&iter, "size",
+							DBUS_TYPE_UINT64,
+							&prop->size);
+		if (prop->ctime)
+			g_dbus_dict_append_entry(&iter, "ctime",
+							DBUS_TYPE_UINT64,
+							&prop->ctime);
+		if (prop->mtime)
+			g_dbus_dict_append_entry(&iter, "mtime",
+							DBUS_TYPE_UINT64,
+							&prop->mtime);
+		dbus_message_iter_close_container(&dict, &iter);
+	}
+
+	dbus_message_iter_close_container(args, &dict);
+}
diff --git a/obexd/client/bip-common.h b/obexd/client/bip-common.h
new file mode 100644
index 0000000..6e7aac3
--- /dev/null
+++ b/obexd/client/bip-common.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2024  Collabora Ltd.
+ *
+ *
+ */
+
+#include <glib.h>
+#include "gdbus/gdbus.h"
+
+struct prop_object;
+
+gboolean parse_pixel_range(const gchar *dim, unsigned int *lower_ret,
+						unsigned int *upper_ret,
+						gboolean *fixed_ratio_ret);
+gboolean verify_encoding(const char *encoding);
+char *parse_transform(const char *transform);
+struct prop_object *parse_properties(char *data, unsigned int length,
+							int *err);
+gboolean verify_properties(struct prop_object *obj);
+void append_properties(DBusMessageIter *args, struct prop_object *obj);
diff --git a/obexd/client/bip.c b/obexd/client/bip.c
new file mode 100644
index 0000000..9d9ecec
--- /dev/null
+++ b/obexd/client/bip.c
@@ -0,0 +1,440 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2024  Collabora Ltd.
+ *
+ *
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gdbus/gdbus.h"
+#include "gobex/gobex.h"
+
+#include "obexd/src/log.h"
+#include "transfer.h"
+#include "session.h"
+#include "driver.h"
+#include "bip-common.h"
+#include "bip.h"
+
+#define OBEX_BIP_AVRCP_UUID \
+	"\x71\x63\xDD\x54\x4A\x7E\x11\xE2\xB4\x7C\x00\x50\xC2\x49\x00\x48"
+#define OBEX_BIP_AVRCP_UUID_LEN 16
+
+#define IMAGE_INTERFACE "org.bluez.obex.Image1"
+#define ERROR_INTERFACE "org.bluez.obex.Error"
+#define IMAGE_UUID "0000111A-0000-1000-8000-00805f9b34fb"
+
+#define IMG_HANDLE_TAG  0x30
+#define IMG_DESC_TAG    0x71
+
+#define EOL_CHARS "\n"
+#define IMG_DESC_BEGIN "<image-descriptor version=\"1.0\">" EOL_CHARS
+#define IMG_BEGIN "<image encoding=\"%s\" pixel=\"%s\""
+#define IMG_TRANSFORM " transformation=\"%s\""
+#define IMG_END "/>" EOL_CHARS
+#define IMG_DESC_END "</image-descriptor>" EOL_CHARS
+
+static DBusConnection *conn;
+
+struct bip_avrcp_data {
+	struct obc_session *session;
+};
+
+static void image_properties_complete_cb(struct obc_session *session,
+						struct obc_transfer *transfer,
+						GError *err, void *user_data)
+{
+	DBusMessage *message = user_data;
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter;
+	char *contents = NULL;
+	size_t size;
+	int perr;
+	struct prop_object *prop = NULL;
+
+	if (err != NULL) {
+		reply = g_dbus_create_error(message,
+					ERROR_INTERFACE ".Failed",
+					"%s", err->message);
+		goto done;
+	}
+
+	perr = obc_transfer_get_contents(transfer, &contents, &size);
+	if (perr < 0) {
+		reply = g_dbus_create_error(message,
+						ERROR_INTERFACE ".Failed",
+						"Error reading contents: %s",
+						strerror(-perr));
+		goto done;
+	}
+
+	prop = parse_properties(contents, size, &perr);
+	if (prop == NULL) {
+		reply = g_dbus_create_error(message,
+						ERROR_INTERFACE ".Failed",
+						"Error parsing contents: %s",
+						strerror(-perr));
+		goto done;
+	}
+
+	if (!verify_properties(prop)) {
+		reply = g_dbus_create_error(message,
+						ERROR_INTERFACE ".Failed",
+						"Error verifying contents");
+		goto done;
+	}
+
+	reply = dbus_message_new_method_return(message);
+	dbus_message_iter_init_append(reply, &iter);
+	append_properties(&iter, prop);
+
+done:
+	g_dbus_send_message(conn, reply);
+	g_free(contents);
+	dbus_message_unref(message);
+}
+
+static DBusMessage *get_image_properties(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct bip_avrcp_data *bip_avrcp = user_data;
+	const char *handle = NULL;
+	struct obc_transfer *transfer;
+	GObexHeader *header;
+	DBusMessage *reply = NULL;
+	GError *err = NULL;
+
+	DBG("");
+
+	if (dbus_message_get_args(message, NULL,
+				DBUS_TYPE_STRING, &handle,
+				DBUS_TYPE_INVALID) == FALSE) {
+		reply = g_dbus_create_error(message,
+				ERROR_INTERFACE ".InvalidArguments", NULL);
+		return reply;
+	}
+
+	transfer = obc_transfer_get("x-bt/img-properties", NULL, NULL, &err);
+	if (transfer == NULL)
+		goto fail;
+
+	header = g_obex_header_new_unicode(IMG_HANDLE_TAG, handle);
+	obc_transfer_add_header(transfer, header);
+
+	if (!obc_session_queue(bip_avrcp->session, transfer,
+			image_properties_complete_cb, message, &err))
+		goto fail;
+
+	dbus_message_ref(message);
+
+	return NULL;
+
+fail:
+	reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+								err->message);
+	g_error_free(err);
+	return reply;
+}
+
+static DBusMessage *get_thumbnail(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct bip_avrcp_data *bip_avrcp = user_data;
+	const char *handle = NULL, *image_path = NULL;
+	struct obc_transfer *transfer;
+	GObexHeader *header;
+	DBusMessage *reply = NULL;
+	GError *err = NULL;
+
+	DBG("");
+
+	if (dbus_message_get_args(message, NULL,
+				DBUS_TYPE_STRING, &image_path,
+				DBUS_TYPE_STRING, &handle,
+				DBUS_TYPE_INVALID) == FALSE) {
+		reply = g_dbus_create_error(message,
+				ERROR_INTERFACE ".InvalidArguments", NULL);
+		return reply;
+	}
+
+	transfer = obc_transfer_get("x-bt/img-thm", NULL, image_path, &err);
+	if (transfer == NULL)
+		goto fail;
+
+	header = g_obex_header_new_unicode(IMG_HANDLE_TAG, handle);
+	obc_transfer_add_header(transfer, header);
+
+	if (!obc_session_queue(bip_avrcp->session, transfer, NULL, NULL, &err))
+		goto fail;
+
+	return obc_transfer_create_dbus_reply(transfer, message);
+
+fail:
+	reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+								err->message);
+	g_error_free(err);
+	return reply;
+}
+
+static gboolean parse_get_image_dict(DBusMessage *msg, char **path,
+					char **handle, char **pixel,
+					char **encoding, uint64_t *maxsize,
+							char **transform)
+{
+	DBusMessageIter iter, array;
+
+	DBG("");
+
+	*path = NULL;
+	*handle = NULL;
+	*pixel = NULL;
+	*encoding = NULL;
+	*transform = NULL;
+
+	dbus_message_iter_init(msg, &iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		goto failed;
+	dbus_message_iter_get_basic(&iter, path);
+	*path = g_strdup(*path);
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		goto failed;
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_get_basic(&iter, handle);
+	*handle = g_strdup(*handle);
+	dbus_message_iter_next(&iter);
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+		goto failed;
+
+	dbus_message_iter_recurse(&iter, &array);
+
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter entry, value;
+		const char *key, *val;
+
+		dbus_message_iter_recurse(&array, &entry);
+
+		if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+			return FALSE;
+		dbus_message_iter_get_basic(&entry, &key);
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+		switch (dbus_message_iter_get_arg_type(&value)) {
+		case DBUS_TYPE_STRING:
+			dbus_message_iter_get_basic(&value, &val);
+			if (g_str_equal(key, "pixel")) {
+				if (!parse_pixel_range(val, NULL, NULL, NULL))
+					goto failed;
+				*pixel = g_strdup(val);
+			} else if (g_str_equal(key, "encoding")) {
+				if (!verify_encoding(val))
+					goto failed;
+				*encoding = g_strdup(val);
+				if (*encoding == NULL)
+					goto failed;
+			} else if (g_str_equal(key, "transformation")) {
+				*transform = parse_transform(val);
+				if (*transform == NULL)
+					goto failed;
+			}
+			break;
+		case DBUS_TYPE_UINT64:
+			if (g_str_equal(key, "maxsize") == TRUE) {
+				dbus_message_iter_get_basic(&value, maxsize);
+				if (*maxsize == 0)
+					goto failed;
+			}
+			break;
+		}
+		dbus_message_iter_next(&array);
+	}
+
+	if (*pixel == NULL)
+		*pixel = strdup("");
+	if (*encoding == NULL)
+		*encoding = strdup("");
+
+	DBG("pixel: '%s' encoding: '%s' maxsize: '%lu' transform: '%s'",
+			*pixel, *encoding, *maxsize, *transform
+	);
+
+	return TRUE;
+failed:
+	g_free(*path);
+	g_free(*handle);
+	g_free(*pixel);
+	g_free(*encoding);
+	g_free(*transform);
+	return FALSE;
+}
+
+static DBusMessage *get_image(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct bip_avrcp_data *bip_avrcp = user_data;
+	char *handle = NULL, *image_path = NULL, *transform = NULL,
+		*encoding = NULL, *pixel = NULL;
+	uint64_t maxsize;
+	struct obc_transfer *transfer;
+	GObexHeader *header;
+	DBusMessage *reply = NULL;
+	GString *descriptor = NULL;
+	GError *err = NULL;
+
+	DBG("");
+
+	if (!parse_get_image_dict(message, &image_path, &handle, &pixel,
+					&encoding, &maxsize, &transform))
+		return g_dbus_create_error(message,
+				ERROR_INTERFACE ".InvalidArguments", NULL);
+
+	transfer = obc_transfer_get("x-bt/img-img", NULL, image_path, &err);
+	if (transfer == NULL) {
+		reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed",
+						"%s",
+						err->message);
+		g_error_free(err);
+		goto fail;
+	}
+
+	header = g_obex_header_new_unicode(IMG_HANDLE_TAG, handle);
+	obc_transfer_add_header(transfer, header);
+
+	descriptor = g_string_new(IMG_DESC_BEGIN);
+	g_string_append_printf(descriptor, IMG_BEGIN, encoding, pixel);
+	if (transform != NULL)
+		g_string_append_printf(descriptor, IMG_TRANSFORM, transform);
+	g_string_append(descriptor, IMG_END);
+	descriptor = g_string_append(descriptor, IMG_DESC_END);
+	header = g_obex_header_new_bytes(IMG_DESC_TAG, descriptor->str,
+						descriptor->len);
+	obc_transfer_add_header(transfer, header);
+	g_string_free(descriptor, TRUE);
+
+	if (!obc_session_queue(bip_avrcp->session, transfer, NULL, NULL,
+								&err)) {
+		reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed",
+						"%s",
+						err->message);
+		g_error_free(err);
+		goto fail;
+	}
+
+	reply = obc_transfer_create_dbus_reply(transfer, message);
+
+fail:
+	g_free(handle);
+	g_free(image_path);
+	g_free(transform);
+	g_free(encoding);
+	g_free(pixel);
+	return reply;
+}
+
+static const GDBusMethodTable bip_avrcp_methods[] = {
+	{ GDBUS_ASYNC_METHOD("Properties",
+		GDBUS_ARGS({ "handle", "s"}),
+		GDBUS_ARGS({ "properties", "aa{sv}" }),
+		get_image_properties) },
+	{ GDBUS_ASYNC_METHOD("Get",
+		GDBUS_ARGS({ "file", "s" }, { "handle", "s"},
+				{"properties", "a{sv}"}),
+		GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
+		get_image) },
+	{ GDBUS_ASYNC_METHOD("GetThumbnail",
+		GDBUS_ARGS({ "file", "s" }, { "handle", "s"}),
+		GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
+		get_thumbnail) },
+	{ }
+};
+
+static void bip_avrcp_free(void *data)
+{
+	struct bip_avrcp_data *bip_avrcp = data;
+
+	obc_session_unref(bip_avrcp->session);
+	g_free(bip_avrcp);
+}
+
+static int bip_avrcp_probe(struct obc_session *session)
+{
+	struct bip_avrcp_data *bip_avrcp;
+	const char *path;
+
+	path = obc_session_get_path(session);
+
+	DBG("%s", path);
+
+	bip_avrcp = g_try_new0(struct bip_avrcp_data, 1);
+	if (!bip_avrcp)
+		return -ENOMEM;
+
+	bip_avrcp->session = obc_session_ref(session);
+
+	if (!g_dbus_register_interface(conn, path, IMAGE_INTERFACE,
+					bip_avrcp_methods,
+					NULL, NULL,
+					bip_avrcp, bip_avrcp_free)) {
+		bip_avrcp_free(bip_avrcp);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void bip_avrcp_remove(struct obc_session *session)
+{
+	const char *path = obc_session_get_path(session);
+
+	DBG("%s", path);
+
+	g_dbus_unregister_interface(conn, path, IMAGE_INTERFACE);
+}
+
+static struct obc_driver bip_avrcp = {
+	.service = "BIP-AVRCP",
+	.uuid = IMAGE_UUID,
+	.target = OBEX_BIP_AVRCP_UUID,
+	.target_len = OBEX_BIP_AVRCP_UUID_LEN,
+	.probe = bip_avrcp_probe,
+	.remove = bip_avrcp_remove
+};
+
+int bip_init(void)
+{
+	int err;
+
+	DBG("");
+
+	conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+	if (!conn)
+		return -EIO;
+
+	err = obc_driver_register(&bip_avrcp);
+	if (err < 0)
+		goto failed;
+
+	return 0;
+
+failed:
+	dbus_connection_unref(conn);
+	conn = NULL;
+	return err;
+}
+
+void bip_exit(void)
+{
+	DBG("");
+
+	dbus_connection_unref(conn);
+	conn = NULL;
+
+	obc_driver_unregister(&bip_avrcp);
+}
diff --git a/obexd/client/bip.h b/obexd/client/bip.h
new file mode 100644
index 0000000..18e3360
--- /dev/null
+++ b/obexd/client/bip.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2024  Collabora Ltd.
+ *
+ *
+ */
+
+int bip_init(void);
+void bip_exit(void);
diff --git a/obexd/client/manager.c b/obexd/client/manager.c
index 75f1bfb..52f4d01 100644
--- a/obexd/client/manager.c
+++ b/obexd/client/manager.c
@@ -32,6 +32,7 @@
 #include "pbap.h"
 #include "sync.h"
 #include "map.h"
+#include "bip.h"
 #include "manager.h"
 
 #define CLIENT_INTERFACE	"org.bluez.obex.Client1"
@@ -107,7 +108,8 @@ done:
 }
 
 static int parse_device_dict(DBusMessageIter *iter,
-		const char **source, const char **target, uint8_t *channel)
+		const char **source, const char **target, uint8_t *channel,
+		uint16_t *psm)
 {
 	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
 		DBusMessageIter entry, value;
@@ -130,6 +132,10 @@ static int parse_device_dict(DBusMessageIter *iter,
 			if (g_str_equal(key, "Channel") == TRUE)
 				dbus_message_iter_get_basic(&value, channel);
 			break;
+		case DBUS_TYPE_UINT16:
+			if (g_str_equal(key, "PSM") == TRUE)
+				dbus_message_iter_get_basic(&value, psm);
+			break;
 		}
 
 		dbus_message_iter_next(iter);
@@ -160,6 +166,7 @@ static DBusMessage *create_session(DBusConnection *connection,
 	struct send_data *data;
 	const char *source = NULL, *dest = NULL, *target = NULL;
 	uint8_t channel = 0;
+	uint16_t psm = 0;
 
 	dbus_message_iter_init(message, &iter);
 	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
@@ -175,8 +182,8 @@ static DBusMessage *create_session(DBusConnection *connection,
 
 	dbus_message_iter_recurse(&iter, &dict);
 
-	parse_device_dict(&dict, &source, &target, &channel);
-	if (dest == NULL || target == NULL)
+	parse_device_dict(&dict, &source, &target, &channel, &psm);
+	if (dest == NULL || target == NULL || (channel && psm))
 		return g_dbus_create_error(message,
 				ERROR_INTERFACE ".InvalidArguments", NULL);
 
@@ -188,7 +195,7 @@ static DBusMessage *create_session(DBusConnection *connection,
 	data->connection = dbus_connection_ref(connection);
 	data->message = dbus_message_ref(message);
 
-	session = obc_session_create(source, dest, target, channel,
+	session = obc_session_create(source, dest, target, channel, psm,
 					dbus_message_get_sender(message),
 					create_callback, data);
 	if (session != NULL) {
@@ -241,7 +248,7 @@ static const GDBusMethodTable client_methods[] = {
 
 static DBusConnection *conn = NULL;
 
-static struct obc_module {
+static const struct obc_module {
 	const char *name;
 	int (*init) (void);
 	void (*exit) (void);
@@ -252,13 +259,14 @@ static struct obc_module {
 	{ "pbap", pbap_init, pbap_exit },
 	{ "sync", sync_init, sync_exit },
 	{ "map", map_init, map_exit },
+	{ "bip", bip_init, bip_exit },
 	{ }
 };
 
 int client_manager_init(void)
 {
 	DBusError derr;
-	struct obc_module *module;
+	const struct obc_module *module;
 
 	dbus_error_init(&derr);
 
@@ -289,7 +297,7 @@ int client_manager_init(void)
 
 void client_manager_exit(void)
 {
-	struct obc_module *module;
+	const struct obc_module *module;
 
 	if (conn == NULL)
 		return;
diff --git a/obexd/client/map.c b/obexd/client/map.c
index 74828cd..513dcaf 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1060,7 +1060,7 @@ static void parse_protected(struct map_msg *msg, const char *value)
 						MAP_MSG_INTERFACE, "Protected");
 }
 
-static struct map_msg_parser {
+static const struct map_msg_parser {
 	const char *name;
 	void (*func) (struct map_msg *msg, const char *value);
 } msg_parsers[] = {
@@ -1120,7 +1120,7 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 								&msg->path);
 
 	for (i = 0, key = names[i]; key; key = names[++i]) {
-		struct map_msg_parser *parser;
+		const struct map_msg_parser *parser;
 
 		for (parser = msg_parsers; parser && parser->name; parser++) {
 			if (strcasecmp(key, parser->name) == 0) {
diff --git a/obexd/client/mns.c b/obexd/client/mns.c
index e525056..c7f86af 100644
--- a/obexd/client/mns.c
+++ b/obexd/client/mns.c
@@ -233,7 +233,7 @@ static void parse_event_report_priority(struct map_event *event,
 	event->priority = g_strdup(value);
 }
 
-static struct map_event_report_parser {
+static const struct map_event_report_parser {
 	const char *name;
 	void (*func) (struct map_event *event, const char *value);
 } event_report_parsers[] = {
@@ -262,7 +262,7 @@ static void event_report_element(GMarkupParseContext *ctxt,
 		return;
 
 	for (i = 0, key = names[i]; key; key = names[++i]) {
-		struct map_event_report_parser *parser;
+		const struct map_event_report_parser *parser;
 
 		for (parser = event_report_parsers; parser && parser->name;
 								parser++) {
@@ -346,7 +346,7 @@ static ssize_t event_report_write(void *obj, const void *buf, size_t count)
 	return count;
 }
 
-static struct obex_service_driver mns = {
+static const struct obex_service_driver mns = {
 	.name = "Message Notification server",
 	.service = OBEX_MNS,
 	.target = MNS_TARGET,
@@ -356,7 +356,7 @@ static struct obex_service_driver mns = {
 	.disconnect = mns_disconnect,
 };
 
-static struct obex_mime_type_driver mime_event_report = {
+static const struct obex_mime_type_driver mime_event_report = {
 	.target = MNS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/MAP-event-report",
diff --git a/obexd/client/pbap.c b/obexd/client/pbap.c
index 1ed8c68..2d2aa95 100644
--- a/obexd/client/pbap.c
+++ b/obexd/client/pbap.c
@@ -285,7 +285,7 @@ static void read_version(struct pbap_data *pbap, GObexApparam *apparam)
 		data = value;
 	}
 
-	if (memcmp(pbap->primary, data, len)) {
+	if (len == sizeof(pbap->primary) && memcmp(pbap->primary, data, len)) {
 		memcpy(pbap->primary, data, len);
 		g_dbus_emit_property_changed(conn,
 					obc_session_get_path(pbap->session),
@@ -299,7 +299,8 @@ static void read_version(struct pbap_data *pbap, GObexApparam *apparam)
 		data = value;
 	}
 
-	if (memcmp(pbap->secondary, data, len)) {
+	if (len == sizeof(pbap->secondary) &&
+			memcmp(pbap->secondary, data, len)) {
 		memcpy(pbap->secondary, data, len);
 		g_dbus_emit_property_changed(conn,
 					obc_session_get_path(pbap->session),
diff --git a/obexd/client/session.c b/obexd/client/session.c
index 7d8ebb0..13a834e 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -88,6 +88,7 @@ struct obc_session {
 	char *source;
 	char *destination;
 	uint8_t channel;
+	uint16_t psm;
 	struct obc_transport *transport;
 	struct obc_driver *driver;
 	char *path;		/* Session path */
@@ -471,6 +472,7 @@ static struct obc_session *session_find(const char *source,
 						const char *destination,
 						const char *service,
 						uint8_t channel,
+						uint16_t psm,
 						const char *owner)
 {
 	GSList *l;
@@ -490,6 +492,9 @@ static struct obc_session *session_find(const char *source,
 		if (channel && session->channel != channel)
 			continue;
 
+		if (psm && session->psm != psm)
+			continue;
+
 		if (g_strcmp0(owner, session->owner))
 			continue;
 
@@ -541,8 +546,9 @@ static int session_connect(struct obc_session *session,
 	}
 
 	session->id = transport->connect(session->source, session->destination,
-					driver->uuid, session->channel,
-					transport_func, callback);
+			driver->uuid,
+			session->channel ? session->channel : session->psm,
+			transport_func, callback);
 	if (session->id == 0) {
 		obc_session_unref(callback->session);
 		g_free(callback);
@@ -558,6 +564,7 @@ struct obc_session *obc_session_create(const char *source,
 						const char *destination,
 						const char *service,
 						uint8_t channel,
+						uint16_t psm,
 						const char *owner,
 						session_callback_t function,
 						void *user_data)
@@ -570,7 +577,8 @@ struct obc_session *obc_session_create(const char *source,
 	if (destination == NULL)
 		return NULL;
 
-	session = session_find(source, destination, service, channel, owner);
+	session = session_find(source, destination, service, channel, psm,
+				owner);
 	if (session != NULL)
 		goto proceed;
 
@@ -598,6 +606,7 @@ struct obc_session *obc_session_create(const char *source,
 	session->source = g_strdup(source);
 	session->destination = g_strdup(destination);
 	session->channel = channel;
+	session->psm = psm;
 	session->queue = g_queue_new();
 	session->folder = g_strdup("/");
 
@@ -762,6 +771,17 @@ static gboolean get_channel(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean get_psm(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_session *session = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+							&session->psm);
+
+	return TRUE;
+}
+
 static const GDBusMethodTable session_methods[] = {
 	{ GDBUS_ASYNC_METHOD("GetCapabilities",
 				NULL, GDBUS_ARGS({ "capabilities", "s" }),
@@ -794,6 +814,7 @@ static const GDBusPropertyTable session_properties[] = {
 	{ "Source", "s", get_source, NULL, source_exists },
 	{ "Destination", "s", get_destination },
 	{ "Channel", "y", get_channel },
+	{ "PSM", "q", get_psm },
 	{ "Target", "s", get_target, NULL, target_exists },
 	{ }
 };
diff --git a/obexd/client/session.h b/obexd/client/session.h
index 2c646df..19c3f36 100644
--- a/obexd/client/session.h
+++ b/obexd/client/session.h
@@ -22,6 +22,7 @@ struct obc_session *obc_session_create(const char *source,
 						const char *destination,
 						const char *service,
 						uint8_t channel,
+						uint16_t psm,
 						const char *owner,
 						session_callback_t function,
 						void *user_data);
diff --git a/obexd/client/transfer.c b/obexd/client/transfer.c
index a7a85a0..879d67d 100644
--- a/obexd/client/transfer.c
+++ b/obexd/client/transfer.c
@@ -57,6 +57,7 @@ struct obc_transfer {
 	GObex *obex;
 	uint8_t status;
 	GObexApparam *apparam;
+	GSList *headers;
 	guint8 op;
 	struct transfer_callback *callback;
 	DBusConnection *conn;
@@ -400,6 +401,11 @@ static const GDBusPropertyTable obc_transfer_properties[] = {
 	{ }
 };
 
+static void header_free(void *data, void *user_data)
+{
+	g_obex_header_free(data);
+}
+
 static void obc_transfer_free(struct obc_transfer *transfer)
 {
 	DBG("%p", transfer);
@@ -441,6 +447,8 @@ static void obc_transfer_free(struct obc_transfer *transfer)
 	if (transfer->obex)
 		g_obex_unref(transfer->obex);
 
+	g_slist_foreach(transfer->headers, header_free, NULL);
+	g_slist_free(transfer->headers);
 	g_free(transfer->callback);
 	g_free(transfer->owner);
 	g_free(transfer->filename);
@@ -820,6 +828,12 @@ static gboolean transfer_start_get(struct obc_transfer *transfer, GError **err)
 		g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, transfer->type,
 						strlen(transfer->type) + 1);
 
+	while (transfer->headers) {
+		hdr = transfer->headers->data;
+		g_obex_packet_add_header(req, hdr);
+		transfer->headers = g_slist_remove(transfer->headers, hdr);
+	}
+
 	if (transfer->apparam != NULL) {
 		hdr = g_obex_header_new_apparam(transfer->apparam);
 		g_obex_packet_add_header(req, hdr);
@@ -974,3 +988,8 @@ gint64 obc_transfer_get_size(struct obc_transfer *transfer)
 {
 	return transfer->size;
 }
+
+void obc_transfer_add_header(struct obc_transfer *transfer, void *data)
+{
+	transfer->headers = g_slist_append(transfer->headers, data);
+}
diff --git a/obexd/client/transfer.h b/obexd/client/transfer.h
index 323332a..1ed1959 100644
--- a/obexd/client/transfer.h
+++ b/obexd/client/transfer.h
@@ -47,3 +47,5 @@ gint64 obc_transfer_get_size(struct obc_transfer *transfer);
 
 DBusMessage *obc_transfer_create_dbus_reply(struct obc_transfer *transfer,
 							DBusMessage *message);
+
+void obc_transfer_add_header(struct obc_transfer *transfer, void *data);
diff --git a/obexd/plugins/bluetooth.c b/obexd/plugins/bluetooth.c
index d232d3f..51afdc9 100644
--- a/obexd/plugins/bluetooth.c
+++ b/obexd/plugins/bluetooth.c
@@ -41,7 +41,7 @@
 
 struct bluetooth_profile {
 	struct obex_server *server;
-	struct obex_service_driver *driver;
+	const struct obex_service_driver *driver;
 	char *uuid;
 	char *path;
 };
@@ -355,7 +355,7 @@ static void *bluetooth_start(struct obex_server *server, int *err)
 	const GSList *l;
 
 	for (l = server->drivers; l; l = l->next) {
-		struct obex_service_driver *driver = l->data;
+		const struct obex_service_driver *driver = l->data;
 		struct bluetooth_profile *profile;
 		const char *uuid;
 
@@ -416,7 +416,7 @@ static int bluetooth_getsockname(GIOChannel *io, char **name)
 	return 0;
 }
 
-static struct obex_transport_driver driver = {
+static const struct obex_transport_driver driver = {
 	.name = "bluetooth",
 	.start = bluetooth_start,
 	.getpeername = bluetooth_getpeername,
diff --git a/obexd/plugins/filesystem.c b/obexd/plugins/filesystem.c
index 09bff8a..a57b25a 100644
--- a/obexd/plugins/filesystem.c
+++ b/obexd/plugins/filesystem.c
@@ -113,6 +113,7 @@ static char *file_stat_line(char *filename, struct stat *fstat,
 {
 	char perm[51], atime[18], ctime[18], mtime[18];
 	char *escaped, *ret = NULL;
+	struct tm a_gmtime, c_gmtime, m_gmtime;
 
 	snprintf(perm, 50, "user-perm=\"%s%s%s\" group-perm=\"%s%s%s\" "
 			"other-perm=\"%s%s%s\"",
@@ -126,9 +127,16 @@ static char *file_stat_line(char *filename, struct stat *fstat,
 			(fstat->st_mode & 0002 ? "W" : ""),
 			(dstat->st_mode & 0002 ? "D" : ""));
 
-	strftime(atime, 17, "%Y%m%dT%H%M%SZ", gmtime(&fstat->st_atime));
-	strftime(ctime, 17, "%Y%m%dT%H%M%SZ", gmtime(&fstat->st_ctime));
-	strftime(mtime, 17, "%Y%m%dT%H%M%SZ", gmtime(&fstat->st_mtime));
+	if (!gmtime_r(&fstat->st_atime, &a_gmtime) ||
+			!gmtime_r(&fstat->st_ctime, &c_gmtime) ||
+			!gmtime_r(&fstat->st_mtime, &m_gmtime)) {
+		error("gmtime_r() returned NULL");
+		return ret;
+	}
+
+	strftime(atime, 17, "%Y%m%dT%H%M%SZ", &a_gmtime);
+	strftime(ctime, 17, "%Y%m%dT%H%M%SZ", &c_gmtime);
+	strftime(mtime, 17, "%Y%m%dT%H%M%SZ", &m_gmtime);
 
 	escaped = g_markup_escape_text(filename, -1);
 
@@ -416,6 +424,7 @@ static void *capability_open(const char *name, int oflag, mode_t mode,
 		}
 
 		object->buffer = g_string_new(buf);
+		g_free(buf);
 
 		if (size)
 			*size = object->buffer->len;
@@ -642,7 +651,7 @@ done:
 	return err;
 }
 
-static struct obex_mime_type_driver file = {
+static const struct obex_mime_type_driver file = {
 	.open = filesystem_open,
 	.close = filesystem_close,
 	.read = filesystem_read,
@@ -652,7 +661,7 @@ static struct obex_mime_type_driver file = {
 	.copy = filesystem_copy,
 };
 
-static struct obex_mime_type_driver capability = {
+static const struct obex_mime_type_driver capability = {
 	.target = FTP_TARGET,
 	.target_size = FTP_TARGET_SIZE,
 	.mimetype = "x-obex/capability",
@@ -661,7 +670,7 @@ static struct obex_mime_type_driver capability = {
 	.read = capability_read,
 };
 
-static struct obex_mime_type_driver folder = {
+static const struct obex_mime_type_driver folder = {
 	.target = FTP_TARGET,
 	.target_size = FTP_TARGET_SIZE,
 	.mimetype = "x-obex/folder-listing",
@@ -670,7 +679,7 @@ static struct obex_mime_type_driver folder = {
 	.read = folder_read,
 };
 
-static struct obex_mime_type_driver pcsuite = {
+static const struct obex_mime_type_driver pcsuite = {
 	.target = FTP_TARGET,
 	.target_size = FTP_TARGET_SIZE,
 	.who = PCSUITE_WHO,
diff --git a/obexd/plugins/ftp.c b/obexd/plugins/ftp.c
index 4b04bab..6c841d2 100644
--- a/obexd/plugins/ftp.c
+++ b/obexd/plugins/ftp.c
@@ -175,6 +175,11 @@ int ftp_chkput(struct obex_session *os, void *user_data)
 
 	ret = obex_put_stream_start(os, path);
 
+	if (ret == 0 && obex_get_size(os) != OBJECT_SIZE_DELETE &&
+				obex_get_size(os) != OBJECT_SIZE_UNKNOWN) {
+		manager_emit_transfer_property(ftp->transfer, "Size");
+	}
+
 	if (ret == 0)
 		manager_emit_transfer_started(ftp->transfer);
 
@@ -494,7 +499,7 @@ static void ftp_reset(struct obex_session *os, void *user_data)
 	manager_emit_transfer_completed(ftp->transfer);
 }
 
-static struct obex_service_driver ftp = {
+static const struct obex_service_driver ftp = {
 	.name = "File Transfer server",
 	.service = OBEX_FTP,
 	.target = FTP_TARGET,
diff --git a/obexd/plugins/irmc.c b/obexd/plugins/irmc.c
index cd143e7..cab97b6 100644
--- a/obexd/plugins/irmc.c
+++ b/obexd/plugins/irmc.c
@@ -419,7 +419,7 @@ static ssize_t irmc_read(void *object, void *buf, size_t count)
 	return len;
 }
 
-static struct obex_mime_type_driver irmc_driver = {
+static const struct obex_mime_type_driver irmc_driver = {
 	.target = IRMC_TARGET,
 	.target_size = IRMC_TARGET_SIZE,
 	.open = irmc_open,
@@ -427,7 +427,7 @@ static struct obex_mime_type_driver irmc_driver = {
 	.read = irmc_read,
 };
 
-static struct obex_service_driver irmc = {
+static const struct obex_service_driver irmc = {
 	.name = "IRMC Sync server",
 	.service = OBEX_IRMC,
 	.target = IRMC_TARGET,
diff --git a/obexd/plugins/mas.c b/obexd/plugins/mas.c
index 5d00bc5..10b972d 100644
--- a/obexd/plugins/mas.c
+++ b/obexd/plugins/mas.c
@@ -781,7 +781,7 @@ static void *notification_registration_open(const char *name, int oflag,
 	return mas;
 }
 
-static struct obex_service_driver mas = {
+static const struct obex_service_driver mas = {
 	.name = "Message Access server",
 	.service = OBEX_MAS,
 	.target = MAS_TARGET,
@@ -793,7 +793,7 @@ static struct obex_service_driver mas = {
 	.disconnect = mas_disconnect,
 };
 
-static struct obex_mime_type_driver mime_map = {
+static const struct obex_mime_type_driver mime_map = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = NULL,
@@ -803,7 +803,7 @@ static struct obex_mime_type_driver mime_map = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_message = {
+static const struct obex_mime_type_driver mime_message = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/message",
@@ -813,7 +813,7 @@ static struct obex_mime_type_driver mime_message = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_folder_listing = {
+static const struct obex_mime_type_driver mime_folder_listing = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-obex/folder-listing",
@@ -824,7 +824,7 @@ static struct obex_mime_type_driver mime_folder_listing = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_msg_listing = {
+static const struct obex_mime_type_driver mime_msg_listing = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/MAP-msg-listing",
@@ -835,7 +835,7 @@ static struct obex_mime_type_driver mime_msg_listing = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_notification_registration = {
+static const struct obex_mime_type_driver mime_notification_registration = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/MAP-NotificationRegistration",
@@ -845,7 +845,7 @@ static struct obex_mime_type_driver mime_notification_registration = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_message_status = {
+static const struct obex_mime_type_driver mime_message_status = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/messageStatus",
@@ -855,7 +855,7 @@ static struct obex_mime_type_driver mime_message_status = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver mime_message_update = {
+static const struct obex_mime_type_driver mime_message_update = {
 	.target = MAS_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/MAP-messageUpdate",
@@ -865,7 +865,7 @@ static struct obex_mime_type_driver mime_message_update = {
 	.write = any_write,
 };
 
-static struct obex_mime_type_driver *map_drivers[] = {
+static const struct obex_mime_type_driver *map_drivers[] = {
 	&mime_map,
 	&mime_message,
 	&mime_folder_listing,
diff --git a/obexd/plugins/messages-dummy.c b/obexd/plugins/messages-dummy.c
index e37b52d..e313c61 100644
--- a/obexd/plugins/messages-dummy.c
+++ b/obexd/plugins/messages-dummy.c
@@ -359,36 +359,45 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 
 	for (i = 0 ; names[i]; ++i) {
 		if (g_strcmp0(names[i], "handle") == 0) {
+			g_free(entry->handle);
 			entry->handle = g_strdup(values[i]);
 			mld->size++;
 			continue;
 		}
 		if (g_strcmp0(names[i], "attachment_size") == 0) {
+			g_free(entry->attachment_size);
 			entry->attachment_size = g_strdup(values[i]);
 			continue;
 		}
 		if (g_strcmp0(names[i], "datetime") == 0) {
+			g_free(entry->datetime);
 			entry->datetime = g_strdup(values[i]);
 			continue;
 		}
 		if (g_strcmp0(names[i], "subject") == 0) {
+			g_free(entry->subject);
 			entry->subject = g_strdup(values[i]);
 			continue;
 		}
 		if (g_strcmp0(names[i], "recipient_addressing") == 0) {
+			g_free(entry->recipient_addressing);
 			entry->recipient_addressing = g_strdup(values[i]);
 			continue;
 		}
 		if (g_strcmp0(names[i], "sender_addressing") == 0) {
+			g_free(entry->sender_addressing);
 			entry->sender_addressing = g_strdup(values[i]);
 			continue;
 		}
 		if (g_strcmp0(names[i], "type") == 0) {
+			g_free(entry->type);
 			entry->type = g_strdup(values[i]);
 			continue;
 		}
-		if (g_strcmp0(names[i], "reception_status") == 0)
+		if (g_strcmp0(names[i], "reception_status") == 0) {
+			g_free(entry->reception_status);
 			entry->reception_status = g_strdup(values[i]);
+		}
 	}
 
 	if (mld->size > mld->offset)
@@ -397,6 +406,7 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 	g_free(entry->reception_status);
 	g_free(entry->type);
 	g_free(entry->sender_addressing);
+	g_free(entry->recipient_addressing);
 	g_free(entry->subject);
 	g_free(entry->datetime);
 	g_free(entry->attachment_size);
diff --git a/obexd/plugins/messages-tracker.c b/obexd/plugins/messages-tracker.c
deleted file mode 100644
index 4ce9f22..0000000
--- a/obexd/plugins/messages-tracker.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2010-2011  Nokia Corporation
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <glib.h>
-#include <string.h>
-
-#include "messages.h"
-
-struct message_folder {
-	char *name;
-	GSList *subfolders;
-	char *query;
-};
-
-struct session {
-	char *cwd;
-	struct message_folder *folder;
-	char *name;
-	uint16_t max;
-	uint16_t offset;
-	void *user_data;
-	void (*folder_list_cb)(void *session, int err, uint16_t size,
-					const char *name, void *user_data);
-};
-
-static struct message_folder *folder_tree = NULL;
-
-static struct message_folder *get_folder(const char *folder)
-{
-	GSList *folders = folder_tree->subfolders;
-	struct message_folder *last = NULL;
-	char **path;
-	int i;
-
-	if (g_strcmp0(folder, "/") == 0)
-		return folder_tree;
-
-	path = g_strsplit(folder, "/", 0);
-
-	for (i = 1; path[i] != NULL; i++) {
-		gboolean match_found = FALSE;
-		GSList *l;
-
-		for (l = folders; l != NULL; l = g_slist_next(l)) {
-			struct message_folder *folder = l->data;
-
-			if (g_strcmp0(folder->name, path[i]) == 0) {
-				match_found = TRUE;
-				last = l->data;
-				folders = folder->subfolders;
-				break;
-			}
-		}
-
-		if (!match_found) {
-			g_strfreev(path);
-			return NULL;
-		}
-	}
-
-	g_strfreev(path);
-
-	return last;
-}
-
-static struct message_folder *create_folder(const char *name, const char *query)
-{
-	struct message_folder *folder = g_new0(struct message_folder, 1);
-
-	folder->name = g_strdup(name);
-	folder->query = g_strdup(query);
-
-	return folder;
-}
-
-static void destroy_folder_tree(void *root)
-{
-	struct message_folder *folder = root;
-	GSList *tmp, *next;
-
-	if (folder == NULL)
-		return;
-
-	g_free(folder->name);
-	g_free(folder->query);
-
-	tmp = folder->subfolders;
-	while (tmp != NULL) {
-		next = g_slist_next(tmp);
-		destroy_folder_tree(tmp->data);
-		tmp = next;
-	}
-
-	g_slist_free(folder->subfolders);
-	g_free(folder);
-}
-
-static void create_folder_tree(void)
-{
-	struct message_folder *parent, *child;
-
-	folder_tree = create_folder("/", "FILTER (!BOUND(?msg))");
-
-	parent = create_folder("telecom", "FILTER (!BOUND(?msg))");
-	folder_tree->subfolders = g_slist_append(folder_tree->subfolders,
-								parent);
-
-	child = create_folder("msg", "FILTER (!BOUND(?msg))");
-	parent->subfolders = g_slist_append(parent->subfolders, child);
-
-	parent = child;
-
-	child = create_folder("inbox", "?msg nmo:isSent \"false\" ; "
-				"nmo:isDeleted \"false\" ; "
-				"nmo:isDraft \"false\". ");
-	parent->subfolders = g_slist_append(parent->subfolders, child);
-
-	child = create_folder("sent", "?msg nmo:isDeleted \"false\" ; "
-				"nmo:isSent \"true\" . ");
-	parent->subfolders = g_slist_append(parent->subfolders, child);
-
-	child = create_folder("deleted", "?msg nmo:isDeleted \"true\" . ");
-	parent->subfolders = g_slist_append(parent->subfolders, child);
-}
-
-int messages_init(void)
-{
-	create_folder_tree();
-
-	return 0;
-}
-
-void messages_exit(void)
-{
-	destroy_folder_tree(folder_tree);
-}
-
-int messages_connect(void **s)
-{
-	struct session *session = g_new0(struct session, 1);
-
-	session->cwd = g_strdup("/");
-	session->folder = folder_tree;
-
-	*s = session;
-
-	return 0;
-}
-
-void messages_disconnect(void *s)
-{
-	struct session *session = s;
-
-	g_free(session->cwd);
-	g_free(session);
-}
-
-int messages_set_notification_registration(void *session,
-		void (*send_event)(void *session,
-			const struct messages_event *event, void *user_data),
-		void *user_data)
-{
-	return -ENOSYS;
-}
-
-int messages_set_folder(void *s, const char *name, gboolean cdup)
-{
-	struct session *session = s;
-	char *newrel = NULL;
-	char *newabs;
-	char *tmp;
-
-	if (name && (strchr(name, '/') || strcmp(name, "..") == 0))
-		return -EBADR;
-
-	if (cdup) {
-		if (session->cwd[0] == 0)
-			return -ENOENT;
-
-		newrel = g_path_get_dirname(session->cwd);
-
-		/* We use empty string for indication of the root directory */
-		if (newrel[0] == '.' && newrel[1] == 0)
-			newrel[0] = 0;
-	}
-
-	tmp = newrel;
-	if (!cdup && (!name || name[0] == 0))
-		newrel = g_strdup("");
-	else
-		newrel = g_build_filename(newrel ? newrel : session->cwd, name,
-									NULL);
-	g_free(tmp);
-
-	if (newrel[0] != '/')
-		newabs = g_build_filename("/", newrel, NULL);
-	else
-		newabs = g_strdup(newrel);
-
-	session->folder = get_folder(newabs);
-	if (session->folder == NULL) {
-		g_free(newrel);
-		g_free(newabs);
-
-		return -ENOENT;
-	}
-
-	g_free(newrel);
-	g_free(session->cwd);
-	session->cwd = newabs;
-
-	return 0;
-}
-
-static gboolean async_get_folder_listing(void *s)
-{
-	struct session *session = s;
-	gboolean count = FALSE;
-	int folder_count = 0;
-	char *path = NULL;
-	struct message_folder *folder;
-	GSList *dir;
-
-	if (session->name && strchr(session->name, '/') != NULL)
-		goto done;
-
-	path = g_build_filename(session->cwd, session->name, NULL);
-
-	if (path == NULL || strlen(path) == 0)
-		goto done;
-
-	folder = get_folder(path);
-
-	if (folder == NULL)
-		goto done;
-
-	if (session->max == 0) {
-		session->max = 0xffff;
-		session->offset = 0;
-		count = TRUE;
-	}
-
-	for (dir = folder->subfolders; dir &&
-				(folder_count - session->offset) < session->max;
-				folder_count++, dir = g_slist_next(dir)) {
-		struct message_folder *dir_data = dir->data;
-
-		if (count == FALSE && session->offset <= folder_count)
-			session->folder_list_cb(session, -EAGAIN, 0,
-					dir_data->name, session->user_data);
-	}
-
- done:
-	session->folder_list_cb(session, 0, folder_count, NULL,
-							session->user_data);
-
-	g_free(path);
-	g_free(session->name);
-
-	return FALSE;
-}
-
-int messages_get_folder_listing(void *s, const char *name,
-					uint16_t max, uint16_t offset,
-					messages_folder_listing_cb callback,
-					void *user_data)
-{
-	struct session *session = s;
-	session->name = g_strdup(name);
-	session->max = max;
-	session->offset = offset;
-	session->folder_list_cb = callback;
-	session->user_data = user_data;
-
-	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
-						session, NULL);
-
-	return 0;
-}
-
-int messages_get_messages_listing(void *session, const char *name,
-				uint16_t max, uint16_t offset,
-				uint8_t subject_len,
-				const struct messages_filter *filter,
-				messages_get_messages_listing_cb callback,
-				void *user_data)
-{
-	return -ENOSYS;
-}
-
-int messages_get_message(void *session, const char *handle,
-				unsigned long flags,
-				messages_get_message_cb callback,
-				void *user_data)
-{
-	return -ENOSYS;
-}
-
-int messages_update_inbox(void *session, messages_status_cb callback,
-							void *user_data)
-{
-	return -ENOSYS;
-}
-
-int messages_set_read(void *session, const char *handle, uint8_t value,
-				messages_status_cb callback, void *user_data)
-{
-	return -ENOSYS;
-}
-
-int messages_set_delete(void *session, const char *handle, uint8_t value,
-					messages_status_cb callback,
-					void *user_data)
-{
-	return -ENOSYS;
-}
-
-void messages_abort(void *session)
-{
-}
diff --git a/obexd/plugins/opp.c b/obexd/plugins/opp.c
index 8601613..2220efd 100644
--- a/obexd/plugins/opp.c
+++ b/obexd/plugins/opp.c
@@ -87,6 +87,11 @@ skip_auth:
 
 	err = obex_put_stream_start(os, path);
 
+	if (err == 0 && obex_get_size(os) != OBJECT_SIZE_DELETE &&
+				obex_get_size(os) != OBJECT_SIZE_UNKNOWN) {
+		manager_emit_transfer_property(user_data, "Size");
+	}
+
 	g_free(path);
 
 	if (err < 0)
@@ -155,7 +160,7 @@ static void opp_reset(struct obex_session *os, void *user_data)
 	manager_emit_transfer_completed(user_data);
 }
 
-static struct obex_service_driver driver = {
+static const struct obex_service_driver driver = {
 	.name = "Object Push server",
 	.service = OBEX_OPP,
 	.connect = opp_connect,
diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index ab52363..4175f9d 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
@@ -634,7 +634,7 @@ static int pbap_chkput(struct obex_session *os, void *user_data)
 	return -EBADR;
 }
 
-static struct obex_service_driver pbap = {
+static const struct obex_service_driver pbap = {
 	.name = "Phonebook Access server",
 	.service = OBEX_PBAP,
 	.target = PBAP_TARGET,
@@ -929,7 +929,7 @@ static ssize_t vobject_vcard_read(void *object, void *buf, size_t count)
 	return string_read(obj->buffer, buf, count);
 }
 
-static struct obex_mime_type_driver mime_pull = {
+static const struct obex_mime_type_driver mime_pull = {
 	.target = PBAP_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/phonebook",
@@ -939,7 +939,7 @@ static struct obex_mime_type_driver mime_pull = {
 	.get_next_header = vobject_pull_get_next_header,
 };
 
-static struct obex_mime_type_driver mime_list = {
+static const struct obex_mime_type_driver mime_list = {
 	.target = PBAP_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/vcard-listing",
@@ -949,7 +949,7 @@ static struct obex_mime_type_driver mime_list = {
 	.get_next_header = vobject_list_get_next_header,
 };
 
-static struct obex_mime_type_driver mime_vcard = {
+static const struct obex_mime_type_driver mime_vcard = {
 	.target = PBAP_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "x-bt/vcard",
diff --git a/obexd/plugins/pcsuite.c b/obexd/plugins/pcsuite.c
index f5a9d9a..07c444f 100644
--- a/obexd/plugins/pcsuite.c
+++ b/obexd/plugins/pcsuite.c
@@ -231,7 +231,7 @@ static void pcsuite_disconnect(struct obex_session *os, void *user_data)
 	g_free(pcsuite);
 }
 
-static struct obex_service_driver pcsuite = {
+static const struct obex_service_driver pcsuite = {
 	.name = "Nokia OBEX PC Suite Services",
 	.service = OBEX_PCSUITE,
 	.channel = PCSUITE_CHANNEL,
@@ -376,6 +376,7 @@ static void *backup_open(const char *name, int oflag, mode_t mode,
 	obj->error_code = 0;
 
 	if (send_backup_dbus_message("open", obj, size) == FALSE) {
+		g_free(obj->cmd);
 		g_free(obj);
 		obj = NULL;
 	}
@@ -467,7 +468,7 @@ static int backup_flush(void *object)
 	return 0;
 }
 
-static struct obex_mime_type_driver backup = {
+static const struct obex_mime_type_driver backup = {
 	.target = FTP_TARGET,
 	.target_size = TARGET_SIZE,
 	.mimetype = "application/vnd.nokia-backup",
diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c
index 29ec9d2..e509dd2 100644
--- a/obexd/plugins/phonebook-ebook.c
+++ b/obexd/plugins/phonebook-ebook.c
@@ -55,7 +55,7 @@ struct query_context {
 	gboolean canceled;
 };
 
-static char *attribute_mask[] = {
+static const char *attribute_mask[] = {
 /* 0 */		"VERSION",
 		"FN",
 		"N",
diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
deleted file mode 100644
index 88744f2..0000000
--- a/obexd/plugins/syncevolution.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2007-2010  Intel Corporation
- *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#include <glib.h>
-#include <dbus/dbus.h>
-
-#include "lib/bluetooth.h"
-
-#include "gdbus/gdbus.h"
-
-#include "btio/btio.h"
-#include "obexd/src/plugin.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/mimetype.h"
-#include "obexd/src/log.h"
-#include "obexd/src/manager.h"
-#include "obexd/src/obexd.h"
-#include "filesystem.h"
-
-#define SYNCML_TARGET_SIZE 11
-
-static const uint8_t SYNCML_TARGET[SYNCML_TARGET_SIZE] = {
-			0x53, 0x59, 0x4E, 0x43, 0x4D, 0x4C, 0x2D, 0x53,
-			0x59, 0x4E, 0x43 };
-
-#define SYNCEVOLUTION_CHANNEL  19
-
-#define SYNCEVOLUTION_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\
-<record>								\
- <attribute id=\"0x0001\">						\
-    <sequence>								\
-      <uuid value=\"00000002-0000-1000-8000-0002ee000002\"/>		\
-    </sequence>							\
- </attribute>								\
-									\
- <attribute id=\"0x0004\">						\
-    <sequence>								\
-      <sequence>							\
-        <uuid value=\"0x0100\"/>					\
-      </sequence>							\
-      <sequence>							\
-        <uuid value=\"0x0003\"/>					\
-        <uint8 value=\"%u\" name=\"channel\"/>				\
-      </sequence>							\
-      <sequence>							\
-        <uuid value=\"0x0008\"/>					\
-      </sequence>							\
-    </sequence>							\
- </attribute>								\
-									\
- <attribute id=\"0x0100\">						\
-    <text value=\"%s\" name=\"name\"/>					\
- </attribute>								\
-</record>"
-
-#define SYNCE_BUS_NAME	"org.syncevolution"
-#define SYNCE_PATH	"/org/syncevolution/Server"
-#define SYNCE_SERVER_INTERFACE	"org.syncevolution.Server"
-#define SYNCE_CONN_INTERFACE	"org.syncevolution.Connection"
-
-struct synce_context {
-	struct obex_session *os;
-	DBusConnection *dbus_conn;
-	char *conn_obj;
-	unsigned int reply_watch;
-	unsigned int abort_watch;
-	GString *buffer;
-	int lasterr;
-	char *id;
-};
-
-static void append_dict_entry(DBusMessageIter *dict, const char *key,
-							int type, void *val)
-{
-	DBusMessageIter entry;
-
-	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
-							NULL, &entry);
-	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &val);
-	dbus_message_iter_close_container(dict, &entry);
-}
-
-static gboolean reply_signal(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	struct synce_context *context = data;
-	const char *path = dbus_message_get_path(msg);
-	DBusMessageIter iter, array_iter;
-	char *value;
-	int length;
-
-	if (strcmp(context->conn_obj, path) != 0) {
-		obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-		context->lasterr = -EPERM;
-		return FALSE;
-	}
-
-	dbus_message_iter_init(msg, &iter);
-
-	dbus_message_iter_recurse(&iter, &array_iter);
-	dbus_message_iter_get_fixed_array(&array_iter, &value, &length);
-
-	context->buffer = g_string_new_len(value, length);
-	obex_object_set_io_flags(context, G_IO_IN, 0);
-	context->lasterr = 0;
-
-	return TRUE;
-}
-
-static gboolean abort_signal(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	struct synce_context *context = data;
-
-	obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-	context->lasterr = -EPERM;
-
-	return TRUE;
-}
-
-static void connect_cb(DBusPendingCall *call, void *user_data)
-{
-	struct synce_context *context = user_data;
-	DBusConnection *conn;
-	DBusMessage *reply;
-	DBusError err;
-	char *path;
-
-	conn = context->dbus_conn;
-
-	reply = dbus_pending_call_steal_reply(call);
-
-	dbus_error_init(&err);
-	if (dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, &path,
-						DBUS_TYPE_INVALID) == FALSE) {
-		error("%s", err.message);
-		dbus_error_free(&err);
-		goto failed;
-	}
-
-	DBG("Got conn object %s from syncevolution", path);
-	context->conn_obj = g_strdup(path);
-
-	context->reply_watch = g_dbus_add_signal_watch(conn, NULL, path,
-						SYNCE_CONN_INTERFACE, "Reply",
-						reply_signal, context, NULL);
-
-	context->abort_watch = g_dbus_add_signal_watch(conn, NULL, path,
-						SYNCE_CONN_INTERFACE, "Abort",
-						abort_signal, context, NULL);
-
-	dbus_message_unref(reply);
-
-	return;
-
-failed:
-	obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-	context->lasterr = -EPERM;
-}
-
-static void process_cb(DBusPendingCall *call, void *user_data)
-{
-	struct synce_context *context = user_data;
-	DBusMessage *reply;
-	DBusError derr;
-
-	reply = dbus_pending_call_steal_reply(call);
-	dbus_error_init(&derr);
-	if (dbus_set_error_from_message(&derr, reply)) {
-		error("process_cb(): syncevolution replied with an error:"
-					" %s, %s", derr.name, derr.message);
-		dbus_error_free(&derr);
-
-		obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-		context->lasterr = -EPERM;
-		goto done;
-	}
-
-	obex_object_set_io_flags(context, G_IO_OUT, 0);
-	context->lasterr = 0;
-
-done:
-	dbus_message_unref(reply);
-}
-
-static void *synce_connect(struct obex_session *os, int *err)
-{
-	DBusConnection *conn;
-	struct synce_context *context;
-	char *address;
-
-	manager_register_session(os);
-
-	conn = manager_dbus_get_connection();
-	if (!conn)
-		goto failed;
-
-	context = g_new0(struct synce_context, 1);
-	context->dbus_conn = conn;
-	context->lasterr = -EAGAIN;
-	context->os = os;
-
-	if (obex_getpeername(os, &address) == 0) {
-		context->id = g_strdup_printf("%s+%d", address,
-							SYNCEVOLUTION_CHANNEL);
-		g_free(address);
-	}
-
-	if (err)
-		*err = 0;
-
-	return context;
-
-failed:
-	if (err)
-		*err = -EPERM;
-
-	return NULL;
-}
-
-static int synce_put(struct obex_session *os, void *user_data)
-{
-	return 0;
-}
-
-static int synce_get(struct obex_session *os, void *user_data)
-{
-	return obex_get_stream_start(os, NULL);
-}
-
-static void close_cb(DBusPendingCall *call, void *user_data)
-{
-	DBusMessage *reply;
-	DBusError derr;
-
-	reply = dbus_pending_call_steal_reply(call);
-	dbus_error_init(&derr);
-	if (dbus_set_error_from_message(&derr, reply)) {
-		error("close_cb(): syncevolution replied with an error:"
-					" %s, %s", derr.name, derr.message);
-		dbus_error_free(&derr);
-	}
-
-	dbus_message_unref(reply);
-}
-
-static void synce_disconnect(struct obex_session *os, void *user_data)
-{
-	struct synce_context *context = user_data;
-
-	g_free(context);
-}
-
-static void *synce_open(const char *name, int oflag, mode_t mode,
-				void *user_data, size_t *size, int *err)
-{
-	struct synce_context *context = user_data;
-
-	if (err)
-		*err = context ? 0 : -EFAULT;
-
-	return user_data;
-}
-
-static int synce_close(void *object)
-{
-	struct synce_context *context = object;
-	DBusMessage *msg;
-	const char *error;
-	gboolean normal;
-	DBusPendingCall *call;
-
-	if (!context->conn_obj)
-		goto done;
-
-	msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
-						SYNCE_CONN_INTERFACE, "Close");
-	if (!msg)
-		goto failed;
-
-	normal = TRUE;
-	error = "none";
-	dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &normal,
-				DBUS_TYPE_STRING, &error, DBUS_TYPE_INVALID);
-
-	g_dbus_send_message_with_reply(context->dbus_conn, msg, &call, -1);
-	dbus_pending_call_set_notify(call, close_cb, NULL, NULL);
-	dbus_message_unref(msg);
-	dbus_pending_call_unref(call);
-
-failed:
-	g_dbus_remove_watch(context->dbus_conn, context->reply_watch);
-	context->reply_watch = 0;
-	g_dbus_remove_watch(context->dbus_conn, context->abort_watch);
-	context->abort_watch = 0;
-
-	g_free(context->conn_obj);
-	context->conn_obj = NULL;
-
-done:
-	dbus_connection_unref(context->dbus_conn);
-	g_free(context);
-	return 0;
-}
-
-static ssize_t synce_read(void *object, void *buf, size_t count)
-{
-	struct synce_context *context = object;
-	DBusConnection *conn;
-	char transport[36], transport_description[24];
-	const char *session;
-	DBusMessage *msg;
-	DBusMessageIter iter, dict;
-	gboolean authenticate;
-	DBusPendingCall *call;
-
-	if (context->buffer)
-		return string_read(context->buffer, buf, count);
-
-	conn = manager_dbus_get_connection();
-	if (conn == NULL)
-		return -EPERM;
-
-	msg = dbus_message_new_method_call(SYNCE_BUS_NAME, SYNCE_PATH,
-				SYNCE_SERVER_INTERFACE, "Connect");
-	if (!msg)
-		return -EPERM;
-
-	dbus_message_iter_init_append(msg, &iter);
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-		DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-		DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
-		DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	append_dict_entry(&dict, "id", DBUS_TYPE_STRING, context->id);
-
-	snprintf(transport, sizeof(transport), "%s.obexd", OBEXD_SERVICE);
-	append_dict_entry(&dict, "transport", DBUS_TYPE_STRING, transport);
-
-	snprintf(transport_description, sizeof(transport_description),
-						"version %s", VERSION);
-	append_dict_entry(&dict, "transport_description", DBUS_TYPE_STRING,
-							transport_description);
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	authenticate = FALSE;
-	session = "";
-	dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &authenticate,
-			DBUS_TYPE_STRING, &session, DBUS_TYPE_INVALID);
-
-	if (!g_dbus_send_message_with_reply(conn, msg, &call, -1)) {
-		error("D-Bus call to %s failed.", SYNCE_SERVER_INTERFACE);
-		dbus_message_unref(msg);
-		return -EPERM;
-	}
-
-	dbus_pending_call_set_notify(call, connect_cb, context, NULL);
-
-	dbus_pending_call_unref(call);
-	dbus_message_unref(msg);
-
-	return -EAGAIN;
-}
-
-static ssize_t synce_write(void *object, const void *buf, size_t count)
-{
-	struct synce_context *context = object;
-	DBusMessage *msg;
-	DBusMessageIter iter, array_iter;
-	DBusPendingCall *call;
-	const char *type = obex_get_type(context->os);
-
-	if (context->lasterr == 0)
-		return count;
-
-	if (!context->conn_obj)
-		return -EFAULT;
-
-	msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
-					SYNCE_CONN_INTERFACE, "Process");
-	if (!msg)
-		return -EFAULT;
-
-	dbus_message_iter_init_append(msg, &iter);
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-				DBUS_TYPE_BYTE_AS_STRING, &array_iter);
-
-	dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
-						&buf, count);
-	dbus_message_iter_close_container(&iter, &array_iter);
-
-	dbus_message_append_args(msg, DBUS_TYPE_STRING, &type,
-						DBUS_TYPE_INVALID);
-
-	if (!g_dbus_send_message_with_reply(context->dbus_conn, msg,
-								&call, -1)) {
-		error("D-Bus call to %s failed.", SYNCE_CONN_INTERFACE);
-		dbus_message_unref(msg);
-		return -EPERM;
-	}
-
-	dbus_pending_call_set_notify(call, process_cb, context, NULL);
-
-	dbus_message_unref(msg);
-	dbus_pending_call_unref(call);
-
-	return -EAGAIN;
-}
-
-static struct obex_mime_type_driver synce_driver = {
-	.target = SYNCML_TARGET,
-	.target_size = SYNCML_TARGET_SIZE,
-	.open = synce_open,
-	.close = synce_close,
-	.read = synce_read,
-	.write = synce_write,
-};
-
-static struct obex_service_driver synce = {
-	.name = "OBEX server for SyncML, using SyncEvolution",
-	.service = OBEX_SYNCEVOLUTION,
-	.channel = SYNCEVOLUTION_CHANNEL,
-	.secure = TRUE,
-	.record = SYNCEVOLUTION_RECORD,
-	.target = SYNCML_TARGET,
-	.target_size = SYNCML_TARGET_SIZE,
-	.get = synce_get,
-	.put = synce_put,
-	.connect = synce_connect,
-	.disconnect = synce_disconnect,
-};
-
-static int synce_init(void)
-{
-	int err;
-
-	err = obex_mime_type_driver_register(&synce_driver);
-	if (err < 0)
-		return err;
-
-	return obex_service_driver_register(&synce);
-}
-
-static void synce_exit(void)
-{
-	obex_service_driver_unregister(&synce);
-	obex_mime_type_driver_unregister(&synce_driver);
-}
-
-OBEX_PLUGIN_DEFINE(syncevolution, synce_init, synce_exit)
diff --git a/obexd/src/genbuiltin b/obexd/src/genbuiltin
index 39f7735..e60b518 100755
--- a/obexd/src/genbuiltin
+++ b/obexd/src/genbuiltin
@@ -2,11 +2,11 @@
 
 for i in $*
 do
-	echo "extern struct obex_plugin_desc __obex_builtin_$i;"
+	echo "extern const struct obex_plugin_desc __obex_builtin_$i;"
 done
 
 echo
-echo "static struct obex_plugin_desc *__obex_builtin[] = {"
+echo "static const struct obex_plugin_desc *__obex_builtin[] = {"
 
 for i in $*
 do
diff --git a/obexd/src/main.c b/obexd/src/main.c
index d950883..151574a 100644
--- a/obexd/src/main.c
+++ b/obexd/src/main.c
@@ -138,7 +138,7 @@ static gboolean parse_debug(const char *key, const char *value,
 	return TRUE;
 }
 
-static GOptionEntry options[] = {
+static const GOptionEntry options[] = {
 	{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
 				G_OPTION_ARG_CALLBACK, parse_debug,
 				"Enable debug information output", "DEBUG" },
diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index 01741fe..3c0c2a7 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -38,6 +38,7 @@
 #define TRANSFER_INTERFACE OBEXD_SERVICE ".Transfer1"
 #define SESSION_INTERFACE OBEXD_SERVICE ".Session1"
 #define AGENT_INTERFACE OBEXD_SERVICE ".Agent1"
+#define OBEX_ERROR_REJECT      "org.bluez.obex.Error.Rejected"
 
 #define TIMEOUT 60*1000 /* Timeout for user response (miliseconds) */
 
@@ -45,6 +46,7 @@ struct agent {
 	char *bus_name;
 	char *path;
 	gboolean auth_pending;
+	gboolean auth_reject;
 	char *new_name;
 	char *new_folder;
 	unsigned int watch_id;
@@ -523,11 +525,16 @@ void manager_cleanup(void)
 void manager_emit_transfer_property(struct obex_transfer *transfer,
 								char *name)
 {
-	if (!transfer->path)
+	if (transfer->path == NULL)
 		return;
 
-	g_dbus_emit_property_changed(connection, transfer->path,
-					TRANSFER_INTERFACE, name);
+	if (strcasecmp("Size", name) == 0)
+		g_dbus_emit_property_changed_full(connection, transfer->path,
+					TRANSFER_INTERFACE, name,
+					G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH);
+	else
+		g_dbus_emit_property_changed(connection, transfer->path,
+						TRANSFER_INTERFACE, name);
 }
 
 void manager_emit_transfer_started(struct obex_transfer *transfer)
@@ -540,9 +547,6 @@ void manager_emit_transfer_started(struct obex_transfer *transfer)
 static void emit_transfer_completed(struct obex_transfer *transfer,
 							gboolean success)
 {
-	if (transfer->path == NULL)
-		return;
-
 	transfer->status = success ? TRANSFER_STATUS_COMPLETE :
 						TRANSFER_STATUS_ERROR;
 
@@ -630,6 +634,8 @@ static void agent_reply(DBusPendingCall *call, void *user_data)
 
 		if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
 			agent_cancel();
+		else if (dbus_error_has_name(&derr, OBEX_ERROR_REJECT))
+			agent->auth_reject = TRUE;
 
 		dbus_error_free(&derr);
 		dbus_message_unref(reply);
@@ -646,7 +652,10 @@ static void agent_reply(DBusPendingCall *call, void *user_data)
 			agent->new_name = g_strdup(name);
 			agent->new_folder = NULL;
 		} else {
-			agent->new_name = g_strdup(slash + 1);
+			if (strlen(slash) == 1)
+				agent->new_name = NULL;
+			else
+				agent->new_name = g_strdup(slash + 1);
 			agent->new_folder = g_strndup(name, slash - name);
 		}
 	}
@@ -694,6 +703,7 @@ int manager_request_authorization(struct obex_transfer *transfer,
 	dbus_message_unref(msg);
 
 	agent->auth_pending = TRUE;
+	agent->auth_reject  = FALSE;
 	got_reply = FALSE;
 
 	/* Catches errors before authorization response comes */
@@ -716,7 +726,7 @@ int manager_request_authorization(struct obex_transfer *transfer,
 
 	dbus_pending_call_unref(call);
 
-	if (!agent || !agent->new_name)
+	if (!agent || agent->auth_reject)
 		return -EPERM;
 
 	*new_folder = agent->new_folder;
diff --git a/obexd/src/mimetype.c b/obexd/src/mimetype.c
index 212f24b..066a71e 100644
--- a/obexd/src/mimetype.c
+++ b/obexd/src/mimetype.c
@@ -73,7 +73,7 @@ static struct io_watch *find_io_watch(void *object)
 	return NULL;
 }
 
-static void reset_io_watch(void *object)
+void obex_object_reset_io_watch(void *object)
 {
 	struct io_watch *watch;
 
@@ -85,16 +85,11 @@ static void reset_io_watch(void *object)
 	g_free(watch);
 }
 
-static int set_io_watch(void *object, obex_object_io_func func,
+int obex_object_set_io_watch(void *object, obex_object_io_func func,
 				void *user_data)
 {
 	struct io_watch *watch;
 
-	if (func == NULL) {
-		reset_io_watch(object);
-		return 0;
-	}
-
 	watch = find_io_watch(object);
 	if (watch)
 		return -EPERM;
@@ -109,7 +104,7 @@ static int set_io_watch(void *object, obex_object_io_func func,
 	return 0;
 }
 
-static struct obex_mime_type_driver *find_driver(const uint8_t *target,
+static const struct obex_mime_type_driver *find_driver(const uint8_t *target,
 				unsigned int target_size,
 				const char *mimetype, const uint8_t *who,
 				unsigned int who_size)
@@ -117,7 +112,7 @@ static struct obex_mime_type_driver *find_driver(const uint8_t *target,
 	GSList *l;
 
 	for (l = drivers; l; l = l->next) {
-		struct obex_mime_type_driver *driver = l->data;
+		const struct obex_mime_type_driver *driver = l->data;
 
 		if (memncmp0(target, target_size, driver->target, driver->target_size))
 			continue;
@@ -139,12 +134,12 @@ static struct obex_mime_type_driver *find_driver(const uint8_t *target,
 	return NULL;
 }
 
-struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target,
-				unsigned int target_size,
+const struct obex_mime_type_driver *
+obex_mime_type_driver_find(const uint8_t *target, unsigned int target_size,
 				const char *mimetype, const uint8_t *who,
 				unsigned int who_size)
 {
-	struct obex_mime_type_driver *driver;
+	const struct obex_mime_type_driver *driver;
 
 	driver = find_driver(target, target_size, mimetype, who, who_size);
 	if (driver == NULL) {
@@ -167,7 +162,7 @@ struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target,
 	return driver;
 }
 
-int obex_mime_type_driver_register(struct obex_mime_type_driver *driver)
+int obex_mime_type_driver_register(const struct obex_mime_type_driver *driver)
 {
 	if (!driver) {
 		error("Invalid driver");
@@ -181,17 +176,15 @@ int obex_mime_type_driver_register(struct obex_mime_type_driver *driver)
 		return -EPERM;
 	}
 
-	if (driver->set_io_watch == NULL)
-		driver->set_io_watch = set_io_watch;
-
 	DBG("driver %p mimetype %s registered", driver, driver->mimetype);
 
-	drivers = g_slist_append(drivers, driver);
+	drivers = g_slist_append(drivers, (gpointer)driver);
 
 	return 0;
 }
 
-void obex_mime_type_driver_unregister(struct obex_mime_type_driver *driver)
+void
+obex_mime_type_driver_unregister(const struct obex_mime_type_driver *driver)
 {
 	if (!g_slist_find(drivers, driver)) {
 		error("Unable to unregister: No such driver %p", driver);
diff --git a/obexd/src/mimetype.h b/obexd/src/mimetype.h
index e1c14f4..d948e2c 100644
--- a/obexd/src/mimetype.h
+++ b/obexd/src/mimetype.h
@@ -28,15 +28,19 @@ struct obex_mime_type_driver {
 	int (*copy) (const char *name, const char *destname);
 	int (*move) (const char *name, const char *destname);
 	int (*remove) (const char *name);
-	int (*set_io_watch) (void *object, obex_object_io_func func,
-				void *user_data);
 };
 
-int obex_mime_type_driver_register(struct obex_mime_type_driver *driver);
-void obex_mime_type_driver_unregister(struct obex_mime_type_driver *driver);
-struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target,
+int obex_mime_type_driver_register(const struct obex_mime_type_driver *driver);
+void
+obex_mime_type_driver_unregister(const struct obex_mime_type_driver *driver);
+const struct obex_mime_type_driver *
+obex_mime_type_driver_find(const uint8_t *target,
 				unsigned int target_size,
 				const char *mimetype, const uint8_t *who,
 				unsigned int who_size);
 
 void obex_object_set_io_flags(void *object, int flags, int err);
+
+void obex_object_reset_io_watch(void *object);
+int obex_object_set_io_watch(void *object, obex_object_io_func func,
+				void *user_data);
diff --git a/obexd/src/obex-priv.h b/obexd/src/obex-priv.h
index db409e7..d2c62a5 100644
--- a/obexd/src/obex-priv.h
+++ b/obexd/src/obex-priv.h
@@ -33,12 +33,12 @@ struct obex_session {
 	void *object;
 	gboolean aborted;
 	int err;
-	struct obex_service_driver *service;
+	const struct obex_service_driver *service;
 	void *service_data;
 	struct obex_server *server;
 	gboolean checked;
 	GObex *obex;
-	struct obex_mime_type_driver *driver;
+	const struct obex_mime_type_driver *driver;
 	gboolean headers_sent;
 };
 
diff --git a/obexd/src/obex.c b/obexd/src/obex.c
index 3a68fd6..370bfac 100644
--- a/obexd/src/obex.c
+++ b/obexd/src/obex.c
@@ -55,7 +55,7 @@ struct auth_header {
 } __attribute__ ((packed));
 
 /* Possible commands */
-static struct {
+static const struct {
 	int cmd;
 	const char *name;
 } obex_command[] = {
@@ -119,7 +119,7 @@ static void os_reset_session(struct obex_session *os)
 	os_session_mark_aborted(os);
 
 	if (os->object) {
-		os->driver->set_io_watch(os->object, NULL, NULL);
+		obex_object_reset_io_watch(os->object);
 		os->driver->close(os->object);
 		if (os->aborted && os->cmd == G_OBEX_OP_PUT && os->path &&
 				os->driver->remove)
@@ -357,7 +357,7 @@ static gssize driver_read(struct obex_session *os, void *buf, gsize size)
 		if (len == -ENOSTR)
 			return 0;
 		if (len == -EAGAIN)
-			os->driver->set_io_watch(os->object, handle_async_io,
+			obex_object_set_io_watch(os->object, handle_async_io,
 									os);
 	}
 
@@ -395,7 +395,7 @@ static void transfer_complete(GObex *obex, GError *err, gpointer user_data)
 	if (os->object && os->driver && os->driver->flush) {
 		if (os->driver->flush(os->object) == -EAGAIN) {
 			g_obex_suspend(os->obex);
-			os->driver->set_io_watch(os->object, handle_async_io,
+			obex_object_set_io_watch(os->object, handle_async_io,
 									os);
 			return;
 		}
@@ -525,7 +525,7 @@ static gboolean recv_data(const void *buf, gsize size, gpointer user_data)
 
 	if (ret == -EAGAIN) {
 		g_obex_suspend(os->obex);
-		os->driver->set_io_watch(os->object, handle_async_io, os);
+		obex_object_set_io_watch(os->object, handle_async_io, os);
 		return TRUE;
 	}
 
@@ -699,7 +699,7 @@ int obex_get_stream_start(struct obex_session *os, const char *filename)
 		return err;
 
 	g_obex_suspend(os->obex);
-	os->driver->set_io_watch(os->object, handle_async_io, os);
+	obex_object_set_io_watch(os->object, handle_async_io, os);
 	return 0;
 }
 
@@ -716,9 +716,6 @@ int obex_put_stream_start(struct obex_session *os, const char *filename)
 		return err;
 	}
 
-	if (os->size != OBJECT_SIZE_DELETE && os->size != OBJECT_SIZE_UNKNOWN)
-		manager_emit_transfer_property(os->service_data, "Size");
-
 	os->path = g_strdup(filename);
 
 	return 0;
@@ -772,7 +769,7 @@ static gboolean check_put(GObex *obex, GObexPacket *req, void *user_data)
 		break;
 	case -EAGAIN:
 		g_obex_suspend(os->obex);
-		os->driver->set_io_watch(os->object, handle_async_io, os);
+		obex_object_set_io_watch(os->object, handle_async_io, os);
 		return TRUE;
 	default:
 		os_set_response(os, ret);
@@ -1085,7 +1082,7 @@ ssize_t obex_get_non_header_data(struct obex_session *os,
 
 int obex_getpeername(struct obex_session *os, char **name)
 {
-	struct obex_transport_driver *transport = os->server->transport;
+	const struct obex_transport_driver *transport = os->server->transport;
 
 	if (transport == NULL || transport->getpeername == NULL)
 		return -ENOTSUP;
@@ -1095,7 +1092,7 @@ int obex_getpeername(struct obex_session *os, char **name)
 
 int obex_getsockname(struct obex_session *os, char **name)
 {
-	struct obex_transport_driver *transport = os->server->transport;
+	const struct obex_transport_driver *transport = os->server->transport;
 
 	if (transport == NULL || transport->getsockname == NULL)
 		return -ENOTSUP;
diff --git a/obexd/src/obex.service.in b/obexd/src/obex.service.in
index fc0dce9..cf4d8c9 100644
--- a/obexd/src/obex.service.in
+++ b/obexd/src/obex.service.in
@@ -4,7 +4,7 @@ Description=Bluetooth OBEX service
 [Service]
 Type=dbus
 BusName=org.bluez.obex
-ExecStart=@pkglibexecdir@/obexd
+ExecStart=@PKGLIBEXECDIR@/obexd
 
 [Install]
 Alias=dbus-org.bluez.obex.service
diff --git a/obexd/src/obexd.h b/obexd/src/obexd.h
index fe312a6..af5265d 100644
--- a/obexd/src/obexd.h
+++ b/obexd/src/obexd.h
@@ -18,7 +18,7 @@
 #define OBEX_MAS	(1 << 8)
 #define OBEX_MNS	(1 << 9)
 
-gboolean plugin_init(const char *pattern, const char *exclude);
+void plugin_init(const char *pattern, const char *exclude);
 void plugin_cleanup(void);
 
 gboolean manager_init(void);
diff --git a/obexd/src/org.bluez.obex.service b/obexd/src/org.bluez.obex.service.in
similarity index 74%
rename from obexd/src/org.bluez.obex.service
rename to obexd/src/org.bluez.obex.service.in
index a538088..873b9d1 100644
--- a/obexd/src/org.bluez.obex.service
+++ b/obexd/src/org.bluez.obex.service.in
@@ -1,4 +1,4 @@
 [D-BUS Service]
 Name=org.bluez.obex
-Exec=/bin/false
+Exec=@PKGLIBEXECDIR@/obexd
 SystemdService=dbus-org.bluez.obex.service
diff --git a/obexd/src/plugin.c b/obexd/src/plugin.c
index 0df9d52..1432778 100644
--- a/obexd/src/plugin.c
+++ b/obexd/src/plugin.c
@@ -34,14 +34,17 @@
 #define PLUGINFLAG (RTLD_NOW)
 #endif
 
+#define IS_ENABLED(x) (x)
+
 static GSList *plugins = NULL;
 
 struct obex_plugin {
 	void *handle;
-	struct obex_plugin_desc *desc;
+	const struct obex_plugin_desc *desc;
 };
 
-static gboolean add_plugin(void *handle, struct obex_plugin_desc *desc)
+static gboolean add_external_plugin(void *handle,
+					const struct obex_plugin_desc *desc)
 {
 	struct obex_plugin *plugin;
 
@@ -66,7 +69,26 @@ static gboolean add_plugin(void *handle, struct obex_plugin_desc *desc)
 	return TRUE;
 }
 
-static gboolean check_plugin(struct obex_plugin_desc *desc,
+static void add_plugin(const struct obex_plugin_desc *desc)
+{
+	struct obex_plugin *plugin;
+
+	plugin = g_try_new0(struct obex_plugin, 1);
+	if (plugin == NULL)
+		return;
+
+	plugin->desc = desc;
+
+	if (desc->init() < 0) {
+		g_free(plugin);
+		return;
+	}
+
+	plugins = g_slist_append(plugins, plugin);
+	DBG("Plugin %s loaded", desc->name);
+}
+
+static gboolean check_plugin(const struct obex_plugin_desc *desc,
 				char **patterns, char **excludes)
 {
 	if (excludes) {
@@ -93,46 +115,26 @@ static gboolean check_plugin(struct obex_plugin_desc *desc,
 }
 
 
-#include "builtin.h"
-
-gboolean plugin_init(const char *pattern, const char *exclude)
+static void external_plugin_init(char **patterns, char **excludes)
 {
-	char **patterns = NULL;
-	char **excludes = NULL;
 	GDir *dir;
 	const char *file;
-	unsigned int i;
 
-	if (strlen(PLUGINDIR) == 0)
-		return FALSE;
+	info("Using external plugins is not officially supported.\n");
+	info("Consider upstreaming your plugins into the BlueZ project.");
 
-	if (pattern)
-		patterns = g_strsplit_set(pattern, ":, ", -1);
-
-	if (exclude)
-		excludes = g_strsplit_set(exclude, ":, ", -1);
-
-	DBG("Loading builtin plugins");
-
-	for (i = 0; __obex_builtin[i]; i++) {
-		if (check_plugin(__obex_builtin[i],
-					patterns, excludes) == FALSE)
-			continue;
-
-		add_plugin(NULL,  __obex_builtin[i]);
-	}
+	if (strlen(PLUGINDIR) == 0)
+		return;
 
 	DBG("Loading plugins %s", PLUGINDIR);
 
 	dir = g_dir_open(PLUGINDIR, 0, NULL);
 	if (!dir) {
-		g_strfreev(patterns);
-		g_strfreev(excludes);
-		return FALSE;
+		return;
 	}
 
 	while ((file = g_dir_read_name(dir)) != NULL) {
-		struct obex_plugin_desc *desc;
+		const struct obex_plugin_desc *desc;
 		void *handle;
 		char *filename;
 
@@ -164,15 +166,42 @@ gboolean plugin_init(const char *pattern, const char *exclude)
 			continue;
 		}
 
-		if (add_plugin(handle, desc) == FALSE)
+		if (add_external_plugin(handle, desc) == FALSE)
 			dlclose(handle);
 	}
 
 	g_dir_close(dir);
+}
+
+#include "builtin.h"
+
+void plugin_init(const char *pattern, const char *exclude)
+{
+	char **patterns = NULL;
+	char **excludes = NULL;
+	unsigned int i;
+
+	if (pattern)
+		patterns = g_strsplit_set(pattern, ":, ", -1);
+
+	if (exclude)
+		excludes = g_strsplit_set(exclude, ":, ", -1);
+
+	DBG("Loading builtin plugins");
+
+	for (i = 0; __obex_builtin[i]; i++) {
+		if (check_plugin(__obex_builtin[i],
+					patterns, excludes) == FALSE)
+			continue;
+
+		add_plugin(__obex_builtin[i]);
+	}
+
+	if IS_ENABLED(EXTERNAL_PLUGINS)
+		external_plugin_init(patterns, excludes);
+
 	g_strfreev(patterns);
 	g_strfreev(excludes);
-
-	return TRUE;
 }
 
 void plugin_cleanup(void)
diff --git a/obexd/src/plugin.h b/obexd/src/plugin.h
index 7038784..e1756b9 100644
--- a/obexd/src/plugin.h
+++ b/obexd/src/plugin.h
@@ -16,14 +16,18 @@ struct obex_plugin_desc {
 
 #ifdef OBEX_PLUGIN_BUILTIN
 #define OBEX_PLUGIN_DEFINE(name, init, exit) \
-		struct obex_plugin_desc __obex_builtin_ ## name = { \
+		const struct obex_plugin_desc __obex_builtin_ ## name = { \
 			#name, init, exit \
 		};
 #else
+#if EXTERNAL_PLUGINS
 #define OBEX_PLUGIN_DEFINE(name,init,exit) \
 		extern struct obex_plugin_desc obex_plugin_desc \
 				__attribute__ ((visibility("default"))); \
-		struct obex_plugin_desc obex_plugin_desc = { \
+		const struct obex_plugin_desc obex_plugin_desc = { \
 			#name, init, exit \
 		};
+#else
+#error "Requested non built-in plugin, while external plugins is disabled"
+#endif
 #endif
diff --git a/obexd/src/server.c b/obexd/src/server.c
index a8fc450..0dca728 100644
--- a/obexd/src/server.c
+++ b/obexd/src/server.c
@@ -34,12 +34,12 @@
 
 static GSList *servers = NULL;
 
-static void init_server(uint16_t service, GSList *transports)
+static void init_server(uint16_t service, const GSList *transports)
 {
-	GSList *l;
+	const GSList *l;
 
 	for (l = transports; l; l = l->next) {
-		struct obex_transport_driver *transport = l->data;
+		const struct obex_transport_driver *transport = l->data;
 		struct obex_server *server;
 		int err;
 
@@ -66,7 +66,7 @@ static void init_server(uint16_t service, GSList *transports)
 int obex_server_init(void)
 {
 	GSList *drivers;
-	GSList *transports;
+	const GSList *transports;
 	GSList *l;
 
 	drivers = obex_service_driver_list(0);
@@ -82,7 +82,7 @@ int obex_server_init(void)
 	}
 
 	for (l = drivers; l; l = l->next) {
-		struct obex_service_driver *driver = l->data;
+		const struct obex_service_driver *driver = l->data;
 
 		init_server(driver->service, transports);
 	}
diff --git a/obexd/src/server.h b/obexd/src/server.h
index c31236e..ec063ae 100644
--- a/obexd/src/server.h
+++ b/obexd/src/server.h
@@ -10,7 +10,7 @@
  */
 
 struct obex_server {
-	struct obex_transport_driver *transport;
+	const struct obex_transport_driver *transport;
 	void *transport_data;
 	GSList *drivers;
 };
diff --git a/obexd/src/service.c b/obexd/src/service.c
index 0f4e420..332d619 100644
--- a/obexd/src/service.c
+++ b/obexd/src/service.c
@@ -26,14 +26,14 @@
 
 static GSList *drivers = NULL;
 
-struct obex_service_driver *obex_service_driver_find(GSList *drivers,
+const struct obex_service_driver *obex_service_driver_find(GSList *drivers,
 			const uint8_t *target, unsigned int target_size,
 			const uint8_t *who, unsigned int who_size)
 {
 	GSList *l;
 
 	for (l = drivers; l; l = l->next) {
-		struct obex_service_driver *driver = l->data;
+		const struct obex_service_driver *driver = l->data;
 
 		/* who is optional, so only check for it if not NULL */
 		if (who != NULL && memncmp0(who, who_size, driver->who,
@@ -57,10 +57,10 @@ GSList *obex_service_driver_list(uint16_t services)
 		return drivers;
 
 	for (l = drivers; l && services; l = l->next) {
-		struct obex_service_driver *driver = l->data;
+		const struct obex_service_driver *driver = l->data;
 
 		if (driver->service & services) {
-			list = g_slist_append(list, driver);
+			list = g_slist_append(list, (gpointer)driver);
 			services &= ~driver->service;
 		}
 	}
@@ -68,12 +68,12 @@ GSList *obex_service_driver_list(uint16_t services)
 	return list;
 }
 
-static struct obex_service_driver *find_driver(uint16_t service)
+static const struct obex_service_driver *find_driver(uint16_t service)
 {
 	GSList *l;
 
 	for (l = drivers; l; l = l->next) {
-		struct obex_service_driver *driver = l->data;
+		const struct obex_service_driver *driver = l->data;
 
 		if (driver->service == service)
 			return driver;
@@ -82,7 +82,7 @@ static struct obex_service_driver *find_driver(uint16_t service)
 	return NULL;
 }
 
-int obex_service_driver_register(struct obex_service_driver *driver)
+int obex_service_driver_register(const struct obex_service_driver *driver)
 {
 	if (!driver) {
 		error("Invalid driver");
@@ -99,14 +99,14 @@ int obex_service_driver_register(struct obex_service_driver *driver)
 
 	/* Drivers that support who has priority */
 	if (driver->who)
-		drivers = g_slist_prepend(drivers, driver);
+		drivers = g_slist_prepend(drivers, (gpointer)driver);
 	else
-		drivers = g_slist_append(drivers, driver);
+		drivers = g_slist_append(drivers, (gpointer)driver);
 
 	return 0;
 }
 
-void obex_service_driver_unregister(struct obex_service_driver *driver)
+void obex_service_driver_unregister(const struct obex_service_driver *driver)
 {
 	if (!g_slist_find(drivers, driver)) {
 		error("Unable to unregister: No such driver %p", driver);
diff --git a/obexd/src/service.h b/obexd/src/service.h
index e3aee3b..8d9f705 100644
--- a/obexd/src/service.h
+++ b/obexd/src/service.h
@@ -32,9 +32,9 @@ struct obex_service_driver {
 	void (*reset) (struct obex_session *os, void *user_data);
 };
 
-int obex_service_driver_register(struct obex_service_driver *driver);
-void obex_service_driver_unregister(struct obex_service_driver *driver);
+int obex_service_driver_register(const struct obex_service_driver *driver);
+void obex_service_driver_unregister(const struct obex_service_driver *driver);
 GSList *obex_service_driver_list(uint16_t services);
-struct obex_service_driver *obex_service_driver_find(GSList *drivers,
+const struct obex_service_driver *obex_service_driver_find(GSList *drivers,
 			const uint8_t *target, unsigned int target_size,
 			const uint8_t *who, unsigned int who_size);
diff --git a/obexd/src/transport.c b/obexd/src/transport.c
index 4b5895e..527d9ff 100644
--- a/obexd/src/transport.c
+++ b/obexd/src/transport.c
@@ -27,13 +27,13 @@
 
 static GSList *drivers = NULL;
 
-static struct obex_transport_driver *obex_transport_driver_find(
-							const char *name)
+static const struct obex_transport_driver *
+obex_transport_driver_find(const char *name)
 {
-	GSList *l;
+	const GSList *l;
 
 	for (l = drivers; l; l = l->next) {
-		struct obex_transport_driver *driver = l->data;
+		const struct obex_transport_driver *driver = l->data;
 
 		if (g_strcmp0(name, driver->name) == 0)
 			return driver;
@@ -42,12 +42,12 @@ static struct obex_transport_driver *obex_transport_driver_find(
 	return NULL;
 }
 
-GSList *obex_transport_driver_list(void)
+const GSList *obex_transport_driver_list(void)
 {
 	return drivers;
 }
 
-int obex_transport_driver_register(struct obex_transport_driver *driver)
+int obex_transport_driver_register(const struct obex_transport_driver *driver)
 {
 	if (!driver) {
 		error("Invalid driver");
@@ -62,12 +62,13 @@ int obex_transport_driver_register(struct obex_transport_driver *driver)
 
 	DBG("driver %p transport %s registered", driver, driver->name);
 
-	drivers = g_slist_prepend(drivers, driver);
+	drivers = g_slist_prepend(drivers, (gpointer)driver);
 
 	return 0;
 }
 
-void obex_transport_driver_unregister(struct obex_transport_driver *driver)
+void
+obex_transport_driver_unregister(const struct obex_transport_driver *driver)
 {
 	if (!g_slist_find(drivers, driver)) {
 		error("Unable to unregister: No such driver %p", driver);
diff --git a/obexd/src/transport.h b/obexd/src/transport.h
index 3a16b76..322d8f5 100644
--- a/obexd/src/transport.h
+++ b/obexd/src/transport.h
@@ -17,6 +17,7 @@ struct obex_transport_driver {
 	void (*stop) (void *data);
 };
 
-int obex_transport_driver_register(struct obex_transport_driver *driver);
-void obex_transport_driver_unregister(struct obex_transport_driver *driver);
-GSList *obex_transport_driver_list(void);
+int obex_transport_driver_register(const struct obex_transport_driver *driver);
+void
+obex_transport_driver_unregister(const struct obex_transport_driver *driver);
+const GSList *obex_transport_driver_list(void);
diff --git a/peripheral/efivars.c b/peripheral/efivars.c
index 987572b..d4e724e 100644
--- a/peripheral/efivars.c
+++ b/peripheral/efivars.c
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <limits.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/param.h>
diff --git a/plugins/admin.c b/plugins/admin.c
index 0787e83..16b74cf 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -502,7 +502,6 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)
 	if (policy_data) {
 		btd_warn(policy_data->adapter_id,
 						"Policy data already exists");
-		admin_policy_free(policy_data);
 		policy_data = NULL;
 	}
 
@@ -618,13 +617,12 @@ static struct btd_adapter_driver admin_policy_driver = {
 	.resume = NULL,
 	.remove = admin_policy_remove,
 	.device_resolved = admin_policy_device_added,
-	.device_removed = admin_policy_device_removed
+	.device_removed = admin_policy_device_removed,
+	.experimental = true,
 };
 
 static int admin_init(void)
 {
-	DBG("");
-
 	dbus_conn = btd_get_dbus_connection();
 
 	return btd_register_adapter_driver(&admin_policy_driver);
@@ -632,8 +630,6 @@ static int admin_init(void)
 
 static void admin_exit(void)
 {
-	DBG("");
-
 	btd_unregister_adapter_driver(&admin_policy_driver);
 }
 
diff --git a/plugins/external-dummy.c b/plugins/external-dummy.c
deleted file mode 100644
index 1c209e8..0000000
--- a/plugins/external-dummy.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "src/plugin.h"
-#include "src/log.h"
-
-static int dummy_init(void)
-{
-	DBG("");
-
-	return 0;
-}
-
-static void dummy_exit(void)
-{
-	DBG("");
-}
-
-BLUETOOTH_PLUGIN_DEFINE(external_dummy, VERSION,
-		BLUETOOTH_PLUGIN_PRIORITY_LOW, dummy_init, dummy_exit)
diff --git a/plugins/hostname.c b/plugins/hostname.c
index 1a9513a..51707f0 100644
--- a/plugins/hostname.c
+++ b/plugins/hostname.c
@@ -16,6 +16,8 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
 
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
@@ -44,8 +46,10 @@
 static uint8_t major_class = MAJOR_CLASS_MISCELLANEOUS;
 static uint8_t minor_class = MINOR_CLASS_UNCATEGORIZED;
 
-static char *pretty_hostname = NULL;
-static char *static_hostname = NULL;
+static char *pretty_hostname    = NULL;
+static char *static_hostname    = NULL;
+static char *transient_hostname = NULL;
+static guint hostname_id = 0;
 
 /*
  * Fallback to static hostname only if empty pretty hostname was already
@@ -60,6 +64,10 @@ static const char *get_hostname(void)
 		if (static_hostname &&
 				g_str_equal(static_hostname, "") == FALSE)
 			return static_hostname;
+
+		if (transient_hostname &&
+				g_str_equal(transient_hostname, "") == FALSE)
+			return transient_hostname;
 	}
 
 	return NULL;
@@ -128,7 +136,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 
 			dbus_message_iter_get_basic(iter, &str);
 
-			DBG("pretty hostname: %s", str);
+			DBG("pretty hostname: '%s'", str);
 
 			g_free(pretty_hostname);
 			pretty_hostname = g_strdup(str);
@@ -146,7 +154,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 
 			dbus_message_iter_get_basic(iter, &str);
 
-			DBG("static hostname: %s", str);
+			DBG("static hostname: '%s'", str);
 
 			g_free(static_hostname);
 			static_hostname = g_strdup(str);
@@ -165,7 +173,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 
 			dbus_message_iter_get_basic(iter, &str);
 
-			DBG("chassis: %s", str);
+			DBG("chassis: '%s'", str);
 
 			for (i = 0; chassis_table[i].chassis; i++) {
 				if (strcmp(chassis_table[i].chassis, str))
@@ -181,6 +189,32 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 	}
 }
 
+static void read_transient_hostname(void)
+{
+	struct utsname u;
+
+	if (uname(&u) != 0) {
+		g_free(transient_hostname);
+		transient_hostname = NULL;
+		DBG("failed to read transient hostname");
+		return;
+	}
+
+	g_free(transient_hostname);
+	transient_hostname = g_strdup(u.nodename);
+
+	DBG("read transient hostname: '%s'", transient_hostname);
+}
+
+static gboolean hostname_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	DBG("transient hostname changed");
+	read_transient_hostname();
+	adapter_foreach(update_class, NULL);
+	return TRUE;
+}
+
 static int hostname_probe(struct btd_adapter *adapter)
 {
 	DBG("");
@@ -261,9 +295,11 @@ static GDBusProxy *hostname_proxy = NULL;
 static int hostname_init(void)
 {
 	DBusConnection *conn = btd_get_dbus_connection();
+	int fd;
 	int err;
 
 	read_dmi_fallback();
+	read_transient_hostname();
 
 	hostname_client = g_dbus_client_new(conn, "org.freedesktop.hostname1",
 						"/org/freedesktop/hostname1");
@@ -289,6 +325,17 @@ static int hostname_init(void)
 		hostname_client = NULL;
 	}
 
+	fd = open("/proc/sys/kernel/hostname", O_RDONLY);
+	if (fd < 0) {
+		error("open(/proc/sys/kernel/hostname): %s (%d)",
+					strerror(errno), errno);
+	} else {
+		GIOChannel *io = g_io_channel_unix_new(fd);
+
+		hostname_id = g_io_add_watch(io, G_IO_ERR, hostname_cb, NULL);
+		g_io_channel_unref(io);
+	}
+
 	return err;
 }
 
@@ -306,8 +353,14 @@ static void hostname_exit(void)
 		hostname_client = NULL;
 	}
 
+	if (hostname_id != 0) {
+		g_source_remove(hostname_id);
+		hostname_id = 0;
+	}
+
 	g_free(pretty_hostname);
 	g_free(static_hostname);
+	g_free(transient_hostname);
 }
 
 BLUETOOTH_PLUGIN_DEFINE(hostname, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
diff --git a/plugins/policy.c b/plugins/policy.c
index 0bbdbfc..9a449da 100644
--- a/plugins/policy.c
+++ b/plugins/policy.c
@@ -74,6 +74,7 @@ static GSList *reconnects = NULL;
 static unsigned int service_id = 0;
 static GSList *devices = NULL;
 
+static const bool default_auto_enable = true;
 static bool auto_enable = false;
 
 struct policy_data {
@@ -858,6 +859,7 @@ static int policy_init(void)
 						sizeof(*reconnect_intervals);
 		reconnect_intervals = util_memdup(default_intervals,
 						sizeof(default_intervals));
+		auto_enable = default_auto_enable;
 		goto done;
 	}
 
@@ -895,7 +897,7 @@ static int policy_init(void)
 								&gerr);
 	if (gerr) {
 		g_clear_error(&gerr);
-		auto_enable = true;
+		auto_enable = default_auto_enable;
 	}
 
 	resume_delay = g_key_file_get_integer(
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index 544ab39..3e69f1d 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -346,6 +346,11 @@ static bool setup_device(int fd, const char *sysfs_path,
 
 	device = btd_adapter_get_device(adapter, &device_bdaddr, BDADDR_BREDR);
 
+	if (!device) {
+		error("sixaxis: unable to set up a new device");
+		return false;
+	}
+
 	info("sixaxis: setting up new device");
 
 	btd_device_device_set_name(device, cp->name);
diff --git a/profiles/audio/a2dp-codecs.h b/profiles/audio/a2dp-codecs.h
index 6f56709..38b9038 100644
--- a/profiles/audio/a2dp-codecs.h
+++ b/profiles/audio/a2dp-codecs.h
@@ -250,6 +250,18 @@
 #define LDAC_CHANNEL_MODE_DUAL		0x02
 #define LDAC_CHANNEL_MODE_STEREO	0x01
 
+#define OPUS_G_VENDOR_ID		0x000000e0
+#define OPUS_G_CODEC_ID			0x0001
+
+#define OPUS_G_FREQUENCY_48000		0x80
+
+#define OPUS_G_DURATION_100		0x08
+#define OPUS_G_DURATION_200		0x10
+
+#define OPUS_G_CHANNELS_MONO		0x01
+#define OPUS_G_CHANNELS_STEREO		0x02
+#define OPUS_G_CHANNELS_DUAL		0x04
+
 typedef struct {
 	uint8_t vendor_id4;
 	uint8_t vendor_id3;
@@ -420,3 +432,8 @@ typedef struct {
 	uint8_t reserved2;
 	uint8_t reserved3;
 } __attribute__ ((packed)) a2dp_aptx_hd_t;
+
+typedef struct {
+	a2dp_vendor_codec_t info;
+	uint8_t data;
+} __attribute__ ((packed)) a2dp_opus_g_t;
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 47b5dd7..d6c97e7 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <limits.h>
 
 #include <dbus/dbus.h>
 #include <glib.h>
@@ -222,6 +223,7 @@ static void setup_free(struct a2dp_setup *s)
 		avdtp_unref(s->session);
 	g_slist_free_full(s->cb, g_free);
 	g_slist_free_full(s->caps, g_free);
+	g_free(s->err);
 	g_free(s);
 }
 
@@ -270,17 +272,34 @@ static void setup_cb_free(struct a2dp_setup_cb *cb)
 	g_free(cb);
 }
 
+static void setup_error_set(struct a2dp_setup *setup, struct avdtp_error *err)
+{
+	if (!err) {
+		g_free(setup->err);
+		setup->err = NULL;
+	} else {
+		if (!setup->err)
+			setup->err = g_new0(struct avdtp_error, 1);
+		memcpy(setup->err, err, sizeof(struct avdtp_error));
+	}
+}
+
+static void setup_error_init(struct a2dp_setup *setup, uint8_t type, int id)
+{
+	struct avdtp_error err;
+
+	avdtp_error_init(&err, type, id);
+	setup_error_set(setup, &err);
+}
+
 static void finalize_setup_errno(struct a2dp_setup *s, int err,
 					GSourceFunc cb1, ...)
 {
 	GSourceFunc finalize;
 	va_list args;
-	struct avdtp_error avdtp_err;
 
-	if (err < 0) {
-		avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
-		s->err = &avdtp_err;
-	}
+	if (err < 0)
+		setup_error_init(s, AVDTP_ERRNO, -err);
 
 	va_start(args, cb1);
 	finalize = cb1;
@@ -307,6 +326,8 @@ static int error_to_errno(struct avdtp_error *err)
 	switch (perr) {
 	case EHOSTDOWN:
 	case ECONNABORTED:
+	case EBADE:
+	case ECONNREFUSED:
 		return -perr;
 	default:
 		/*
@@ -575,10 +596,7 @@ done:
 
 	finalize_config(setup);
 
-	if (setup->err) {
-		g_free(setup->err);
-		setup->err = NULL;
-	}
+	setup_error_set(setup, NULL);
 
 	setup_unref(setup);
 
@@ -587,11 +605,9 @@ done:
 
 static void endpoint_setconf_cb(struct a2dp_setup *setup, gboolean ret)
 {
-	if (ret == FALSE) {
-		setup->err = g_new(struct avdtp_error, 1);
-		avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+	if (ret == FALSE)
+		setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
-	}
 
 	auto_config(setup);
 	setup_unref(setup);
@@ -670,8 +686,7 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 
 		if (cap->category == AVDTP_DELAY_REPORTING &&
 					!a2dp_sep->delay_reporting) {
-			setup->err = g_new(struct avdtp_error, 1);
-			avdtp_error_init(setup->err, AVDTP_DELAY_REPORTING,
+			setup_error_init(setup, AVDTP_DELAY_REPORTING,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
 			goto done;
 		}
@@ -682,8 +697,7 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 		codec = (struct avdtp_media_codec_capability *) cap->data;
 
 		if (codec->media_codec_type != a2dp_sep->codec) {
-			setup->err = g_new(struct avdtp_error, 1);
-			avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+			setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
 			goto done;
 		}
@@ -703,10 +717,9 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 			return TRUE;
 		}
 
-		setup_unref(setup);
-		setup->err = g_new(struct avdtp_error, 1);
-		avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+		setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
+		setup_unref(setup);
 		break;
 	}
 
@@ -885,7 +898,7 @@ static void invalidate_remote_cache(struct a2dp_setup *setup,
 		/* Set error to -EAGAIN so the likes of policy plugin can
 		 * reattempt to connect.
 		 */
-		avdtp_error_init(setup->err, AVDTP_ERRNO, -EAGAIN);
+		setup_error_init(setup, AVDTP_ERRNO, -EAGAIN);
 	}
 }
 
@@ -909,10 +922,10 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	if (err) {
 		if (setup) {
 			setup_ref(setup);
-			setup->err = err;
+			setup_error_set(setup, err);
 			invalidate_remote_cache(setup, err);
 			finalize_config(setup);
-			setup->err = NULL;
+			setup_error_set(setup, NULL);
 			setup_unref(setup);
 		}
 
@@ -1115,7 +1128,7 @@ static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 		if (setup->start)
 			finalize_resume(setup);
 	} else if (setup->chan)
@@ -1190,7 +1203,7 @@ static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_resume(setup);
@@ -1269,7 +1282,7 @@ static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_suspend(setup);
@@ -1316,6 +1329,9 @@ static struct a2dp_remote_sep *find_remote_sep(struct a2dp_channel *chan,
 {
 	struct avdtp_remote_sep *rsep;
 
+	if (!chan || !sep)
+		return NULL;
+
 	rsep = avdtp_find_remote_sep(chan->session, sep->lsep);
 
 	return queue_find(chan->seps, match_remote_sep, rsep);
@@ -1417,7 +1433,7 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 		finalize_config(setup);
 		return;
 	}
@@ -1527,7 +1543,7 @@ static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_config(setup);
@@ -2884,7 +2900,7 @@ static void discover_cb(struct avdtp *session, GSList *seps,
 
 	setup->seps = seps;
 	if (err)
-		setup->err = err;
+		setup_error_set(setup, err);
 
 	if (!err) {
 		g_slist_foreach(seps, foreach_register_remote_sep, setup->chan);
diff --git a/profiles/audio/asha.c b/profiles/audio/asha.c
new file mode 100644
index 0000000..10115b9
--- /dev/null
+++ b/profiles/audio/asha.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Asymptotic Inc.
+ *
+ *  Author: Arun Raghavan <arun@asymptotic.io>
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+#include "btio/btio.h"
+#include "gdbus/gdbus.h"
+#include "lib/bluetooth.h"
+#include "lib/l2cap.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/adapter.h"
+#include "src/device.h"
+#include "src/log.h"
+#include "src/plugin.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/shared/util.h"
+
+#include "profiles/audio/asha.h"
+#include "profiles/audio/media.h"
+#include "profiles/audio/transport.h"
+
+#define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
+
+/* 2 byte SDU length, 1 byte sequence number, and then 20ms of G.722 */
+#define ASHA_MIN_MTU 163
+/* The default of 672 does not work */
+#define ASHA_CONNECTION_MTU 512
+
+struct bt_asha_device {
+	struct bt_asha *asha;
+	struct btd_device *device;
+	struct media_transport *transport;
+
+	GIOChannel *io;
+	uint16_t imtu, omtu;
+
+	unsigned int resume_id;
+};
+
+static char *make_endpoint_path(struct bt_asha_device *asha_dev)
+{
+	char *path;
+	int err;
+
+	err = asprintf(&path, "%s/asha", device_get_path(asha_dev->device));
+	if (err < 0) {
+		error("Could not allocate path for remote %s",
+				device_get_path(asha_dev->device));
+		return NULL;
+	}
+
+	return path;
+}
+
+struct connect_data {
+	struct bt_asha_device *asha_dev;
+	bt_asha_cb_t cb;
+	void *cb_user_data;
+};
+
+static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+	struct connect_data *conn_data = user_data;
+	struct bt_asha_device *asha_dev = conn_data->asha_dev;
+	GError *gerr = NULL;
+
+	if (!bt_io_get(io, &gerr,
+				BT_IO_OPT_IMTU, &asha_dev->imtu,
+				BT_IO_OPT_OMTU, &asha_dev->omtu,
+				BT_IO_OPT_INVALID)) {
+		/* Let this be non-fatal? */
+		asha_dev->omtu = ASHA_MIN_MTU;
+		asha_dev->imtu = ASHA_CONNECTION_MTU;
+		error("Could not get L2CAP CoC socket MTU: %s", err->message);
+		g_error_free(gerr);
+	}
+
+	asha_dev->io = io;
+
+	bt_asha_start(asha_dev->asha, conn_data->cb,
+					conn_data->cb_user_data);
+}
+
+static int asha_connect_socket(struct bt_asha_device *asha_dev,
+					bt_asha_cb_t cb, void *user_data)
+{
+	GError *gerr = NULL;
+	const bdaddr_t *src_addr;
+	struct connect_data *conn_data;
+
+	if (asha_dev->asha->state != ASHA_STOPPED) {
+		error("ASHA device connect failed. Bad state %d",
+							asha_dev->asha->state);
+		return 0;
+	}
+
+	conn_data = g_new0(struct connect_data, 1);
+	conn_data->asha_dev = asha_dev;
+	conn_data->cb = cb;
+	conn_data->cb_user_data = user_data;
+
+	src_addr = btd_adapter_get_address(
+			device_get_adapter(asha_dev->device));
+
+	if (!bt_io_connect(connect_cb, conn_data,
+				g_free, &gerr,
+				BT_IO_OPT_MODE, BT_IO_MODE_LE_FLOWCTL,
+				BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
+				BT_IO_OPT_SOURCE_BDADDR, src_addr,
+				BT_IO_OPT_DEST_TYPE, BDADDR_LE_PUBLIC,
+				BT_IO_OPT_DEST_BDADDR,
+				device_get_address(asha_dev->device),
+				BT_IO_OPT_PSM, asha_dev->asha->psm,
+				BT_IO_OPT_OMTU, ASHA_MIN_MTU,
+				BT_IO_OPT_IMTU, ASHA_CONNECTION_MTU,
+				BT_IO_OPT_INVALID)) {
+		error("Could not open L2CAP CoC socket: %s", gerr->message);
+		g_error_free(gerr);
+		goto error;
+	}
+
+	DBG("L2CAP CoC socket is open");
+	return 0;
+
+error:
+	return -1;
+}
+
+unsigned int bt_asha_device_start(struct bt_asha_device *asha_dev,
+					bt_asha_cb_t cb, void *user_data)
+{
+	int ret;
+
+	btd_device_set_conn_param(asha_dev->device,
+			0x0010 /* min interval = 1.25ms intervals => 20ms */,
+			0x0010 /* max interval = 1.25ms intervals => 20ms */,
+			0x000A /* 10 events' latency */,
+			0x0064 /* 1s timeout */);
+
+	ret = asha_connect_socket(asha_dev, cb, user_data);
+
+	if (ret < 0)
+		return 0;
+	else
+		return (++asha_dev->resume_id);
+}
+
+unsigned int bt_asha_device_stop(struct bt_asha_device *asha_dev,
+					bt_asha_cb_t cb, void *user_data)
+{
+	bt_asha_stop(asha_dev->asha, cb, user_data);
+
+	if (asha_dev->io) {
+		g_io_channel_shutdown(asha_dev->io, TRUE, NULL);
+		g_io_channel_unref(asha_dev->io);
+		asha_dev->io = NULL;
+	};
+
+	return asha_dev->resume_id;
+}
+
+void bt_asha_device_state_reset(struct bt_asha_device *asha_dev)
+{
+	if (asha_dev->io) {
+		g_io_channel_shutdown(asha_dev->io, TRUE, NULL);
+		g_io_channel_unref(asha_dev->io);
+		asha_dev->io = NULL;
+	};
+
+	bt_asha_state_reset(asha_dev->asha);
+
+	asha_dev->resume_id = 0;
+}
+
+unsigned int bt_asha_device_device_get_resume_id(
+					struct bt_asha_device *asha_dev)
+{
+	return asha_dev->resume_id;
+}
+
+enum bt_asha_state_t bt_asha_device_get_state(
+					struct bt_asha_device *asha_dev)
+{
+	return asha_dev->asha->state;
+}
+
+uint16_t bt_asha_device_get_render_delay(struct bt_asha_device *asha_dev)
+{
+	return asha_dev->asha->render_delay;
+}
+
+int8_t bt_asha_device_get_volume(struct bt_asha_device *asha_dev)
+{
+	return asha_dev->asha->volume;
+}
+
+bool bt_asha_device_set_volume(struct bt_asha_device *asha_dev, int8_t volume)
+{
+	return bt_asha_set_volume(asha_dev->asha, volume);
+}
+
+int bt_asha_device_get_fd(struct bt_asha_device *asha_dev)
+{
+	return g_io_channel_unix_get_fd(asha_dev->io);
+}
+
+uint16_t bt_asha_device_get_imtu(struct bt_asha_device *asha_dev)
+{
+	return asha_dev->imtu;
+}
+
+uint16_t bt_asha_device_get_omtu(struct bt_asha_device *asha_dev)
+{
+	return asha_dev->omtu;
+}
+
+
+static gboolean get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	const char *uuid;
+
+	uuid = ASHA_PROFILE_UUID;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean get_side(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	const char *side = asha_dev->asha->right_side ? "right" : "left";
+
+	/* Use a string in case we want to support more types in the future */
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &side);
+
+	return TRUE;
+}
+
+
+static gboolean get_binaural(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	dbus_bool_t binaural = asha_dev->asha->binaural;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &binaural);
+
+	return TRUE;
+}
+
+static gboolean get_hisyncid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	DBusMessageIter array;
+	uint8_t *hisyncid = asha_dev->asha->hisyncid;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+			&hisyncid, sizeof(asha_dev->asha->hisyncid));
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static gboolean get_codecs(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	dbus_uint16_t codecs = asha_dev->asha->codec_ids;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &codecs);
+
+	return TRUE;
+}
+
+static gboolean get_device(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	const char *path;
+
+	path = device_get_path(asha_dev->device);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	return TRUE;
+}
+
+static gboolean get_transport(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bt_asha_device *asha_dev = data;
+	const char *path;
+
+	path = media_transport_get_path(asha_dev->transport);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	return TRUE;
+}
+
+static int asha_source_device_probe(struct btd_service *service)
+{
+	struct bt_asha_device *asha_dev;
+	struct btd_device *device = btd_service_get_device(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("Probing ASHA device %s", addr);
+
+	asha_dev = g_new0(struct bt_asha_device, 1);
+
+	asha_dev->device = device;
+	asha_dev->asha = bt_asha_new();
+	asha_dev->io = NULL;
+
+	btd_service_set_user_data(service, asha_dev);
+
+	return 0;
+}
+
+static void asha_source_device_remove(struct btd_service *service)
+{
+	struct bt_asha_device *asha_dev;
+	struct btd_device *device = btd_service_get_device(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("Removing ASHA device %s", addr);
+
+	asha_dev = btd_service_get_user_data(service);
+	if (!asha_dev) {
+		/* Can this actually happen? */
+		DBG("Not handlihng ASHA profile");
+		return;
+	}
+
+	bt_asha_free(asha_dev->asha);
+	g_free(asha_dev);
+}
+
+static const GDBusMethodTable asha_ep_methods[] = {
+	{ },
+};
+
+static const GDBusPropertyTable asha_ep_properties[] = {
+	{ "UUID", "s", get_uuid, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Side", "s", get_side, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Binaural", "b", get_binaural, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "HiSyncId", "ay", get_hisyncid, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Codecs", "q", get_codecs, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Device", "o", get_device, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Transport", "o", get_transport, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ }
+};
+
+static void asha_source_endpoint_register(struct bt_asha_device *asha_dev)
+{
+	char *path;
+	const struct media_endpoint *asha_ep;
+
+	path = make_endpoint_path(asha_dev);
+	if (!path)
+		goto error;
+
+	if (g_dbus_register_interface(btd_get_dbus_connection(),
+				path, MEDIA_ENDPOINT_INTERFACE,
+				asha_ep_methods, NULL,
+				asha_ep_properties,
+				asha_dev, NULL) == FALSE) {
+		error("Could not register remote ep %s", path);
+		goto error;
+	}
+
+	asha_ep = media_endpoint_get_asha();
+	asha_dev->transport = media_transport_create(asha_dev->device, path,
+					NULL, 0, (void *) asha_ep, asha_dev);
+
+error:
+	if (path)
+		free(path);
+}
+
+static void asha_source_endpoint_unregister(struct bt_asha_device *asha)
+{
+	char *path;
+
+	path = make_endpoint_path(asha);
+	if (!path)
+		goto error;
+
+	g_dbus_unregister_interface(btd_get_dbus_connection(),
+				path, MEDIA_ENDPOINT_INTERFACE);
+
+	if (asha->transport) {
+		media_transport_destroy(asha->transport);
+		asha->transport = NULL;
+	}
+
+error:
+	if (path)
+		free(path);
+}
+
+static int asha_source_accept(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct gatt_db *db = btd_device_get_gatt_db(device);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	struct bt_asha_device *asha_dev = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("Accepting ASHA connection on %s", addr);
+
+	if (!asha_dev) {
+		/* Can this actually happen? */
+		DBG("Not handling ASHA profile");
+		return -1;
+	}
+
+	if (!bt_asha_probe(asha_dev->asha, db, client))
+		return -1;
+
+	asha_source_endpoint_register(asha_dev);
+
+	btd_service_connecting_complete(service, 0);
+
+	return 0;
+}
+
+static int asha_source_disconnect(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bt_asha_device *asha_dev = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("Disconnecting ASHA on %s", addr);
+
+	if (!asha_dev) {
+		/* Can this actually happen? */
+		DBG("Not handlihng ASHA profile");
+		return -1;
+	}
+
+	asha_source_endpoint_unregister(asha_dev);
+	bt_asha_reset(asha_dev->asha);
+
+	btd_service_disconnecting_complete(service, 0);
+
+	return 0;
+}
+
+static struct btd_profile asha_source_profile = {
+	.name		= "asha-source",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= ASHA_PROFILE_UUID,
+	.experimental	= true,
+
+	.device_probe	= asha_source_device_probe,
+	.device_remove	= asha_source_device_remove,
+
+	.auto_connect	= true,
+	.accept		= asha_source_accept,
+	.disconnect	= asha_source_disconnect,
+};
+
+static int asha_init(void)
+{
+	int err;
+
+	err = btd_profile_register(&asha_source_profile);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static void asha_exit(void)
+{
+	btd_profile_unregister(&asha_source_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(asha, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+							asha_init, asha_exit)
diff --git a/profiles/audio/asha.h b/profiles/audio/asha.h
new file mode 100644
index 0000000..afd23e1
--- /dev/null
+++ b/profiles/audio/asha.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Asymptotic Inc.
+ *
+ *  Author: Arun Raghavan <arun@asymptotic.io>
+ *
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "src/shared/asha.h"
+
+struct bt_asha_device;
+
+unsigned int bt_asha_device_start(struct bt_asha_device *asha_dev,
+					bt_asha_cb_t cb, void *user_data);
+unsigned int bt_asha_device_stop(struct bt_asha_device *asha_dev,
+					bt_asha_cb_t cb, void *user_data);
+
+void bt_asha_device_state_reset(struct bt_asha_device *asha_dev);
+unsigned int bt_asha_device_device_get_resume_id(
+					struct bt_asha_device *asha_dev);
+
+uint16_t bt_asha_device_get_render_delay(struct bt_asha_device *asha_dev);
+enum bt_asha_state_t bt_asha_device_get_state(
+					struct bt_asha_device *asha_dev);
+
+int bt_asha_device_get_fd(struct bt_asha_device *asha_dev);
+uint16_t bt_asha_device_get_omtu(struct bt_asha_device *asha_dev);
+uint16_t bt_asha_device_get_imtu(struct bt_asha_device *asha_dev);
+
+int8_t bt_asha_device_get_volume(struct bt_asha_device *asha_dev);
+bool bt_asha_device_set_volume(struct bt_asha_device *asha_dev, int8_t volume);
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 6f64f16..8ad146d 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -228,7 +228,7 @@ struct avctp_browsing_pdu_handler {
 	GDestroyNotify destroy;
 };
 
-static struct {
+static const struct {
 	const char *name;
 	uint8_t avc;
 	uint16_t uinput;
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 10ef380..80fbe84 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -184,13 +184,17 @@ struct getcap_resp {
 } __attribute__ ((packed));
 
 struct start_req {
-	struct seid first_seid;
-	struct seid other_seids[0];
+	union {
+		struct seid required[1];
+		struct seid seids[0];
+	};
 } __attribute__ ((packed));
 
 struct suspend_req {
-	struct seid first_seid;
-	struct seid other_seids[0];
+	union {
+		struct seid required[1];
+		struct seid seids[0];
+	};
 } __attribute__ ((packed));
 
 struct seid_rej {
@@ -286,7 +290,6 @@ struct in_buf {
 	gboolean active;
 	int no_of_packets;
 	uint8_t transaction;
-	uint8_t message_type;
 	uint8_t signal_id;
 	uint8_t buf[1024];
 	uint8_t data_size;
@@ -397,7 +400,8 @@ struct avdtp {
 	uint16_t imtu;
 	uint16_t omtu;
 
-	struct in_buf in;
+	struct in_buf in_resp;
+	struct in_buf in_cmd;
 
 	char *buf;
 
@@ -1462,15 +1466,16 @@ static void setconf_cb(struct avdtp *session, struct avdtp_stream *stream,
 	if (err != NULL) {
 		rej.error = AVDTP_UNSUPPORTED_CONFIGURATION;
 		rej.category = err->err.error_code;
-		avdtp_send(session, session->in.transaction,
-				AVDTP_MSG_TYPE_REJECT, AVDTP_SET_CONFIGURATION,
-				&rej, sizeof(rej));
+		avdtp_send(session, session->in_cmd.transaction,
+			   AVDTP_MSG_TYPE_REJECT, AVDTP_SET_CONFIGURATION,
+			   &rej, sizeof(rej));
 		stream_free(stream);
 		return;
 	}
 
-	if (!avdtp_send(session, session->in.transaction, AVDTP_MSG_TYPE_ACCEPT,
-					AVDTP_SET_CONFIGURATION, NULL, 0)) {
+	if (!avdtp_send(session, session->in_cmd.transaction,
+			AVDTP_MSG_TYPE_ACCEPT,
+			AVDTP_SET_CONFIGURATION, NULL, 0)) {
 		stream_free(stream);
 		return;
 	}
@@ -1671,12 +1676,12 @@ static void check_seid_collision(struct pending_req *req, uint8_t id)
 static void check_start_collision(struct pending_req *req, uint8_t id)
 {
 	struct start_req *start = req->data;
-	struct seid *seid = &start->first_seid;
 	int count = 1 + req->data_size - sizeof(struct start_req);
 	int i;
 
-	for (i = 0; i < count; i++, seid++) {
-		if (seid->seid == id) {
+	for (i = 0; i < count; i++) {
+		struct seid seid = start->seids[i];
+		if (seid.seid == id) {
 			req->collided = TRUE;
 			return;
 		}
@@ -1686,12 +1691,12 @@ static void check_start_collision(struct pending_req *req, uint8_t id)
 static void check_suspend_collision(struct pending_req *req, uint8_t id)
 {
 	struct suspend_req *suspend = req->data;
-	struct seid *seid = &suspend->first_seid;
 	int count = 1 + req->data_size - sizeof(struct suspend_req);
 	int i;
 
-	for (i = 0; i < count; i++, seid++) {
-		if (seid->seid == id) {
+	for (i = 0; i < count; i++) {
+		struct seid seid = suspend->seids[i];
+		if (seid.seid == id) {
 			req->collided = TRUE;
 			return;
 		}
@@ -1784,7 +1789,6 @@ static gboolean avdtp_start_cmd(struct avdtp *session, uint8_t transaction,
 	struct avdtp_local_sep *sep;
 	struct avdtp_stream *stream;
 	struct stream_rej rej;
-	struct seid *seid;
 	uint8_t err, failed_seid;
 	int seid_count, i;
 
@@ -1795,12 +1799,12 @@ static gboolean avdtp_start_cmd(struct avdtp *session, uint8_t transaction,
 
 	seid_count = 1 + size - sizeof(struct start_req);
 
-	seid = &req->first_seid;
+	for (i = 0; i < seid_count; i++) {
+		struct seid seid = req->seids[i];
 
-	for (i = 0; i < seid_count; i++, seid++) {
-		failed_seid = seid->seid;
+		failed_seid = seid.seid;
 
-		sep = find_local_sep_by_seid(session, seid->seid);
+		sep = find_local_sep_by_seid(session, seid.seid);
 		if (!sep || !sep->stream) {
 			err = AVDTP_BAD_ACP_SEID;
 			goto failed;
@@ -1897,7 +1901,6 @@ static gboolean avdtp_suspend_cmd(struct avdtp *session, uint8_t transaction,
 	struct avdtp_local_sep *sep;
 	struct avdtp_stream *stream;
 	struct stream_rej rej;
-	struct seid *seid;
 	uint8_t err, failed_seid;
 	int seid_count, i;
 
@@ -1908,12 +1911,11 @@ static gboolean avdtp_suspend_cmd(struct avdtp *session, uint8_t transaction,
 
 	seid_count = 1 + size - sizeof(struct suspend_req);
 
-	seid = &req->first_seid;
-
-	for (i = 0; i < seid_count; i++, seid++) {
-		failed_seid = seid->seid;
+	for (i = 0; i < seid_count; i++) {
+		struct seid seid = req->seids[i];
+		failed_seid = seid.seid;
 
-		sep = find_local_sep_by_seid(session, seid->seid);
+		sep = find_local_sep_by_seid(session, seid.seid);
 		if (!sep || !sep->stream) {
 			err = AVDTP_BAD_ACP_SEID;
 			goto failed;
@@ -2035,6 +2037,14 @@ failed:
 static gboolean avdtp_parse_cmd(struct avdtp *session, uint8_t transaction,
 				uint8_t signal_id, void *buf, int size)
 {
+	/* Reset disconnect timer if command is received */
+	if (session->dc_timer) {
+		timeout_remove(session->dc_timer);
+		session->dc_timer = timeout_add_seconds(session->dc_timeout,
+						disconnect_timeout,
+						session, NULL);
+	}
+
 	switch (signal_id) {
 	case AVDTP_DISCOVER:
 		DBG("Received DISCOVER_CMD");
@@ -2092,6 +2102,12 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 	struct avdtp_start_header *start = (void *) session->buf;
 	void *payload;
 	gsize payload_size;
+	struct in_buf *in;
+
+	if (header->message_type == AVDTP_MSG_TYPE_COMMAND)
+		in = &session->in_cmd;
+	else
+		in = &session->in_resp;
 
 	switch (header->packet_type) {
 	case AVDTP_PKT_TYPE_SINGLE:
@@ -2099,7 +2115,7 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 			error("Received too small single packet (%zu bytes)", size);
 			return PARSE_ERROR;
 		}
-		if (session->in.active) {
+		if (in->active) {
 			error("SINGLE: Invalid AVDTP packet fragmentation");
 			return PARSE_ERROR;
 		}
@@ -2107,12 +2123,11 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 		payload = session->buf + sizeof(*single);
 		payload_size = size - sizeof(*single);
 
-		session->in.active = TRUE;
-		session->in.data_size = 0;
-		session->in.no_of_packets = 1;
-		session->in.transaction = header->transaction;
-		session->in.message_type = header->message_type;
-		session->in.signal_id = single->signal_id;
+		in->active = TRUE;
+		in->data_size = 0;
+		in->no_of_packets = 1;
+		in->transaction = header->transaction;
+		in->signal_id = single->signal_id;
 
 		break;
 	case AVDTP_PKT_TYPE_START:
@@ -2120,17 +2135,16 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 			error("Received too small start packet (%zu bytes)", size);
 			return PARSE_ERROR;
 		}
-		if (session->in.active) {
+		if (in->active) {
 			error("START: Invalid AVDTP packet fragmentation");
 			return PARSE_ERROR;
 		}
 
-		session->in.active = TRUE;
-		session->in.data_size = 0;
-		session->in.transaction = header->transaction;
-		session->in.message_type = header->message_type;
-		session->in.no_of_packets = start->no_of_packets;
-		session->in.signal_id = start->signal_id;
+		in->active = TRUE;
+		in->data_size = 0;
+		in->transaction = header->transaction;
+		in->no_of_packets = start->no_of_packets;
+		in->signal_id = start->signal_id;
 
 		payload = session->buf + sizeof(*start);
 		payload_size = size - sizeof(*start);
@@ -2142,15 +2156,15 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 									size);
 			return PARSE_ERROR;
 		}
-		if (!session->in.active) {
+		if (!in->active) {
 			error("CONTINUE: Invalid AVDTP packet fragmentation");
 			return PARSE_ERROR;
 		}
-		if (session->in.transaction != header->transaction) {
+		if (in->transaction != header->transaction) {
 			error("Continue transaction id doesn't match");
 			return PARSE_ERROR;
 		}
-		if (session->in.no_of_packets <= 1) {
+		if (in->no_of_packets <= 1) {
 			error("Too few continue packets");
 			return PARSE_ERROR;
 		}
@@ -2164,15 +2178,15 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 			error("Received too small end packet (%zu bytes)", size);
 			return PARSE_ERROR;
 		}
-		if (!session->in.active) {
+		if (!in->active) {
 			error("END: Invalid AVDTP packet fragmentation");
 			return PARSE_ERROR;
 		}
-		if (session->in.transaction != header->transaction) {
+		if (in->transaction != header->transaction) {
 			error("End transaction id doesn't match");
 			return PARSE_ERROR;
 		}
-		if (session->in.no_of_packets > 1) {
+		if (in->no_of_packets > 1) {
 			error("Got an end packet too early");
 			return PARSE_ERROR;
 		}
@@ -2186,23 +2200,23 @@ static enum avdtp_parse_result avdtp_parse_data(struct avdtp *session,
 		return PARSE_ERROR;
 	}
 
-	if (session->in.data_size + payload_size >
-					sizeof(session->in.buf)) {
+	if (in->data_size + payload_size >
+					sizeof(in->buf)) {
 		error("Not enough incoming buffer space!");
 		return PARSE_ERROR;
 	}
 
-	memcpy(session->in.buf + session->in.data_size, payload, payload_size);
-	session->in.data_size += payload_size;
+	memcpy(in->buf + in->data_size, payload, payload_size);
+	in->data_size += payload_size;
 
-	if (session->in.no_of_packets > 1) {
-		session->in.no_of_packets--;
+	if (in->no_of_packets > 1) {
+		in->no_of_packets--;
 		DBG("Received AVDTP fragment. %d to go",
-						session->in.no_of_packets);
+						in->no_of_packets);
 		return PARSE_FRAGMENT;
 	}
 
-	session->in.active = FALSE;
+	in->active = FALSE;
 
 	return PARSE_SUCCESS;
 }
@@ -2246,11 +2260,11 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 		break;
 	}
 
-	if (session->in.message_type == AVDTP_MSG_TYPE_COMMAND) {
-		if (!avdtp_parse_cmd(session, session->in.transaction,
-					session->in.signal_id,
-					session->in.buf,
-					session->in.data_size)) {
+	if (header->message_type == AVDTP_MSG_TYPE_COMMAND) {
+		if (!avdtp_parse_cmd(session, session->in_cmd.transaction,
+				     session->in_cmd.signal_id,
+				     session->in_cmd.buf,
+				     session->in_cmd.data_size)) {
 			error("Unable to handle command. Disconnecting");
 			goto failed;
 		}
@@ -2273,7 +2287,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 		return TRUE;
 	}
 
-	if (session->in.signal_id != session->req->signal_id) {
+	if (session->in_resp.signal_id != session->req->signal_id) {
 		error("Response signal doesn't match");
 		return TRUE;
 	}
@@ -2284,20 +2298,20 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 	switch (header->message_type) {
 	case AVDTP_MSG_TYPE_ACCEPT:
 		if (!avdtp_parse_resp(session, session->req->stream,
-						session->in.transaction,
-						session->in.signal_id,
-						session->in.buf,
-						session->in.data_size)) {
+						session->in_resp.transaction,
+						session->in_resp.signal_id,
+						session->in_resp.buf,
+						session->in_resp.data_size)) {
 			error("Unable to parse accept response");
 			goto failed;
 		}
 		break;
 	case AVDTP_MSG_TYPE_REJECT:
 		if (!avdtp_parse_rej(session, session->req->stream,
-						session->in.transaction,
-						session->in.signal_id,
-						session->in.buf,
-						session->in.data_size)) {
+						session->in_resp.transaction,
+						session->in_resp.signal_id,
+						session->in_resp.buf,
+						session->in_resp.data_size)) {
 			error("Unable to parse reject response");
 			goto failed;
 		}
@@ -3197,6 +3211,10 @@ gboolean avdtp_stream_has_capabilities(struct avdtp_stream *stream,
 	return TRUE;
 }
 
+gboolean avdtp_stream_has_delay_reporting(struct avdtp_stream *stream) {
+	return stream->delay_reporting;
+}
+
 struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
 						struct avdtp_stream *stream)
 {
@@ -3658,7 +3676,7 @@ int avdtp_start(struct avdtp *session, struct avdtp_stream *stream)
 	}
 
 	memset(&req, 0, sizeof(req));
-	req.first_seid.seid = stream->rseid;
+	req.required->seid = stream->rseid;
 
 	ret = send_request(session, FALSE, stream, AVDTP_START,
 							&req, sizeof(req));
@@ -3763,11 +3781,12 @@ int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
 		return -EINVAL;
 
 	if (stream->lsep->state != AVDTP_STATE_CONFIGURED &&
+				stream->lsep->state != AVDTP_STATE_OPEN &&
 				stream->lsep->state != AVDTP_STATE_STREAMING)
 		return -EINVAL;
 
 	if (!stream->delay_reporting || session->version < 0x0103)
-		return -EINVAL;
+		return -ENOTSUP;
 
 	stream->delay = delay;
 
@@ -3913,6 +3932,9 @@ struct btd_device *avdtp_get_device(struct avdtp *session)
 
 gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
 {
+	if (!session || !stream)
+		return FALSE;
+
 	return g_slist_find(session->streams, stream) ? TRUE : FALSE;
 }
 
diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
index 102a260..500b814 100644
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -252,6 +252,7 @@ struct avdtp_service_capability *avdtp_stream_get_codec(
 						struct avdtp_stream *stream);
 gboolean avdtp_stream_has_capabilities(struct avdtp_stream *stream,
 					GSList *caps);
+gboolean avdtp_stream_has_delay_reporting(struct avdtp_stream *stream);
 struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
 						struct avdtp_stream *stream);
 
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 80f34c7..b5e6548 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -48,6 +48,7 @@
 #include "src/dbus-common.h"
 #include "src/shared/timeout.h"
 #include "src/shared/util.h"
+#include "src/btd.h"
 
 #include "avctp.h"
 #include "avrcp.h"
@@ -118,8 +119,14 @@
 #define AVRCP_FEATURE_CATEGORY_2	0x0002
 #define AVRCP_FEATURE_CATEGORY_3	0x0004
 #define AVRCP_FEATURE_CATEGORY_4	0x0008
-#define AVRCP_FEATURE_PLAYER_SETTINGS	0x0010
-#define AVRCP_FEATURE_BROWSING			0x0040
+#define AVRCP_FEATURE_TG_PLAYER_SETTINGS	0x0010
+#define AVRCP_FEATURE_TG_GROUP_NAVIGATION	0x0020
+#define AVRCP_FEATURE_BROWSING				0x0040
+#define AVRCP_FEATURE_TG_MULTIPLE_PLAYER	0x0080
+#define AVRCP_FEATURE_TG_COVERT_ART			0x0100
+#define AVRCP_FEATURE_CT_GET_IMAGE_PROP		0x0080
+#define AVRCP_FEATURE_CT_GET_IMAGE			0x0100
+#define AVRCP_FEATURE_CT_GET_THUMBNAIL		0x0200
 
 #define AVRCP_BATTERY_STATUS_NORMAL		0
 #define AVRCP_BATTERY_STATUS_WARNING		1
@@ -254,6 +261,7 @@ struct avrcp_data {
 	struct avrcp_player *player;
 	uint16_t version;
 	int features;
+	uint16_t obex_port;
 	GSList *players;
 };
 
@@ -290,7 +298,7 @@ struct control_pdu_handler {
 							uint8_t transaction);
 };
 
-static struct {
+static const struct {
 	uint8_t feature_bit;
 	uint8_t avc;
 } passthrough_map[] = {
@@ -361,7 +369,7 @@ static unsigned int avctp_id = 0;
 static uint8_t default_features[16];
 
 /* Company IDs supported by this device */
-static uint32_t company_ids[] = {
+static const uint32_t company_ids[] = {
 	IEEEID_BTSIG,
 };
 
@@ -408,9 +416,12 @@ static sdp_record_t *avrcp_ct_record(bool browsing)
 	uint16_t lp = AVCTP_CONTROL_PSM;
 	uint16_t avctp_ver = 0x0103;
 	uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
-						AVRCP_FEATURE_CATEGORY_2 |
-						AVRCP_FEATURE_CATEGORY_3 |
-						AVRCP_FEATURE_CATEGORY_4);
+					AVRCP_FEATURE_CATEGORY_2 |
+					AVRCP_FEATURE_CATEGORY_3 |
+					AVRCP_FEATURE_CATEGORY_4 |
+					AVRCP_FEATURE_CT_GET_IMAGE_PROP |
+					AVRCP_FEATURE_CT_GET_IMAGE |
+					AVRCP_FEATURE_CT_GET_THUMBNAIL);
 
 	record = sdp_record_alloc();
 	if (!record)
@@ -487,7 +498,7 @@ static sdp_record_t *avrcp_tg_record(bool browsing)
 					AVRCP_FEATURE_CATEGORY_2 |
 					AVRCP_FEATURE_CATEGORY_3 |
 					AVRCP_FEATURE_CATEGORY_4 |
-					AVRCP_FEATURE_PLAYER_SETTINGS );
+					AVRCP_FEATURE_TG_PLAYER_SETTINGS);
 
 	record = sdp_record_alloc();
 	if (!record)
@@ -876,6 +887,8 @@ static const char *metadata_to_str(uint32_t id)
 		return "NumberOfTracks";
 	case AVRCP_MEDIA_ATTRIBUTE_DURATION:
 		return "Duration";
+	case AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE:
+		return "ImgHandle";
 	}
 
 	return NULL;
@@ -1190,6 +1203,8 @@ static uint32_t str_to_metadata(const char *str)
 		return AVRCP_MEDIA_ATTRIBUTE_N_TRACKS;
 	else if (strcasecmp(str, "Duration") == 0)
 		return AVRCP_MEDIA_ATTRIBUTE_DURATION;
+	else if (strcasecmp(str, "ImgHandle") == 0)
+		return AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE;
 
 	return 0;
 }
@@ -1210,6 +1225,10 @@ static GList *player_list_metadata(struct avrcp_player *player)
 					GUINT_TO_POINTER(str_to_metadata(key)));
 	}
 
+	if (attrs == NULL)
+		return g_list_prepend(NULL,
+				GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+
 	return attrs;
 }
 
@@ -1746,6 +1765,19 @@ err:
 	return AVC_CTYPE_REJECTED;
 }
 
+/* SetAbsoluteVolume requires at least version 1.4 and a category-2 */
+static bool avrcp_volume_supported(struct avrcp_data *data)
+{
+	if (!data || data->version < 0x0104)
+		return false;
+
+	if (btd_opts.avrcp.volume_category &&
+			!(data->features & AVRCP_FEATURE_CATEGORY_2))
+		return false;
+
+	return true;
+}
+
 static uint8_t avrcp_handle_set_absolute_volume(struct avrcp *session,
 						struct avrcp_header *pdu,
 						uint8_t transaction)
@@ -1756,6 +1788,11 @@ static uint8_t avrcp_handle_set_absolute_volume(struct avrcp *session,
 	if (len != 1)
 		goto err;
 
+	if (!avrcp_volume_supported(session->target)) {
+		error("SetAbsoluteVolume not supported");
+		goto err;
+	}
+
 	volume = pdu->params[0] & 0x7F;
 
 	media_transport_update_device_volume(session->dev, volume);
@@ -2118,7 +2155,7 @@ failed:
 	pdu->param_len = cpu_to_be16(1);
 }
 
-static struct browsing_pdu_handler {
+static const struct browsing_pdu_handler {
 	uint8_t pdu_id;
 	void (*func) (struct avrcp *session, struct avrcp_browsing_header *pdu,
 							uint8_t transaction);
@@ -2147,7 +2184,7 @@ static size_t handle_browsing_pdu(struct avctp *conn,
 					size_t operand_count, void *user_data)
 {
 	struct avrcp *session = user_data;
-	struct browsing_pdu_handler *handler;
+	const struct browsing_pdu_handler *handler;
 	struct avrcp_browsing_header *pdu = (void *) operands;
 
 	DBG("AVRCP Browsing PDU 0x%02X, len 0x%04X", pdu->pdu_id,
@@ -2396,16 +2433,12 @@ static void avrcp_list_player_attributes(struct avrcp *session)
 }
 
 static void avrcp_parse_attribute_list(struct avrcp_player *player,
+					struct media_item *item,
 					uint8_t *operands, uint8_t count)
 {
 	struct media_player *mp = player->user_data;
-	struct media_item *item;
 	int i;
 
-	media_player_clear_metadata(mp);
-
-	item = media_player_set_playlist_item(mp, player->uid);
-
 	for (i = 0; count > 0; count--) {
 		uint32_t id;
 		uint16_t charset, len;
@@ -2430,8 +2463,6 @@ static void avrcp_parse_attribute_list(struct avrcp_player *player,
 
 		i += len;
 	}
-
-	media_player_metadata_changed(mp);
 }
 
 static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
@@ -2444,6 +2475,8 @@ static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
 	struct avrcp *session = user_data;
 	struct avrcp_player *player = session->controller->player;
 	struct avrcp_header *pdu = (void *) operands;
+	struct media_player *mp = player->user_data;
+	struct media_item *item;
 	uint8_t count;
 
 	if (code == AVC_CTYPE_REJECTED)
@@ -2456,7 +2489,13 @@ static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
 		return FALSE;
 	}
 
-	avrcp_parse_attribute_list(player, &pdu->params[1], count);
+	media_player_clear_metadata(mp);
+
+	item = media_player_set_playlist_item(mp, player->uid);
+
+	avrcp_parse_attribute_list(player, item, &pdu->params[1], count);
+
+	media_player_metadata_changed(mp);
 
 	avrcp_get_play_status(session);
 
@@ -2542,20 +2581,23 @@ static struct media_item *parse_media_element(struct avrcp *session,
 	struct avrcp_player *player;
 	struct media_player *mp;
 	struct media_item *item;
-	uint16_t namelen;
+	uint16_t namelen, namesize;
 	char name[255];
 	uint64_t uid;
+	uint8_t count;
 
 	if (len < 13)
 		return NULL;
 
 	uid = get_be64(&operands[0]);
 
-	namelen = MIN(get_be16(&operands[11]), sizeof(name) - 1);
-	if (namelen > 0) {
+	memset(name, 0, sizeof(name));
+	namesize = get_be16(&operands[11]);
+	namelen = MIN(namesize, sizeof(name) - 1);
+	if (namelen > 0)
 		memcpy(name, &operands[13], namelen);
-		name[namelen] = '\0';
-	}
+
+	count = operands[13 + namesize];
 
 	player = session->controller->player;
 	mp = player->user_data;
@@ -2566,6 +2608,9 @@ static struct media_item *parse_media_element(struct avrcp *session,
 
 	media_item_set_playable(item, true);
 
+	avrcp_parse_attribute_list(player, item, &operands[14 + namesize],
+					count);
+
 	return item;
 }
 
@@ -2588,11 +2633,10 @@ static struct media_item *parse_media_folder(struct avrcp *session,
 	type = operands[8];
 	playable = operands[9];
 
+	memset(name, 0, sizeof(name));
 	namelen = MIN(get_be16(&operands[12]), sizeof(name) - 1);
-	if (namelen > 0) {
+	if (namelen > 0)
 		memcpy(name, &operands[14], namelen);
-		name[namelen] = '\0';
-	}
 
 	item = media_player_create_folder(mp, name, type, uid);
 	if (!item)
@@ -2701,20 +2745,25 @@ static void avrcp_list_items(struct avrcp *session, uint32_t start,
 	memset(buf, 0, sizeof(buf));
 
 	pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
-	pdu->param_len = cpu_to_be16(10 + sizeof(uint32_t));
+	pdu->param_len = cpu_to_be16(10 + (6 * sizeof(uint32_t)));
 
 	pdu->params[0] = player->scope;
 
 	put_be32(start, &pdu->params[1]);
 	put_be32(end, &pdu->params[5]);
 
-	pdu->params[9] = 1;
+	pdu->params[9] = 6;
 
 	/* Only the title (0x01) is mandatory. This can be extended to
 	 * support AVRCP_MEDIA_ATTRIBUTE_* attributes */
 	put_be32(AVRCP_MEDIA_ATTRIBUTE_TITLE, &pdu->params[10]);
+	put_be32(AVRCP_MEDIA_ATTRIBUTE_ARTIST, &pdu->params[14]);
+	put_be32(AVRCP_MEDIA_ATTRIBUTE_ALBUM, &pdu->params[18]);
+	put_be32(AVRCP_MEDIA_ATTRIBUTE_TRACK, &pdu->params[22]);
+	put_be32(AVRCP_MEDIA_ATTRIBUTE_DURATION, &pdu->params[26]);
+	put_be32(AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE, &pdu->params[30]);
 
-	length += sizeof(uint32_t);
+	length += 6 * sizeof(uint32_t);
 
 	avctp_send_browsing_req(session->conn, buf, length,
 					avrcp_list_items_rsp, session);
@@ -2839,6 +2888,8 @@ static gboolean avrcp_get_item_attributes_rsp(struct avctp *conn,
 	struct avrcp *session = user_data;
 	struct avrcp_player *player = session->controller->player;
 	struct avrcp_browsing_header *pdu = (void *) operands;
+	struct media_player *mp = player->user_data;
+	struct media_item *item;
 	uint8_t count;
 
 	if (pdu == NULL) {
@@ -2858,7 +2909,13 @@ static gboolean avrcp_get_item_attributes_rsp(struct avctp *conn,
 		return FALSE;
 	}
 
-	avrcp_parse_attribute_list(player, &pdu->params[2], count);
+	media_player_clear_metadata(mp);
+
+	item = media_player_set_playlist_item(mp, player->uid);
+
+	avrcp_parse_attribute_list(player, item, &pdu->params[2], count);
+
+	media_player_metadata_changed(mp);
 
 	avrcp_get_play_status(session);
 
@@ -3520,6 +3577,7 @@ static struct avrcp_player *create_ct_player(struct avrcp *session,
 		return NULL;
 	}
 
+	media_player_set_obex_port(mp, session->controller->obex_port);
 	media_player_set_callbacks(mp, &ct_cbs, player);
 	player->user_data = mp;
 	player->destroy = (GDestroyNotify) media_player_destroy;
@@ -3727,6 +3785,11 @@ static void avrcp_volume_changed(struct avrcp *session,
 	struct avrcp_player *player = target_get_player(session);
 	int8_t volume;
 
+	if (!avrcp_volume_supported(session->controller)) {
+		error("EVENT_VOLUME_CHANGED not supported");
+		return;
+	}
+
 	volume = pdu->params[1] & 0x7F;
 
 	/* Always attempt to update the transport volume */
@@ -3802,6 +3865,17 @@ static void avrcp_setting_changed(struct avrcp *session,
 	}
 }
 
+static void avrcp_now_playing_changed(struct avrcp *session,
+						struct avrcp_header *pdu)
+{
+	struct avrcp_player *player = session->controller->player;
+	struct media_player *mp = player->user_data;
+
+	DBG("NowPlaying changed");
+
+	media_player_clear_playlist(mp);
+}
+
 static void avrcp_available_players_changed(struct avrcp *session,
 						struct avrcp_header *pdu)
 {
@@ -3892,6 +3966,9 @@ static gboolean avrcp_handle_event(struct avctp *conn, uint8_t code,
 	case AVRCP_EVENT_SETTINGS_CHANGED:
 		avrcp_setting_changed(session, pdu);
 		break;
+	case AVRCP_EVENT_NOW_PLAYING_CHANGED:
+		avrcp_now_playing_changed(session, pdu);
+		break;
 	case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
 		avrcp_available_players_changed(session, pdu);
 		break;
@@ -3901,6 +3978,12 @@ static gboolean avrcp_handle_event(struct avctp *conn, uint8_t code,
 	case AVRCP_EVENT_UIDS_CHANGED:
 		avrcp_uids_changed(session, pdu);
 		break;
+	default:
+		if (event > AVRCP_EVENT_LAST) {
+			warn("Unsupported event: %u", event);
+			return FALSE;
+		}
+		break;
 	}
 
 	session->registered_events |= (1 << event);
@@ -3977,10 +4060,11 @@ static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
 		case AVRCP_EVENT_TRACK_CHANGED:
 		case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
 		case AVRCP_EVENT_SETTINGS_CHANGED:
+		case AVRCP_EVENT_NOW_PLAYING_CHANGED:
 		case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
 		case AVRCP_EVENT_UIDS_CHANGED:
 		case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
-			/* These events above requires a player */
+			/* These events above require a player */
 			if (!session->controller ||
 						!session->controller->player)
 				break;
@@ -3998,7 +4082,8 @@ static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
 	if (events == (1 << AVRCP_EVENT_VOLUME_CHANGED))
 		return FALSE;
 
-	if ((session->controller->features & AVRCP_FEATURE_PLAYER_SETTINGS) &&
+	if ((session->controller->features &
+			AVRCP_FEATURE_TG_PLAYER_SETTINGS) &&
 			!(events & (1 << AVRCP_EVENT_SETTINGS_CHANGED)))
 		avrcp_list_player_attributes(session);
 
@@ -4067,8 +4152,9 @@ static struct avrcp_data *data_init(struct avrcp *session, const char *uuid)
 {
 	struct avrcp_data *data;
 	const sdp_record_t *rec;
-	sdp_list_t *list;
+	sdp_list_t *list, *protos;
 	sdp_profile_desc_t *desc;
+	int port = 0;
 
 	data = g_new0(struct avrcp_data, 1);
 
@@ -4084,6 +4170,35 @@ static struct avrcp_data *data_init(struct avrcp *session, const char *uuid)
 	sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, &data->features);
 	sdp_list_free(list, free);
 
+	if ((g_strcmp0(uuid, AVRCP_TARGET_UUID) != 0) ||
+			!(data->features & AVRCP_FEATURE_TG_COVERT_ART) ||
+			(sdp_get_add_access_protos(rec, &protos) != 0))
+		return data;
+
+	/* Get the PSM port from the Additional Protocol Descriptor list
+	 * entry containing OBEX UUID
+	 */
+	for (list = protos; list; list = list->next) {
+		sdp_list_t *p;
+
+		for (p = list->data; p; p = p->next) {
+			sdp_data_t *seq = p->data;
+
+			if ((sdp_uuid_to_proto(&seq->val.uuid) == OBEX_UUID) &&
+					SDP_IS_UUID(seq->dtd)) {
+				port = sdp_get_proto_port(list, L2CAP_UUID);
+				goto done;
+			}
+		}
+	}
+
+done:
+	if (port > 0)
+		data->obex_port = port;
+
+	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
+	sdp_list_free(protos, NULL);
+
 	return data;
 }
 
@@ -4153,10 +4268,13 @@ static void target_init(struct avrcp *session)
 	if (target->version < 0x0104)
 		return;
 
+	if (!avrcp_volume_supported(target))
+		session->supported_events |=
+				(1 << AVRCP_EVENT_VOLUME_CHANGED);
+
 	session->supported_events |=
 				(1 << AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED) |
-				(1 << AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED) |
-				(1 << AVRCP_EVENT_VOLUME_CHANGED);
+				(1 << AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED);
 
 	/* Only check capabilities if controller is not supported */
 	if (session->controller == NULL)
@@ -4181,6 +4299,8 @@ static void controller_init(struct avrcp *session)
 	session->controller = controller;
 
 	DBG("%p version 0x%04x", controller, controller->version);
+	if (controller->obex_port)
+		DBG("%p OBEX PSM 0x%04x", controller, controller->obex_port);
 
 	service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
 	btd_service_connecting_complete(service, 0);
@@ -4571,15 +4691,26 @@ int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
 		return -ENOTCONN;
 
 	if (notify) {
-		if (!session->target)
+		if (!avrcp_volume_supported(session->target)) {
+			error("EVENT_VOLUME_CHANGED not supported");
 			return -ENOTSUP;
+		}
 		return avrcp_event(session, AVRCP_EVENT_VOLUME_CHANGED,
 								&volume);
 	}
 
-	if (!session->controller && !avrcp_event_registered(session,
-					AVRCP_EVENT_VOLUME_CHANGED))
+	if (btd_opts.avrcp.volume_without_target) {
+		/* If there is no target profile (we didn't create a controller
+		 * for it), allow the call to pass through if the remote
+		 * controller registered for a volume changed event.
+		 */
+		if (!session->controller && !avrcp_event_registered(session,
+						AVRCP_EVENT_VOLUME_CHANGED))
+			return -ENOTSUP;
+	} else if (!avrcp_volume_supported(session->controller)) {
+		error("SetAbsoluteVolume not supported");
 		return -ENOTSUP;
+	}
 
 	memset(buf, 0, sizeof(buf));
 
diff --git a/profiles/audio/avrcp.h b/profiles/audio/avrcp.h
index dcc580e..887753d 100644
--- a/profiles/audio/avrcp.h
+++ b/profiles/audio/avrcp.h
@@ -46,7 +46,8 @@
 #define AVRCP_MEDIA_ATTRIBUTE_N_TRACKS	0x05
 #define AVRCP_MEDIA_ATTRIBUTE_GENRE	0x06
 #define AVRCP_MEDIA_ATTRIBUTE_DURATION	0x07
-#define AVRCP_MEDIA_ATTRIBUTE_LAST	AVRCP_MEDIA_ATTRIBUTE_DURATION
+#define AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE	0x08
+#define AVRCP_MEDIA_ATTRIBUTE_LAST	AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE
 
 /* play status */
 #define AVRCP_PLAY_STATUS_STOPPED	0x00
@@ -63,6 +64,7 @@
 #define AVRCP_EVENT_TRACK_REACHED_START		0x04
 #define AVRCP_EVENT_PLAYBACK_POS_CHANGED	0x05
 #define AVRCP_EVENT_SETTINGS_CHANGED		0x08
+#define AVRCP_EVENT_NOW_PLAYING_CHANGED		0x09
 #define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED	0x0a
 #define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED	0x0b
 #define AVRCP_EVENT_UIDS_CHANGED		0x0c
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 67aba3b..df685c6 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -33,7 +34,9 @@
 #include "lib/hci.h"
 #include "lib/sdp.h"
 #include "lib/uuid.h"
+#include "lib/iso.h"
 
+#include "src/btd.h"
 #include "src/dbus-common.h"
 #include "src/shared/util.h"
 #include "src/shared/att.h"
@@ -53,27 +56,60 @@
 #include "src/log.h"
 #include "src/error.h"
 
+#include "bap.h"
+#include "bass.h"
+
+#define ISO_SOCKET_UUID "6fbaf188-05e0-496a-9885-d6ddfdb4e03e"
 #define PACS_UUID_STR "00001850-0000-1000-8000-00805f9b34fb"
+#define BCAAS_UUID_STR "00001852-0000-1000-8000-00805f9b34fb"
 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
+#define MEDIA_INTERFACE "org.bluez.Media1"
 
-struct bap_ep {
-	char *path;
-	struct bap_data *data;
-	struct bt_bap_pac *lpac;
-	struct bt_bap_pac *rpac;
+/* Periodic advertisments are performed by an idle timer, which,
+ * at every tick, checks a queue for pending PA requests.
+ * When there is no pending requests, an item is popped from the
+ * queue, marked as pending and then it gets processed.
+ */
+#define PA_IDLE_TIMEOUT 2
+
+struct bap_setup {
+	struct bap_ep *ep;
 	struct bt_bap_stream *stream;
+	struct bt_bap_qos qos;
+	int (*qos_parser)(struct bap_setup *setup, const char *key, int var,
+							DBusMessageIter *iter);
 	GIOChannel *io;
 	unsigned int io_id;
 	bool recreate;
+	bool cig_active;
 	struct iovec *caps;
 	struct iovec *metadata;
-	struct bt_bap_qos qos;
 	unsigned int id;
+	struct iovec *base;
 	DBusMessage *msg;
+	void (*destroy)(struct bap_setup *setup);
+};
+
+struct bap_ep {
+	char *path;
+	struct bap_data *data;
+	struct bt_bap_pac *lpac;
+	struct bt_bap_pac *rpac;
+	uint32_t locations;
+	uint16_t supported_context;
+	uint16_t context;
+	struct queue *setups;
+};
+
+struct bap_adapter {
+	struct btd_adapter *adapter;
+	unsigned int pa_timer_id;
+	struct queue *bcast_pa_requests;
 };
 
 struct bap_data {
 	struct btd_device *device;
+	struct bap_adapter *adapter;
 	struct btd_service *service;
 	struct bt_bap *bap;
 	unsigned int ready_id;
@@ -81,11 +117,83 @@ struct bap_data {
 	unsigned int pac_id;
 	struct queue *srcs;
 	struct queue *snks;
+	struct queue *bcast;
+	struct queue *bcast_snks;
 	struct queue *streams;
 	GIOChannel *listen_io;
+	int selecting;
+	void *user_data;
+};
+
+enum {
+	BAP_PA_SHORT_REQ = 0,	/* Request for short PA sync */
+	BAP_PA_LONG_REQ,	/* Request for long PA sync */
+	BAP_PA_BIG_SYNC_REQ,	/* Request for PA Sync and BIG Sync */
+};
+
+struct bap_bcast_pa_req {
+	uint8_t type;
+	bool in_progress;
+	struct bap_data *bap_data;
+	union {
+		struct btd_service *service;
+		struct queue *setups;
+	} data;
+	unsigned int io_id;	/* io_id for BIG Info watch */
+	GIOChannel *io;
 };
 
 static struct queue *sessions;
+static struct queue *adapters;
+
+/* Structure holding the parameters for Periodic Advertisement create sync.
+ * The full QOS is populated at the time the user selects and endpoint and
+ * configures it using SetConfiguration.
+ */
+static struct bt_iso_qos bap_sink_pa_qos = {
+	.bcast = {
+		.options		= 0x00,
+		.skip			= 0x0000,
+		.sync_timeout		= BT_ISO_SYNC_TIMEOUT,
+		.sync_cte_type	= 0x00,
+		/* TODO: The following parameters are not needed for PA Sync.
+		 * They will be removed when the kernel checks will be removed.
+		 */
+		.big			= BT_ISO_QOS_BIG_UNSET,
+		.bis			= BT_ISO_QOS_BIS_UNSET,
+		.encryption		= 0x00,
+		.bcode			= {0x00},
+		.mse			= 0x00,
+		.timeout		= BT_ISO_SYNC_TIMEOUT,
+		.sync_factor		= 0x07,
+		.packing		= 0x00,
+		.framing		= 0x00,
+		.in = {
+			.interval	= 10000,
+			.latency	= 10,
+			.sdu		= 40,
+			.phy		= 0x02,
+			.rtn		= 2,
+		},
+		.out = {
+			.interval	= 10000,
+			.latency	= 10,
+			.sdu		= 40,
+			.phy		= 0x02,
+			.rtn		= 2,
+		}
+	}
+};
+
+static bool bap_data_set_user_data(struct bap_data *data, void *user_data)
+{
+	if (!data)
+		return false;
+
+	data->user_data = user_data;
+
+	return true;
+}
 
 static void bap_debug(const char *str, void *user_data)
 {
@@ -102,6 +210,8 @@ static void ep_unregister(void *data)
 						MEDIA_ENDPOINT_INTERFACE);
 }
 
+static void setup_free(void *data);
+
 static void bap_data_free(struct bap_data *data)
 {
 	if (data->listen_io) {
@@ -116,10 +226,12 @@ static void bap_data_free(struct bap_data *data)
 
 	queue_destroy(data->snks, ep_unregister);
 	queue_destroy(data->srcs, ep_unregister);
+	queue_destroy(data->bcast, ep_unregister);
 	queue_destroy(data->streams, NULL);
+	queue_destroy(data->bcast_snks, setup_free);
 	bt_bap_ready_unregister(data->bap, data->ready_id);
 	bt_bap_state_unregister(data->bap, data->state_id);
-	bt_bap_pac_unregister(data->pac_id);
+	bt_bap_pac_unregister(data->bap, data->pac_id);
 	bt_bap_unref(data->bap);
 	free(data);
 }
@@ -165,8 +277,13 @@ static gboolean get_uuid(const GDBusPropertyTable *property,
 
 	if (queue_find(ep->data->snks, NULL, ep))
 		uuid = PAC_SINK_UUID;
-	else
+	else if (queue_find(ep->data->srcs, NULL, ep))
 		uuid = PAC_SOURCE_UUID;
+	else if ((queue_find(ep->data->bcast, NULL, ep)
+		&& (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SINK)))
+		uuid = BCAA_SERVICE_UUID;
+	else
+		uuid = BAA_SERVICE_UUID;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
 
@@ -179,13 +296,32 @@ static gboolean get_codec(const GDBusPropertyTable *property,
 	struct bap_ep *ep = data;
 	uint8_t codec;
 
-	bt_bap_pac_get_codec(ep->rpac, &codec, NULL, NULL);
+	/* For broadcast source, rpac is null so the codec
+	 * is retrieved from the lpac
+	 */
+	if (ep->rpac == NULL)
+		bt_bap_pac_get_codec(ep->lpac, &codec, NULL, NULL);
+	else
+		bt_bap_pac_get_codec(ep->rpac, &codec, NULL, NULL);
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &codec);
 
 	return TRUE;
 }
 
+static gboolean has_capabilities(const GDBusPropertyTable *property, void *data)
+{
+	struct bap_ep *ep = data;
+	struct iovec *d = NULL;
+
+	bt_bap_pac_get_codec(ep->rpac, NULL, &d, NULL);
+
+	if (d)
+		return TRUE;
+
+	return FALSE;
+}
+
 static gboolean get_capabilities(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -206,57 +342,353 @@ static gboolean get_capabilities(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean has_metadata(const GDBusPropertyTable *property, void *data)
+{
+	struct bap_ep *ep = data;
+	struct iovec *d = NULL;
+
+	bt_bap_pac_get_codec(ep->rpac, NULL, NULL, &d);
+
+	if (d)
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean get_metadata(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bap_ep *ep = data;
+	DBusMessageIter array;
+	struct iovec *d;
+
+	bt_bap_pac_get_codec(ep->rpac, NULL, NULL, &d);
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+						&d->iov_base, d->iov_len);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
 static gboolean get_device(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct bap_ep *ep = data;
 	const char *path;
 
-	path = device_get_path(ep->data->device);
+	if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE)
+		path = adapter_get_path(ep->data->adapter->adapter);
+	else
+		path = device_get_path(ep->data->device);
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
 
 	return TRUE;
 }
 
+static gboolean get_locations(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bap_ep *ep = data;
+
+	ep->locations = bt_bap_pac_get_locations(ep->rpac);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ep->locations);
+
+	return TRUE;
+}
+
+static gboolean get_supported_context(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bap_ep *ep = data;
+
+	ep->supported_context = bt_bap_pac_get_supported_context(ep->rpac);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&ep->supported_context);
+
+	return TRUE;
+}
+
+static gboolean get_context(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bap_ep *ep = data;
+
+	ep->context = bt_bap_pac_get_context(ep->rpac);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &ep->context);
+
+	return TRUE;
+}
+
+static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct bap_ep *ep = data;
+	struct bt_bap_pac_qos *qos;
+
+	qos = bt_bap_pac_get_qos(ep->rpac);
+	if (!qos)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean get_qos(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bap_ep *ep = data;
+	struct bt_bap_pac_qos *qos;
+	DBusMessageIter dict;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	qos = bt_bap_pac_get_qos(ep->rpac);
+	if (!qos)
+		return FALSE;
+
+	dict_append_entry(&dict, "Framing", DBUS_TYPE_BYTE, &qos->framing);
+	dict_append_entry(&dict, "PHY", DBUS_TYPE_BYTE, &qos->phy);
+	dict_append_entry(&dict, "Retransmissions", DBUS_TYPE_BYTE, &qos->rtn);
+	dict_append_entry(&dict, "MaximumLatency", DBUS_TYPE_UINT16,
+					&qos->latency);
+	dict_append_entry(&dict, "MimimumDelay", DBUS_TYPE_UINT32,
+					&qos->pd_min);
+	dict_append_entry(&dict, "MaximumDelay", DBUS_TYPE_UINT32,
+					&qos->pd_max);
+	dict_append_entry(&dict, "PreferredMimimumDelay", DBUS_TYPE_UINT32,
+					&qos->ppd_min);
+	dict_append_entry(&dict, "PreferredMaximumDelay", DBUS_TYPE_UINT32,
+					&qos->ppd_max);
+
+	dbus_message_iter_close_container(iter, &dict);
+
+	return TRUE;
+}
+
 static const GDBusPropertyTable ep_properties[] = {
 	{ "UUID", "s", get_uuid, NULL, NULL,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{ "Codec", "y", get_codec, NULL, NULL,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
-	{ "Capabilities", "ay", get_capabilities, NULL, NULL,
+	{ "Capabilities", "ay", get_capabilities, NULL, has_capabilities,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Metadata", "ay", get_metadata, NULL, has_metadata,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{ "Device", "o", get_device, NULL, NULL,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Locations", "u", get_locations, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "SupportedContext", "q", get_supported_context, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Context", "q", get_context, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "QoS", "a{sv}", get_qos, NULL, qos_exists,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{ }
 };
 
-static int parse_array(DBusMessageIter *iter, struct iovec **iov)
+static int parse_array(DBusMessageIter *iter, struct iovec *iov)
 {
 	DBusMessageIter array;
 
 	if (!iov)
 		return 0;
 
-	if (!(*iov))
-		*iov = new0(struct iovec, 1);
-
 	dbus_message_iter_recurse(iter, &array);
-	dbus_message_iter_get_fixed_array(&array, &(*iov)->iov_base,
-						(int *)&(*iov)->iov_len);
+	dbus_message_iter_get_fixed_array(&array, &iov->iov_base,
+						(int *)&iov->iov_len);
+
+	return 0;
+}
+
+static int parse_io_qos(const char *key, int var, DBusMessageIter *iter,
+				struct bt_bap_io_qos *qos)
+{
+	if (!strcasecmp(key, "Interval")) {
+		if (var != DBUS_TYPE_UINT32)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->interval);
+	} else if (!strcasecmp(key, "PHY")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->phy);
+	} else if (!strcasecmp(key, "SDU")) {
+		if (var != DBUS_TYPE_UINT16)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->sdu);
+	} else if (!strcasecmp(key, "Retransmissions")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->rtn);
+	} else if (!strcasecmp(key, "Latency")) {
+		if (var != DBUS_TYPE_UINT16)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->latency);
+	}
+
+	return 0;
+}
+
+static int setup_parse_ucast_qos(struct bap_setup *setup, const char *key,
+					int var, DBusMessageIter *iter)
+{
+	struct bt_bap_qos *qos = &setup->qos;
+
+	if (!strcasecmp(key, "CIG")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->ucast.cig_id);
+	} else if (!strcasecmp(key, "CIS")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->ucast.cis_id);
+	} else if (!strcasecmp(key, "Framing")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->ucast.framing);
+	} else if (!strcasecmp(key, "PresentationDelay")) {
+		if (var != DBUS_TYPE_UINT32)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->ucast.delay);
+	} else if (!strcasecmp(key, "TargetLatency")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->ucast.target_latency);
+	} else {
+		int err;
+
+		err = parse_io_qos(key, var, iter, &qos->ucast.io_qos);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static void setup_bcast_destroy(struct bap_setup *setup)
+{
+	struct bt_bap_qos *qos = &setup->qos;
+
+	util_iov_free(qos->bcast.bcode, 1);
+}
+
+static int setup_parse_bcast_qos(struct bap_setup *setup, const char *key,
+					int var, DBusMessageIter *iter)
+{
+	struct bt_bap_qos *qos = &setup->qos;
+
+	if (!strcasecmp(key, "Encryption")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.encryption);
+	} else if (!strcasecmp(key, "BIG")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.big);
+	} else if (!strcasecmp(key, "Options")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.options);
+	} else if (!strcasecmp(key, "Skip")) {
+		if (var != DBUS_TYPE_UINT16)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.skip);
+	} else if (!strcasecmp(key, "SyncTimeout")) {
+		if (var != DBUS_TYPE_UINT16)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.sync_timeout);
+	} else if (!strcasecmp(key, "SyncType")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.sync_cte_type);
+	} else if (!strcasecmp(key, "SyncFactor")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.sync_factor);
+	} else if (!strcasecmp(key, "MSE")) {
+		if (var != DBUS_TYPE_BYTE)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.mse);
+	} else if (!strcasecmp(key, "Timeout")) {
+		if (var != DBUS_TYPE_UINT16)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.timeout);
+	} else if (!strcasecmp(key, "PresentationDelay")) {
+		if (var != DBUS_TYPE_UINT32)
+			return -EINVAL;
+
+		dbus_message_iter_get_basic(iter, &qos->bcast.delay);
+	} else if (!strcasecmp(key, "BCode")) {
+		struct iovec iov;
+
+		if (var != DBUS_TYPE_ARRAY)
+			return -EINVAL;
+
+		memset(&iov, 0, sizeof(iov));
+
+		parse_array(iter, &iov);
+
+		if (iov.iov_len != 16) {
+			error("Invalid size for BCode: %zu != 16", iov.iov_len);
+			return -EINVAL;
+		}
+
+		util_iov_free(qos->bcast.bcode, 1);
+		qos->bcast.bcode = util_iov_dup(&iov, 1);
+	} else {
+		int err;
+
+		err = parse_io_qos(key, var, iter, &qos->bcast.io_qos);
+		if (err)
+			return err;
+	}
+
 	return 0;
 }
 
-static int parse_properties(DBusMessageIter *props, struct iovec **caps,
-				struct iovec **metadata, struct bt_bap_qos *qos)
+static int setup_parse_qos(struct bap_setup *setup, DBusMessageIter *iter)
 {
+	DBusMessageIter array;
 	const char *key;
 
-	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+	dbus_message_iter_recurse(iter, &array);
+
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
 		DBusMessageIter value, entry;
-		int var;
+		int var, err;
 
-		dbus_message_iter_recurse(props, &entry);
+		dbus_message_iter_recurse(&array, &entry);
 		dbus_message_iter_get_basic(&entry, &key);
 
 		dbus_message_iter_next(&entry);
@@ -264,82 +696,62 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 
 		var = dbus_message_iter_get_arg_type(&value);
 
-		if (!strcasecmp(key, "Capabilities")) {
-			if (var != DBUS_TYPE_ARRAY)
-				goto fail;
+		err = setup->qos_parser(setup, key, var, &value);
+		if (err) {
+			DBG("Failed parsing %s", key);
+			return err;
+		}
 
-			if (parse_array(&value, caps))
-				goto fail;
-		} else if (!strcasecmp(key, "Metadata")) {
-			if (var != DBUS_TYPE_ARRAY)
-				goto fail;
+		dbus_message_iter_next(&array);
+	}
 
-			if (parse_array(&value, metadata))
-				goto fail;
-		} else if (!strcasecmp(key, "CIG")) {
-			if (var != DBUS_TYPE_BYTE)
-				goto fail;
+	return 0;
+}
 
-			dbus_message_iter_get_basic(&value, &qos->cig_id);
-		} else if (!strcasecmp(key, "CIS")) {
-			if (var != DBUS_TYPE_BYTE)
-				goto fail;
+static int setup_parse_configuration(struct bap_setup *setup,
+					DBusMessageIter *props)
+{
+	const char *key;
+	struct iovec iov;
 
-			dbus_message_iter_get_basic(&value, &qos->cis_id);
-		} else if (!strcasecmp(key, "Interval")) {
-			if (var != DBUS_TYPE_UINT32)
-				goto fail;
+	memset(&iov, 0, sizeof(iov));
 
-			dbus_message_iter_get_basic(&value, &qos->interval);
-		} else if (!strcasecmp(key, "Framing")) {
-			dbus_bool_t val;
+	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter value, entry;
+		int var;
 
-			if (var != DBUS_TYPE_BOOLEAN)
-				goto fail;
+		dbus_message_iter_recurse(props, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
 
-			dbus_message_iter_get_basic(&value, &val);
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
 
-			qos->framing = val;
-		} else if (!strcasecmp(key, "PHY")) {
-			const char *str;
+		var = dbus_message_iter_get_arg_type(&value);
 
-			if (var != DBUS_TYPE_STRING)
+		if (!strcasecmp(key, "Capabilities")) {
+			if (var != DBUS_TYPE_ARRAY)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &str);
-
-			if (!strcasecmp(str, "1M"))
-				qos->phy = 0x01;
-			else if (!strcasecmp(str, "2M"))
-				qos->phy = 0x02;
-			else
-				goto fail;
-		} else if (!strcasecmp(key, "SDU")) {
-			if (var != DBUS_TYPE_UINT16)
+			if (parse_array(&value, &iov))
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->sdu);
-		} else if (!strcasecmp(key, "Retransmissions")) {
-			if (var != DBUS_TYPE_BYTE)
+			util_iov_free(setup->caps, 1);
+			setup->caps = util_iov_dup(&iov, 1);
+		} else if (!strcasecmp(key, "Metadata")) {
+			if (var != DBUS_TYPE_ARRAY)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->rtn);
-		} else if (!strcasecmp(key, "Latency")) {
-			if (var != DBUS_TYPE_UINT16)
+			if (parse_array(&value, &iov))
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->latency);
-		} else if (!strcasecmp(key, "Delay")) {
-			if (var != DBUS_TYPE_UINT32)
+			util_iov_free(setup->metadata, 1);
+			setup->metadata = util_iov_dup(&iov, 1);
+		} else if (!strcasecmp(key, "QoS")) {
+			if (var != DBUS_TYPE_ARRAY)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->delay);
-		} else if (!strcasecmp(key, "TargetLatency")) {
-			if (var != DBUS_TYPE_BYTE)
+			if (setup_parse_qos(setup, &value))
 				goto fail;
-
-			dbus_message_iter_get_basic(&value,
-							&qos->target_latency);
 		}
 
 		dbus_message_iter_next(props);
@@ -350,92 +762,184 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 fail:
 	DBG("Failed parsing %s", key);
 
-	if (*caps) {
-		free(*caps);
-		*caps = NULL;
-	}
-
 	return -EINVAL;
 }
 
 static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason,
 					void *user_data)
 {
-	struct bap_ep *ep = user_data;
+	struct bap_setup *setup = user_data;
 	DBusMessage *reply;
 
 	DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason);
 
-	if (!ep->msg)
+	setup->id = 0;
+
+	if (!setup->msg)
 		return;
 
 	if (!code)
-		reply = dbus_message_new_method_return(ep->msg);
+		reply = dbus_message_new_method_return(setup->msg);
 	else
-		reply = btd_error_failed(ep->msg, "Unable to configure");
+		reply = btd_error_failed(setup->msg, "Unable to configure");
 
 	g_dbus_send_message(btd_get_dbus_connection(), reply);
 
-	dbus_message_unref(ep->msg);
-	ep->msg = NULL;
+	dbus_message_unref(setup->msg);
+	setup->msg = NULL;
 }
 
 static void config_cb(struct bt_bap_stream *stream,
 					uint8_t code, uint8_t reason,
 					void *user_data)
 {
-	struct bap_ep *ep = user_data;
+	struct bap_setup *setup = user_data;
 	DBusMessage *reply;
 
 	DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason);
 
-	ep->id = 0;
+	setup->id = 0;
+
+	if (!code) {
+		/* Check state is already set to config then proceed to qos */
+		if (bt_bap_stream_get_state(stream) ==
+					BT_BAP_STREAM_STATE_CONFIG) {
+			setup->id = bt_bap_stream_qos(stream, &setup->qos,
+							qos_cb, setup);
+			if (!setup->id) {
+				error("Failed to Configure QoS");
+				bt_bap_stream_release(stream, NULL, NULL);
+			}
+		}
 
-	if (!code)
 		return;
+	}
 
-	if (!ep->msg)
+	if (!setup->msg)
 		return;
 
-	reply = btd_error_failed(ep->msg, "Unable to configure");
+	reply = btd_error_failed(setup->msg, "Unable to configure");
 	g_dbus_send_message(btd_get_dbus_connection(), reply);
 
-	dbus_message_unref(ep->msg);
-	ep->msg = NULL;
+	dbus_message_unref(setup->msg);
+	setup->msg = NULL;
 }
 
-static void bap_io_close(struct bap_ep *ep)
+static void setup_io_close(void *data, void *user_data)
 {
+	struct bap_setup *setup = data;
 	int fd;
 
-	if (ep->io_id) {
-		g_source_remove(ep->io_id);
-		ep->io_id = 0;
+	if (setup->io_id) {
+		g_source_remove(setup->io_id);
+		setup->io_id = 0;
 	}
 
-	if (!ep->io)
+	if (!setup->io)
 		return;
 
 
-	DBG("ep %p", ep);
+	DBG("setup %p", setup);
 
-	fd = g_io_channel_unix_get_fd(ep->io);
+	fd = g_io_channel_unix_get_fd(setup->io);
 	close(fd);
 
-	g_io_channel_unref(ep->io);
-	ep->io = NULL;
+	g_io_channel_unref(setup->io);
+	setup->io = NULL;
+	setup->cig_active = false;
+
+	bt_bap_stream_io_connecting(setup->stream, -1);
+}
+
+static void ep_close(struct bap_ep *ep)
+{
+	if (!ep)
+		return;
+
+	queue_foreach(ep->setups, setup_io_close, NULL);
+}
+
+static struct bap_setup *setup_new(struct bap_ep *ep)
+{
+	struct bap_setup *setup;
+
+	setup = new0(struct bap_setup, 1);
+	setup->ep = ep;
+
+	/* Broadcast Source has endpoints in bcast list, Broadcast Sink
+	 * does not have endpoints
+	 */
+	if (((ep != NULL) && queue_find(ep->data->bcast, NULL, ep)) ||
+			(ep == NULL)) {
+		/* Mark BIG and BIS to be auto assigned */
+		setup->qos.bcast.big = BT_ISO_QOS_BIG_UNSET;
+		setup->qos.bcast.bis = BT_ISO_QOS_BIS_UNSET;
+		setup->qos.bcast.sync_factor = 0x01;
+		setup->qos.bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
+		setup->qos.bcast.timeout = BT_ISO_SYNC_TIMEOUT;
+		setup->qos_parser = setup_parse_bcast_qos;
+		setup->destroy = setup_bcast_destroy;
+	} else {
+		/* Mark CIG and CIS to be auto assigned */
+		setup->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
+		setup->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
+		setup->qos_parser = setup_parse_ucast_qos;
+	}
+
+	if (ep) {
+		if (!ep->setups)
+			ep->setups = queue_new();
+
+		queue_push_tail(ep->setups, setup);
+
+		DBG("ep %p setup %p", ep, setup);
+	}
+
+	return setup;
+}
+
+static void setup_free(void *data)
+{
+	struct bap_setup *setup = data;
+	DBusMessage *reply;
+
+	DBG("%p", setup);
+
+	if (setup->stream && setup->id) {
+		bt_bap_stream_cancel(setup->stream, setup->id);
+		setup->id = 0;
+	}
+
+	if (setup->msg) {
+		reply = btd_error_failed(setup->msg, "Canceled");
+		g_dbus_send_message(btd_get_dbus_connection(), reply);
+		dbus_message_unref(setup->msg);
+		setup->msg = NULL;
+	}
+
+	if (setup->ep)
+		queue_remove(setup->ep->setups, setup);
+
+	setup_io_close(setup, NULL);
+
+	util_iov_free(setup->caps, 1);
+	util_iov_free(setup->metadata, 1);
+	util_iov_free(setup->base, 1);
+
+	if (setup->destroy)
+		setup->destroy(setup);
+
+	free(setup);
 }
 
 static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
 	struct bap_ep *ep = data;
+	struct bap_setup *setup;
 	const char *path;
 	DBusMessageIter args, props;
 
-	if (ep->msg)
-		return btd_error_busy(msg);
-
 	dbus_message_iter_init(msg, &args);
 
 	dbus_message_iter_get_basic(&args, &path);
@@ -445,67 +949,526 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
 	if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
 		return btd_error_invalid_args(msg);
 
-	/* Disconnect IO if connecting since QoS is going to be reconfigured */
-	if (bt_bap_stream_io_is_connecting(ep->stream, NULL)) {
-		bap_io_close(ep);
-		bt_bap_stream_io_connecting(ep->stream, -1);
-	}
+	/* Broadcast source supports multiple setups, each setup will be BIS
+	 * and will be configured with the set_configuration command
+	 * TO DO reconfiguration of a BIS.
+	 */
+	if (bt_bap_pac_get_type(ep->lpac) != BT_BAP_BCAST_SOURCE)
+		ep_close(ep);
 
-	/* Mark CIG and CIS to be auto assigned */
-	ep->qos.cig_id = BT_ISO_QOS_CIG_UNSET;
-	ep->qos.cis_id = BT_ISO_QOS_CIS_UNSET;
+	setup = setup_new(ep);
 
-	if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) {
-		DBG("Unable to parse properties");
+	if (setup_parse_configuration(setup, &props) < 0) {
+		DBG("Unable to parse configuration");
+		setup_free(setup);
 		return btd_error_invalid_args(msg);
 	}
 
-	/* TODO: Check if stream capabilities match add support for Latency
-	 * and PHY.
-	 */
-	if (ep->stream)
-		ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
-						config_cb, ep);
-	else
-		ep->stream = bt_bap_config(ep->data->bap, ep->lpac, ep->rpac,
-						&ep->qos, ep->caps,
-						config_cb, ep);
-
-	if (!ep->stream) {
+	setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac,
+						&setup->qos, setup->caps);
+	bt_bap_stream_set_user_data(setup->stream, ep->path);
+	setup->id = bt_bap_stream_config(setup->stream, &setup->qos,
+						setup->caps, config_cb, setup);
+	if (!setup->id) {
 		DBG("Unable to config stream");
-		free(ep->caps);
-		ep->caps = NULL;
+		setup_free(setup);
 		return btd_error_invalid_args(msg);
 	}
 
-	bt_bap_stream_set_user_data(ep->stream, ep->path);
-	ep->msg = dbus_message_ref(msg);
+	if (setup->metadata && setup->metadata->iov_len)
+		bt_bap_stream_metadata(setup->stream, setup->metadata, NULL,
+								NULL);
+
+	switch (bt_bap_stream_get_type(setup->stream)) {
+	case BT_BAP_STREAM_TYPE_UCAST:
+		setup->msg = dbus_message_ref(msg);
+		break;
+	case BT_BAP_STREAM_TYPE_BCAST:
+		/* No message sent over the air for broadcast */
+		setup->id = 0;
+
+		if (ep->data->service)
+			service_set_connecting(ep->data->service);
+
+		return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+	}
 
 	return NULL;
 }
 
-static const GDBusMethodTable ep_methods[] = {
+static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
+{
+	struct bap_bcast_pa_req *req = user_data;
+	struct bap_setup *setup;
+	int fd;
+	struct bap_data *bap_data = req->bap_data;
+
+	DBG("BIG Sync completed");
+
+	/* The order of the BIS fds notified from kernel corresponds
+	 * to the order of the BISes that were enqueued before
+	 * calling bt_io_bcast_accept.
+	 */
+	setup = queue_pop_head(req->data.setups);
+
+	if (queue_isempty(req->data.setups)) {
+		/* All fds have been notified. Mark service as connected. */
+		btd_service_connecting_complete(bap_data->service, 0);
+
+		if (req->io) {
+			g_io_channel_unref(req->io);
+			g_io_channel_shutdown(req->io, TRUE, NULL);
+			req->io = NULL;
+		}
+
+		queue_remove(bap_data->adapter->bcast_pa_requests, req);
+		queue_destroy(req->data.setups, NULL);
+		free(req);
+	}
+
+	fd = g_io_channel_unix_get_fd(io);
+
+	if (bt_bap_stream_set_io(setup->stream, fd)) {
+		g_io_channel_set_close_on_unref(io, FALSE);
+		return;
+	}
+}
+
+static void print_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+		void *user_data)
+{
+	util_debug(user_data, NULL, "CC #%zu: l:%u t:%u", i, l, t);
+	util_hexdump(' ', v, l, user_data, NULL);
+}
+
+static void create_stream_for_bis(struct bap_data *bap_data,
+		struct bt_bap_pac *lpac, struct bt_iso_qos *qos,
+		struct iovec *caps, struct iovec *meta, char *path)
+{
+	struct bap_setup *setup;
+
+	setup = setup_new(NULL);
+
+	/* Create BAP QoS structure */
+	setup->qos.bcast.big = qos->bcast.big;
+	setup->qos.bcast.bis = qos->bcast.bis;
+	setup->qos.bcast.sync_factor = qos->bcast.sync_factor;
+	setup->qos.bcast.packing = qos->bcast.packing;
+	setup->qos.bcast.framing = qos->bcast.framing;
+	setup->qos.bcast.encryption = qos->bcast.encryption;
+	if (setup->qos.bcast.encryption)
+		setup->qos.bcast.bcode = util_iov_new(qos->bcast.bcode,
+						sizeof(qos->bcast.bcode));
+	setup->qos.bcast.options = qos->bcast.options;
+	setup->qos.bcast.skip = qos->bcast.skip;
+	setup->qos.bcast.sync_timeout = qos->bcast.sync_timeout;
+	setup->qos.bcast.sync_cte_type =
+			qos->bcast.sync_cte_type;
+	setup->qos.bcast.mse = qos->bcast.mse;
+	setup->qos.bcast.timeout = qos->bcast.timeout;
+	setup->qos.bcast.io_qos.interval =
+			qos->bcast.in.interval;
+	setup->qos.bcast.io_qos.latency = qos->bcast.in.latency;
+	setup->qos.bcast.io_qos.phy = qos->bcast.in.phy;
+	setup->qos.bcast.io_qos.rtn = qos->bcast.in.rtn;
+	setup->qos.bcast.io_qos.sdu = qos->bcast.in.sdu;
+
+	queue_push_tail(bap_data->bcast_snks, setup);
+
+	/* Create and configure stream */
+	setup->stream = bt_bap_stream_new(bap_data->bap,
+			lpac, NULL, &setup->qos, caps);
+
+	bt_bap_stream_set_user_data(setup->stream, path);
+	bt_bap_stream_config(setup->stream, &setup->qos,
+			caps, NULL, NULL);
+	bt_bap_stream_metadata(setup->stream, meta,
+			NULL, NULL);
+}
+
+static bool parse_base(struct bap_data *bap_data, struct bt_iso_base *base,
+		struct bt_iso_qos *qos, util_debug_func_t func)
+{
+	struct iovec iov = {
+		.iov_base = base->base,
+		.iov_len = base->base_len,
+	};
+	uint32_t pres_delay;
+	uint8_t num_subgroups;
+	bool ret = true;
+
+	util_debug(func, NULL, "BASE len: %ld", iov.iov_len);
+
+	if (!util_iov_pull_le24(&iov, &pres_delay))
+		return false;
+	util_debug(func, NULL, "PresentationDelay: %d", pres_delay);
+
+	if (!util_iov_pull_u8(&iov, &num_subgroups))
+		return false;
+	util_debug(func, NULL, "Number of Subgroups: %d", num_subgroups);
+
+	/* Loop subgroups */
+	for (int idx = 0; idx < num_subgroups; idx++) {
+		uint8_t num_bis;
+		struct bt_bap_codec codec;
+		struct iovec *l2_caps = NULL;
+		struct iovec *meta = NULL;
+
+		util_debug(func, NULL, "Subgroup #%d", idx);
+
+		if (!util_iov_pull_u8(&iov, &num_bis)) {
+			ret = false;
+			goto fail;
+		}
+		util_debug(func, NULL, "Number of BISes: %d", num_bis);
+
+		memcpy(&codec,
+				util_iov_pull_mem(&iov,
+						sizeof(struct bt_bap_codec)),
+				sizeof(struct bt_bap_codec));
+		util_debug(func, NULL, "Codec: ID %d CID 0x%2.2x VID 0x%2.2x",
+				codec.id, codec.cid, codec.vid);
+
+		/* Level 2 */
+		/* Read Codec Specific Configuration */
+		l2_caps = new0(struct iovec, 1);
+		if (!util_iov_pull_u8(&iov, (void *)&l2_caps->iov_len)) {
+			ret = false;
+			goto group_fail;
+		}
+
+		util_iov_memcpy(l2_caps, util_iov_pull_mem(&iov,
+				l2_caps->iov_len),
+				l2_caps->iov_len);
+
+		/* Print Codec Specific Configuration */
+		util_debug(func, NULL, "CC len: %ld", l2_caps->iov_len);
+		util_ltv_foreach(l2_caps->iov_base, l2_caps->iov_len, NULL,
+				print_ltv, func);
+
+		/* Read Metadata */
+		meta = new0(struct iovec, 1);
+		if (!util_iov_pull_u8(&iov, (void *)&meta->iov_len)) {
+			ret = false;
+			goto group_fail;
+		}
+
+		util_iov_memcpy(meta,
+				util_iov_pull_mem(&iov, meta->iov_len),
+				meta->iov_len);
+
+		/* Print Metadata */
+		util_debug(func, NULL, "Metadata len: %i",
+				(uint8_t)meta->iov_len);
+		util_hexdump(' ', meta->iov_base, meta->iov_len, func, NULL);
+
+		/* Level 3 */
+		for (; num_bis; num_bis--) {
+			uint8_t bis_index;
+			struct iovec *l3_caps;
+			struct iovec *merged_caps;
+			struct bt_bap_pac *matched_lpac;
+			char *path;
+			int err;
+
+			if (!util_iov_pull_u8(&iov, &bis_index)) {
+				ret = false;
+				goto group_fail;
+			}
+
+			util_debug(func, NULL, "BIS #%d", bis_index);
+			err = asprintf(&path, "%s/bis%d",
+					device_get_path(bap_data->device),
+					bis_index);
+			if (err < 0)
+				continue;
+
+			/* Read Codec Specific Configuration */
+			l3_caps = new0(struct iovec, 1);
+			if (!util_iov_pull_u8(&iov,
+						(void *)&l3_caps->iov_len)) {
+				free(l3_caps);
+				free(path);
+				ret = false;
+				goto group_fail;
+			}
+
+			util_iov_memcpy(l3_caps,
+					util_iov_pull_mem(&iov,
+							l3_caps->iov_len),
+					l3_caps->iov_len);
+
+			/* Print Codec Specific Configuration */
+			util_debug(func, NULL, "CC Len: %d",
+					(uint8_t)l3_caps->iov_len);
+			util_ltv_foreach(l3_caps->iov_base,
+					l3_caps->iov_len, NULL, print_ltv,
+					func);
+
+			merged_caps = bt_bap_merge_caps(l2_caps, l3_caps);
+			if (!merged_caps) {
+				free(path);
+				continue;
+			}
+
+			bass_add_stream(bap_data->device, meta, merged_caps,
+						qos, idx, bis_index);
+
+			if (!bass_check_bis(bap_data->device, bis_index)) {
+				/* If this Broadcast Sink is acting as a Scan
+				 * Delegator, only attempt to create streams
+				 * for the BISes required by the peer Broadcast
+				 * Assistant.
+				 */
+				continue;
+			}
+
+			/* Check if this BIS matches any local PAC */
+			bt_bap_verify_bis(bap_data->bap, bis_index,
+					merged_caps, &matched_lpac);
+
+			if (matched_lpac == NULL) {
+				free(path);
+				continue;
+			}
+
+			create_stream_for_bis(bap_data, matched_lpac, qos,
+					merged_caps, meta, path);
+		}
+
+group_fail:
+		if (l2_caps != NULL)
+			free(l2_caps);
+		if (meta != NULL)
+			free(meta);
+		if (!ret)
+			break;
+	}
+
+fail:
+	if (!ret)
+		util_debug(func, NULL, "Unable to parse Base");
+
+	return ret;
+}
+
+static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	GError *err = NULL;
+	struct bap_bcast_pa_req *req = user_data;
+	struct bap_data *data = btd_service_get_user_data(req->data.service);
+	struct bt_iso_base base;
+	struct bt_iso_qos qos;
+
+	DBG("BIG Info received");
+
+	bt_io_get(io, &err,
+			BT_IO_OPT_BASE, &base,
+			BT_IO_OPT_QOS, &qos,
+			BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		g_io_channel_shutdown(io, TRUE, NULL);
+		req->io_id = 0;
+		return FALSE;
+	}
+
+	/* Close the listen io */
+	g_io_channel_shutdown(data->listen_io, TRUE, NULL);
+	g_io_channel_unref(data->listen_io);
+	data->listen_io = NULL;
+
+	if (req->type == BAP_PA_LONG_REQ) {
+		/* If long-lived PA sync was requested, keep a reference
+		 * to the PA sync io to keep the sync active.
+		 */
+		data->listen_io = io;
+		g_io_channel_ref(io);
+	} else {
+		/* For short-lived PA, the sync is no longer needed at
+		 * this point, so the io can be closed.
+		 */
+		g_io_channel_shutdown(io, TRUE, NULL);
+	}
+
+	/* Notify the BASS plugin about the session. */
+	bass_bcast_probe(data->device, data->bap);
+
+	/* Analyze received BASE data and create remote media endpoints for each
+	 * BIS matching our capabilities
+	 */
+	parse_base(data, &base, &qos, bap_debug);
+
+	service_set_connecting(req->data.service);
+
+	queue_remove(data->adapter->bcast_pa_requests, req);
+	req->io_id = 0;
+	free(req);
+
+	return FALSE;
+}
+
+static void iso_pa_sync_confirm_cb(GIOChannel *io, void *user_data)
+{
+	struct bap_bcast_pa_req *req = user_data;
+	/* PA Sync was established, wait for BIG Info report so that the
+	 * encryption flag is also available.
+	 */
+	DBG("PA Sync done");
+	req->io_id = g_io_add_watch(io, G_IO_OUT, big_info_report_cb,
+								user_data);
+}
+
+static bool match_data_bap_data(const void *data, const void *match_data)
+{
+	const struct bap_data *bdata = data;
+	const struct btd_adapter *adapter = match_data;
+
+	return bdata->user_data == adapter;
+}
+
+static const GDBusMethodTable ep_methods[] = {
 	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("SetConfiguration",
 					GDBUS_ARGS({ "endpoint", "o" },
-						{ "properties", "a{sv}" } ),
+						{ "Configuration", "a{sv}" } ),
 					NULL, set_configuration) },
 	{ },
 };
 
+static void ep_cancel_select(struct bap_ep *ep);
+
 static void ep_free(void *data)
 {
 	struct bap_ep *ep = data;
+	struct queue *setups = ep->setups;
 
-	if (ep->id)
-		bt_bap_stream_cancel(ep->stream, ep->id);
+	ep_cancel_select(ep);
 
-	bap_io_close(ep);
-
-	free(ep->caps);
+	ep->setups = NULL;
+	queue_destroy(setups, setup_free);
 	free(ep->path);
 	free(ep);
 }
 
+struct match_ep {
+	struct bt_bap_pac *lpac;
+	struct bt_bap_pac *rpac;
+};
+
+static bool match_ep(const void *data, const void *user_data)
+{
+	const struct bap_ep *ep = data;
+	const struct match_ep *match = user_data;
+
+	if (ep->lpac != match->lpac)
+		return false;
+
+	return ep->rpac == match->rpac;
+}
+
+static struct bap_ep *ep_register_bcast(struct bap_data *data,
+					struct bt_bap_pac *lpac,
+					struct bt_bap_pac *rpac)
+{
+	struct btd_adapter *adapter = data->adapter->adapter;
+	struct btd_device *device = data->device;
+	struct bap_ep *ep;
+	struct queue *queue;
+	int i, err = 0;
+	const char *suffix;
+	struct match_ep match = { lpac, rpac };
+
+	switch (bt_bap_pac_get_type(lpac)) {
+	case BT_BAP_BCAST_SOURCE:
+	case BT_BAP_BCAST_SINK:
+		queue = data->bcast;
+		i = queue_length(data->bcast);
+		suffix = "bcast";
+		break;
+	default:
+		return NULL;
+	}
+
+	ep = queue_find(queue, match_ep, &match);
+	if (ep)
+		return ep;
+
+	ep = new0(struct bap_ep, 1);
+	ep->data = data;
+	ep->lpac = lpac;
+	ep->rpac = rpac;
+
+	if (device)
+		ep->data->device = device;
+
+	switch (bt_bap_pac_get_type(lpac)) {
+	case BT_BAP_BCAST_SOURCE:
+		err = asprintf(&ep->path, "%s/pac_%s%d",
+				adapter_get_path(adapter), suffix, i);
+		break;
+	case BT_BAP_BCAST_SINK:
+		err = asprintf(&ep->path, "%s/pac_%s%d",
+				device_get_path(device), suffix, i);
+		break;
+	}
+
+	if (err < 0) {
+		error("Could not allocate path for remote pac %s/pac%d",
+				adapter_get_path(adapter), i);
+		free(ep);
+		return NULL;
+	}
+
+	if (g_dbus_register_interface(btd_get_dbus_connection(),
+			ep->path, MEDIA_ENDPOINT_INTERFACE,
+			ep_methods, NULL, ep_properties,
+			ep, ep_free) == FALSE) {
+		error("Could not register remote ep %s", ep->path);
+		ep_free(ep);
+		return NULL;
+	}
+
+	/*
+	 * The broadcast source local endpoint has only lpac and broadcast
+	 * sink local endpoint has a rpac and a lpac
+	 */
+	if (rpac)
+		bt_bap_pac_set_user_data(rpac, ep->path);
+
+	DBG("ep %p lpac %p rpac %p path %s", ep, ep->lpac, ep->rpac, ep->path);
+
+	queue_push_tail(queue, ep);
+
+	return ep;
+}
+
+static void ep_update_properties(struct bap_ep *ep)
+{
+	if (!ep->rpac)
+		return;
+
+	if (ep->locations != bt_bap_pac_get_locations(ep->rpac))
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						ep->path,
+						MEDIA_ENDPOINT_INTERFACE,
+						"Locations");
+
+	if (ep->supported_context !=
+				bt_bap_pac_get_supported_context(ep->rpac))
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						ep->path,
+						MEDIA_ENDPOINT_INTERFACE,
+						"SupportedContext");
+
+	if (ep->context != bt_bap_pac_get_context(ep->rpac))
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						ep->path,
+						MEDIA_ENDPOINT_INTERFACE,
+						"Context");
+}
+
 static struct bap_ep *ep_register(struct btd_service *service,
 					struct bt_bap_pac *lpac,
 					struct bt_bap_pac *rpac)
@@ -516,6 +1479,7 @@ static struct bap_ep *ep_register(struct btd_service *service,
 	struct queue *queue;
 	int i, err;
 	const char *suffix;
+	struct match_ep match = { lpac, rpac };
 
 	switch (bt_bap_pac_get_type(rpac)) {
 	case BT_BAP_SINK:
@@ -532,6 +1496,12 @@ static struct bap_ep *ep_register(struct btd_service *service,
 		return NULL;
 	}
 
+	ep = queue_find(queue, match_ep, &match);
+	if (ep) {
+		ep_update_properties(ep);
+		return ep;
+	}
+
 	ep = new0(struct bap_ep, 1);
 	ep->data = data;
 	ep->lpac = lpac;
@@ -564,42 +1534,75 @@ static struct bap_ep *ep_register(struct btd_service *service,
 	return ep;
 }
 
+static void setup_config(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	struct bap_ep *ep = setup->ep;
+
+	DBG("setup %p caps %p metadata %p", setup, setup->caps,
+						setup->metadata);
+
+	/* TODO: Check if stream capabilities match add support for Latency
+	 * and PHY.
+	 */
+	if (!setup->stream)
+		setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac,
+						ep->rpac, &setup->qos,
+						setup->caps);
+
+	setup->id = bt_bap_stream_config(setup->stream, &setup->qos,
+						setup->caps, config_cb, setup);
+	if (!setup->id) {
+		DBG("Unable to config stream");
+		setup_free(setup);
+		return;
+	}
+
+	if (setup->metadata && setup->metadata->iov_len)
+		bt_bap_stream_metadata(setup->stream, setup->metadata, NULL,
+								NULL);
+
+	bt_bap_stream_set_user_data(setup->stream, ep->path);
+}
+
+static void bap_config(void *data, void *user_data)
+{
+	struct bap_ep *ep = data;
+
+	queue_foreach(ep->setups, setup_config, NULL);
+}
+
 static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
 				struct iovec *metadata, struct bt_bap_qos *qos,
 				void *user_data)
 {
 	struct bap_ep *ep = user_data;
+	struct bap_setup *setup;
 
 	if (err) {
 		error("err %d", err);
-		return;
+		ep->data->selecting--;
+		goto done;
 	}
 
-	ep->caps = caps;
-	ep->metadata = metadata;
-	ep->qos = *qos;
+	setup = setup_new(ep);
+	setup->caps = util_iov_dup(caps, 1);
+	setup->metadata = util_iov_dup(metadata, 1);
+	setup->qos = *qos;
 
-	/* TODO: Check if stream capabilities match add support for Latency
-	 * and PHY.
-	 */
-	if (ep->stream)
-		ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
-						config_cb, ep);
-	else
-		ep->stream = bt_bap_config(ep->data->bap, ep->lpac, ep->rpac,
-						&ep->qos, ep->caps,
-						config_cb, ep);
+	DBG("selecting %d", ep->data->selecting);
+	ep->data->selecting--;
 
-	if (!ep->stream) {
-		DBG("Unable to config stream");
-		free(ep->caps);
-		ep->caps = NULL;
-	}
+done:
+	if (ep->data->selecting)
+		return;
 
-	bt_bap_stream_set_user_data(ep->stream, ep->path);
+	queue_foreach(ep->data->srcs, bap_config, NULL);
+	queue_foreach(ep->data->snks, bap_config, NULL);
+	queue_foreach(ep->data->bcast, bap_config, NULL);
 }
 
-static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+static bool pac_register(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 							void *user_data)
 {
 	struct btd_service *service = user_data;
@@ -608,14 +1611,80 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	DBG("lpac %p rpac %p", lpac, rpac);
 
 	ep = ep_register(service, lpac, rpac);
-	if (!ep) {
+	if (!ep)
 		error("Unable to register endpoint for pac %p", rpac);
+
+	return true;
+}
+
+static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
+{
+	struct btd_service *service = user_data;
+	struct bap_data *data = btd_service_get_user_data(service);
+	struct match_ep match = { lpac, rpac };
+	struct queue *queue;
+	struct bap_ep *ep;
+
+	switch (bt_bap_pac_get_type(rpac)) {
+	case BT_BAP_SINK:
+		queue = data->snks;
+		break;
+	case BT_BAP_SOURCE:
+		queue = data->srcs;
+		break;
+	default:
+		return true;
+	}
+
+	ep = queue_find(queue, match_ep, &match);
+	if (!ep) {
+		error("Unable to find endpoint for pac %p", rpac);
 		return true;
 	}
 
 	/* TODO: Cache LRU? */
 	if (btd_service_is_initiator(service))
-		bt_bap_select(lpac, rpac, select_cb, ep);
+		bt_bap_select(lpac, rpac, &ep->data->selecting, select_cb, ep);
+
+	return true;
+}
+
+static bool pac_cancel_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
+{
+	struct bap_ep *ep = user_data;
+
+	bt_bap_cancel_select(lpac, select_cb, ep);
+
+	return true;
+}
+
+static void ep_cancel_select(struct bap_ep *ep)
+{
+	struct bt_bap *bap = ep->data->bap;
+
+	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_cancel_select, ep);
+	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_cancel_select, ep);
+}
+
+static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
+{
+	struct bap_data *data = user_data;
+	struct bap_ep *ep;
+
+	DBG("lpac %p rpac %p", lpac, rpac);
+
+	ep = ep_register_bcast(user_data, lpac, rpac);
+	if (!ep) {
+		error("Unable to register endpoint for pac %p", rpac);
+		return true;
+	}
+
+	/* Mark the device as connetable if an Endpoint is registered */
+	if (data->device)
+		btd_device_set_connectable(data->device, true);
 
 	return true;
 }
@@ -626,28 +1695,82 @@ static void bap_ready(struct bt_bap *bap, void *user_data)
 
 	DBG("bap %p", bap);
 
-	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_found, service);
-	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_found, service);
+	/* Register all ep before selecting, so that sound server
+	 * knows all.
+	 */
+	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_register, service);
+	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_register, service);
+
+	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_select, service);
+	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_select, service);
+}
+
+static bool match_setup_stream(const void *data, const void *user_data)
+{
+	const struct bap_setup *setup = data;
+	const struct bt_bap_stream *stream = user_data;
+
+	return setup->stream == stream;
 }
 
-static bool match_ep_by_stream(const void *data, const void *user_data)
+static bool match_ep_stream(const void *data, const void *user_data)
 {
 	const struct bap_ep *ep = data;
 	const struct bt_bap_stream *stream = user_data;
 
-	return ep->stream == stream;
+	return queue_find(ep->setups, match_setup_stream, stream);
 }
 
-static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data,
+static struct bap_setup *bap_find_setup_by_stream(struct bap_data *data,
 					struct bt_bap_stream *stream)
 {
-	struct bap_ep *ep;
+	struct bap_ep *ep = NULL;
+	struct queue *queue = NULL;
+
+	switch (bt_bap_stream_get_type(stream)) {
+	case BT_BAP_STREAM_TYPE_UCAST:
+		ep = queue_find(data->snks, match_ep_stream, stream);
+		if (!ep)
+			ep = queue_find(data->srcs, match_ep_stream, stream);
+
+		break;
+	case BT_BAP_STREAM_TYPE_BCAST:
+		ep = queue_find(data->bcast, match_ep_stream, stream);
+		break;
+	}
 
-	ep = queue_find(data->snks, match_ep_by_stream, stream);
 	if (ep)
-		return ep;
+		queue = ep->setups;
+	else
+		queue = data->bcast_snks;
 
-	return queue_find(data->srcs, match_ep_by_stream, stream);
+	return queue_find(queue, match_setup_stream, stream);
+}
+
+static void iso_connect_bcast_cb(GIOChannel *chan, GError *err,
+					gpointer user_data)
+{
+	struct bt_bap_stream *stream = user_data;
+	int fd;
+
+	if (err) {
+		error("%s", err->message);
+		bt_bap_stream_set_io(stream, -1);
+		return;
+	}
+
+	DBG("ISO connected");
+
+	fd = g_io_channel_unix_get_fd(chan);
+
+	if (bt_bap_stream_set_io(stream, fd)) {
+		bt_bap_stream_start(stream, NULL, NULL);
+		g_io_channel_set_close_on_unref(chan, FALSE);
+		return;
+	}
+
+	error("Unable to set IO");
+	bt_bap_stream_set_io(stream, -1);
 }
 
 static void iso_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -679,11 +1802,11 @@ static void bap_iso_qos(struct bt_bap_qos *qos, struct bt_iso_io_qos *io)
 	if (!qos)
 		return;
 
-	io->interval = qos->interval;
-	io->latency = qos->latency;
-	io->sdu = qos->sdu;
-	io->phy = qos->phy;
-	io->rtn = qos->rtn;
+	io->interval = qos->ucast.io_qos.interval;
+	io->latency = qos->ucast.io_qos.latency;
+	io->sdu = qos->ucast.io_qos.sdu;
+	io->phy = qos->ucast.io_qos.phy;
+	io->rtn = qos->ucast.io_qos.rtn;
 }
 
 static bool match_stream_qos(const void *data, const void *user_data)
@@ -694,10 +1817,10 @@ static bool match_stream_qos(const void *data, const void *user_data)
 
 	qos = bt_bap_stream_get_qos((void *)stream);
 
-	if (iso_qos->cig != qos->cig_id)
+	if (iso_qos->ucast.cig != qos->ucast.cig_id)
 		return false;
 
-	return iso_qos->cis == qos->cis_id;
+	return iso_qos->ucast.cis == qos->ucast.cis_id;
 }
 
 static void iso_confirm_cb(GIOChannel *io, void *user_data)
@@ -719,7 +1842,7 @@ static void iso_confirm_cb(GIOChannel *io, void *user_data)
 	}
 
 	DBG("ISO: incoming connect from %s (CIG 0x%02x CIS 0x%02x)",
-					address, qos.cig, qos.cis);
+					address, qos.ucast.cig, qos.ucast.cis);
 
 	stream = queue_remove_if(data->streams, match_stream_qos, &qos);
 	if (!stream) {
@@ -739,8 +1862,9 @@ drop:
 	g_io_channel_shutdown(io, TRUE, NULL);
 }
 
-static void bap_accept_io(struct bap_data *data, struct bt_bap_stream *stream,
-							int fd, int defer)
+static void setup_accept_io(struct bap_setup *setup,
+				struct bt_bap_stream *stream,
+				int fd, int defer)
 {
 	char c;
 	struct pollfd pfd;
@@ -769,66 +1893,174 @@ static void bap_accept_io(struct bap_data *data, struct bt_bap_stream *stream,
 		goto fail;
 	}
 
-	if (!(pfd.revents & POLLOUT)) {
-		if (read(fd, &c, 1) < 0) {
-			error("read: %s (%d)", strerror(errno), errno);
-			goto fail;
-		}
-	}
+	if (!(pfd.revents & POLLOUT)) {
+		if (read(fd, &c, 1) < 0) {
+			error("read: %s (%d)", strerror(errno), errno);
+			goto fail;
+		}
+	}
+
+	setup->cig_active = true;
+
+	return;
+
+fail:
+	close(fd);
+}
+
+struct cig_busy_data {
+	struct btd_adapter *adapter;
+	uint8_t cig;
+};
+
+static bool match_cig_active(const void *data, const void *match_data)
+{
+	const struct bap_setup *setup = data;
+	const struct cig_busy_data *info = match_data;
+
+	return (setup->qos.ucast.cig_id == info->cig) && setup->cig_active;
+}
+
+static bool cig_busy_ep(const void *data, const void *match_data)
+{
+	const struct bap_ep *ep = data;
+	const struct cig_busy_data *info = match_data;
+
+	return queue_find(ep->setups, match_cig_active, info);
+}
+
+static bool cig_busy_session(const void *data, const void *match_data)
+{
+	const struct bap_data *session = data;
+	const struct cig_busy_data *info = match_data;
+
+	if (device_get_adapter(session->device) != info->adapter)
+		return false;
+
+	return queue_find(session->snks, cig_busy_ep, match_data) ||
+			queue_find(session->srcs, cig_busy_ep, match_data);
+}
+
+static bool is_cig_busy(struct bap_data *data, uint8_t cig)
+{
+	struct cig_busy_data info;
+
+	if (cig == BT_ISO_QOS_CIG_UNSET)
+		return false;
+
+	info.adapter = device_get_adapter(data->device);
+	info.cig = cig;
+
+	return queue_find(sessions, cig_busy_session, &info);
+}
+
+static void setup_create_io(struct bap_data *data, struct bap_setup *setup,
+				struct bt_bap_stream *stream, int defer);
+
+static gboolean setup_io_recreate(void *user_data)
+{
+	struct bap_setup *setup = user_data;
+
+	DBG("%p", setup);
+
+	setup->io_id = 0;
+
+	setup_create_io(setup->ep->data, setup, setup->stream, true);
+
+	return FALSE;
+}
+
+static void setup_recreate(void *data, void *match_data)
+{
+	struct bap_setup *setup = data;
+	struct cig_busy_data *info = match_data;
+
+	if (setup->qos.ucast.cig_id != info->cig || !setup->recreate ||
+						setup->io_id)
+		return;
+
+	setup->recreate = false;
+	setup->io_id = g_idle_add(setup_io_recreate, setup);
+}
 
-	return;
+static void recreate_cig_ep(void *data, void *match_data)
+{
+	struct bap_ep *ep = data;
 
-fail:
-	close(fd);
+	queue_foreach(ep->setups, setup_recreate, match_data);
 }
 
-static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
-				struct bt_bap_stream *stream, int defer);
+static void recreate_cig_session(void *data, void *match_data)
+{
+	struct bap_data *session = data;
+	struct cig_busy_data *info = match_data;
+
+	if (device_get_adapter(session->device) != info->adapter)
+		return;
+
+	queue_foreach(session->snks, recreate_cig_ep, match_data);
+	queue_foreach(session->srcs, recreate_cig_ep, match_data);
+}
 
-static gboolean bap_io_recreate(void *user_data)
+static void recreate_cig(struct bap_setup *setup)
 {
-	struct bap_ep *ep = user_data;
+	struct bap_data *data = setup->ep->data;
+	struct cig_busy_data info;
 
-	DBG("ep %p", ep);
+	info.adapter = device_get_adapter(data->device);
+	info.cig = setup->qos.ucast.cig_id;
 
-	ep->io_id = 0;
+	DBG("adapter %p setup %p recreate CIG %d", info.adapter, setup,
+							info.cig);
 
-	bap_create_io(ep->data, ep, ep->stream, true);
+	if (setup->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET) {
+		recreate_cig_ep(setup->ep, &info);
+		return;
+	}
 
-	return FALSE;
+	queue_foreach(sessions, recreate_cig_session, &info);
 }
 
-static gboolean bap_io_disconnected(GIOChannel *io, GIOCondition cond,
+static gboolean setup_io_disconnected(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
-	struct bap_ep *ep = user_data;
+	struct bap_setup *setup = user_data;
 
-	DBG("ep %p recreate %s", ep, ep->recreate ? "true" : "false");
+	DBG("%p recreate %s", setup, setup->recreate ? "true" : "false");
 
-	ep->io_id = 0;
+	setup->io_id = 0;
 
-	bap_io_close(ep);
+	setup_io_close(setup, NULL);
 
 	/* Check if connecting recreate IO */
-	if (ep->recreate) {
-		ep->recreate = false;
-		ep->io_id = g_idle_add(bap_io_recreate, ep);
-	}
+	if (!is_cig_busy(setup->ep->data, setup->qos.ucast.cig_id))
+		recreate_cig(setup);
 
 	return FALSE;
 }
 
+static void bap_connect_bcast_io_cb(GIOChannel *chan, GError *err,
+					gpointer user_data)
+{
+	struct bap_setup *setup = user_data;
+
+	if (!setup->stream)
+		return;
+
+	iso_connect_bcast_cb(chan, err, setup->stream);
+}
+
 static void bap_connect_io_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
-	struct bap_ep *ep = user_data;
+	struct bap_setup *setup = user_data;
 
-	if (!ep->stream)
+	if (!setup->stream)
 		return;
 
-	iso_connect_cb(chan, err, ep->stream);
+	iso_connect_cb(chan, err, setup->stream);
 }
 
-static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
+static void setup_connect_io(struct bap_data *data, struct bap_setup *setup,
 				struct bt_bap_stream *stream,
 				struct bt_iso_qos *qos, int defer)
 {
@@ -838,36 +2070,43 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
 	int fd;
 
 	/* If IO already set skip creating it again */
-	if (bt_bap_stream_get_io(stream))
+	if (bt_bap_stream_get_io(stream)) {
+		DBG("setup %p stream %p has existing io", setup, stream);
 		return;
+	}
 
 	if (bt_bap_stream_io_is_connecting(stream, &fd)) {
-		bap_accept_io(data, stream, fd, defer);
+		setup_accept_io(setup, stream, fd, defer);
 		return;
 	}
 
-	/* If IO channel still up wait for it to be disconnected and then
-	 * recreate.
+	/* If IO channel still up or CIG is busy, wait for it to be
+	 * disconnected and then recreate.
 	 */
-	if (ep->io) {
-		ep->recreate = true;
+	if (setup->io || is_cig_busy(data, setup->qos.ucast.cig_id)) {
+		DBG("setup %p stream %p defer %s wait recreate", setup, stream,
+						defer ? "true" : "false");
+		setup->recreate = true;
 		return;
 	}
 
-	if (ep->io_id) {
-		g_source_remove(ep->io_id);
-		ep->io_id = 0;
+	if (setup->io_id) {
+		g_source_remove(setup->io_id);
+		setup->io_id = 0;
 	}
 
-	DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
+	DBG("setup %p stream %p defer %s", setup, stream,
+				defer ? "true" : "false");
 
-	io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err,
+	io = bt_io_connect(bap_connect_io_cb, setup, NULL, &err,
 				BT_IO_OPT_SOURCE_BDADDR,
 				btd_adapter_get_address(adapter),
+				BT_IO_OPT_SOURCE_TYPE,
+				btd_adapter_get_address_type(adapter),
 				BT_IO_OPT_DEST_BDADDR,
-				device_get_address(ep->data->device),
+				device_get_address(data->device),
 				BT_IO_OPT_DEST_TYPE,
-				device_get_le_address_type(ep->data->device),
+				device_get_le_address_type(data->device),
 				BT_IO_OPT_MODE, BT_IO_MODE_ISO,
 				BT_IO_OPT_QOS, qos,
 				BT_IO_OPT_DEFER_TIMEOUT, defer,
@@ -878,15 +2117,75 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
 		return;
 	}
 
-	ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-						bap_io_disconnected, ep);
+	setup->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+						setup_io_disconnected, setup);
+
+	setup->io = io;
+	setup->cig_active = !defer;
+
+	bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
+}
+
+static void setup_connect_io_broadcast(struct bap_data *data,
+					struct bap_setup *setup,
+					struct bt_bap_stream *stream,
+					struct bt_iso_qos *qos, int defer)
+{
+	struct btd_adapter *adapter = data->user_data;
+	GIOChannel *io = NULL;
+	GError *err = NULL;
+	bdaddr_t dst_addr = {0};
+	char addr[18];
+	struct bt_iso_base base;
+
+	/* If IO already set and we are in the creation step,
+	 * skip creating it again
+	 */
+	if (bt_bap_stream_get_io(stream))
+		return;
+
+	if (setup->io_id) {
+		g_source_remove(setup->io_id);
+		setup->io_id = 0;
+	}
+	base.base_len = setup->base->iov_len;
+
+	memset(base.base, 0, 248);
+	memcpy(base.base, setup->base->iov_base, setup->base->iov_len);
+	ba2str(btd_adapter_get_address(adapter), addr);
+
+	DBG("setup %p stream %p", setup, stream);
+
+	io = bt_io_connect(bap_connect_bcast_io_cb, setup, NULL, &err,
+			BT_IO_OPT_SOURCE_BDADDR,
+			btd_adapter_get_address(adapter),
+			BT_IO_OPT_SOURCE_TYPE,
+			btd_adapter_get_address_type(adapter),
+			BT_IO_OPT_DEST_BDADDR,
+			&dst_addr,
+			BT_IO_OPT_DEST_TYPE,
+			BDADDR_LE_PUBLIC,
+			BT_IO_OPT_MODE, BT_IO_MODE_ISO,
+			BT_IO_OPT_QOS, qos,
+			BT_IO_OPT_BASE, &base,
+			BT_IO_OPT_DEFER_TIMEOUT, defer,
+			BT_IO_OPT_INVALID);
+
+	if (!io) {
+		error("%s", err->message);
+		g_error_free(err);
+		return;
+	}
+
+	setup->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					setup_io_disconnected, setup);
 
-	ep->io = io;
+	setup->io = io;
 
 	bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
 }
 
-static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
+static void setup_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
 						struct bt_iso_qos *qos)
 {
 	struct btd_adapter *adapter = device_get_adapter(data->device);
@@ -902,10 +2201,12 @@ static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
 	io = bt_io_listen(NULL, iso_confirm_cb, data, NULL, &err,
 				BT_IO_OPT_SOURCE_BDADDR,
 				btd_adapter_get_address(adapter),
+				BT_IO_OPT_SOURCE_TYPE,
+				btd_adapter_get_address_type(adapter),
 				BT_IO_OPT_DEST_BDADDR,
-				device_get_address(data->device),
+				BDADDR_ANY,
 				BT_IO_OPT_DEST_TYPE,
-				device_get_le_address_type(data->device),
+				BDADDR_LE_PUBLIC,
 				BT_IO_OPT_MODE, BT_IO_MODE_ISO,
 				BT_IO_OPT_QOS, qos,
 				BT_IO_OPT_INVALID);
@@ -918,19 +2219,104 @@ static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
 	data->listen_io = io;
 }
 
-static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
-				struct bt_bap_stream *stream, int defer)
+static void check_pa_req_in_progress(void *data, void *user_data)
 {
-	struct bt_bap_qos *qos[2] = {};
-	struct bt_iso_qos iso_qos;
+	struct bap_bcast_pa_req *req = data;
+
+	if (req->in_progress == TRUE)
+		*((bool *)user_data) = TRUE;
+}
 
-	DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
+static int pa_sync(struct bap_bcast_pa_req *req);
+static void pa_and_big_sync(struct bap_bcast_pa_req *req);
 
-	if (!data->streams)
-		data->streams = queue_new();
+static gboolean pa_idle_timer(gpointer user_data)
+{
+	struct bap_adapter *adapter = user_data;
+	struct bap_bcast_pa_req *req;
+	bool in_progress = FALSE;
+
+	/* Handle timer if no request is in progress */
+	queue_foreach(adapter->bcast_pa_requests, check_pa_req_in_progress,
+			&in_progress);
+	if (in_progress == FALSE) {
+		req = queue_peek_head(adapter->bcast_pa_requests);
+		if (req != NULL)
+			switch (req->type) {
+			case BAP_PA_SHORT_REQ:
+				DBG("do short lived PA Sync");
+				pa_sync(req);
+				break;
+			case BAP_PA_LONG_REQ:
+				DBG("do long lived PA Sync");
+				pa_sync(req);
+				break;
+			case BAP_PA_BIG_SYNC_REQ:
+				DBG("do PA Sync and BIG Sync");
+				pa_and_big_sync(req);
+				break;
+			}
+		else {
+			/* pa_req queue is empty, stop the timer by returning
+			 * FALSE and set the pa_timer_id to 0. This will later
+			 * be used to check if the timer is active.
+			 */
+			adapter->pa_timer_id = 0;
+			return FALSE;
+		}
+	}
 
-	if (!queue_find(data->streams, NULL, stream))
-		queue_push_tail(data->streams, stream);
+	return TRUE;
+}
+
+static void setup_accept_io_broadcast(struct bap_data *data,
+					struct bap_setup *setup)
+{
+	struct bap_bcast_pa_req *req = new0(struct bap_bcast_pa_req, 1);
+	struct bap_adapter *adapter = data->adapter;
+	struct queue *links = bt_bap_stream_io_get_links(setup->stream);
+	const struct queue_entry *entry;
+
+	/* Timer could be stopped if all other requests were treated.
+	 * Check the state of the timer and turn it on so that this request
+	 * can also be treated.
+	 */
+	if (adapter->pa_timer_id == 0)
+		adapter->pa_timer_id = g_timeout_add_seconds(PA_IDLE_TIMEOUT,
+								pa_idle_timer,
+								adapter);
+
+	/* Add this request to the PA queue.
+	 * We don't need to check the queue here, as we cannot have
+	 * BAP_PA_BIG_SYNC_REQ before a short PA (BAP_PA_SHORT_REQ)
+	 */
+	req->type = BAP_PA_BIG_SYNC_REQ;
+	req->in_progress = FALSE;
+	req->bap_data = data;
+
+	req->data.setups = queue_new();
+
+	/* Enqueue all linked setups to the request */
+	queue_push_tail(req->data.setups, setup);
+
+	for (entry = queue_get_entries(links); entry;
+							entry = entry->next) {
+		struct bt_bap_stream *stream = entry->data;
+
+		queue_push_tail(req->data.setups,
+				bap_find_setup_by_stream(data, stream));
+	}
+
+	queue_push_tail(adapter->bcast_pa_requests, req);
+}
+
+static void setup_create_ucast_io(struct bap_data *data,
+					struct bap_setup *setup,
+					struct bt_bap_stream *stream,
+					int defer)
+{
+	struct bt_bap_qos *qos[2] = {};
+	struct bt_iso_qos iso_qos;
 
 	if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
 		error("bt_bap_stream_get_qos_links: failed");
@@ -938,66 +2324,413 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
 	}
 
 	memset(&iso_qos, 0, sizeof(iso_qos));
-	iso_qos.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id;
-	iso_qos.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id;
 
-	bap_iso_qos(qos[0], &iso_qos.in);
-	bap_iso_qos(qos[1], &iso_qos.out);
+	iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id :
+						qos[1]->ucast.cig_id;
+	iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id :
+						qos[1]->ucast.cis_id;
 
-	if (ep)
-		bap_connect_io(data, ep, stream, &iso_qos, defer);
+	bap_iso_qos(qos[0], &iso_qos.ucast.in);
+	bap_iso_qos(qos[1], &iso_qos.ucast.out);
+
+	if (setup)
+		setup_connect_io(data, setup, stream, &iso_qos, defer);
+	else
+		setup_listen_io(data, stream, &iso_qos);
+}
+
+static void setup_create_bcast_io(struct bap_data *data,
+					struct bap_setup *setup,
+					struct bt_bap_stream *stream, int defer)
+{
+	struct bt_bap_qos *qos = &setup->qos;
+	struct iovec *bcode = qos->bcast.bcode;
+	struct bt_iso_qos iso_qos;
+
+	memset(&iso_qos, 0, sizeof(iso_qos));
+
+	iso_qos.bcast.big = setup->qos.bcast.big;
+	iso_qos.bcast.bis = setup->qos.bcast.bis;
+	iso_qos.bcast.sync_factor = setup->qos.bcast.sync_factor;
+	iso_qos.bcast.packing = setup->qos.bcast.packing;
+	iso_qos.bcast.framing = setup->qos.bcast.framing;
+	iso_qos.bcast.encryption = setup->qos.bcast.encryption;
+	if (bcode && bcode->iov_base)
+		memcpy(iso_qos.bcast.bcode, bcode->iov_base, bcode->iov_len);
+	iso_qos.bcast.options = setup->qos.bcast.options;
+	iso_qos.bcast.skip = setup->qos.bcast.skip;
+	iso_qos.bcast.sync_timeout = setup->qos.bcast.sync_timeout;
+	iso_qos.bcast.sync_cte_type = setup->qos.bcast.sync_cte_type;
+	iso_qos.bcast.mse = setup->qos.bcast.mse;
+	iso_qos.bcast.timeout = setup->qos.bcast.timeout;
+	memcpy(&iso_qos.bcast.out, &setup->qos.bcast.io_qos,
+				sizeof(struct bt_iso_io_qos));
+
+	if (bt_bap_stream_get_dir(stream) == BT_BAP_BCAST_SINK)
+		setup_connect_io_broadcast(data, setup, stream, &iso_qos,
+			defer);
 	else
-		bap_listen_io(data, stream, &iso_qos);
+		setup_accept_io_broadcast(data, setup);
+}
+
+static void setup_create_io(struct bap_data *data, struct bap_setup *setup,
+				struct bt_bap_stream *stream, int defer)
+{
+	DBG("setup %p stream %p defer %s", setup, stream,
+				defer ? "true" : "false");
+
+	if (!data->streams)
+		data->streams = queue_new();
+
+	if (!queue_find(data->streams, NULL, stream))
+		queue_push_tail(data->streams, stream);
+
+	switch (bt_bap_stream_get_type(stream)) {
+	case BT_BAP_STREAM_TYPE_UCAST:
+		setup_create_ucast_io(data, setup, stream, defer);
+		break;
+	case BT_BAP_STREAM_TYPE_BCAST:
+		setup_create_bcast_io(data, setup, stream, defer);
+		break;
+	}
 }
 
 static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
 				uint8_t new_state, void *user_data)
 {
 	struct bap_data *data = user_data;
-	struct bap_ep *ep;
+	struct bap_setup *setup;
 
 	DBG("stream %p: %s(%u) -> %s(%u)", stream,
 			bt_bap_stream_statestr(old_state), old_state,
 			bt_bap_stream_statestr(new_state), new_state);
 
-	if (new_state == old_state)
+	/* Ignore transitions back to same state (ASCS allows some of these).
+	 * Of these we need to handle only the config->config case, which will
+	 * occur when reconfiguring the codec from initial config state.
+	 */
+	if (new_state == old_state && new_state != BT_BAP_STREAM_STATE_CONFIG)
 		return;
 
-	ep = bap_find_ep_by_stream(data, stream);
+	setup = bap_find_setup_by_stream(data, stream);
 
 	switch (new_state) {
 	case BT_BAP_STREAM_STATE_IDLE:
 		/* Release stream if idle */
-		if (ep)
-			bap_io_close(ep);
+		if (setup)
+			setup_free(setup);
 		else
 			queue_remove(data->streams, stream);
 		break;
 	case BT_BAP_STREAM_STATE_CONFIG:
-		if (ep && !ep->id) {
-			bap_create_io(data, ep, stream, true);
-			if (!ep->io) {
+		if (setup && !setup->id) {
+			setup_create_io(data, setup, stream, true);
+			if (!setup->io) {
 				error("Unable to create io");
-				bt_bap_stream_release(stream, NULL, NULL);
+				if (old_state != BT_BAP_STREAM_STATE_RELEASING)
+					bt_bap_stream_release(stream, NULL,
+								NULL);
 				return;
 			}
 
-
 			/* Wait QoS response to respond */
-			ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
-									ep);
-			if (!ep->id) {
+			setup->id = bt_bap_stream_qos(stream,
+							&setup->qos,
+							qos_cb,	setup);
+			if (!setup->id) {
 				error("Failed to Configure QoS");
-				bt_bap_stream_release(stream, NULL, NULL);
+				bt_bap_stream_release(stream,
+							NULL, NULL);
 			}
 		}
 		break;
 	case BT_BAP_STREAM_STATE_QOS:
-		bap_create_io(data, ep, stream, true);
+			setup_create_io(data, setup, stream, true);
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		if (setup)
+			setup_create_io(data, setup, stream, false);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		break;
+	}
+}
+
+/* This function will call setup_create_io on all BISes from a BIG.
+ * The defer parameter will be set on true on all but the last one.
+ * This is done to inform the kernel when to when to start the BIG.
+ */
+static bool create_io_bises(struct bap_setup *setup,
+				uint8_t nb_bises, struct bap_data *data)
+{
+	const struct queue_entry *entry;
+	struct bap_setup *ent_setup;
+	bool defer = true;
+	uint8_t active_bis_cnt = 1;
+
+	for (entry = queue_get_entries(setup->ep->setups);
+				entry; entry = entry->next) {
+		ent_setup = entry->data;
+
+		if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.big !=
+				bt_bap_stream_get_qos(setup->stream)->bcast.big)
+			continue;
+
+		if (active_bis_cnt == nb_bises)
+			defer = false;
+
+		setup_create_io(data, ent_setup, ent_setup->stream, defer);
+		if (!ent_setup->io) {
+			error("Unable to create io");
+			goto fail;
+		}
+
+		active_bis_cnt++;
+	}
+
+	return true;
+
+fail:
+	/* Clear the io of the created sockets if one
+	 * socket creation fails.
+	 */
+	for (entry = queue_get_entries(setup->ep->setups);
+				entry; entry = entry->next) {
+		ent_setup = entry->data;
+
+		if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.big !=
+				bt_bap_stream_get_qos(setup->stream)->bcast.big)
+			continue;
+
+		if (setup->io)
+			g_io_channel_unref(setup->io);
+	}
+	return false;
+}
+
+static void iterate_setup_update_base(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	struct bap_setup *data_setup = user_data;
+
+	if ((setup->stream != data_setup->stream) &&
+		(setup->qos.bcast.big == data_setup->qos.bcast.big)) {
+
+		if (setup->base)
+			util_iov_free(setup->base, 1);
+
+		setup->base = util_iov_dup(data_setup->base, 1);
+	}
+}
+
+/* Function checks the state of all streams in the same BIG
+ * as the parameter stream, so it can decide if any sockets need
+ * to be created. Returns he number of streams that need a socket
+ * from that BIG.
+ */
+static uint8_t get_streams_nb_by_state(struct bap_setup *setup)
+{
+	const struct queue_entry *entry;
+	struct bap_setup *ent_setup;
+	uint8_t stream_cnt = 0;
+
+	if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET)
+		/* If BIG ID is unset this is a single BIS BIG.
+		 * return 1 as create one socket only for this BIS
+		 */
+		return 1;
+
+	for (entry = queue_get_entries(setup->ep->setups);
+				entry; entry = entry->next) {
+		ent_setup = entry->data;
+
+		/* Skip the curent stream form testing */
+		if (ent_setup == setup) {
+			stream_cnt++;
+			continue;
+		}
+
+		/* Test only BISes for the same BIG */
+		if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.big !=
+				bt_bap_stream_get_qos(setup->stream)->bcast.big)
+			continue;
+
+		if (bt_bap_stream_get_state(ent_setup->stream) ==
+				BT_BAP_STREAM_STATE_STREAMING)
+			/* If one stream in a multiple BIS BIG is in
+			 * streaming state this means that just the current
+			 * stream must have is socket created so return 1.
+			 */
+			return 1;
+		else if (bt_bap_stream_get_state(ent_setup->stream) !=
+				BT_BAP_STREAM_STATE_ENABLING)
+			/* Not all streams form a BIG have received transport
+			 * acquire, so wait for the other streams to.
+			 */
+			return 0;
+
+		stream_cnt++;
+	}
+
+	/* Return the number of streams for the BIG
+	 * as all are ready to create sockets
+	 */
+	return stream_cnt;
+}
+
+static void bap_state_bcast_src(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct bap_data *data = user_data;
+	struct bap_setup *setup;
+	bool defer = false;
+	uint8_t nb_bises = 0;
+
+	DBG("stream %p: %s(%u) -> %s(%u)", stream,
+			bt_bap_stream_statestr(old_state), old_state,
+			bt_bap_stream_statestr(new_state), new_state);
+
+	/* Ignore transitions back to same state */
+	if (new_state == old_state)
+		return;
+
+	setup = bap_find_setup_by_stream(data, stream);
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_IDLE:
+		/* Release stream if idle */
+		if (setup)
+			setup_free(setup);
+		else
+			queue_remove(data->streams, stream);
+		break;
+	case BT_BAP_STREAM_STATE_CONFIG:
+		// TO DO Reconfiguration
+		break;
+	/* Use the ENABLING state to know when a transport
+	 * linked to a stream has been acquired by a process
+	 * and in the case of a BIG with one BIS stream goes
+	 * in the ENABLING state waiting for the response
+	 * from the kernel that the BIG has been created
+	 * so it can go to the streaming state.
+	 * For the case of a BIG with multiple BISes,
+	 * the BIG is created when all BISes are acquired.
+	 * So we use the ENABLING state to  verify that all
+	 * transports attached to that streams form BIG have
+	 * been acquired so we can create the BIG.
+	 */
+	case BT_BAP_STREAM_STATE_ENABLING:
+		/* If the stream attached to a broadcast
+		 * source endpoint generate the base.
+		 */
+		if (setup->base == NULL) {
+			setup->base = bt_bap_stream_get_base(
+					setup->stream);
+			/* Set the generated BASE on all setups
+			 * from the same BIG.
+			 */
+			queue_foreach(setup->ep->setups,
+				iterate_setup_update_base, setup);
+		}
+		/* The kernel has 2 requirements when handling
+		 * multiple BIS connections for the same BIG:
+		 * 1 - setup_create_io for all but the last BIS
+		 * must be with defer true so we can inform the
+		 * kernel when to start the BIG.
+		 * 2 - The order in which the setup_create_io
+		 * are called must be in the order of BIS
+		 * indexes in BASE from first to last.
+		 * To address this requirement we will call
+		 * setup_create_io on all BISes only when all
+		 * transport acquire have been received and will
+		 * send it in the order of the BIS index
+		 * from BASE.
+		 */
+		nb_bises = get_streams_nb_by_state(setup);
+
+		if (nb_bises == 1) {
+			setup_create_io(data, setup,
+			stream, defer);
+			if (!setup->io) {
+				error("Unable to create io");
+				if (old_state !=
+					BT_BAP_STREAM_STATE_RELEASING)
+					bt_bap_stream_release(stream,
+							NULL, NULL);
+			}
+			break;
+		} else if (nb_bises == 0)
+			break;
+
+		if (!create_io_bises(setup, nb_bises, data)) {
+			if (old_state !=
+				BT_BAP_STREAM_STATE_RELEASING)
+				bt_bap_stream_release(stream,
+					NULL, NULL);
+		}
+		break;
+	}
+}
+
+static bool link_enabled(const void *data, const void *match_data)
+{
+	struct bt_bap_stream *stream = (struct bt_bap_stream *)data;
+	uint8_t state = bt_bap_stream_get_state(stream);
+
+	return ((state == BT_BAP_STREAM_STATE_ENABLING) ||
+			bt_bap_stream_get_io(stream));
+}
+
+static void bap_state_bcast_sink(struct bt_bap_stream *stream,
+				uint8_t old_state, uint8_t new_state,
+				void *user_data)
+{
+	struct bap_data *data = user_data;
+	struct bap_setup *setup;
+	bool defer = false;
+
+	DBG("stream %p: %s(%u) -> %s(%u)", stream,
+			bt_bap_stream_statestr(old_state), old_state,
+			bt_bap_stream_statestr(new_state), new_state);
+
+	if (new_state == old_state && new_state != BT_BAP_STREAM_STATE_CONFIG)
+		return;
+
+	setup = bap_find_setup_by_stream(data, stream);
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_IDLE:
+		/* Release stream if idle */
+		if (setup)
+			setup_free(setup);
+		else
+			queue_remove(data->streams, stream);
+		break;
+	case BT_BAP_STREAM_STATE_CONFIG:
+		if (!setup)
+			break;
+		if (old_state ==
+				BT_BAP_STREAM_STATE_STREAMING)
+			setup_io_close(setup, NULL);
 		break;
 	case BT_BAP_STREAM_STATE_ENABLING:
-		if (ep)
-			bap_create_io(data, ep, stream, false);
+		/* For a Broadcast Sink, the ENABLING state suggests that
+		 * the upper layer process requires the stream to start
+		 * receiving audio. This state is used to differentiate
+		 * between all configured streams and the ones that have
+		 * been enabled by the upper layer.
+		 *
+		 * Create stream io if not already created and if no
+		 * link has been enabled or started.
+		 *
+		 * The first enabled link will create and set fds for
+		 * all links.
+		 */
+		if (!bt_bap_stream_get_io(stream) &&
+			!queue_find(bt_bap_stream_io_get_links(stream),
+							link_enabled, NULL))
+			setup_create_io(data, setup, stream, defer);
+
 		break;
 	}
 }
@@ -1014,32 +2747,79 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data)
 
 	data = btd_service_get_user_data(service);
 
-	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_found, service);
-	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_found, service);
+	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_register, service);
+	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_register, service);
+
+	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_select, service);
+	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_select, service);
+}
+
+static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data)
+{
+	struct bap_data *data = user_data;
+
+	/*
+	 * If pac type is BT_BAP_BCAST_SOURCE locally create an endpoint
+	 * without a remote pac.
+	 * If pac type is BT_BAP_BCAST_SOURCE and remote then look for a
+	 * local broadcast sink pac locally before creating an endpoint.
+	 */
+	if (bt_bap_pac_bcast_is_local(data->bap, pac) &&
+		(bt_bap_pac_get_type(pac) == BT_BAP_BCAST_SOURCE))
+		pac_found_bcast(pac, NULL, user_data);
+	else
+		bt_bap_foreach_pac(data->bap, bt_bap_pac_get_type(pac),
+					pac_found_bcast, data);
 }
 
-static bool ep_match_rpac(const void *data, const void *match_data)
+static bool ep_match_pac(const void *data, const void *match_data)
 {
 	const struct bap_ep *ep = data;
 	const struct bt_bap_pac *pac = match_data;
 
-	return ep->rpac == pac;
+	return ep->rpac == pac || ep->lpac == pac;
+}
+
+static void pac_removed(struct bt_bap_pac *pac, void *user_data)
+{
+	struct btd_service *service = user_data;
+	struct bap_data *data;
+	struct queue *queue;
+	struct bap_ep *ep;
+
+	DBG("pac %p", pac);
+
+	if (btd_service_get_state(service) != BTD_SERVICE_STATE_CONNECTED)
+		return;
+
+	data = btd_service_get_user_data(service);
+
+	switch (bt_bap_pac_get_type(pac)) {
+	case BT_BAP_SINK:
+		queue = data->srcs;
+		break;
+	case BT_BAP_SOURCE:
+		queue = data->snks;
+		break;
+	default:
+		return;
+	}
+
+	ep = queue_remove_if(queue, ep_match_pac, pac);
+	if (!ep)
+		return;
+
+	ep_unregister(ep);
 }
 
-static void pac_removed(struct bt_bap_pac *pac, void *user_data)
+static void pac_removed_broadcast(struct bt_bap_pac *pac, void *user_data)
 {
-	struct btd_service *service = user_data;
-	struct bap_data *data;
+	struct bap_data *data = user_data;
 	struct queue *queue;
 	struct bap_ep *ep;
 
 	DBG("pac %p", pac);
 
-	if (btd_service_get_state(service) != BTD_SERVICE_STATE_CONNECTED)
-		return;
-
-	data = btd_service_get_user_data(service);
-
 	switch (bt_bap_pac_get_type(pac)) {
 	case BT_BAP_SINK:
 		queue = data->srcs;
@@ -1047,17 +2827,39 @@ static void pac_removed(struct bt_bap_pac *pac, void *user_data)
 	case BT_BAP_SOURCE:
 		queue = data->snks;
 		break;
+	case BT_BAP_BCAST_SOURCE:
+		queue = data->bcast;
+		break;
 	default:
 		return;
 	}
 
-	ep = queue_remove_if(queue, ep_match_rpac, pac);
+	ep = queue_remove_if(queue, ep_match_pac, pac);
 	if (!ep)
 		return;
 
 	ep_unregister(ep);
 }
 
+static bool match_device(const void *data, const void *match_data)
+{
+	const struct bap_data *bdata = data;
+	const struct btd_device *device = match_data;
+
+	return bdata->device == device;
+}
+
+struct bt_bap *bap_get_session(struct btd_device *device)
+{
+	struct bap_data *data;
+
+	data = queue_find(sessions, match_device, device);
+	if (!data)
+		return NULL;
+
+	return data->bap;
+}
+
 static struct bap_data *bap_data_new(struct btd_device *device)
 {
 	struct bap_data *data;
@@ -1066,6 +2868,7 @@ static struct bap_data *bap_data_new(struct btd_device *device)
 	data->device = device;
 	data->srcs = queue_new();
 	data->snks = queue_new();
+	data->bcast = queue_new();
 
 	return data;
 }
@@ -1098,50 +2901,111 @@ static bool match_data(const void *data, const void *match_data)
 	return bdata->bap == bap;
 }
 
+static bool io_get_qos(GIOChannel *io, struct bt_iso_qos *qos)
+{
+	GError *err = NULL;
+	bool ret;
+
+	ret = bt_io_get(io, &err, BT_IO_OPT_QOS, qos, BT_IO_OPT_INVALID);
+	if (!ret) {
+		error("%s", err->message);
+		g_error_free(err);
+	}
+
+	return ret;
+}
+
 static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
 							void *user_data)
 {
 	struct bap_data *data = user_data;
-	struct bap_ep *ep;
+	struct bap_setup *setup;
+	struct bt_bap_qos *qos;
 	GIOChannel *io;
 
 	if (!state)
 		return;
 
-	ep = bap_find_ep_by_stream(data, stream);
-	if (!ep)
+	setup = bap_find_setup_by_stream(data, stream);
+	if (!setup)
 		return;
 
-	ep->recreate = false;
+	setup->recreate = false;
+	qos = &setup->qos;
 
-	if (!ep->io) {
+	if (!setup->io) {
 		io = g_io_channel_unix_new(fd);
-		ep->io = io;
+		setup->io_id = g_io_add_watch(io,
+					      G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					      setup_io_disconnected, setup);
+		setup->io = io;
 	} else
-		io = ep->io;
+		io = setup->io;
 
 	g_io_channel_set_close_on_unref(io, FALSE);
 
 	/* Attempt to get CIG/CIS if they have not been set */
-	if (ep->qos.cig_id == BT_ISO_QOS_CIG_UNSET ||
-				ep->qos.cis_id == BT_ISO_QOS_CIS_UNSET) {
-		struct bt_iso_qos qos;
-		GError *err = NULL;
-
-		if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
-					BT_IO_OPT_INVALID)) {
-			error("%s", err->message);
-			g_error_free(err);
+	if (qos->ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
+			qos->ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
+		struct bt_iso_qos iso_qos;
+
+		if (!io_get_qos(io, &iso_qos)) {
 			g_io_channel_unref(io);
 			return;
 		}
 
-		ep->qos.cig_id = qos.cig;
-		ep->qos.cis_id = qos.cis;
+		qos->ucast.cig_id = iso_qos.ucast.cig;
+		qos->ucast.cis_id = iso_qos.ucast.cis;
 	}
 
 	DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
-					ep->qos.cig_id, ep->qos.cis_id);
+			qos->ucast.cig_id, qos->ucast.cis_id);
+}
+
+static void bap_connecting_bcast(struct bt_bap_stream *stream, bool state,
+							int fd, void *user_data)
+{
+	struct bap_data *data = user_data;
+	struct bap_setup *setup;
+	GIOChannel *io;
+
+	if (!state)
+		return;
+
+	setup = bap_find_setup_by_stream(data, stream);
+	if (!setup)
+		return;
+
+	setup->recreate = false;
+
+	if (!setup->io) {
+		io = g_io_channel_unix_new(fd);
+		setup->io_id = g_io_add_watch(io,
+				G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				setup_io_disconnected, setup);
+		setup->io = io;
+	} else
+		io = setup->io;
+
+	g_io_channel_set_close_on_unref(io, FALSE);
+
+	/* Attempt to get BIG/BIS if they have not been set */
+	if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
+			setup->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
+		struct bt_iso_qos iso_qos;
+
+		if (!io_get_qos(io, &iso_qos)) {
+			g_io_channel_unref(io);
+			return;
+		}
+
+		setup->qos.bcast.big = iso_qos.bcast.big;
+		setup->qos.bcast.bis = iso_qos.bcast.bis;
+		bt_bap_stream_qos(setup->stream, &setup->qos, NULL, NULL);
+	}
+
+	DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
+			setup->qos.bcast.big, setup->qos.bcast.bis);
 }
 
 static void bap_attached(struct bt_bap *bap, void *user_data)
@@ -1196,6 +3060,320 @@ static void bap_detached(struct bt_bap *bap, void *user_data)
 	bap_data_remove(data);
 }
 
+static int pa_sync(struct bap_bcast_pa_req *req)
+{
+	struct btd_service *service = req->data.service;
+	struct bap_data *data = btd_service_get_user_data(service);
+	GError *err = NULL;
+
+	if (data->listen_io) {
+		DBG("Already probed");
+		return -1;
+	}
+
+	DBG("Create PA sync with this source");
+	req->in_progress = TRUE;
+	data->listen_io = bt_io_listen(NULL, iso_pa_sync_confirm_cb, req,
+		NULL, &err,
+		BT_IO_OPT_SOURCE_BDADDR,
+		btd_adapter_get_address(data->adapter->adapter),
+		BT_IO_OPT_SOURCE_TYPE,
+		btd_adapter_get_address_type(data->adapter->adapter),
+		BT_IO_OPT_DEST_BDADDR,
+		device_get_address(data->device),
+		BT_IO_OPT_DEST_TYPE,
+		btd_device_get_bdaddr_type(data->device),
+		BT_IO_OPT_MODE, BT_IO_MODE_ISO,
+		BT_IO_OPT_QOS, &bap_sink_pa_qos,
+		BT_IO_OPT_INVALID);
+	if (!data->listen_io) {
+		error("%s", err->message);
+		g_error_free(err);
+	}
+
+	return 0;
+}
+
+static void append_setup(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	struct sockaddr_iso_bc *addr = user_data;
+	char *path = bt_bap_stream_get_user_data(setup->stream);
+	int bis = 1;
+	int s_err;
+	const char *strbis = NULL;
+
+	strbis = strstr(path, "/bis");
+	if (!strbis) {
+		DBG("bis index cannot be found");
+		return;
+	}
+
+	s_err = sscanf(strbis, "/bis%d", &bis);
+	if (s_err == -1) {
+		DBG("sscanf error");
+		return;
+	}
+
+	DBG("Do BIG Sync with BIS %d", bis);
+
+	addr->bc_bis[addr->bc_num_bis] = bis;
+	addr->bc_num_bis++;
+}
+
+static void setup_refresh_qos(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+
+	setup->qos = *bt_bap_stream_get_qos(setup->stream);
+}
+
+static void iso_do_big_sync(GIOChannel *io, void *user_data)
+{
+	GError *err = NULL;
+	struct bap_bcast_pa_req *req = user_data;
+	struct queue *setups = req->data.setups;
+	struct bap_setup *setup = queue_peek_head(setups);
+	struct bap_data *data = req->bap_data;
+	struct sockaddr_iso_bc iso_bc_addr = {0};
+	struct bt_iso_qos qos;
+
+	DBG("PA Sync done");
+
+	if (req->io) {
+		g_io_channel_unref(req->io);
+		g_io_channel_shutdown(req->io, TRUE, NULL);
+		req->io = io;
+		g_io_channel_ref(req->io);
+	}
+
+	iso_bc_addr.bc_bdaddr_type = btd_device_get_bdaddr_type(data->device);
+	memcpy(&iso_bc_addr.bc_bdaddr, device_get_address(data->device),
+			sizeof(bdaddr_t));
+
+	/* Append each linked BIS to the BIG sync request */
+	queue_foreach(setups, append_setup, &iso_bc_addr);
+
+	/* Refresh qos stored in setups */
+	queue_foreach(setups, setup_refresh_qos, NULL);
+
+	/* Set the user requested QOS */
+	memset(&qos, 0, sizeof(qos));
+	qos.bcast.big = setup->qos.bcast.big;
+	qos.bcast.bis = setup->qos.bcast.bis;
+	qos.bcast.sync_factor = setup->qos.bcast.sync_factor;
+	qos.bcast.packing = setup->qos.bcast.packing;
+	qos.bcast.framing = setup->qos.bcast.framing;
+	qos.bcast.encryption = setup->qos.bcast.encryption;
+	if (setup->qos.bcast.bcode && setup->qos.bcast.bcode->iov_base)
+		memcpy(qos.bcast.bcode, setup->qos.bcast.bcode->iov_base,
+				setup->qos.bcast.bcode->iov_len);
+	qos.bcast.options = setup->qos.bcast.options;
+	qos.bcast.skip = setup->qos.bcast.skip;
+	qos.bcast.sync_timeout = setup->qos.bcast.sync_timeout;
+	qos.bcast.sync_cte_type = setup->qos.bcast.sync_cte_type;
+	qos.bcast.mse = setup->qos.bcast.mse;
+	qos.bcast.timeout = setup->qos.bcast.timeout;
+	memcpy(&qos.bcast.out, &setup->qos.bcast.io_qos,
+			sizeof(struct bt_iso_io_qos));
+
+	if (!bt_io_set(io, &err,
+			BT_IO_OPT_QOS, &qos,
+			BT_IO_OPT_INVALID)) {
+		error("bt_io_set: %s", err->message);
+		g_error_free(err);
+	}
+
+	if (!bt_io_bcast_accept(io,
+			iso_bcast_confirm_cb,
+			req, NULL, &err,
+			BT_IO_OPT_ISO_BC_NUM_BIS,
+			iso_bc_addr.bc_num_bis, BT_IO_OPT_ISO_BC_BIS,
+			iso_bc_addr.bc_bis, BT_IO_OPT_INVALID)) {
+		error("bt_io_bcast_accept: %s", err->message);
+		g_error_free(err);
+	}
+}
+
+static void pa_and_big_sync(struct bap_bcast_pa_req *req)
+{
+	GError *err = NULL;
+	struct bap_data *bap_data = req->bap_data;
+
+	req->in_progress = TRUE;
+
+	if (bap_data->listen_io) {
+		/* If there is an active listen io for the BAP session
+		 * with the Broadcast Source, it means that PA sync is
+		 * already established. Go straight to establishing BIG
+		 * sync.
+		 */
+		iso_do_big_sync(bap_data->listen_io, req);
+		return;
+	}
+
+	DBG("Create PA sync with this source");
+	req->io = bt_io_listen(NULL, iso_do_big_sync, req,
+			NULL, &err,
+			BT_IO_OPT_SOURCE_BDADDR,
+			btd_adapter_get_address(bap_data->adapter->adapter),
+			BT_IO_OPT_DEST_BDADDR,
+			device_get_address(bap_data->device),
+			BT_IO_OPT_DEST_TYPE,
+			btd_device_get_bdaddr_type(bap_data->device),
+			BT_IO_OPT_MODE, BT_IO_MODE_ISO,
+			BT_IO_OPT_QOS, &bap_sink_pa_qos,
+			BT_IO_OPT_INVALID);
+	if (!req->io) {
+		error("%s", err->message);
+		g_error_free(err);
+	}
+}
+
+static bool match_bap_adapter(const void *data, const void *match_data)
+{
+	struct bap_adapter *adapter = (struct bap_adapter *)data;
+
+	return adapter->adapter == match_data;
+}
+
+void bap_scan_delegator_probe(struct btd_device *device)
+{
+	struct bap_data *data;
+
+	/* Create BAP session for the Broadcaster device */
+	data = bap_data_new(device);
+	data->device = device;
+
+	bap_data_add(data);
+
+	/* Add Broadcast Audio Announcement Service UUID
+	 * to device and probe service.
+	 */
+	btd_device_add_uuid(device, BCAAS_UUID_STR);
+}
+
+static int bap_bcast_probe(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct bap_bcast_pa_req *req;
+	uint8_t type = BAP_PA_LONG_REQ;
+	struct bap_data *data;
+
+	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) {
+		error("BAP requires ISO Socket which is not enabled");
+		return -ENOTSUP;
+	}
+
+	data = queue_find(sessions, match_device, device);
+	if (data && data->service) {
+		error("Profile probed twice for the same device!");
+		return -EINVAL;
+	}
+
+	if (!data) {
+		data = bap_data_new(device);
+		data->device = device;
+		bap_data_add(data);
+
+		/* The Broadcaster was scanned autonomously,
+		 * so it should be probed short-lived.
+		 */
+		type = BAP_PA_SHORT_REQ;
+	}
+
+	data->service = service;
+	btd_service_set_user_data(service, data);
+
+	data->adapter = queue_find(adapters, match_bap_adapter, adapter);
+	data->bap = bt_bap_new(btd_gatt_database_get_db(database),
+			btd_gatt_database_get_db(database));
+	if (!data->bap) {
+		error("Unable to create BAP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	bt_bap_set_debug(data->bap, bap_debug, NULL, NULL);
+
+	data->bcast_snks = queue_new();
+
+	if (!bt_bap_attach(data->bap, NULL)) {
+		error("BAP unable to attach");
+		return -EINVAL;
+	}
+
+	data->ready_id = bt_bap_ready_register(data->bap, bap_ready, service,
+								NULL);
+	data->state_id = bt_bap_state_register(data->bap, bap_state_bcast_sink,
+					bap_connecting_bcast, data, NULL);
+	data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
+				pac_removed_broadcast, data, NULL);
+
+	bt_bap_set_user_data(data->bap, service);
+
+	/* Start the PA timer if it hasn't been started yet */
+	if (data->adapter->pa_timer_id == 0)
+		data->adapter->pa_timer_id = g_timeout_add_seconds(
+							PA_IDLE_TIMEOUT,
+							pa_idle_timer,
+							data->adapter);
+
+	/* Enqueue this device advertisement so that we can create PA sync. */
+	DBG("enqueue service: %p", service);
+	req = new0(struct bap_bcast_pa_req, 1);
+	req->type = type;
+	req->in_progress = FALSE;
+	req->data.service = service;
+	queue_push_tail(data->adapter->bcast_pa_requests, req);
+
+	return 0;
+}
+
+static bool match_service(const void *data, const void *match_data)
+{
+	struct bap_bcast_pa_req *req = (struct bap_bcast_pa_req *)data;
+
+	return req->data.service == match_data;
+}
+
+static void bap_bcast_remove(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bap_data *data;
+	struct bap_bcast_pa_req *req;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	data = btd_service_get_user_data(service);
+	if (!data) {
+		error("BAP service not handled by profile");
+		return;
+	}
+	/* Remove the corresponding entry from the pa_req queue. Any pa_req that
+	 * are in progress will be stopped by bap_data_remove which calls
+	 * bap_data_free.
+	 */
+	req = queue_remove_if(data->adapter->bcast_pa_requests,
+						match_service, service);
+	if (req && req->io_id) {
+		g_source_remove(req->io_id);
+		req->io_id = 0;
+	}
+	free(req);
+
+	/* Notify the BASS plugin about the removed session. */
+	bass_bcast_remove(device);
+
+	bap_data_remove(data);
+
+	bass_remove_stream(device);
+}
+
 static int bap_probe(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
@@ -1235,8 +3413,8 @@ static int bap_probe(struct btd_service *service)
 								NULL);
 	data->state_id = bt_bap_state_register(data->bap, bap_state,
 						bap_connecting, data, NULL);
-	data->pac_id = bt_bap_pac_register(pac_added, pac_removed, service,
-								NULL);
+	data->pac_id = bt_bap_pac_register(data->bap, pac_added, pac_removed,
+						service, NULL);
 
 	bt_bap_set_user_data(data->bap, service);
 
@@ -1289,6 +3467,83 @@ static int bap_disconnect(struct btd_service *service)
 	return 0;
 }
 
+static int bap_adapter_probe(struct btd_profile *p, struct btd_adapter *adapter)
+{
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct bap_data *data;
+	char addr[18];
+
+	ba2str(btd_adapter_get_address(adapter), addr);
+	DBG("%s", addr);
+
+	if (!btd_kernel_experimental_enabled(ISO_SOCKET_UUID)) {
+		error("BAP requires ISO Socket which is not enabled");
+		return -ENOTSUP;
+	}
+
+	data = bap_data_new(NULL);
+
+	data->bap = bt_bap_new(btd_gatt_database_get_db(database),
+					btd_gatt_database_get_db(database));
+	if (!data->bap) {
+		error("Unable to create BAP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	bap_data_add(data);
+
+	if (!bt_bap_attach_broadcast(data->bap)) {
+		error("BAP unable to attach");
+		return -EINVAL;
+	}
+
+	data->state_id = bt_bap_state_register(data->bap, bap_state_bcast_src,
+					bap_connecting_bcast, data, NULL);
+	data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
+					pac_removed_broadcast, data, NULL);
+
+	bt_bap_set_user_data(data->bap, adapter);
+	bap_data_set_user_data(data, adapter);
+
+	data->adapter = new0(struct bap_adapter, 1);
+	data->adapter->adapter = adapter;
+
+	if (adapters == NULL)
+		adapters = queue_new();
+	data->adapter->bcast_pa_requests = queue_new();
+	queue_push_tail(adapters, data->adapter);
+
+	return 0;
+}
+
+static void bap_adapter_remove(struct btd_profile *p,
+					struct btd_adapter *adapter)
+{
+	struct bap_data *data = queue_find(sessions, match_data_bap_data,
+						adapter);
+	char addr[18];
+
+	ba2str(btd_adapter_get_address(adapter), addr);
+	DBG("%s", addr);
+
+	queue_destroy(data->adapter->bcast_pa_requests, free);
+	queue_remove(adapters, data->adapter);
+	free(data->adapter);
+
+	if (queue_isempty(adapters)) {
+		queue_destroy(adapters, NULL);
+		adapters = NULL;
+	}
+
+	if (!data) {
+		error("BAP service not handled by profile");
+		return;
+	}
+
+	bap_data_remove(data);
+}
+
 static struct btd_profile bap_profile = {
 	.name		= "bap",
 	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
@@ -1297,18 +3552,37 @@ static struct btd_profile bap_profile = {
 	.device_remove	= bap_remove,
 	.accept		= bap_accept,
 	.disconnect	= bap_disconnect,
+	.adapter_probe	= bap_adapter_probe,
+	.adapter_remove	= bap_adapter_remove,
+	.auto_connect	= true,
+	.experimental	= true,
+};
+
+static struct btd_profile bap_bcast_profile = {
+	.name		= "bcaa",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= BCAAS_UUID_STR,
+	.device_probe	= bap_bcast_probe,
+	.device_remove	= bap_bcast_remove,
+	.disconnect	= bap_disconnect,
+	.auto_connect	= false,
+	.experimental	= true,
 };
 
 static unsigned int bap_id = 0;
 
 static int bap_init(void)
 {
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
-		warn("D-Bus experimental not enabled");
-		return -ENOTSUP;
-	}
+	int err;
+
+	err = btd_profile_register(&bap_profile);
+	if (err)
+		return err;
+
+	err = btd_profile_register(&bap_bcast_profile);
+	if (err)
+		return err;
 
-	btd_profile_register(&bap_profile);
 	bap_id = bt_bap_register(bap_attached, bap_detached, NULL);
 
 	return 0;
@@ -1316,10 +3590,8 @@ static int bap_init(void)
 
 static void bap_exit(void)
 {
-	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
-		btd_profile_unregister(&bap_profile);
-		bt_bap_unregister(bap_id);
-	}
+	btd_profile_unregister(&bap_profile);
+	bt_bap_unregister(bap_id);
 }
 
 BLUETOOTH_PLUGIN_DEFINE(bap, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
diff --git a/profiles/audio/bap.h b/profiles/audio/bap.h
new file mode 100644
index 0000000..cfe6333
--- /dev/null
+++ b/profiles/audio/bap.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2024 NXP
+ *
+ */
+
+struct bt_bap *bap_get_session(struct btd_device *device);
+void bap_scan_delegator_probe(struct btd_device *device);
diff --git a/profiles/audio/bass.c b/profiles/audio/bass.c
new file mode 100644
index 0000000..6237f5a
--- /dev/null
+++ b/profiles/audio/bass.c
@@ -0,0 +1,1241 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2023-2024 NXP
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/adapter.h"
+#include "src/shared/bass.h"
+#include "src/shared/bap.h"
+#include "src/shared/ad.h"
+
+#include "src/plugin.h"
+#include "src/gatt-database.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+#include "src/error.h"
+
+#include "bass.h"
+#include "bap.h"
+
+#define BASS_UUID_STR "0000184f-0000-1000-8000-00805f9b34fb"
+#define BCAAS_UUID_STR "00001852-0000-1000-8000-00805f9b34fb"
+
+#define MEDIA_ASSISTANT_INTERFACE "org.bluez.MediaAssistant1"
+
+enum assistant_state {
+	ASSISTANT_STATE_IDLE,		/* Assistant object was created for
+					 * the stream
+					 */
+	ASSISTANT_STATE_PENDING,	/* Assistant object was pushed */
+	ASSISTANT_STATE_REQUESTING,	/* Remote device requires
+					 * Broadcast_Code
+					 */
+	ASSISTANT_STATE_ACTIVE,		/* Remote device started receiving
+					 * stream
+					 */
+};
+
+static const char *const str_state[] = {
+	"ASSISTANT_STATE_IDLE",
+	"ASSISTANT_STATE_PENDING",
+	"ASSISTANT_STATE_REQUESTING",
+	"ASSISTANT_STATE_ACTIVE",
+};
+
+struct bass_data {
+	struct btd_device *device;
+	struct btd_service *service;
+	struct bt_bass *bass;
+	unsigned int src_id;
+	unsigned int cp_id;
+};
+
+struct bass_assistant {
+	struct btd_device *device;	/* Broadcast source device */
+	struct bass_data *data;		/* BASS session with peer device */
+	uint8_t sgrp;
+	uint8_t bis;
+	uint32_t bid;
+	struct bt_iso_qos qos;
+	struct iovec *meta;
+	struct iovec *caps;
+	enum assistant_state state;
+	char *path;
+};
+
+struct bass_delegator {
+	struct btd_device *device;	/* Broadcast source device */
+	struct bt_bcast_src *src;
+	struct bt_bap *bap;
+	unsigned int state_id;
+	uint8_t *bcode;
+	unsigned int timeout;
+	struct queue *bcode_reqs;
+};
+
+struct bass_bcode_req {
+	struct bt_bap_stream *stream;
+	bt_bass_bcode_func_t cb;
+	void *user_data;
+};
+
+static struct queue *sessions;
+static struct queue *assistants;
+static struct queue *delegators;
+
+static const char *state2str(enum assistant_state state);
+
+static void bass_debug(const char *str, void *user_data)
+{
+	DBG_IDX(0xffff, "%s", str);
+}
+
+static gboolean req_timeout(gpointer user_data)
+{
+	struct bass_delegator *dg = user_data;
+	struct bass_bcode_req *req;
+
+	DBG("delegator %p", dg);
+
+	dg->timeout = 0;
+
+	while ((req = queue_pop_head(dg->bcode_reqs))) {
+		if (req->cb)
+			req->cb(req->user_data, -ETIMEDOUT);
+
+		free(req);
+	}
+
+	return FALSE;
+}
+
+static bool delegator_match_bap(const void *data, const void *match_data)
+{
+	const struct bass_delegator *dg = data;
+	const struct bt_bap *bap = match_data;
+
+	return dg->bap == bap;
+}
+
+static void stream_set_bcode(uint8_t *bcode, struct bt_bap_stream *stream,
+				bt_bass_bcode_func_t cb, void *user_data)
+{
+	struct bt_bap_qos *qos = bt_bap_stream_get_qos(stream);
+
+	/* Allocate Broadcast Code inside stream QoS */
+	qos->bcast.bcode = util_iov_new(bcode, BT_BASS_BCAST_CODE_SIZE);
+
+	if (cb)
+		cb(user_data, 0);
+}
+
+void bass_req_bcode(struct bt_bap_stream *stream,
+				bt_bass_bcode_func_t cb,
+				void *user_data)
+{
+	struct bt_bap *bap = bt_bap_stream_get_session(stream);
+	struct bass_delegator *dg;
+	struct bass_bcode_req *req;
+
+	dg = queue_find(delegators, delegator_match_bap, bap);
+	if (!dg) {
+		cb(user_data, -EINVAL);
+		return;
+	}
+
+	if (dg->bcode) {
+		/* Broadcast Code has already been received before. */
+		stream_set_bcode(dg->bcode, stream, cb, user_data);
+		return;
+	}
+
+	/* Create a request for the Broadcast Code. The request
+	 * will be considered handled when the Broadcast Code is
+	 * received from a Broadcast Assistant.
+	 */
+	req = new0(struct bass_bcode_req, 1);
+	if (!req)
+		return;
+
+	req->stream = stream;
+	req->cb = cb;
+	req->user_data = user_data;
+
+	queue_push_tail(dg->bcode_reqs, req);
+
+	/* Mark the encryption status as "Broadcast Code Required"
+	 * in the Broadcast Receive State characteristic and notify
+	 * Broadcast Assistants.
+	 */
+	bt_bass_set_enc(dg->src, BT_BASS_BIG_ENC_STATE_BCODE_REQ);
+
+	/* Add timeout for Broadcast Assistants to provide the Code. */
+	if (!dg->timeout)
+		dg->timeout = g_timeout_add_seconds(10, req_timeout, dg);
+}
+
+static bool delegator_match_device(const void *data, const void *match_data)
+{
+	const struct bass_delegator *dg = data;
+	const struct btd_device *device = match_data;
+
+	return dg->device == device;
+}
+
+bool bass_check_bis(struct btd_device *device, uint8_t bis)
+{
+	struct bass_delegator *dg;
+
+	dg = queue_find(delegators, delegator_match_device, device);
+	if (!dg)
+		return true;
+
+	if (!bt_bass_check_bis(dg->src, bis))
+		return false;
+
+	return true;
+}
+
+static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct bass_delegator *dg = user_data;
+	int bis;
+	char *path = bt_bap_stream_get_user_data(stream);
+	struct bt_bap *bap = bt_bap_stream_get_session(stream);
+	const char *strbis;
+	int err;
+
+	if (dg->bap != bap)
+		return;
+
+	strbis = strstr(path, "/bis");
+	if (strbis == NULL) {
+		DBG("bis index cannot be found");
+		return;
+	}
+
+	err = sscanf(strbis, "/bis%d", &bis);
+	if (err < 0) {
+		DBG("sscanf error");
+		return;
+	}
+
+	DBG("stream %p: %s(%u) -> %s(%u)", stream,
+			bt_bap_stream_statestr(old_state), old_state,
+			bt_bap_stream_statestr(new_state), new_state);
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_STREAMING:
+		/* BAP stream was started. Mark BIS index as synced inside the
+		 * Broadcast Receive State characteristic and notify peers about
+		 * the update.
+		 */
+		bt_bass_set_bis_sync(dg->src, bis);
+		break;
+	case BT_BAP_STREAM_STATE_CONFIG:
+		if (old_state == BT_BAP_STREAM_STATE_STREAMING)
+			/* BAP stream was disabled. Clear BIS index from the
+			 * bitmask inside the Broadcast Receive State
+			 * characteristic and notify peers about the update.
+			 */
+			bt_bass_clear_bis_sync(dg->src, bis);
+		break;
+	}
+}
+
+bool bass_bcast_probe(struct btd_device *device, struct bt_bap *bap)
+{
+	struct bass_delegator *dg;
+
+	dg = queue_find(delegators, delegator_match_device, device);
+	if (!dg)
+		return false;
+
+	DBG("%p", dg);
+
+	dg->bap = bap;
+
+	/* Update Broadcast Receive State characteristic value and notify
+	 * peers.
+	 */
+	if (bt_bass_set_pa_sync(dg->src, BT_BASS_SYNCHRONIZED_TO_PA))
+		DBG("Failed to update Broadcast Receive State characteristic");
+
+	/* Register BAP stream state changed callback, to keep up to
+	 * date with BIG/PA sync state.
+	 */
+	dg->state_id = bt_bap_state_register(bap, bap_state_changed,
+			NULL, dg, NULL);
+
+	return true;
+}
+
+bool bass_bcast_remove(struct btd_device *device)
+{
+	struct bass_delegator *dg;
+
+	dg = queue_remove_if(delegators, delegator_match_device, device);
+	if (!dg)
+		return false;
+
+	DBG("%p", dg);
+
+	/* Update Broadcast Receive State characteristic value and notify
+	 * peers.
+	 */
+	if (bt_bass_set_pa_sync(dg->src, BT_BASS_NOT_SYNCHRONIZED_TO_PA))
+		DBG("Failed to update Broadcast Receive State characteristic");
+
+	/* Unregister BAP stream state changed callback. */
+	bt_bap_state_unregister(dg->bap, dg->state_id);
+
+	if (dg->timeout)
+		g_source_remove(dg->timeout);
+
+	queue_destroy(dg->bcode_reqs, free);
+
+	free(dg->bcode);
+
+	free(dg);
+
+	return true;
+}
+
+static void assistant_set_state(struct bass_assistant *assistant,
+					enum assistant_state state)
+{
+	enum assistant_state old_state = assistant->state;
+	const char *str;
+
+	if (old_state == state)
+		return;
+
+	assistant->state = state;
+
+	DBG("State changed %s: %s -> %s", assistant->path, str_state[old_state],
+							str_state[state]);
+
+	str = state2str(state);
+
+	if (g_strcmp0(str, state2str(old_state)) != 0)
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						assistant->path,
+						MEDIA_ASSISTANT_INTERFACE,
+						"State");
+}
+
+static int assistant_parse_qos(struct bass_assistant *assistant,
+						DBusMessageIter *iter)
+{
+	DBusMessageIter dict;
+	const char *key;
+
+	dbus_message_iter_recurse(iter, &dict);
+
+	while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter value, entry;
+		int var;
+
+		dbus_message_iter_recurse(&dict, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		var = dbus_message_iter_get_arg_type(&value);
+
+		if (!strcasecmp(key, "BCode")) {
+			DBusMessageIter array;
+			struct iovec iov = {0};
+
+			if (var != DBUS_TYPE_ARRAY)
+				return -EINVAL;
+
+			dbus_message_iter_recurse(&value, &array);
+			dbus_message_iter_get_fixed_array(&array,
+							&iov.iov_base,
+							(int *)&iov.iov_len);
+
+			if (iov.iov_len != BT_BASS_BCAST_CODE_SIZE) {
+				error("Invalid size for BCode: %zu != 16",
+								iov.iov_len);
+				return -EINVAL;
+			}
+
+			memcpy(assistant->qos.bcast.bcode, iov.iov_base,
+								iov.iov_len);
+
+			return 0;
+		}
+
+		dbus_message_iter_next(&dict);
+	}
+
+	return 0;
+}
+
+static int assistant_parse_props(struct bass_assistant *assistant,
+					DBusMessageIter *props)
+{
+	DBusMessageIter value, entry, array;
+	const char *key;
+
+	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+		dbus_message_iter_recurse(props, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		if (!strcasecmp(key, "Metadata")) {
+			struct iovec iov;
+
+			if (dbus_message_iter_get_arg_type(&value) !=
+							DBUS_TYPE_ARRAY)
+				goto fail;
+
+			dbus_message_iter_recurse(&value, &array);
+			dbus_message_iter_get_fixed_array(&array,
+							&iov.iov_base,
+							(int *)&iov.iov_len);
+
+			util_iov_free(assistant->meta, 1);
+			assistant->meta = util_iov_dup(&iov, 1);
+			DBG("Parsed Metadata");
+		} else if (!strcasecmp(key, "QoS")) {
+			if (dbus_message_iter_get_arg_type(&value) !=
+							DBUS_TYPE_ARRAY)
+				goto fail;
+
+			if (assistant_parse_qos(assistant, &value))
+				goto fail;
+
+			DBG("Parsed QoS");
+		}
+
+		dbus_message_iter_next(props);
+	}
+
+	return 0;
+
+fail:
+	DBG("Failed parsing %s", key);
+
+	return -EINVAL;
+}
+
+static DBusMessage *push(DBusConnection *conn, DBusMessage *msg,
+							  void *user_data)
+{
+	struct bass_assistant *assistant = user_data;
+	struct bt_bass_bcast_audio_scan_cp_hdr hdr;
+	struct bt_bass_add_src_params params;
+	struct iovec iov = {0};
+	uint32_t bis_sync = 0;
+	uint8_t meta_len = 0;
+	int err;
+	DBusMessageIter props, dict;
+
+	DBG("");
+
+	dbus_message_iter_init(msg, &props);
+
+	if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_ARRAY) {
+		DBG("Unable to parse properties");
+		return btd_error_invalid_args(msg);
+	}
+
+	dbus_message_iter_recurse(&props, &dict);
+
+	if (assistant_parse_props(assistant, &dict)) {
+		DBG("Unable to parse properties");
+		return btd_error_invalid_args(msg);
+	}
+
+	hdr.op = BT_BASS_ADD_SRC;
+
+	if (device_get_le_address_type(assistant->device) == BDADDR_LE_PUBLIC)
+		params.addr_type = BT_BASS_ADDR_PUBLIC;
+	else
+		params.addr_type = BT_BASS_ADDR_RANDOM;
+
+	bacpy(&params.addr, device_get_address(assistant->device));
+	put_le24(assistant->bid, params.bid);
+	params.pa_sync = PA_SYNC_NO_PAST;
+	params.pa_interval = PA_INTERVAL_UNKNOWN;
+	params.num_subgroups = assistant->sgrp + 1;
+
+	util_iov_append(&iov, &params, sizeof(params));
+
+	/* Metadata and the BIS index associated with the MediaAssistant
+	 * object will be set in the subgroup they belong to. For the other
+	 * subgroups, no metadata and no BIS index will be provided.
+	 */
+	for (uint8_t sgrp = 0; sgrp < assistant->sgrp; sgrp++) {
+		util_iov_append(&iov, &bis_sync, sizeof(bis_sync));
+		util_iov_append(&iov, &meta_len, sizeof(meta_len));
+	}
+
+	bis_sync = (1 << (assistant->bis - 1));
+	meta_len = assistant->meta->iov_len;
+
+	util_iov_append(&iov, &bis_sync, sizeof(bis_sync));
+	util_iov_append(&iov, &meta_len, sizeof(meta_len));
+	util_iov_append(&iov, assistant->meta->iov_base,
+				assistant->meta->iov_len);
+
+	err = bt_bass_send(assistant->data->bass, &hdr, &iov);
+	if (err) {
+		DBG("Unable to send BASS Write Command");
+		return btd_error_failed(msg, strerror(-err));
+	}
+
+	free(iov.iov_base);
+
+	assistant_set_state(assistant, ASSISTANT_STATE_PENDING);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static const GDBusMethodTable assistant_methods[] = {
+	{GDBUS_EXPERIMENTAL_ASYNC_METHOD("Push",
+					GDBUS_ARGS({ "Props", "a{sv}" }),
+					NULL, push)},
+	{},
+};
+
+static const char *state2str(enum assistant_state state)
+{
+	switch (state) {
+	case ASSISTANT_STATE_IDLE:
+		return "idle";
+	case ASSISTANT_STATE_PENDING:
+		return "pending";
+	case ASSISTANT_STATE_REQUESTING:
+		return "requesting";
+	case ASSISTANT_STATE_ACTIVE:
+		return "active";
+	}
+
+	return NULL;
+}
+
+static gboolean get_state(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bass_assistant *assistant = data;
+	const char *state = state2str(assistant->state);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state);
+
+	return TRUE;
+}
+
+static gboolean get_metadata(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bass_assistant *assistant = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	if (assistant->meta)
+		dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+						&assistant->meta->iov_base,
+						assistant->meta->iov_len);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static gboolean get_qos(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct bass_assistant *assistant = data;
+	DBusMessageIter dict;
+	uint8_t *bcode = assistant->qos.bcast.bcode;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE,
+				&assistant->qos.bcast.encryption);
+	dict_append_array(&dict, "BCode", DBUS_TYPE_BYTE,
+				&bcode, BT_BASS_BCAST_CODE_SIZE);
+
+	dbus_message_iter_close_container(iter, &dict);
+
+	return TRUE;
+}
+
+static const GDBusPropertyTable assistant_properties[] = {
+	{ "State", "s", get_state },
+	{ "Metadata", "ay", get_metadata, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "QoS", "a{sv}", get_qos, NULL, NULL,
+					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ }
+};
+
+static void assistant_free(void *data)
+{
+	struct bass_assistant *assistant = data;
+
+	g_free(assistant->path);
+	util_iov_free(assistant->meta, 1);
+	util_iov_free(assistant->caps, 1);
+
+	free(assistant);
+}
+
+static void src_ad_search_bid(void *data, void *user_data)
+{
+	struct bt_ad_service_data *sd = data;
+	struct bass_assistant *assistant = user_data;
+	struct iovec iov;
+
+	if (sd->uuid.type != BT_UUID16 || sd->uuid.value.u16 != BCAA_SERVICE)
+		return;
+
+	iov.iov_base = sd->data;
+	iov.iov_len = sd->len;
+
+	util_iov_pull_le24(&iov, &assistant->bid);
+}
+
+static struct bass_assistant *assistant_new(struct btd_adapter *adapter,
+		struct btd_device *device, struct bass_data *data,
+		uint8_t sgrp, uint8_t bis, struct bt_iso_qos *qos,
+		struct iovec *meta, struct iovec *caps)
+{
+	struct bass_assistant *assistant;
+	char src_addr[18];
+	char dev_addr[18];
+
+	assistant = new0(struct bass_assistant, 1);
+	if (!assistant)
+		return NULL;
+
+	DBG("assistant %p", assistant);
+
+	assistant->device = device;
+	assistant->data = data;
+	assistant->sgrp = sgrp;
+	assistant->bis = bis;
+	assistant->qos = *qos;
+	assistant->meta = util_iov_dup(meta, 1);
+	assistant->caps = util_iov_dup(caps, 1);
+
+	btd_device_foreach_service_data(assistant->device, src_ad_search_bid,
+							assistant);
+
+	ba2str(device_get_address(device), src_addr);
+	ba2str(device_get_address(data->device), dev_addr);
+
+	assistant->path = g_strdup_printf("%s/src_%s/dev_%s/bis%d",
+		adapter_get_path(adapter), src_addr, dev_addr, bis);
+
+	g_strdelimit(assistant->path, ":", '_');
+
+	if (!assistants)
+		assistants = queue_new();
+
+	queue_push_tail(assistants, assistant);
+
+	return assistant;
+}
+
+void bass_add_stream(struct btd_device *device, struct iovec *meta,
+			struct iovec *caps, struct bt_iso_qos *qos,
+			uint8_t sgrp, uint8_t bis)
+{
+	const struct queue_entry *entry;
+	struct bt_bap *bap;
+	struct bt_bap_pac *pac;
+	struct bass_assistant *assistant;
+	char addr[18];
+
+	for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
+		struct bass_data *data = entry->data;
+		struct btd_adapter *adapter = device_get_adapter(data->device);
+
+		if (!bt_bass_get_client(data->bass))
+			/* Only client sessions must be handled */
+			continue;
+
+		bap = bap_get_session(data->device);
+		if (!bap)
+			continue;
+
+		/* Check stream capabilities against peer caps. */
+		bt_bap_verify_bis(bap, bis, caps, &pac);
+
+		if (!pac)
+			/* Capabilities did not match. */
+			continue;
+
+		ba2str(device_get_address(device), addr);
+
+		DBG("%s data %p BIS %d", addr, data, bis);
+
+		assistant = assistant_new(adapter, device, data, sgrp,
+							bis, qos, meta, caps);
+
+		if (g_dbus_register_interface(btd_get_dbus_connection(),
+						assistant->path,
+						MEDIA_ASSISTANT_INTERFACE,
+						assistant_methods, NULL,
+						assistant_properties,
+						assistant,
+						assistant_free) == FALSE)
+			DBG("Could not register path %s", assistant->path);
+	}
+}
+
+static bool assistant_match_device(const void *data, const void *match_data)
+{
+	const struct bass_assistant *assistant = data;
+	const struct btd_device *device = match_data;
+
+	return (assistant->device == device);
+}
+
+static void unregister_assistant(void *data)
+{
+	struct bass_assistant *assistant = data;
+
+	DBG("%p", assistant);
+
+	g_dbus_unregister_interface(btd_get_dbus_connection(),
+				assistant->path, MEDIA_ASSISTANT_INTERFACE);
+}
+
+void bass_remove_stream(struct btd_device *device)
+{
+	queue_remove_all(assistants, assistant_match_device,
+		device, unregister_assistant);
+}
+
+static struct bass_data *bass_data_new(struct btd_device *device)
+{
+	struct bass_data *data;
+
+	data = new0(struct bass_data, 1);
+	data->device = device;
+
+	return data;
+}
+
+static void bass_data_add(struct bass_data *data)
+{
+	DBG("data %p", data);
+
+	if (queue_find(sessions, NULL, data)) {
+		error("data %p already added", data);
+		return;
+	}
+
+	bt_bass_set_debug(data->bass, bass_debug, NULL, NULL);
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, data);
+
+	if (data->service)
+		btd_service_set_user_data(data->service, data);
+}
+
+static bool match_data(const void *data, const void *match_data)
+{
+	const struct bass_data *bdata = data;
+	const struct bt_bass *bass = match_data;
+
+	return bdata->bass == bass;
+}
+
+static bool assistant_match_data(const void *data, const void *match_data)
+{
+	const struct bass_assistant *assistant = data;
+	const struct bass_data *bdata = match_data;
+
+	return (assistant->data == bdata);
+}
+
+static void bass_data_free(struct bass_data *data)
+{
+	if (data->service) {
+		btd_service_set_user_data(data->service, NULL);
+		bt_bass_set_user_data(data->bass, NULL);
+	}
+
+	bt_bass_src_unregister(data->bass, data->src_id);
+	bt_bass_cp_handler_unregister(data->bass, data->cp_id);
+
+	bt_bass_unref(data->bass);
+
+	queue_remove_all(assistants, assistant_match_data,
+		data, unregister_assistant);
+
+	free(data);
+}
+
+static void bass_data_remove(struct bass_data *data)
+{
+	DBG("data %p", data);
+
+	if (!queue_remove(sessions, data))
+		return;
+
+	bass_data_free(data);
+
+	if (queue_isempty(sessions)) {
+		queue_destroy(sessions, NULL);
+		sessions = NULL;
+	}
+}
+
+static void bass_detached(struct bt_bass *bass, void *user_data)
+{
+	struct bass_data *data;
+
+	DBG("%p", bass);
+
+	data = queue_find(sessions, match_data, bass);
+	if (!data) {
+		error("Unable to find bass session");
+		return;
+	}
+
+	/* If there is a service it means there is BASS thus we can keep
+	 * instance allocated.
+	 */
+	if (data->service)
+		return;
+
+	bass_data_remove(data);
+}
+
+static int handle_add_src_req(struct bt_bcast_src *bcast_src,
+			struct bt_bass_add_src_params *params,
+			struct bass_data *data)
+{
+	struct btd_adapter *adapter = device_get_adapter(data->device);
+	struct btd_device *device;
+	struct bass_delegator *dg;
+
+	/* Create device for Broadcast Source using the parameters
+	 * provided by Broadcast Assistant.
+	 */
+	device = btd_adapter_get_device(adapter, &params->addr,
+						params->addr_type);
+	if (!device) {
+		DBG("Unable to get device");
+		return -EINVAL;
+	}
+
+	DBG("device %p", device);
+
+	/* Probe Broadcast Source, if it has not already been
+	 * autonomously probed inside BAP.
+	 */
+	if (!btd_device_get_service(device, BCAAS_UUID_STR))
+		goto probe;
+
+	return 0;
+
+probe:
+	dg = new0(struct bass_delegator, 1);
+	if (!dg)
+		return -ENOMEM;
+
+	dg->device = device;
+	dg->src = bcast_src;
+	dg->bcode_reqs = queue_new();
+
+	if (!delegators)
+		delegators = queue_new();
+
+	queue_push_tail(delegators, dg);
+
+	DBG("delegator %p", dg);
+
+	/* Probe device with BAP. */
+	bap_scan_delegator_probe(device);
+
+	return 0;
+}
+
+static bool delegator_match_src(const void *data, const void *match_data)
+{
+	const struct bass_delegator *dg = data;
+	const struct bt_bcast_src *src = match_data;
+
+	return dg->src == src;
+}
+
+static int handle_set_bcode_req(struct bt_bcast_src *bcast_src,
+			struct bt_bass_set_bcast_code_params *params,
+			struct bass_data *data)
+{
+	struct bass_delegator *dg;
+	struct bass_bcode_req *req;
+
+	dg = queue_find(delegators, delegator_match_src, bcast_src);
+	if (!dg)
+		return -EINVAL;
+
+	dg->bcode = new0(uint8_t, BT_BASS_BCAST_CODE_SIZE);
+	memcpy(dg->bcode, params->bcast_code, BT_BASS_BCAST_CODE_SIZE);
+
+	if (dg->timeout) {
+		g_source_remove(dg->timeout);
+		dg->timeout = 0;
+	}
+
+	/* Set the Broadcast Code for each stream that required it. */
+	while ((req = queue_pop_head(dg->bcode_reqs))) {
+		stream_set_bcode(dg->bcode, req->stream, req->cb,
+							req->user_data);
+		free(req);
+	}
+
+	return 0;
+}
+
+static int cp_handler(struct bt_bcast_src *bcast_src, uint8_t op, void *params,
+		void *user_data)
+{
+	struct bass_data *data = user_data;
+	int err = 0;
+
+	switch (op) {
+	case BT_BASS_ADD_SRC:
+		err = handle_add_src_req(bcast_src, params, data);
+		break;
+	case BT_BASS_SET_BCAST_CODE:
+		err = handle_set_bcode_req(bcast_src, params, data);
+		break;
+	}
+
+	return err;
+}
+
+static void bass_attached(struct bt_bass *bass, void *user_data)
+{
+	struct bass_data *data;
+	struct bt_att *att;
+	struct btd_device *device;
+
+	DBG("%p", bass);
+
+	data = queue_find(sessions, match_data, bass);
+	if (data)
+		return;
+
+	att = bt_bass_get_att(bass);
+	if (!att)
+		return;
+
+	device = btd_adapter_find_device_by_fd(bt_att_get_fd(att));
+	if (!device) {
+		error("Unable to find device");
+		return;
+	}
+
+	data = bass_data_new(device);
+	data->bass = bass;
+
+	data->cp_id = bt_bass_cp_handler_register(data->bass,
+			cp_handler, NULL, data);
+
+	bass_data_add(data);
+}
+
+static void bass_handle_bcode_req(struct bass_assistant *assistant, int id)
+{
+	struct bt_bass_bcast_audio_scan_cp_hdr hdr;
+	struct bt_bass_set_bcast_code_params params;
+	struct iovec iov = {0};
+	int err;
+
+	assistant_set_state(assistant, ASSISTANT_STATE_REQUESTING);
+
+	hdr.op = BT_BASS_SET_BCAST_CODE;
+
+	params.id = id;
+	memcpy(params.bcast_code, assistant->qos.bcast.bcode,
+					BT_BASS_BCAST_CODE_SIZE);
+
+	iov.iov_base = malloc0(sizeof(params));
+	if (!iov.iov_base)
+		return;
+
+	util_iov_push_mem(&iov, sizeof(params), &params);
+
+	err = bt_bass_send(assistant->data->bass, &hdr, &iov);
+	if (err) {
+		DBG("Unable to send BASS Write Command");
+		return;
+	}
+
+	free(iov.iov_base);
+}
+
+static void bass_src_changed(uint8_t id, uint32_t bid, uint8_t enc,
+					uint32_t bis_sync, void *user_data)
+{
+	const struct queue_entry *entry;
+
+	for (entry = queue_get_entries(assistants); entry;
+						entry = entry->next) {
+		struct bass_assistant *assistant = entry->data;
+		uint32_t bis = 1 << (assistant->bis - 1);
+
+		if (assistant->bid != bid)
+			/* Only handle assistant objects
+			 * that match the source
+			 */
+			continue;
+
+		switch (enc) {
+		case BT_BASS_BIG_ENC_STATE_BCODE_REQ:
+			if (assistant->state != ASSISTANT_STATE_PENDING)
+				/* Only handle assistant objects that
+				 * have been pushed by the user
+				 */
+				break;
+
+			/* Provide Broadcast Code to peer */
+			bass_handle_bcode_req(assistant, id);
+			break;
+		case BT_BASS_BIG_ENC_STATE_NO_ENC:
+			if (assistant->state != ASSISTANT_STATE_PENDING)
+				/* Only handle assistant objects that
+				 * have been pushed by the user
+				 */
+				break;
+
+			/* Match BIS index */
+			if (bis & bis_sync)
+				assistant_set_state(assistant,
+						ASSISTANT_STATE_ACTIVE);
+			break;
+		case BT_BASS_BIG_ENC_STATE_DEC:
+			/* Only handle assistant objects that
+			 * have requested a Broadcast Code
+			 */
+			if (assistant->state != ASSISTANT_STATE_REQUESTING)
+				break;
+
+			/* Match BIS index */
+			if (bis & bis_sync)
+				assistant_set_state(assistant,
+						ASSISTANT_STATE_ACTIVE);
+			break;
+		default:
+			continue;
+		}
+	}
+}
+
+static int bass_probe(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct bass_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	/* Ignore, if we were probed for this device already */
+	if (data) {
+		error("Profile probed twice for the same device!");
+		return -EINVAL;
+	}
+
+	data = bass_data_new(device);
+	data->service = service;
+
+	data->bass = bt_bass_new(btd_gatt_database_get_db(database),
+					btd_device_get_gatt_db(device),
+					btd_adapter_get_address(adapter));
+	if (!data->bass) {
+		error("Unable to create BASS instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	bass_data_add(data);
+	bt_bass_set_user_data(data->bass, service);
+
+	/* Register callback to be called when notifications for
+	 * Broadcast Receive State characteristics are received.
+	 */
+	data->src_id = bt_bass_src_register(data->bass, bass_src_changed,
+						data, NULL);
+
+	data->cp_id = bt_bass_cp_handler_register(data->bass,
+			cp_handler, NULL, data);
+
+	return 0;
+}
+
+static void bass_remove(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bass_data *data;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	data = btd_service_get_user_data(service);
+	if (!data) {
+		error("BASS service not handled by profile");
+		return;
+	}
+
+	bass_data_remove(data);
+}
+static int bass_accept(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	struct bass_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (!data) {
+		error("BASS service not handled by profile");
+		return -EINVAL;
+	}
+
+	if (!bt_bass_attach(data->bass, client)) {
+		error("BASS unable to attach");
+		return -EINVAL;
+	}
+
+	btd_service_connecting_complete(service, 0);
+
+	return 0;
+}
+
+static int bass_disconnect(struct btd_service *service)
+{
+	struct bass_data *data = btd_service_get_user_data(service);
+	struct btd_device *device = btd_service_get_device(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	bt_bass_detach(data->bass);
+
+	btd_service_disconnecting_complete(service, 0);
+
+	return 0;
+}
+
+static int bass_server_probe(struct btd_profile *p,
+				struct btd_adapter *adapter)
+{
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+
+	DBG("BASS path %s", adapter_get_path(adapter));
+
+	bt_bass_add_db(btd_gatt_database_get_db(database),
+				btd_adapter_get_address(adapter));
+
+	return 0;
+}
+
+static void bass_server_remove(struct btd_profile *p,
+					struct btd_adapter *adapter)
+{
+	DBG("BASS remove Adapter");
+}
+
+static struct btd_profile bass_service = {
+	.name		= "bass",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= BASS_UUID_STR,
+	.device_probe	= bass_probe,
+	.device_remove	= bass_remove,
+	.accept		= bass_accept,
+	.disconnect	= bass_disconnect,
+	.adapter_probe	= bass_server_probe,
+	.adapter_remove	= bass_server_remove,
+	.experimental	= true,
+};
+
+static unsigned int bass_id;
+
+static int bass_init(void)
+{
+	int err;
+
+	err = btd_profile_register(&bass_service);
+	if (err)
+		return err;
+
+	bass_id = bt_bass_register(bass_attached, bass_detached, NULL);
+
+	return 0;
+}
+
+static void bass_exit(void)
+{
+	btd_profile_unregister(&bass_service);
+	bt_bass_unregister(bass_id);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(bass, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+							bass_init, bass_exit)
diff --git a/profiles/audio/bass.h b/profiles/audio/bass.h
new file mode 100644
index 0000000..2573463
--- /dev/null
+++ b/profiles/audio/bass.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2024 NXP
+ *
+ */
+
+void bass_add_stream(struct btd_device *device, struct iovec *meta,
+			struct iovec *caps, struct bt_iso_qos *qos,
+			uint8_t sgrp, uint8_t bis);
+void bass_remove_stream(struct btd_device *device);
+
+bool bass_bcast_probe(struct btd_device *device, struct bt_bap *bap);
+bool bass_bcast_remove(struct btd_device *device);
+
+bool bass_check_bis(struct btd_device *device, uint8_t bis);
+
+typedef void (*bt_bass_bcode_func_t)(void *user_data, int err);
+
+void bass_req_bcode(struct bt_bap_stream *stream,
+				bt_bass_bcode_func_t cb,
+				void *user_data);
diff --git a/profiles/audio/ccp.c b/profiles/audio/ccp.c
new file mode 100644
index 0000000..ae17a31
--- /dev/null
+++ b/profiles/audio/ccp.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/sdp.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/ccp.h"
+
+#include "btio/btio.h"
+#include "src/plugin.h"
+#include "src/adapter.h"
+#include "src/gatt-database.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+#include "src/error.h"
+
+#define GTBS_UUID_STR "0000184C-0000-1000-8000-00805f9b34fb"
+
+struct ccp_data {
+	struct btd_device *device;
+	struct btd_service *service;
+	struct bt_ccp *ccp;
+	unsigned int state_id;
+};
+
+static void ccp_debug(const char *str, void *user_data)
+{
+	DBG_IDX(0xffff, "%s", str);
+}
+
+static struct ccp_data *ccp_data_new(struct btd_device *device)
+{
+	struct ccp_data *data;
+
+	data = new0(struct ccp_data, 1);
+	data->device = device;
+
+	return data;
+}
+
+static int ccp_probe(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct ccp_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (data) {
+		error("Profile probed twice for the same device!");
+		return -EINVAL;
+	}
+
+	data = ccp_data_new(device);
+	data->service = service;
+
+	data->ccp = bt_ccp_new(btd_gatt_database_get_db(database),
+			       btd_device_get_gatt_db(device));
+
+	bt_ccp_set_debug(data->ccp, ccp_debug, NULL, NULL);
+	btd_service_set_user_data(service, data);
+
+	return 0;
+}
+
+static void ccp_data_free(struct ccp_data *data)
+{
+	if (data->service) {
+		btd_service_set_user_data(data->service, NULL);
+		bt_ccp_set_user_data(data->ccp, NULL);
+	}
+
+	bt_ccp_unref(data->ccp);
+	free(data);
+}
+
+static void ccp_data_remove(struct ccp_data *data)
+{
+	DBG("data %p", data);
+
+	ccp_data_free(data);
+}
+
+static void ccp_remove(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct ccp_data *data;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	data = btd_service_get_user_data(service);
+	if (!data) {
+		error("CCP service not handled by profile");
+		return;
+	}
+
+	ccp_data_remove(data);
+}
+
+static int ccp_accept(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	struct ccp_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (!bt_ccp_attach(data->ccp, client)) {
+		error("CCP unable to attach");
+		return -EINVAL;
+	}
+
+	/* TODO: register telephony operations here */
+
+	btd_service_connecting_complete(service, 0);
+
+	return 0;
+}
+
+static int ccp_connect(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	return 0;
+}
+
+static int ccp_disconnect(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct ccp_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	bt_ccp_detach(data->ccp);
+
+	btd_service_disconnecting_complete(service, 0);
+
+	return 0;
+}
+
+static int ccp_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
+{
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+
+	bt_ccp_register(btd_gatt_database_get_db(database));
+
+	return 0;
+}
+
+static void
+ccp_server_remove(struct btd_profile *p,
+		  struct btd_adapter *adapter)
+{
+	DBG("CCP remove adapter");
+}
+
+static struct btd_profile ccp_profile = {
+	.name		= "ccp",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= GTBS_UUID_STR,
+	.device_probe	= ccp_probe,
+	.device_remove	= ccp_remove,
+	.accept		= ccp_accept,
+	.connect	= ccp_connect,
+	.disconnect	= ccp_disconnect,
+	.adapter_probe	= ccp_server_probe,
+	.adapter_remove = ccp_server_remove,
+	.testing	= true,
+};
+
+static int ccp_init(void)
+{
+	return btd_profile_register(&ccp_profile);
+}
+
+static void ccp_exit(void)
+{
+	btd_profile_unregister(&ccp_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(ccp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+			ccp_init, ccp_exit)
diff --git a/profiles/audio/csip.c b/profiles/audio/csip.c
new file mode 100644
index 0000000..a697ebd
--- /dev/null
+++ b/profiles/audio/csip.c
@@ -0,0 +1,479 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/sdp.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/csip.h"
+#include "src/shared/crypto.h"
+
+#include "btio/btio.h"
+#include "src/plugin.h"
+#include "src/adapter.h"
+#include "src/gatt-database.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+#include "src/error.h"
+#include "src/btd.h"
+
+#define CSIS_UUID_STR "00001846-0000-1000-8000-00805f9b34fb"
+
+struct csis_data {
+	struct btd_adapter *adapter;
+	struct bt_csip *csip;
+};
+
+struct csip_data {
+	struct btd_adapter *adapter;
+	struct btd_device *device;
+	struct btd_service *service;
+	struct bt_csip *csip;
+	unsigned int ready_id;
+};
+
+static struct queue *sessions;
+static struct queue *servers;
+
+static void csip_debug(const char *str, void *user_data)
+{
+	DBG_IDX(0xffff, "%s", str);
+}
+
+static struct csip_data *csip_data_new(struct btd_device *device)
+{
+	struct csip_data *data;
+
+	data = new0(struct csip_data, 1);
+	data->device = device;
+
+	return data;
+}
+
+static void csip_data_add(struct csip_data *data)
+{
+	DBG("data %p", data);
+
+	if (queue_find(sessions, NULL, data)) {
+		error("data %p already added", data);
+		return;
+	}
+
+	bt_csip_set_debug(data->csip, csip_debug, NULL, NULL);
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, data);
+
+	if (data->service)
+		btd_service_set_user_data(data->service, data);
+}
+
+static int csip_disconnect(struct btd_service *service)
+{
+	struct csip_data *data = btd_service_get_user_data(service);
+
+	bt_csip_detach(data->csip);
+
+	btd_service_disconnecting_complete(service, 0);
+
+	return 0;
+}
+
+static bool match_data(const void *data, const void *match_data)
+{
+	const struct csip_data *vdata = data;
+	const struct bt_csip *csip = match_data;
+
+	return vdata->csip == csip;
+}
+
+static void csip_data_free(struct csip_data *data)
+{
+	if (data->service) {
+		btd_service_set_user_data(data->service, NULL);
+		bt_csip_set_user_data(data->csip, NULL);
+	}
+
+	bt_csip_ready_unregister(data->csip, data->ready_id);
+	bt_csip_unref(data->csip);
+	free(data);
+}
+
+static void csip_data_remove(struct csip_data *data)
+{
+	DBG("data %p", data);
+
+	if (!queue_remove(sessions, data))
+		return;
+
+	csip_data_free(data);
+
+	if (queue_isempty(sessions)) {
+		queue_destroy(sessions, NULL);
+		sessions = NULL;
+	}
+}
+
+static void csip_detached(struct bt_csip *csip, void *user_data)
+{
+	struct csip_data *data;
+
+	DBG("%p", csip);
+
+	data = queue_find(sessions, match_data, csip);
+	if (!data) {
+		error("Unable to find csip session");
+		return;
+	}
+
+	/* If there is a service it means there is CSIS thus we can keep
+	 * instance allocated.
+	 */
+	if (data->service)
+		return;
+
+	csip_data_remove(data);
+}
+
+static void csip_attached(struct bt_csip *csip, void *user_data)
+{
+	struct csip_data *data;
+	struct bt_att *att;
+	struct btd_device *device;
+
+	DBG("%p", csip);
+
+	data = queue_find(sessions, match_data, csip);
+	if (data)
+		return;
+
+	att = bt_csip_get_att(csip);
+	if (!att)
+		return;
+
+	device = btd_adapter_find_device_by_fd(bt_att_get_fd(att));
+	if (!device) {
+		error("Unable to find device");
+		return;
+	}
+
+	data = csip_data_new(device);
+	data->csip = csip;
+
+	csip_data_add(data);
+}
+
+static int csip_accept(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	struct csip_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (!data) {
+		error("CSIP service not handled by profile");
+		return -EINVAL;
+	}
+
+	if (!bt_csip_attach(data->csip, client)) {
+		error("CSIP unable to attach");
+		return -EINVAL;
+	}
+
+	btd_service_connecting_complete(service, 0);
+
+	return 0;
+}
+
+static void csip_ready(struct bt_csip *csip, void *user_data)
+{
+	struct btd_service *service = user_data;
+	struct btd_device *device = btd_service_get_device(service);
+	uint8_t type, size, rank;
+	uint8_t k[16];
+
+	DBG("csip %p", csip);
+
+	if (!bt_csip_get_sirk(csip, &type, k, &size, &rank)) {
+		error("Unable to read SIRK");
+		return;
+	}
+
+	btd_device_add_set(device, type == BT_CSIP_SIRK_ENCRYPT ? true : false,
+								k, size, rank);
+}
+
+static int csip_probe(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct csip_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	/* Ignore, if we were probed for this device already */
+	if (data) {
+		error("Profile probed twice for the same device!");
+		return -EINVAL;
+	}
+
+	data = csip_data_new(device);
+	data->service = service;
+
+	data->csip = bt_csip_new(btd_gatt_database_get_db(database),
+					btd_device_get_gatt_db(device));
+	if (!data->csip) {
+		error("Unable to create CSIP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	csip_data_add(data);
+
+	data->ready_id = bt_csip_ready_register(data->csip, csip_ready, service,
+								NULL);
+
+	bt_csip_set_user_data(data->csip, service);
+
+	return 0;
+}
+
+static void csip_remove(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct csip_data *data;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	data = btd_service_get_user_data(service);
+	if (!data) {
+		error("CSIP service not handled by profile");
+		return;
+	}
+
+	csip_data_remove(data);
+}
+
+static struct btd_profile csip_profile = {
+	.name		= "csip",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= CSIS_UUID_STR,
+
+	.device_probe	= csip_probe,
+	.device_remove	= csip_remove,
+
+	.accept		= csip_accept,
+	.disconnect	= csip_disconnect,
+
+	.experimental	= true,
+};
+
+static bool csis_encrypt(struct bt_att *att, uint8_t val[16])
+{
+	struct btd_device *device;
+	struct bt_crypto *crypto;
+	uint8_t ltk[16];
+	bool ret;
+
+	device = btd_adapter_find_device_by_fd(bt_att_get_fd(att));
+	if (!device) {
+		error("Unable to find device");
+		return false;
+	}
+
+	if (!btd_device_get_ltk(device, ltk, NULL, NULL)) {
+		error("Unable to get device LTK");
+		return false;
+	}
+
+	crypto = bt_crypto_new();
+	if (!crypto) {
+		error("Failed to open crypto");
+		return false;
+	}
+
+	ret = bt_crypto_sef(crypto, ltk, val, val);
+	if (!ret)
+		error("Failed to encrypt SIRK using LTK");
+
+	bt_crypto_unref(crypto);
+
+	return ret;
+}
+
+static void csis_data_add(struct csis_data *data)
+{
+	DBG("data %p", data);
+
+	if (queue_find(servers, NULL, data)) {
+		error("data %p already added", data);
+		return;
+	}
+
+	bt_csip_set_debug(data->csip, csip_debug, NULL, NULL);
+
+	bt_csip_set_sirk(data->csip, btd_opts.csis.encrypt, btd_opts.csis.sirk,
+				btd_opts.csis.size, btd_opts.csis.rank,
+				csis_encrypt);
+
+	if (!servers)
+		servers = queue_new();
+
+	queue_push_tail(servers, data);
+}
+
+static struct csis_data *csis_data_new(struct btd_adapter *adapter)
+{
+	struct csis_data *data;
+
+	data = new0(struct csis_data, 1);
+	data->adapter = adapter;
+
+	return data;
+}
+
+static int csis_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
+{
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct csis_data *data;
+
+	DBG("path %s", adapter_get_path(adapter));
+
+	data = csis_data_new(adapter);
+
+	data->csip = bt_csip_new(btd_gatt_database_get_db(database), NULL);
+	if (!data->csip) {
+		error("Unable to create CSIP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	csis_data_add(data);
+
+	return 0;
+}
+
+static bool match_csis(const void *data, const void *match_data)
+{
+	const struct csis_data *csis = data;
+	const struct btd_adapter *adapter = match_data;
+
+	return csis->adapter == adapter;
+}
+
+static void csis_data_free(struct csis_data *data)
+{
+	bt_csip_unref(data->csip);
+	free(data);
+}
+
+static void csis_data_remove(struct csis_data *data)
+{
+	DBG("data %p", data);
+
+	csis_data_free(data);
+
+	if (queue_isempty(servers)) {
+		queue_destroy(servers, NULL);
+		servers = NULL;
+	}
+}
+
+static void csis_server_remove(struct btd_profile *p,
+					struct btd_adapter *adapter)
+{
+	struct csis_data *data;
+
+	DBG("path %s", adapter_get_path(adapter));
+
+	data = queue_remove_if(servers, match_csis, adapter);
+	if (!data)
+		return;
+
+	csis_data_remove(data);
+}
+
+static struct btd_profile csis_profile = {
+	.name		= "csis",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.local_uuid	= CSIS_UUID_STR,
+
+	.adapter_probe	= csis_server_probe,
+	.adapter_remove	= csis_server_remove,
+	.experimental	= true,
+};
+
+static unsigned int csip_id;
+
+static int csip_init(void)
+{
+	int err;
+
+	err = btd_profile_register(&csis_profile);
+	if (err)
+		return err;
+
+	err = btd_profile_register(&csip_profile);
+	if (err)
+		return err;
+
+	csip_id = bt_csip_register(csip_attached, csip_detached, NULL);
+
+	return 0;
+}
+
+static void csip_exit(void)
+{
+	btd_profile_unregister(&csis_profile);
+	btd_profile_unregister(&csip_profile);
+	bt_csip_unregister(csip_id);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(csip, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+						csip_init, csip_exit)
diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c
index f3ea330..0a2991f 100644
--- a/profiles/audio/mcp.c
+++ b/profiles/audio/mcp.c
@@ -169,7 +169,7 @@ static void cb_track_duration(struct bt_mcp *mcp, int32_t duration)
 	unsigned char buf[10];
 
 	/* MCP defines duration is int32 but api takes it as uint32 */
-	sprintf((char *)buf, "%d", duration);
+	snprintf((char *)buf, 10, "%d", duration);
 	media_player_set_metadata(mp, NULL, "Duration", buf, sizeof(buf));
 	media_player_metadata_changed(mp);
 }
@@ -224,13 +224,27 @@ static int ct_stop(struct media_player *mp, void *user_data)
 	return bt_mcp_stop(mcp);
 }
 
+static int ct_next(struct media_player *mp, void *user_data)
+{
+	struct bt_mcp *mcp = user_data;
+
+	return bt_mcp_next_track(mcp);
+}
+
+static int ct_previous(struct media_player *mp, void *user_data)
+{
+	struct bt_mcp *mcp = user_data;
+
+	return bt_mcp_previous_track(mcp);
+}
+
 static const struct media_player_callback ct_cbs = {
 	.set_setting	= NULL,
 	.play		= &ct_play,
 	.pause		= &ct_pause,
 	.stop		= &ct_stop,
-	.next		= NULL,
-	.previous	= NULL,
+	.next		= &ct_next,
+	.previous	= &ct_previous,
 	.fast_forward	= NULL,
 	.rewind		= NULL,
 	.press		= NULL,
@@ -403,27 +417,18 @@ static struct btd_profile mcp_profile = {
 
 	.adapter_probe	= media_control_server_probe,
 	.adapter_remove = media_control_server_remove,
+
+	.experimental	= true,
 };
 
 static int mcp_init(void)
 {
-	DBG("");
-
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
-		warn("D-Bus experimental not enabled");
-		return -ENOTSUP;
-	}
-
-	btd_profile_register(&mcp_profile);
-	return 0;
+	return btd_profile_register(&mcp_profile);
 }
 
 static void mcp_exit(void)
 {
-	DBG("");
-
-	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)
-		btd_profile_unregister(&mcp_profile);
+	btd_profile_unregister(&mcp_profile);
 }
 
 BLUETOOTH_PLUGIN_DEFINE(mcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index c9328ab..746e538 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -6,7 +6,7 @@
  *  Copyright (C) 2006-2007  Nokia Corporation
  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
- *
+ *  Copyright 2023 NXP
  *
  */
 
@@ -23,6 +23,7 @@
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
 #include "lib/uuid.h"
+#include "lib/mgmt.h"
 
 #include "gdbus/gdbus.h"
 
@@ -37,10 +38,12 @@
 #include "src/log.h"
 #include "src/error.h"
 #include "src/gatt-database.h"
+#include "src/shared/asha.h"
 #include "src/shared/util.h"
 #include "src/shared/queue.h"
 #include "src/shared/att.h"
 #include "src/shared/bap.h"
+#include "src/shared/bap-debug.h"
 
 #include "avdtp.h"
 #include "media.h"
@@ -86,15 +89,19 @@ struct endpoint_request {
 struct media_endpoint {
 	struct a2dp_sep		*sep;
 	struct bt_bap_pac	*pac;
-	void			*stream;
+	struct bt_asha_device	*asha;
 	char			*sender;	/* Endpoint DBus bus id */
 	char			*path;		/* Endpoint object path */
 	char			*uuid;		/* Endpoint property UUID */
 	uint8_t			codec;		/* Endpoint codec */
+	uint16_t                cid;            /* Endpoint company ID */
+	uint16_t                vid;            /* Endpoint vendor codec ID */
 	bool			delay_reporting;/* Endpoint delay_reporting */
 	struct bt_bap_pac_qos	qos;		/* Endpoint qos */
 	uint8_t			*capabilities;	/* Endpoint property capabilities */
 	size_t			size;		/* Endpoint capabilities size */
+	uint8_t                 *metadata;      /* Endpoint property metadata */
+	size_t                  metadata_size;  /* Endpoint metadata size */
 	guint			hs_watch;
 	guint			ag_watch;
 	guint			watch;
@@ -144,6 +151,11 @@ static void media_endpoint_cancel(struct endpoint_request *request)
 {
 	struct media_endpoint *endpoint = request->endpoint;
 
+	DBG("Canceling %s: name = %s path = %s",
+			dbus_message_get_member(request->msg),
+			dbus_message_get_destination(request->msg),
+			dbus_message_get_path(request->msg));
+
 	if (request->call)
 		dbus_pending_call_cancel(request->call);
 
@@ -178,6 +190,7 @@ static void media_endpoint_destroy(struct media_endpoint *endpoint)
 
 	g_dbus_remove_watch(btd_get_dbus_connection(), endpoint->watch);
 	g_free(endpoint->capabilities);
+	g_free(endpoint->metadata);
 	g_free(endpoint->sender);
 	g_free(endpoint->path);
 	g_free(endpoint->uuid);
@@ -725,33 +738,33 @@ struct pac_select_data {
 	void *user_data;
 };
 
-static int parse_array(DBusMessageIter *iter, struct iovec **iov)
+static int parse_array(DBusMessageIter *iter, struct iovec *iov)
 {
 	DBusMessageIter array;
 
 	if (!iov)
 		return 0;
 
-	if (!(*iov))
-		*iov = new0(struct iovec, 1);
-
 	dbus_message_iter_recurse(iter, &array);
-	dbus_message_iter_get_fixed_array(&array, &(*iov)->iov_base,
-						(int *)&(*iov)->iov_len);
+	dbus_message_iter_get_fixed_array(&array, &iov->iov_base,
+						(int *)&iov->iov_len);
 	return 0;
 }
 
-static int parse_select_properties(DBusMessageIter *props, struct iovec **caps,
-					struct iovec **metadata,
-					struct bt_bap_qos *qos)
+static int parse_ucast_qos(DBusMessageIter *iter, struct bt_bap_qos *qos)
 {
+	DBusMessageIter array;
 	const char *key;
+	struct bt_bap_io_qos io_qos;
 
-	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+	dbus_message_iter_recurse(iter, &array);
+
+	memset(&io_qos, 0, sizeof(io_qos));
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
 		DBusMessageIter value, entry;
 		int var;
 
-		dbus_message_iter_recurse(props, &entry);
+		dbus_message_iter_recurse(&array, &entry);
 		dbus_message_iter_get_basic(&entry, &key);
 
 		dbus_message_iter_next(&entry);
@@ -759,97 +772,119 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec **caps,
 
 		var = dbus_message_iter_get_arg_type(&value);
 
-		if (!strcasecmp(key, "Capabilities")) {
-			if (var != DBUS_TYPE_ARRAY)
-				goto fail;
-
-			if (parse_array(&value, caps))
-				goto fail;
-		} else if (!strcasecmp(key, "Metadata")) {
-			if (var != DBUS_TYPE_ARRAY)
-				goto fail;
-
-			if (parse_array(&value, metadata))
-				goto fail;
-		} else if (!strcasecmp(key, "CIG")) {
+		if (!strcasecmp(key, "CIG")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cig_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
 		} else if (!strcasecmp(key, "CIS")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cis_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cis_id);
 		} else if (!strcasecmp(key, "Interval")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->interval);
+			dbus_message_iter_get_basic(&value, &io_qos.interval);
 		} else if (!strcasecmp(key, "Framing")) {
-			dbus_bool_t val;
-
-			if (var != DBUS_TYPE_BOOLEAN)
+			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &val);
-
-			qos->framing = val;
+			dbus_message_iter_get_basic(&value,
+							&qos->ucast.framing);
 		} else if (!strcasecmp(key, "PHY")) {
-			const char *str;
-
-			if (var != DBUS_TYPE_STRING)
+			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &str);
-
-			if (!strcasecmp(str, "1M"))
-				qos->phy = 0x01;
-			else if (!strcasecmp(str, "2M"))
-				qos->phy = 0x02;
-			else
-				goto fail;
+			dbus_message_iter_get_basic(&value, &io_qos.phy);
 		} else if (!strcasecmp(key, "SDU")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->sdu);
+			dbus_message_iter_get_basic(&value, &io_qos.sdu);
 		} else if (!strcasecmp(key, "Retransmissions")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->rtn);
+			dbus_message_iter_get_basic(&value, &io_qos.rtn);
 		} else if (!strcasecmp(key, "Latency")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->latency);
-		} else if (!strcasecmp(key, "Delay")) {
+			dbus_message_iter_get_basic(&value, &io_qos.latency);
+		} else if (!strcasecmp(key, "PresentationDelay")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->delay);
+			dbus_message_iter_get_basic(&value, &qos->ucast.delay);
 		} else if (!strcasecmp(key, "TargetLatency")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
 			dbus_message_iter_get_basic(&value,
-							&qos->target_latency);
+						&qos->ucast.target_latency);
 		}
 
-		dbus_message_iter_next(props);
+		dbus_message_iter_next(&array);
 	}
 
+	memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
+
 	return 0;
 
 fail:
 	DBG("Failed parsing %s", key);
 
-	if (*caps) {
-		free(*caps);
-		*caps = NULL;
+	return -EINVAL;
+}
+
+static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
+					struct iovec *metadata,
+					struct bt_bap_qos *qos)
+{
+	const char *key;
+
+	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter value, entry;
+		int var;
+
+		dbus_message_iter_recurse(props, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		var = dbus_message_iter_get_arg_type(&value);
+
+		if (!strcasecmp(key, "Capabilities")) {
+			if (var != DBUS_TYPE_ARRAY)
+				goto fail;
+
+			if (parse_array(&value, caps))
+				goto fail;
+		} else if (!strcasecmp(key, "Metadata")) {
+			if (var != DBUS_TYPE_ARRAY)
+				goto fail;
+
+			if (parse_array(&value, metadata))
+				goto fail;
+		} else if (!strcasecmp(key, "QoS")) {
+			if (var != DBUS_TYPE_ARRAY)
+				goto fail;
+
+			if (parse_ucast_qos(&value, qos))
+				goto fail;
+		}
+
+		dbus_message_iter_next(props);
 	}
 
+	return 0;
+
+fail:
+	DBG("Failed parsing %s", key);
+
 	return -EINVAL;
 }
 
@@ -859,7 +894,7 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
 	struct pac_select_data *data = user_data;
 	DBusMessageIter *iter = ret;
 	int err;
-	struct iovec *caps = NULL, *metadata = NULL;
+	struct iovec caps, meta;
 	struct bt_bap_qos qos;
 
 	if (!ret) {
@@ -878,19 +913,22 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
 	memset(&qos, 0, sizeof(qos));
 
 	/* Mark CIG and CIS to be auto assigned */
-	qos.cig_id = BT_ISO_QOS_CIG_UNSET;
-	qos.cis_id = BT_ISO_QOS_CIS_UNSET;
+	qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
+	qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
 
-	err = parse_select_properties(iter, &caps, &metadata, &qos);
+	memset(&caps, 0, sizeof(caps));
+	memset(&meta, 0, sizeof(meta));
+
+	err = parse_select_properties(iter, &caps, &meta, &qos);
 	if (err < 0)
 		DBG("Unable to parse properties");
 
 done:
-	data->cb(data->pac, err, caps, metadata, &qos, data->user_data);
+	data->cb(data->pac, err, &caps, &meta, &qos, data->user_data);
 }
 
 static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-			struct bt_bap_pac_qos *qos,
+			uint32_t location, struct bt_bap_pac_qos *qos,
 			bt_bap_pac_select_t cb, void *cb_data, void *user_data)
 {
 	struct media_endpoint *endpoint = user_data;
@@ -901,6 +939,7 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	DBusMessage *msg;
 	DBusMessageIter iter, dict;
 	const char *key = "Capabilities";
+	uint32_t loc;
 
 	bt_bap_pac_get_codec(rpac, NULL, &caps, &metadata);
 	if (!caps)
@@ -932,6 +971,15 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 					DBUS_TYPE_BYTE, &caps->iov_base,
 					caps->iov_len);
 
+	loc = bt_bap_pac_get_locations(rpac);
+	if (loc)
+		g_dbus_dict_append_entry(&dict, "Locations", DBUS_TYPE_UINT32,
+									&loc);
+
+	if (location)
+		g_dbus_dict_append_entry(&dict, "ChannelAllocation",
+					DBUS_TYPE_UINT32, &location);
+
 	if (metadata) {
 		key = "Metadata";
 		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
@@ -941,26 +989,44 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	}
 
 	if (qos && qos->phy) {
-		g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BYTE,
+		DBusMessageIter entry, variant, qos_dict;
+
+		key = "QoS";
+		dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+								NULL, &entry);
+		dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+		dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+							"a{sv}", &variant);
+		dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+							"{sv}", &qos_dict);
+
+		g_dbus_dict_append_entry(&qos_dict, "Framing", DBUS_TYPE_BYTE,
 							&qos->framing);
 
-		g_dbus_dict_append_entry(&dict, "PHY", DBUS_TYPE_BYTE,
+		g_dbus_dict_append_entry(&qos_dict, "PHY", DBUS_TYPE_BYTE,
 							&qos->phy);
 
-		g_dbus_dict_append_entry(&dict, "Latency", DBUS_TYPE_UINT16,
-							&qos->latency);
+		g_dbus_dict_append_entry(&qos_dict, "Retransmissions",
+					DBUS_TYPE_BYTE, &qos->rtn);
+
+		g_dbus_dict_append_entry(&qos_dict, "MaximumLatency",
+					DBUS_TYPE_UINT16, &qos->latency);
 
-		g_dbus_dict_append_entry(&dict, "MinimumDelay",
+		g_dbus_dict_append_entry(&qos_dict, "MinimumDelay",
 					DBUS_TYPE_UINT32, &qos->pd_min);
 
-		g_dbus_dict_append_entry(&dict, "MaximumDelay",
+		g_dbus_dict_append_entry(&qos_dict, "MaximumDelay",
 					DBUS_TYPE_UINT32, &qos->pd_max);
 
-		g_dbus_dict_append_entry(&dict, "PreferredMinimumDelay",
+		g_dbus_dict_append_entry(&qos_dict, "PreferredMinimumDelay",
 					DBUS_TYPE_UINT32, &qos->ppd_min);
 
-		g_dbus_dict_append_entry(&dict, "PreferredMaximumDelay",
-					DBUS_TYPE_UINT32, &qos->ppd_min);
+		g_dbus_dict_append_entry(&qos_dict, "PreferredMaximumDelay",
+					DBUS_TYPE_UINT32, &qos->ppd_max);
+
+		dbus_message_iter_close_container(&variant, &qos_dict);
+		dbus_message_iter_close_container(&entry, &variant);
+		dbus_message_iter_close_container(&dict, &entry);
 	}
 
 	dbus_message_iter_close_container(&iter, &dict);
@@ -969,6 +1035,33 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 								data, free);
 }
 
+static void pac_cancel_select(struct bt_bap_pac *lpac, bt_bap_pac_select_t cb,
+						void *cb_data, void *user_data)
+{
+	struct media_endpoint *endpoint = user_data;
+	GSList *l = endpoint->requests;
+
+	while (l) {
+		struct endpoint_request *req = l->data;
+		struct pac_select_data *data;
+
+		if (req->cb != pac_select_cb) {
+			l = g_slist_next(l);
+			continue;
+		}
+
+		data = req->user_data;
+		if (data->pac != lpac || data->cb != cb ||
+						data->user_data != cb_data) {
+			l = g_slist_next(l);
+			continue;
+		}
+
+		media_endpoint_cancel(req);
+		l = endpoint->requests;
+	}
+}
+
 struct pac_config_data {
 	struct bt_bap_stream *stream;
 	bt_bap_pac_config_t cb;
@@ -978,23 +1071,20 @@ struct pac_config_data {
 static int transport_cmp(gconstpointer data, gconstpointer user_data)
 {
 	const struct media_transport *transport = data;
-	const char *path = user_data;
 
-	if (g_str_has_prefix(media_transport_get_path((void *)transport), path))
+	if (media_transport_get_stream((void *)transport) == user_data)
 		return 0;
 
 	return -1;
 }
 
 static struct media_transport *find_transport(struct media_endpoint *endpoint,
-						const char *path)
+						void *stream)
 {
 	GSList *match;
 
-	if (!path)
-		return NULL;
-
-	match = g_slist_find_custom(endpoint->transports, path, transport_cmp);
+	match = g_slist_find_custom(endpoint->transports, stream,
+								transport_cmp);
 	if (match == NULL)
 		return NULL;
 
@@ -1006,13 +1096,68 @@ static void pac_config_cb(struct media_endpoint *endpoint, void *ret, int size,
 {
 	struct pac_config_data *data = user_data;
 	gboolean *ret_value = ret;
+	struct media_transport *transport;
 
-	if (ret_value)
-		endpoint->stream = data->stream;
+	/* If transport was cleared, configuration was cancelled */
+	transport = find_transport(endpoint, data->stream);
+	if (!transport)
+		return;
 
 	data->cb(data->stream, ret_value ? 0 : -EINVAL);
 }
 
+static struct media_transport *pac_ucast_config(struct bt_bap_stream *stream,
+						struct iovec *cfg,
+						struct media_endpoint *endpoint)
+{
+	struct bt_bap *bap = bt_bap_stream_get_session(stream);
+	struct btd_service *service = bt_bap_get_user_data(bap);
+	struct btd_device *device;
+	const char *path;
+
+	if (service)
+		device = btd_service_get_device(service);
+	else {
+		struct bt_att *att = bt_bap_get_att(bap);
+		int fd = bt_att_get_fd(att);
+
+		device = btd_adapter_find_device_by_fd(fd);
+	}
+
+	if (!device) {
+		error("Unable to find device");
+		return NULL;
+	}
+
+	path = bt_bap_stream_get_user_data(stream);
+
+	return media_transport_create(device, path, cfg->iov_base, cfg->iov_len,
+					endpoint, stream);
+}
+
+static struct media_transport *pac_bcast_config(struct bt_bap_stream *stream,
+						struct iovec *cfg,
+						struct media_endpoint *endpoint)
+{
+	struct bt_bap *bap = bt_bap_stream_get_session(stream);
+	struct btd_adapter *adapter = endpoint->adapter->btd_adapter;
+	struct btd_device *device;
+	const char *path;
+
+	if (!adapter)
+		return NULL;
+
+	if (!strcmp(endpoint->uuid, BCAA_SERVICE_UUID))
+		device = NULL;
+	else
+		device = btd_service_get_device(bt_bap_get_user_data(bap));
+
+	path = bt_bap_stream_get_user_data(stream);
+
+	return media_transport_create(device, path, cfg->iov_base, cfg->iov_len,
+					endpoint, stream);
+}
+
 static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 			struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
 			void *user_data)
@@ -1025,38 +1170,24 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 	DBusMessageIter iter;
 	const char *path;
 
-	path = bt_bap_stream_get_user_data(stream);
-
-	DBG("endpoint %p path %s", endpoint, path);
+	DBG("endpoint %p stream %p", endpoint, stream);
 
-	transport = find_transport(endpoint, path);
+	transport = find_transport(endpoint, stream);
 	if (!transport) {
-		struct bt_bap *bap = bt_bap_stream_get_session(stream);
-		struct btd_service *service = bt_bap_get_user_data(bap);
-		struct btd_device *device;
-
-		if (service)
-			device = btd_service_get_device(service);
-		else {
-			struct bt_att *att = bt_bap_get_att(bap);
-			int fd = bt_att_get_fd(att);
-
-			device = btd_adapter_find_device_by_fd(fd);
-		}
-
-		if (!device) {
-			error("Unable to find device");
-			return -EINVAL;
+		switch (bt_bap_stream_get_type(stream)) {
+		case BT_BAP_STREAM_TYPE_UCAST:
+			transport = pac_ucast_config(stream, cfg, endpoint);
+			break;
+		case BT_BAP_STREAM_TYPE_BCAST:
+			transport = pac_bcast_config(stream, cfg, endpoint);
+			break;
 		}
 
-		transport = media_transport_create(device, path, cfg->iov_base,
-							cfg->iov_len, endpoint,
-							stream);
 		if (!transport)
 			return -EINVAL;
 
-		path = media_transport_get_path(transport);
-		bt_bap_stream_set_user_data(stream, (void *)path);
+		endpoint->transports = g_slist_append(endpoint->transports,
+								transport);
 	}
 
 	msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
@@ -1064,7 +1195,7 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 						"SetConfiguration");
 	if (msg == NULL) {
 		error("Couldn't allocate D-Bus message");
-		media_transport_destroy(transport);
+		endpoint_remove_transport(endpoint, transport);
 		return FALSE;
 	}
 
@@ -1073,8 +1204,6 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 	data->cb = cb;
 	data->user_data = user_data;
 
-	endpoint->transports = g_slist_append(endpoint->transports, transport);
-
 	dbus_message_iter_init_append(msg, &iter);
 
 	path = media_transport_get_path(transport);
@@ -1089,15 +1218,18 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 static void pac_clear(struct bt_bap_stream *stream, void *user_data)
 {
 	struct media_endpoint *endpoint = user_data;
+	struct media_transport *transport;
 
-	endpoint->stream = NULL;
+	DBG("endpoint %p stream %p", endpoint, stream);
 
-	while (endpoint->transports != NULL)
-		clear_configuration(endpoint, endpoint->transports->data);
+	transport = find_transport(endpoint, stream);
+	if (transport)
+		clear_configuration(endpoint, transport);
 }
 
 static struct bt_bap_pac_ops pac_ops = {
 	.select = pac_select,
+	.cancel_select = pac_cancel_select,
 	.config = pac_config,
 	.clear = pac_clear,
 };
@@ -1113,6 +1245,7 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
 	struct btd_gatt_database *database;
 	struct gatt_db *db;
 	struct iovec data;
+	struct iovec *metadata = NULL;
 	char *name;
 
 	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
@@ -1127,29 +1260,44 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
 		return false;
 	}
 
-	if (!bap_print_cc(endpoint->capabilities, endpoint->size, bap_debug,
-								NULL)) {
+	if (!bt_bap_debug_caps(endpoint->capabilities, endpoint->size,
+				bap_debug, NULL)) {
 		error("Unable to parse endpoint capabilities");
 		return false;
 	}
 
+	if (!bt_bap_debug_metadata(endpoint->metadata, endpoint->metadata_size,
+					bap_debug, NULL)) {
+		error("Unable to parse endpoint metadata");
+		return false;
+	}
+
 	db = btd_gatt_database_get_db(database);
 
 	data.iov_base = endpoint->capabilities;
 	data.iov_len = endpoint->size;
 
-	/* TODO: Add support for metadata */
-
 	if (asprintf(&name, "%s:%s", endpoint->sender, endpoint->path) < 0) {
 		error("Could not allocate name for pac %s:%s",
 				endpoint->sender, endpoint->path);
+		free(name);
 		return false;
 	}
 
-	endpoint->pac = bt_bap_add_pac(db, name, type, endpoint->codec,
-					&endpoint->qos, &data, NULL);
+	/* TODO: Add support for metadata */
+	if (endpoint->metadata_size) {
+		metadata = g_new0(struct iovec, 1);
+		metadata->iov_base = endpoint->metadata;
+		metadata->iov_len = endpoint->metadata_size;
+	}
+
+	endpoint->pac = bt_bap_add_vendor_pac(db, name, type, endpoint->codec,
+				endpoint->cid, endpoint->vid, &endpoint->qos,
+				&data, metadata);
 	if (!endpoint->pac) {
 		error("Unable to create PAC");
+		free(name);
+		free(metadata);
 		return false;
 	}
 
@@ -1158,6 +1306,7 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
 	DBG("PAC %s registered", name);
 
 	free(name);
+	free(metadata);
 
 	return true;
 }
@@ -1172,6 +1321,24 @@ static bool endpoint_init_pac_source(struct media_endpoint *endpoint, int *err)
 	return endpoint_init_pac(endpoint, BT_BAP_SOURCE, err);
 }
 
+static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint,
+						int *err)
+{
+	return endpoint_init_pac(endpoint, BT_BAP_BCAST_SOURCE, err);
+}
+
+static bool endpoint_init_broadcast_sink(struct media_endpoint *endpoint,
+						int *err)
+{
+	return endpoint_init_pac(endpoint, BT_BAP_BCAST_SINK, err);
+}
+
+static bool endpoint_init_asha(struct media_endpoint *endpoint,
+						int *err)
+{
+	return true;
+}
+
 static bool endpoint_properties_exists(const char *uuid,
 						struct btd_device *dev,
 						void *user_data)
@@ -1254,8 +1421,11 @@ static bool endpoint_properties_get(const char *uuid,
 	return true;
 }
 
-static bool endpoint_supported(struct btd_adapter *adapter)
+static bool a2dp_endpoint_supported(struct btd_adapter *adapter)
 {
+	if (!btd_adapter_has_settings(adapter, MGMT_SETTING_BREDR))
+		return false;
+
 	return true;
 }
 
@@ -1264,20 +1434,59 @@ static bool experimental_endpoint_supported(struct btd_adapter *adapter)
 	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
 		return false;
 
+	if (!btd_adapter_has_settings(adapter, MGMT_SETTING_CIS_CENTRAL |
+					MGMT_SETTING_CIS_PERIPHERAL))
+		return false;
+
 	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
 }
 
-static struct media_endpoint_init {
+static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter)
+{
+	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
+		return false;
+
+	if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_BROADCASTER))
+		return false;
+
+	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
+}
+
+static bool experimental_bcast_sink_ep_supported(struct btd_adapter *adapter)
+{
+	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
+		return false;
+
+	if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_SYNC_RECEIVER))
+		return false;
+
+	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
+}
+
+static bool experimental_asha_supported(struct btd_adapter *adapter)
+{
+	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
+}
+
+static const struct media_endpoint_init {
 	const char *uuid;
 	bool (*func)(struct media_endpoint *endpoint, int *err);
 	bool (*supported)(struct btd_adapter *adapter);
 } init_table[] = {
-	{ A2DP_SOURCE_UUID, endpoint_init_a2dp_source, endpoint_supported },
-	{ A2DP_SINK_UUID, endpoint_init_a2dp_sink, endpoint_supported },
+	{ A2DP_SOURCE_UUID, endpoint_init_a2dp_source,
+				a2dp_endpoint_supported },
+	{ A2DP_SINK_UUID, endpoint_init_a2dp_sink,
+				a2dp_endpoint_supported },
 	{ PAC_SINK_UUID, endpoint_init_pac_sink,
 				experimental_endpoint_supported },
 	{ PAC_SOURCE_UUID, endpoint_init_pac_source,
 				experimental_endpoint_supported },
+	{ BCAA_SERVICE_UUID, endpoint_init_broadcast_source,
+			experimental_broadcaster_ep_supported },
+	{ BAA_SERVICE_UUID, endpoint_init_broadcast_sink,
+			experimental_bcast_sink_ep_supported },
+	{ ASHA_PROFILE_UUID, endpoint_init_asha,
+			experimental_asha_supported },
 };
 
 static struct media_endpoint *
@@ -1287,13 +1496,17 @@ media_endpoint_create(struct media_adapter *adapter,
 						const char *uuid,
 						gboolean delay_reporting,
 						uint8_t codec,
+						uint16_t cid,
+						uint16_t vid,
 						struct bt_bap_pac_qos *qos,
 						uint8_t *capabilities,
 						int size,
+						uint8_t *metadata,
+						int metadata_size,
 						int *err)
 {
 	struct media_endpoint *endpoint;
-	struct media_endpoint_init *init;
+	const struct media_endpoint_init *init;
 	size_t i;
 	bool succeeded = false;
 
@@ -1302,6 +1515,8 @@ media_endpoint_create(struct media_adapter *adapter,
 	endpoint->path = g_strdup(path);
 	endpoint->uuid = g_strdup(uuid);
 	endpoint->codec = codec;
+	endpoint->cid = cid;
+	endpoint->vid = vid;
 	endpoint->delay_reporting = delay_reporting;
 
 	if (qos)
@@ -1313,6 +1528,12 @@ media_endpoint_create(struct media_adapter *adapter,
 		endpoint->size = size;
 	}
 
+	if (metadata_size > 0) {
+		endpoint->metadata = g_new(uint8_t, metadata_size);
+		memcpy(endpoint->metadata, metadata, metadata_size);
+		endpoint->metadata_size = metadata_size;
+	}
+
 	endpoint->adapter = adapter;
 
 	for (i = 0; i < ARRAY_SIZE(init_table); i++) {
@@ -1352,13 +1573,21 @@ media_endpoint_create(struct media_adapter *adapter,
 	return endpoint;
 }
 
+struct vendor {
+	uint16_t cid;
+	uint16_t vid;
+} __packed;
+
 static int parse_properties(DBusMessageIter *props, const char **uuid,
 				gboolean *delay_reporting, uint8_t *codec,
+				uint16_t *cid, uint16_t *vid,
 				struct bt_bap_pac_qos *qos,
-				uint8_t **capabilities, int *size)
+				uint8_t **capabilities, int *size,
+				uint8_t **metadata, int *metadata_size)
 {
 	gboolean has_uuid = FALSE;
 	gboolean has_codec = FALSE;
+	struct vendor vendor;
 
 	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
 		const char *key;
@@ -1382,6 +1611,12 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
 				return -EINVAL;
 			dbus_message_iter_get_basic(&value, codec);
 			has_codec = TRUE;
+		} else if (strcasecmp(key, "Vendor") == 0) {
+			if (var != DBUS_TYPE_UINT32)
+				return -EINVAL;
+			dbus_message_iter_get_basic(&value, &vendor);
+			*cid = vendor.cid;
+			*vid = vendor.vid;
 		} else if (strcasecmp(key, "DelayReporting") == 0) {
 			if (var != DBUS_TYPE_BOOLEAN)
 				return -EINVAL;
@@ -1395,6 +1630,15 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
 			dbus_message_iter_recurse(&value, &array);
 			dbus_message_iter_get_fixed_array(&array, capabilities,
 							size);
+		} else if (strcasecmp(key, "Metadata") == 0) {
+			DBusMessageIter array;
+
+			if (var != DBUS_TYPE_ARRAY)
+				return -EINVAL;
+
+			dbus_message_iter_recurse(&value, &array);
+			dbus_message_iter_get_fixed_array(&array, metadata,
+							metadata_size);
 		} else if (strcasecmp(key, "Framing") == 0) {
 			if (var != DBUS_TYPE_BYTE)
 				return -EINVAL;
@@ -1403,7 +1647,7 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
 			if (var != DBUS_TYPE_BYTE)
 				return -EINVAL;
 			dbus_message_iter_get_basic(&value, &qos->phy);
-		} else if (strcasecmp(key, "RTN") == 0) {
+		} else if (strcasecmp(key, "Retransmissions") == 0) {
 			if (var != DBUS_TYPE_BYTE)
 				return -EINVAL;
 			dbus_message_iter_get_basic(&value, &qos->rtn);
@@ -1418,11 +1662,24 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
 		} else if (strcasecmp(key, "PreferredMinimumDelay") == 0) {
 			if (var != DBUS_TYPE_UINT16)
 				return -EINVAL;
-			dbus_message_iter_get_basic(&value, &qos->pd_min);
+			dbus_message_iter_get_basic(&value, &qos->ppd_min);
 		} else if (strcasecmp(key, "PreferredMaximumDelay") == 0) {
 			if (var != DBUS_TYPE_UINT16)
 				return -EINVAL;
-			dbus_message_iter_get_basic(&value, &qos->pd_max);
+			dbus_message_iter_get_basic(&value, &qos->ppd_max);
+		} else if (strcasecmp(key, "Locations") == 0) {
+			if (var != DBUS_TYPE_UINT32)
+				return -EINVAL;
+			dbus_message_iter_get_basic(&value, &qos->location);
+		} else if (strcasecmp(key, "Context") == 0) {
+			if (var != DBUS_TYPE_UINT16)
+				return -EINVAL;
+			dbus_message_iter_get_basic(&value, &qos->context);
+		} else if (strcasecmp(key, "SupportedContext") == 0) {
+			if (var != DBUS_TYPE_UINT16)
+				return -EINVAL;
+			dbus_message_iter_get_basic(&value,
+						    &qos->supported_context);
 		}
 
 		dbus_message_iter_next(props);
@@ -1439,9 +1696,13 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
 	const char *sender, *path, *uuid;
 	gboolean delay_reporting = FALSE;
 	uint8_t codec = 0;
+	uint16_t cid = 0;
+	uint16_t vid = 0;
 	struct bt_bap_pac_qos qos = {};
 	uint8_t *capabilities = NULL;
+	uint8_t *metadata = NULL;
 	int size = 0;
+	int metadata_size = 0;
 	int err;
 
 	sender = dbus_message_get_sender(msg);
@@ -1458,12 +1719,14 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
 	if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
 		return btd_error_invalid_args(msg);
 
-	if (parse_properties(&props, &uuid, &delay_reporting, &codec, &qos,
-						&capabilities, &size) < 0)
+	if (parse_properties(&props, &uuid, &delay_reporting, &codec, &cid,
+			&vid, &qos, &capabilities, &size, &metadata,
+			&metadata_size) < 0)
 		return btd_error_invalid_args(msg);
 
 	if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
-					codec, &qos, capabilities, size,
+					codec, cid, vid, &qos, capabilities,
+					size, metadata, metadata_size,
 					&err) == NULL) {
 		if (err == -EPROTONOSUPPORT)
 			return btd_error_not_supported(msg);
@@ -2490,9 +2753,12 @@ static void app_register_endpoint(void *data, void *user_data)
 	const char *uuid;
 	gboolean delay_reporting = FALSE;
 	uint8_t codec;
+	struct vendor vendor;
 	struct bt_bap_pac_qos qos;
 	uint8_t *capabilities = NULL;
 	int size = 0;
+	uint8_t *metadata = NULL;
+	int metadata_size = 0;
 	DBusMessageIter iter, array;
 	struct media_endpoint *endpoint;
 
@@ -2519,6 +2785,15 @@ static void app_register_endpoint(void *data, void *user_data)
 
 	dbus_message_iter_get_basic(&iter, &codec);
 
+	memset(&vendor, 0, sizeof(vendor));
+
+	if (g_dbus_proxy_get_property(proxy, "Vendor", &iter)) {
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+			goto fail;
+
+		dbus_message_iter_get_basic(&iter, &vendor);
+	}
+
 	/* DelayReporting and Capabilities are considered optional */
 	if (g_dbus_proxy_get_property(proxy, "DelayReporting", &iter))	{
 		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
@@ -2535,6 +2810,15 @@ static void app_register_endpoint(void *data, void *user_data)
 		dbus_message_iter_get_fixed_array(&array, &capabilities, &size);
 	}
 
+	if (g_dbus_proxy_get_property(proxy, "Metadata", &iter)) {
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+			goto fail;
+
+		dbus_message_iter_recurse(&iter, &array);
+		dbus_message_iter_get_fixed_array(&array, &metadata,
+						&metadata_size);
+	}
+
 	/* Parse QoS preferences */
 	memset(&qos, 0, sizeof(qos));
 	if (g_dbus_proxy_get_property(proxy, "Framing", &iter)) {
@@ -2551,7 +2835,7 @@ static void app_register_endpoint(void *data, void *user_data)
 		dbus_message_iter_get_basic(&iter, &qos.phy);
 	}
 
-	if (g_dbus_proxy_get_property(proxy, "Latency", &iter)) {
+	if (g_dbus_proxy_get_property(proxy, "MaximumLatency", &iter)) {
 		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
 			goto fail;
 
@@ -2586,9 +2870,33 @@ static void app_register_endpoint(void *data, void *user_data)
 		dbus_message_iter_get_basic(&iter, &qos.ppd_min);
 	}
 
+	if (g_dbus_proxy_get_property(proxy, "Locations", &iter)) {
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+			goto fail;
+
+		dbus_message_iter_get_basic(&iter, &qos.location);
+	}
+
+	if (g_dbus_proxy_get_property(proxy, "Context", &iter)) {
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
+			goto fail;
+
+		dbus_message_iter_get_basic(&iter, &qos.context);
+	}
+
+	if (g_dbus_proxy_get_property(proxy, "SupportedContext", &iter)) {
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
+			goto fail;
+
+		dbus_message_iter_get_basic(&iter, &qos.supported_context);
+	}
+
 	endpoint = media_endpoint_create(app->adapter, app->sender, path, uuid,
-						delay_reporting, codec, &qos,
-						capabilities, size, &app->err);
+						delay_reporting, codec,
+						vendor.cid, vendor.vid, &qos,
+						capabilities, size,
+						metadata, metadata_size,
+						&app->err);
 	if (!endpoint) {
 		error("Unable to register endpoint %s:%s: %s", app->sender,
 						path, strerror(-app->err));
@@ -2726,9 +3034,6 @@ static void client_ready_cb(GDBusClient *client, void *user_data)
 		goto reply;
 	}
 
-	queue_foreach(app->proxies, app_register_endpoint, app);
-	queue_foreach(app->proxies, app_register_player, app);
-
 	if (app->err) {
 		if (app->err == -EPROTONOSUPPORT)
 			reply = btd_error_not_supported(app->reg);
@@ -2772,6 +3077,10 @@ static void proxy_added_cb(GDBusProxy *proxy, void *user_data)
 	path = g_dbus_proxy_get_path(proxy);
 
 	DBG("Proxy added: %s, iface: %s", path, iface);
+
+	app_register_endpoint(proxy, app);
+	app_register_player(proxy, app);
+
 }
 
 static bool match_endpoint_by_path(const void *a, const void *b)
@@ -2985,7 +3294,7 @@ static gboolean supported_uuids(const GDBusPropertyTable *property,
 				DBUS_TYPE_STRING_AS_STRING, &entry);
 
 	for (i = 0; i < ARRAY_SIZE(init_table); i++) {
-		struct media_endpoint_init *init = &init_table[i];
+		const struct media_endpoint_init *init = &init_table[i];
 
 		if (init->supported(adapter->btd_adapter))
 			dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
@@ -3085,3 +3394,33 @@ uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint)
 {
 	return endpoint->codec;
 }
+
+struct btd_adapter *media_endpoint_get_btd_adapter(
+					struct media_endpoint *endpoint)
+{
+	return endpoint->adapter->btd_adapter;
+}
+
+bool media_endpoint_is_broadcast(struct media_endpoint *endpoint)
+{
+	if (!strcmp(endpoint->uuid, BCAA_SERVICE_UUID)
+		|| !strcmp(endpoint->uuid, BAA_SERVICE_UUID))
+		return true;
+
+	return false;
+}
+
+const struct media_endpoint *media_endpoint_get_asha(void)
+{
+	/*
+	 * Because ASHA does not require the application to register an
+	 * endpoint, we need a minimal media_endpoint for transport creation to
+	 * work, so let's create one
+	 */
+	static struct media_endpoint asha_endpoint =  {
+		.uuid = ASHA_PROFILE_UUID,
+		.codec = 0x2, /* Currently on G.722 is defined by the spec */
+	};
+
+	return &asha_endpoint;
+}
diff --git a/profiles/audio/media.h b/profiles/audio/media.h
index 96bea9d..2b2e8e1 100644
--- a/profiles/audio/media.h
+++ b/profiles/audio/media.h
@@ -20,5 +20,9 @@ void media_unregister(struct btd_adapter *btd_adapter);
 struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint);
 const char *media_endpoint_get_uuid(struct media_endpoint *endpoint);
 uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint);
-
+struct btd_adapter *media_endpoint_get_btd_adapter(
+					struct media_endpoint *endpoint);
+bool media_endpoint_is_broadcast(struct media_endpoint *endpoint);
 int8_t media_player_get_device_volume(struct btd_device *device);
+
+const struct media_endpoint *media_endpoint_get_asha(void);
diff --git a/profiles/audio/micp.c b/profiles/audio/micp.c
new file mode 100644
index 0000000..452027c
--- /dev/null
+++ b/profiles/audio/micp.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  NXP Semiconductors. All rights reserved.
+ *
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define	_GNU_SOURCE
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/sdp.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/micp.h"
+
+#include "btio/btio.h"
+#include "src/plugin.h"
+#include "src/adapter.h"
+#include "src/gatt-database.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+#include "src/error.h"
+
+#define MICS_UUID_STR	"0000184D-0000-1000-8000-00805f9b34fb"
+
+struct micp_data {
+	struct btd_device *device;
+	struct btd_service *service;
+	struct bt_micp *micp;
+	unsigned int ready_id;
+};
+
+static struct queue *sessions;
+
+static void micp_debug(const char *str, void *user_data)
+{
+	DBG_IDX(0xffff, "%s", str);
+}
+
+static int micp_disconnect(struct btd_service *service)
+{
+	return 0;
+}
+
+static struct micp_data *micp_data_new(struct btd_device *device)
+{
+	struct micp_data *data;
+
+	data = new0(struct micp_data, 1);
+	g_assert(data);
+	data->device = device;
+
+	return data;
+}
+
+static void micp_data_add(struct micp_data *data)
+{
+	DBG("data %p", data);
+
+	if (queue_find(sessions, NULL, data)) {
+		error("data %p allready added", data);
+		return;
+	}
+
+	bt_micp_set_debug(data->micp, micp_debug, NULL, NULL);
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, data);
+
+	if (data->service)
+		btd_service_set_user_data(data->service, data);
+}
+
+static bool match_data(const void *data, const void *match_data)
+{
+	const struct micp_data *mdata = data;
+	const struct bt_micp *micp = match_data;
+
+	return mdata->micp == micp;
+}
+
+static void micp_data_free(struct micp_data *data)
+{
+	if (data->service) {
+		btd_service_set_user_data(data->service, NULL);
+		bt_micp_set_user_data(data->micp, NULL);
+	}
+
+	bt_micp_ready_unregister(data->micp, data->ready_id);
+	bt_micp_unref(data->micp);
+	free(data);
+}
+
+static void micp_data_remove(struct micp_data *data)
+{
+	DBG("data %p", data);
+
+	if (!queue_remove(sessions, data))
+		return;
+
+	micp_data_free(data);
+
+	if (queue_isempty(sessions)) {
+		queue_destroy(sessions, NULL);
+		sessions = NULL;
+	}
+}
+
+static void micp_detached(struct bt_micp *micp, void *user_data)
+{
+	struct micp_data *data;
+
+	DBG("%p", micp);
+
+	data = queue_find(sessions, match_data, micp);
+	if (!data) {
+		error("unable to find sessio");
+		return;
+	}
+
+	micp_data_remove(data);
+}
+
+static void micp_ready(struct bt_micp *micp, void *user_data)
+{
+	DBG("micp %p\n", micp);
+}
+
+static void micp_attached(struct bt_micp *micp, void *user_data)
+{
+	struct micp_data *data;
+	struct bt_att *att;
+	struct btd_device *device;
+
+	DBG("%p", micp);
+
+	data = queue_find(sessions, match_data, micp);
+	if (data)
+		return;
+
+	att = bt_micp_get_att(micp);
+	if (!att)
+		return;
+
+	device = btd_adapter_find_device_by_fd(bt_att_get_fd(att));
+	if (!device) {
+		error("unable to find device");
+		return;
+	}
+
+	data = micp_data_new(device);
+	g_assert(data);
+	data->micp = micp;
+
+	micp_data_add(data);
+}
+
+static int micp_probe(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct micp_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	/*Ignore, if we probed for this device allready */
+	if (data) {
+		error("Profile probed twice for this device");
+		return -EINVAL;
+	}
+
+	data = micp_data_new(device);
+	data->service = service;
+
+	data->micp = bt_micp_new(btd_gatt_database_get_db(database),
+					btd_device_get_gatt_db(device));
+
+	if (!data->micp) {
+		error("unable to create MICP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	micp_data_add(data);
+
+	data->ready_id = bt_micp_ready_register(data->micp, micp_ready, service,
+								NULL);
+
+	bt_micp_set_user_data(data->micp, service);
+
+	return 0;
+}
+
+static void micp_remove(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct micp_data *data;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	data = btd_service_get_user_data(service);
+	if (!data) {
+		error("MICP Service not handled by profile");
+		return;
+	}
+
+	micp_data_remove(data);
+}
+
+static int micp_accept(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	struct micp_data *data = btd_service_get_user_data(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (!data) {
+		error("MICP Service not handled by profile");
+		return -EINVAL;
+	}
+
+	if (!bt_micp_attach(data->micp, client)) {
+		error("MICP unable to attach");
+		return -EINVAL;
+	}
+
+	btd_service_connecting_complete(service, 0);
+
+	return 0;
+}
+
+static int micp_connect(struct btd_service *service)
+{
+	struct btd_device *device = btd_service_get_device(service);
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	return 0;
+}
+
+static int micp_server_probe(struct btd_profile *p,
+				struct btd_adapter *adapter)
+{
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+
+	DBG("MICP path %s", adapter_get_path(adapter));
+
+	bt_micp_add_db(btd_gatt_database_get_db(database));
+
+	return 0;
+}
+
+static void micp_server_remove(struct btd_profile *p,
+					struct btd_adapter *adapter)
+{
+	DBG("MICP remove adapter");
+}
+
+static struct btd_profile micp_profile = {
+	.name		= "micp",
+	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
+	.remote_uuid	= MICS_UUID_STR,
+
+	.device_probe	= micp_probe,
+	.device_remove	= micp_remove,
+
+	.accept	= micp_accept,
+	.connect	= micp_connect,
+	.disconnect	= micp_disconnect,
+
+	.adapter_probe	= micp_server_probe,
+	.adapter_remove = micp_server_remove,
+};
+
+static unsigned int micp_id;
+
+static int micp_init(void)
+{
+	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+		warn("D-Bus experimental not enabled");
+		return -ENOTSUP;
+	}
+
+	btd_profile_register(&micp_profile);
+	micp_id = bt_micp_register(micp_attached, micp_detached, NULL);
+
+	return 0;
+}
+
+static void micp_exit(void)
+{
+	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
+		btd_profile_unregister(&micp_profile);
+		bt_micp_unregister(micp_id);
+	}
+}
+
+BLUETOOTH_PLUGIN_DEFINE(micp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+							micp_init, micp_exit)
diff --git a/profiles/audio/player.c b/profiles/audio/player.c
index c995697..0f72d76 100644
--- a/profiles/audio/player.c
+++ b/profiles/audio/player.c
@@ -88,6 +88,7 @@ struct media_player {
 	struct player_callback	*cb;
 	GSList			*pending;
 	GSList			*folders;
+	uint16_t		obex_port;
 };
 
 static void append_track(void *key, void *value, void *user_data)
@@ -437,6 +438,28 @@ static gboolean get_playlist(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean obexport_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct media_player *mp = data;
+
+	return mp->obex_port != 0;
+}
+
+static gboolean get_obexport(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_player *mp = data;
+
+	if (mp->obex_port == 0)
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+							&mp->obex_port);
+
+	return TRUE;
+}
+
 static DBusMessage *media_player_play(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
@@ -778,6 +801,8 @@ static const GDBusPropertyTable media_player_properties[] = {
 	{ "Browsable", "b", get_browsable, NULL, browsable_exists },
 	{ "Searchable", "b", get_searchable, NULL, searchable_exists },
 	{ "Playlist", "o", get_playlist, NULL, playlist_exists },
+	{ "ObexPort", "q", get_obexport, NULL, obexport_exists,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{ }
 };
 
@@ -1413,18 +1438,19 @@ void media_player_set_metadata(struct media_player *mp,
 				void *data, size_t len)
 {
 	char *value, *curval;
+	GHashTable *metadata = item ? item->metadata : mp->track;
 
 	value = g_strndup(data, len);
 
 	DBG("%s: %s", key, value);
 
-	curval = g_hash_table_lookup(mp->track, key);
+	curval = g_hash_table_lookup(metadata, key);
 	if (g_strcmp0(curval, value) == 0) {
 		g_free(value);
 		return;
 	}
 
-	g_hash_table_replace(mp->track, g_strdup(key), value);
+	g_hash_table_replace(metadata, g_strdup(key), value);
 }
 
 void media_player_metadata_changed(struct media_player *mp)
@@ -1997,3 +2023,19 @@ struct media_item *media_player_set_playlist_item(struct media_player *mp,
 
 	return item;
 }
+
+void media_player_clear_playlist(struct media_player *mp)
+{
+	if (mp->playlist) {
+		g_slist_free_full(mp->playlist->items, media_item_destroy);
+		mp->playlist->items = NULL;
+	}
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path,
+					MEDIA_PLAYER_INTERFACE, "Playlist");
+}
+
+void media_player_set_obex_port(struct media_player *mp, uint16_t port)
+{
+	mp->obex_port = port;
+}
diff --git a/profiles/audio/player.h b/profiles/audio/player.h
index 74fb7d7..5e18159 100644
--- a/profiles/audio/player.h
+++ b/profiles/audio/player.h
@@ -86,6 +86,8 @@ void media_player_set_folder(struct media_player *mp, const char *path,
 void media_player_set_playlist(struct media_player *mp, const char *name);
 struct media_item *media_player_set_playlist_item(struct media_player *mp,
 								uint64_t uid);
+void media_player_clear_playlist(struct media_player *mp);
+void media_player_set_obex_port(struct media_player *mp, uint16_t port);
 
 struct media_item *media_player_create_folder(struct media_player *mp,
 						const char *name,
diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c
index 56c4917..77f1954 100644
--- a/profiles/audio/sink.c
+++ b/profiles/audio/sink.c
@@ -62,7 +62,7 @@ struct sink_state_callback {
 
 static GSList *sink_callbacks = NULL;
 
-static char *str_state[] = {
+static const char *str_state[] = {
 	"SINK_STATE_DISCONNECTED",
 	"SINK_STATE_CONNECTING",
 	"SINK_STATE_CONNECTED",
@@ -137,6 +137,11 @@ static void stream_state_changed(struct avdtp_stream *stream,
 	case AVDTP_STATE_IDLE:
 		btd_service_disconnecting_complete(sink->service, 0);
 
+		if (sink->connect_id > 0) {
+			a2dp_cancel(sink->connect_id);
+			sink->connect_id = 0;
+		}
+
 		if (sink->disconnect_id > 0) {
 			a2dp_cancel(sink->disconnect_id);
 			sink->disconnect_id = 0;
diff --git a/profiles/audio/source.c b/profiles/audio/source.c
index c6009d0..db777e8 100644
--- a/profiles/audio/source.c
+++ b/profiles/audio/source.c
@@ -61,7 +61,7 @@ struct source_state_callback {
 
 static GSList *source_callbacks = NULL;
 
-static char *str_state[] = {
+static const char *str_state[] = {
 	"SOURCE_STATE_DISCONNECTED",
 	"SOURCE_STATE_CONNECTING",
 	"SOURCE_STATE_CONNECTED",
@@ -134,6 +134,11 @@ static void stream_state_changed(struct avdtp_stream *stream,
 	case AVDTP_STATE_IDLE:
 		btd_service_disconnecting_complete(source->service, 0);
 
+		if (source->connect_id > 0) {
+			a2dp_cancel(source->connect_id);
+			source->connect_id = 0;
+		}
+
 		if (source->disconnect_id > 0) {
 			a2dp_cancel(source->disconnect_id);
 			source->disconnect_id = 0;
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 41339da..c7a0eae 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2006-2007  Nokia Corporation
  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -34,8 +35,10 @@
 #include "src/shared/util.h"
 #include "src/shared/queue.h"
 #include "src/shared/bap.h"
+#include "src/shared/bass.h"
 #include "src/shared/io.h"
 
+#include "asha.h"
 #include "avdtp.h"
 #include "media.h"
 #include "transport.h"
@@ -43,20 +46,26 @@
 #include "sink.h"
 #include "source.h"
 #include "avrcp.h"
+#include "bass.h"
 
 #define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport1"
 
 typedef enum {
 	TRANSPORT_STATE_IDLE,		/* Not acquired and suspended */
 	TRANSPORT_STATE_PENDING,	/* Playing but not acquired */
+	/* Playing but not acquired, applicable only for transports
+	 * created by a broadcast sink
+	 */
+	TRANSPORT_STATE_BROADCASTING,
 	TRANSPORT_STATE_REQUESTING,	/* Acquire in progress */
 	TRANSPORT_STATE_ACTIVE,		/* Acquired and playing */
 	TRANSPORT_STATE_SUSPENDING,     /* Release in progress */
 } transport_state_t;
 
-static char *str_state[] = {
+static const char *str_state[] = {
 	"TRANSPORT_STATE_IDLE",
 	"TRANSPORT_STATE_PENDING",
+	"TRANSPORT_STATE_BROADCASTING",
 	"TRANSPORT_STATE_REQUESTING",
 	"TRANSPORT_STATE_ACTIVE",
 	"TRANSPORT_STATE_SUSPENDING",
@@ -78,25 +87,45 @@ struct a2dp_transport {
 	struct avdtp		*session;
 	uint16_t		delay;
 	int8_t			volume;
+	guint			watch;
 };
 
 struct bap_transport {
 	struct bt_bap_stream	*stream;
 	unsigned int		state_id;
 	bool			linked;
-	uint32_t		interval;
-	uint8_t			framing;
-	uint8_t			phy;
-	uint16_t		sdu;
-	uint8_t			rtn;
-	uint16_t		latency;
-	uint32_t		delay;
+	struct bt_bap_qos	qos;
+	guint			resume_id;
+};
+
+struct media_transport_ops {
+	const char *uuid;
+	const GDBusPropertyTable *properties;
+	void (*set_owner)(struct media_transport *transport,
+				struct media_owner *owner);
+	void (*remove_owner)(struct media_transport *transport,
+				struct media_owner *owner);
+	void *(*init)(struct media_transport *transport, void *stream);
+	guint (*resume)(struct media_transport *transport,
+				struct media_owner *owner);
+	guint (*suspend)(struct media_transport *transport,
+				struct media_owner *owner);
+	void (*cancel)(struct media_transport *transport, guint id);
+	void (*set_state)(struct media_transport *transport,
+				transport_state_t state);
+	void *(*get_stream)(struct media_transport *transport);
+	int8_t (*get_volume)(struct media_transport *transport);
+	int (*set_volume)(struct media_transport *transport, int8_t level);
+	int (*set_delay)(struct media_transport *transport, uint16_t delay);
+	void (*update_links)(const struct media_transport *transport);
+	GDestroyNotify destroy;
 };
 
 struct media_transport {
 	char			*path;		/* Transport object path */
 	struct btd_device	*device;	/* Transport device */
-	const char		*remote_endpoint; /* Transport remote SEP */
+	struct btd_adapter	*adapter;	/* Transport adapter bcast*/
+	char			*remote_endpoint; /* Transport remote SEP */
 	struct media_endpoint	*endpoint;	/* Transport endpoint */
 	struct media_owner	*owner;		/* Transport owner */
 	uint8_t			*configuration; /* Transport configuration */
@@ -105,18 +134,7 @@ struct media_transport {
 	uint16_t		imtu;		/* Transport input mtu */
 	uint16_t		omtu;		/* Transport output mtu */
 	transport_state_t	state;
-	guint			hs_watch;
-	guint			source_watch;
-	guint			sink_watch;
-	guint			(*resume) (struct media_transport *transport,
-					struct media_owner *owner);
-	guint			(*suspend) (struct media_transport *transport,
-					struct media_owner *owner);
-	void			(*cancel) (struct media_transport *transport,
-								guint id);
-	void			(*set_state) (struct media_transport *transport,
-						transport_state_t state);
-	GDestroyNotify		destroy;
+	const struct media_transport_ops *ops;
 	void			*data;
 };
 
@@ -130,6 +148,8 @@ static const char *state2str(transport_state_t state)
 		return "idle";
 	case TRANSPORT_STATE_PENDING:
 		return "pending";
+	case TRANSPORT_STATE_BROADCASTING:
+		return "broadcasting";
 	case TRANSPORT_STATE_ACTIVE:
 	case TRANSPORT_STATE_SUSPENDING:
 		return "active";
@@ -143,6 +163,7 @@ static gboolean state_in_use(transport_state_t state)
 	switch (state) {
 	case TRANSPORT_STATE_IDLE:
 	case TRANSPORT_STATE_PENDING:
+	case TRANSPORT_STATE_BROADCASTING:
 		return FALSE;
 	case TRANSPORT_STATE_REQUESTING:
 	case TRANSPORT_STATE_ACTIVE:
@@ -164,7 +185,8 @@ find_transport_by_bap_stream(const struct bt_bap_stream *stream)
 		struct bap_transport *bap;
 
 		if (strcasecmp(uuid, PAC_SINK_UUID) &&
-				strcasecmp(uuid, PAC_SOURCE_UUID))
+				strcasecmp(uuid, PAC_SOURCE_UUID) &&
+				strcasecmp(uuid, BAA_SERVICE_UUID))
 			continue;
 
 		bap = transport->data;
@@ -199,20 +221,14 @@ static void transport_set_state(struct media_transport *transport,
 						"State");
 
 	/* Update transport specific data */
-	if (transport->set_state)
-		transport->set_state(transport, state);
+	if (transport->ops && transport->ops->set_state)
+		transport->ops->set_state(transport, state);
 }
 
 void media_transport_destroy(struct media_transport *transport)
 {
 	char *path;
 
-	if (transport->sink_watch)
-		sink_remove_state_cb(transport->sink_watch);
-
-	if (transport->source_watch)
-		source_remove_state_cb(transport->source_watch);
-
 	path = g_strdup(transport->path);
 	g_dbus_unregister_interface(btd_get_dbus_connection(), path,
 						MEDIA_TRANSPORT_INTERFACE);
@@ -262,8 +278,8 @@ static void media_owner_remove(struct media_owner *owner)
 	DBG("Owner %s Request %s", owner->name,
 					dbus_message_get_member(req->msg));
 
-	if (req->id)
-		transport->cancel(transport, req->id);
+	if (req->id && transport->ops && transport->ops->cancel)
+		transport->ops->cancel(transport, req->id);
 
 	owner->pending = NULL;
 	if (req->msg)
@@ -274,10 +290,15 @@ static void media_owner_remove(struct media_owner *owner)
 
 static void media_owner_free(struct media_owner *owner)
 {
+	struct media_transport *transport = owner->transport;
+
 	DBG("Owner %s", owner->name);
 
 	media_owner_remove(owner);
 
+	if (transport)
+		transport->owner = NULL;
+
 	g_free(owner->name);
 	g_free(owner);
 }
@@ -298,10 +319,33 @@ static void linked_transport_remove_owner(void *data, void *user_data)
 	transport->owner = NULL;
 }
 
+static guint media_transport_suspend(struct media_transport *transport,
+					struct media_owner *owner)
+{
+	if (!state_in_use(transport->state))
+		return 0;
+
+	DBG("Transport %s Owner %s", transport->path, owner ? owner->name : "");
+
+	if (transport->ops && transport->ops->suspend)
+		return transport->ops->suspend(transport, owner);
+
+	return 0;
+}
+
+static void transport_bap_remove_owner(struct media_transport *transport,
+					struct media_owner *owner)
+{
+	struct bap_transport *bap = transport->data;
+
+	if (bap && bap->linked)
+		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
+				linked_transport_remove_owner, owner);
+}
+
 static void media_transport_remove_owner(struct media_transport *transport)
 {
 	struct media_owner *owner = transport->owner;
-	struct bap_transport *bap = transport->data;
 
 	if (!transport->owner)
 		return;
@@ -313,17 +357,16 @@ static void media_transport_remove_owner(struct media_transport *transport)
 		media_request_reply(owner->pending, EIO);
 
 	transport->owner = NULL;
-	if (bap->linked)
-		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
-				linked_transport_remove_owner, owner);
+
+	if (transport->ops && transport->ops->remove_owner)
+		transport->ops->remove_owner(transport, owner);
 
 	if (owner->watch)
 		g_dbus_remove_watch(btd_get_dbus_connection(), owner->watch);
 
 	media_owner_free(owner);
 
-	if (state_in_use(transport->state))
-		transport->suspend(transport, NULL);
+	media_transport_suspend(transport, NULL);
 }
 
 static gboolean media_transport_set_fd(struct media_transport *transport,
@@ -341,13 +384,22 @@ static gboolean media_transport_set_fd(struct media_transport *transport,
 	return TRUE;
 }
 
+static void *transport_a2dp_get_stream(struct media_transport *transport)
+{
+	struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
+
+	if (!sep)
+		return NULL;
+
+	return a2dp_sep_get_stream(sep);
+}
+
 static void a2dp_resume_complete(struct avdtp *session, int err,
 							void *user_data)
 {
 	struct media_owner *owner = user_data;
 	struct media_request *req = owner->pending;
 	struct media_transport *transport = owner->transport;
-	struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
 	struct avdtp_stream *stream;
 	int fd;
 	uint16_t imtu, omtu;
@@ -358,7 +410,7 @@ static void a2dp_resume_complete(struct avdtp *session, int err,
 	if (err)
 		goto fail;
 
-	stream = a2dp_sep_get_stream(sep);
+	stream = transport_a2dp_get_stream(transport);
 	if (stream == NULL)
 		goto fail;
 
@@ -386,7 +438,7 @@ fail:
 	media_transport_remove_owner(transport);
 }
 
-static guint resume_a2dp(struct media_transport *transport,
+static guint transport_a2dp_resume(struct media_transport *transport,
 				struct media_owner *owner)
 {
 	struct a2dp_transport *a2dp = transport->data;
@@ -440,7 +492,7 @@ static void a2dp_suspend_complete(struct avdtp *session, int err,
 	media_transport_remove_owner(transport);
 }
 
-static guint suspend_a2dp(struct media_transport *transport,
+static guint transport_a2dp_suspend(struct media_transport *transport,
 						struct media_owner *owner)
 {
 	struct a2dp_transport *a2dp = transport->data;
@@ -457,15 +509,85 @@ static guint suspend_a2dp(struct media_transport *transport,
 	return 0;
 }
 
-static void cancel_a2dp(struct media_transport *transport, guint id)
+static void transport_a2dp_cancel(struct media_transport *transport, guint id)
 {
 	a2dp_cancel(id);
 }
 
+static int8_t transport_a2dp_get_volume(struct media_transport *transport)
+{
+	struct a2dp_transport *a2dp = transport->data;
+	return a2dp->volume;
+}
+
+static int transport_a2dp_src_set_volume(struct media_transport *transport,
+					int8_t level)
+{
+	struct a2dp_transport *a2dp = transport->data;
+
+	if (a2dp->volume == level)
+		return 0;
+
+	return avrcp_set_volume(transport->device, level, false);
+}
+
+static int transport_a2dp_snk_set_volume(struct media_transport *transport,
+					int8_t level)
+{
+	struct a2dp_transport *a2dp = transport->data;
+	bool notify;
+
+	if (a2dp->volume == level)
+		return 0;
+
+	notify = a2dp->watch ? true : false;
+	if (notify) {
+		a2dp->volume = level;
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Volume");
+	}
+
+	return avrcp_set_volume(transport->device, level, notify);
+}
+
+static int transport_a2dp_snk_set_delay(struct media_transport *transport,
+					uint16_t delay)
+{
+	struct a2dp_transport *a2dp = transport->data;
+	struct avdtp_stream *stream;
+
+	if (a2dp->delay == delay)
+		return 0;
+
+	if (a2dp->session == NULL) {
+		a2dp->session = a2dp_avdtp_get(transport->device);
+		if (a2dp->session == NULL)
+			return -EIO;
+	}
+
+	stream = media_transport_get_stream(transport);
+	if (stream == NULL)
+		return -EIO;
+
+	if (a2dp->watch) {
+		a2dp->delay = delay;
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Delay");
+	}
+
+	return avdtp_delay_report(a2dp->session, stream, delay);
+}
+
 static void media_owner_exit(DBusConnection *connection, void *user_data)
 {
 	struct media_owner *owner = user_data;
 
+	DBG("Owner %s", owner->name);
+
 	owner->watch = 0;
 
 	media_owner_remove(owner);
@@ -489,17 +611,24 @@ static void linked_transport_set_owner(void *data, void *user_data)
 	transport->owner = owner;
 }
 
-static void media_transport_set_owner(struct media_transport *transport,
+static void transport_bap_set_owner(struct media_transport *transport,
 					struct media_owner *owner)
 {
 	struct bap_transport *bap = transport->data;
 
+	if (bap && bap->linked)
+		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
+				linked_transport_set_owner, owner);
+}
+
+static void media_transport_set_owner(struct media_transport *transport,
+					struct media_owner *owner)
+{
 	DBG("Transport %s Owner %s", transport->path, owner->name);
 	transport->owner = owner;
 
-	if (bap->linked)
-		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
-				linked_transport_set_owner, owner);
+	if (transport->ops && transport->ops->set_owner)
+		transport->ops->set_owner(transport, owner);
 
 	owner->transport = transport;
 	owner->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
@@ -529,12 +658,30 @@ static void media_owner_add(struct media_owner *owner,
 	owner->pending = req;
 }
 
+static void *transport_bap_get_stream(struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+
+	return bap->stream;
+}
+
+static guint media_transport_resume(struct media_transport *transport,
+					struct media_owner *owner)
+{
+	DBG("Transport %s Owner %s", transport->path, owner ? owner->name : "");
+
+	if (transport->ops && transport->ops->resume)
+		return transport->ops->resume(transport, owner);
+
+	return 0;
+}
+
 static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct media_transport *transport = data;
 	struct media_owner *owner;
-	struct media_request *req;
+	struct media_request *req = NULL;
 	guint id;
 
 	if (transport->owner != NULL)
@@ -544,15 +691,27 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
 		return btd_error_not_authorized(msg);
 
 	owner = media_owner_create(msg);
-	id = transport->resume(transport, owner);
+
+	if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID)
+		|| !strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BCAA_SERVICE_UUID)) {
+		req = media_request_create(msg, 0x00);
+		media_owner_add(owner, req);
+		media_transport_set_owner(transport, owner);
+	}
+
+	id = media_transport_resume(transport, owner);
 	if (id == 0) {
 		media_owner_free(owner);
 		return btd_error_not_authorized(msg);
 	}
 
-	req = media_request_create(msg, id);
-	media_owner_add(owner, req);
-	media_transport_set_owner(transport, owner);
+	if (!req) {
+		req = media_request_create(msg, id);
+		media_owner_add(owner, req);
+		media_transport_set_owner(transport, owner);
+	}
 
 	return NULL;
 }
@@ -571,11 +730,12 @@ static DBusMessage *try_acquire(DBusConnection *conn, DBusMessage *msg,
 	if (transport->state >= TRANSPORT_STATE_REQUESTING)
 		return btd_error_not_authorized(msg);
 
-	if (transport->state != TRANSPORT_STATE_PENDING)
+	if ((transport->state != TRANSPORT_STATE_PENDING) &&
+		(transport->state != TRANSPORT_STATE_BROADCASTING))
 		return btd_error_not_available(msg);
 
 	owner = media_owner_create(msg);
-	id = transport->resume(transport, owner);
+	id = media_transport_resume(transport, owner);
 	if (id == 0) {
 		media_owner_free(owner);
 		return btd_error_not_authorized(msg);
@@ -588,6 +748,41 @@ static DBusMessage *try_acquire(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+static void bap_stop_complete(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	struct media_owner *owner = user_data;
+	struct media_request *req;
+	struct media_transport *transport;
+
+	if (!owner)
+		return;
+
+	req = owner->pending;
+
+	/* Release always succeeds */
+	if (req) {
+		req->id = 0;
+		media_request_reply(req, 0);
+		media_owner_remove(owner);
+	}
+
+	transport = owner->transport;
+
+	if (transport) {
+		transport_set_state(transport, TRANSPORT_STATE_IDLE);
+		media_transport_remove_owner(transport);
+	}
+}
+
+static void bap_disable_complete(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	bap_stop_complete(stream, code, reason, user_data);
+}
+
 static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
@@ -602,6 +797,8 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
 	if (owner == NULL || g_strcmp0(owner->name, sender) != 0)
 		return btd_error_not_authorized(msg);
 
+	DBG("Owner %s", owner->name);
+
 	if (owner->pending) {
 		const char *member;
 
@@ -615,7 +812,7 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
 
 	transport_set_state(transport, TRANSPORT_STATE_SUSPENDING);
 
-	id = transport->suspend(transport, owner);
+	id = media_transport_suspend(transport, owner);
 	if (id == 0) {
 		media_transport_remove_owner(transport);
 		return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
@@ -631,7 +828,12 @@ static gboolean get_device(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
-	const char *path = device_get_path(transport->device);
+	const char *path;
+
+	if (transport->device)
+		path = device_get_path(transport->device);
+	else
+		path = adapter_get_path(transport->adapter);
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
 
@@ -693,12 +895,16 @@ static gboolean delay_reporting_exists(const GDBusPropertyTable *property,
 							void *data)
 {
 	struct media_transport *transport = data;
-	struct a2dp_transport *a2dp = transport->data;
+	struct avdtp_stream *stream;
+
+	stream = media_transport_get_stream(transport);
+	if (stream == NULL)
+		return FALSE;
 
-	return a2dp->delay != 0;
+	return avdtp_stream_has_delay_reporting(stream);
 }
 
-static gboolean get_delay_reporting(const GDBusPropertyTable *property,
+static gboolean get_delay_report(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
@@ -709,64 +915,147 @@ static gboolean get_delay_reporting(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static int media_transport_set_delay(struct media_transport *transport,
+					uint16_t delay)
+{
+	DBG("Transport %s delay %d", transport->path, delay);
+
+	if (transport->ops && transport->ops->set_delay)
+		return transport->ops->set_delay(transport, delay);
+
+	return 0;
+}
+
+static void set_delay_report(const GDBusPropertyTable *property,
+				DBusMessageIter *iter,
+				GDBusPendingPropertySet id,
+				void *data)
+{
+	struct media_transport *transport = data;
+	struct media_owner *owner = transport->owner;
+	const char *sender;
+	uint16_t arg;
+	int err;
+
+	if (owner != NULL) {
+		/* If the transport is acquired, do not allow to modify
+		 * the delay anyone but the owner.
+		 */
+		sender = g_dbus_pending_property_get_sender(id);
+		if (g_strcmp0(owner->name, sender) != 0) {
+			g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".NotAuthorized",
+					"Operation Not Authorized");
+			return;
+		}
+	}
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) {
+		g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Expected UINT16");
+		return;
+	}
+
+	dbus_message_iter_get_basic(iter, &arg);
+
+	err = media_transport_set_delay(transport, arg);
+	if (err) {
+		error("Unable to set delay: %s (%d)", strerror(-err), err);
+		g_dbus_pending_property_error(id,
+						ERROR_INTERFACE ".Failed",
+						"Internal error %s (%d)",
+						strerror(-err), err);
+		return;
+	}
+
+	g_dbus_pending_property_success(id);
+}
+
 static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
 {
 	struct media_transport *transport = data;
-	struct a2dp_transport *a2dp = transport->data;
+	int8_t volume;
+
+	if (media_transport_get_volume(transport, &volume))
+		return FALSE;
+
+	return volume >= 0;
+}
+
+int media_transport_get_volume(struct media_transport *transport,
+					int8_t *volume)
+{
+	if (transport->ops && transport->ops->get_volume) {
+		*volume = transport->ops->get_volume(transport);
+		return 0;
+	}
 
-	return a2dp->volume >= 0;
+	return -EINVAL;
 }
 
 static gboolean get_volume(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
-	struct a2dp_transport *a2dp = transport->data;
-	uint16_t volume = (uint16_t)a2dp->volume;
+	int8_t level;
+	uint16_t volume;
+
+	if (media_transport_get_volume(transport, &level))
+		return FALSE;
+
+	volume = level;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
 
 	return TRUE;
 }
 
+static int media_transport_set_volume(struct media_transport *transport,
+					int8_t level)
+{
+	DBG("Transport %s level %d", transport->path, level);
+
+	if (transport->ops && transport->ops->set_volume)
+		return transport->ops->set_volume(transport, level);
+
+	return 0;
+}
+
 static void set_volume(const GDBusPropertyTable *property,
 			DBusMessageIter *iter, GDBusPendingPropertySet id,
 			void *data)
 {
 	struct media_transport *transport = data;
-	struct a2dp_transport *a2dp = transport->data;
 	uint16_t arg;
-	int8_t volume;
-	bool notify;
+	int err;
 
-	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
-		goto error;
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) {
+		g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Expected UINT16");
+		return;
+	}
 
 	dbus_message_iter_get_basic(iter, &arg);
-	if (arg > INT8_MAX)
-		goto error;
-
-	g_dbus_pending_property_success(id);
-
-	volume = (int8_t)arg;
-	if (a2dp->volume == volume)
+	if (arg > INT8_MAX) {
+		g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Volume must not be larger than 127");
 		return;
-
-	notify = transport->source_watch ? true : false;
-	if (notify) {
-		a2dp->volume = volume;
-		g_dbus_emit_property_changed(btd_get_dbus_connection(),
-						transport->path,
-						MEDIA_TRANSPORT_INTERFACE,
-						"Volume");
 	}
 
-	avrcp_set_volume(transport->device, volume, notify);
-	return;
+	err = media_transport_set_volume(transport, arg);
+	if (err) {
+		error("Unable to set volume: %s (%d)", strerror(-err), err);
+		g_dbus_pending_property_error(id,
+						ERROR_INTERFACE ".Failed",
+						"Internal error %s (%d)",
+						strerror(-err), err);
+		return;
+	}
 
-error:
-	g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
-					"Invalid arguments in method call");
+	g_dbus_pending_property_success(id);
 }
 
 static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
@@ -787,6 +1076,12 @@ static gboolean get_endpoint(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static DBusMessage *select_transport(DBusConnection *conn, DBusMessage *msg,
+					void *data);
+
+static DBusMessage *unselect_transport(DBusConnection *conn, DBusMessage *msg,
+					void *data);
+
 static const GDBusMethodTable transport_methods[] = {
 	{ GDBUS_ASYNC_METHOD("Acquire",
 			NULL,
@@ -799,192 +1094,414 @@ static const GDBusMethodTable transport_methods[] = {
 							{ "mtu_w", "q" }),
 			try_acquire) },
 	{ GDBUS_ASYNC_METHOD("Release", NULL, NULL, release) },
+	{ GDBUS_ASYNC_METHOD("Select",
+			NULL, NULL, select_transport) },
+	{ GDBUS_ASYNC_METHOD("Unselect",
+			NULL, NULL, unselect_transport) },
 	{ },
 };
 
-static const GDBusPropertyTable a2dp_properties[] = {
+static const GDBusPropertyTable transport_a2dp_properties[] = {
 	{ "Device", "o", get_device },
 	{ "UUID", "s", get_uuid },
 	{ "Codec", "y", get_codec },
 	{ "Configuration", "ay", get_configuration },
 	{ "State", "s", get_state },
-	{ "Delay", "q", get_delay_reporting, NULL, delay_reporting_exists },
+	{ "Delay", "q", get_delay_report, set_delay_report,
+				delay_reporting_exists },
 	{ "Volume", "q", get_volume, set_volume, volume_exists },
 	{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists,
 				G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{ }
 };
 
-static gboolean get_interval(const GDBusPropertyTable *property,
+static void append_io_qos(DBusMessageIter *dict, struct bt_bap_io_qos *qos)
+{
+	dict_append_entry(dict, "Interval", DBUS_TYPE_UINT32, &qos->interval);
+	dict_append_entry(dict, "Latency", DBUS_TYPE_UINT16, &qos->latency);
+	dict_append_entry(dict, "SDU", DBUS_TYPE_UINT16, &qos->sdu);
+	dict_append_entry(dict, "PHY", DBUS_TYPE_BYTE, &qos->phy);
+	dict_append_entry(dict, "Retransmissions", DBUS_TYPE_BYTE, &qos->rtn);
+}
+
+static gboolean get_ucast_qos(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
+	DBusMessageIter dict;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE,
+					&bap->qos.ucast.cig_id);
+	dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE,
+					&bap->qos.ucast.cis_id);
+	dict_append_entry(&dict, "Framing", DBUS_TYPE_BYTE,
+					&bap->qos.ucast.framing);
+	dict_append_entry(&dict, "PresentationDelay", DBUS_TYPE_UINT32,
+					&bap->qos.ucast.delay);
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->interval);
+	append_io_qos(&dict, &bap->qos.ucast.io_qos);
+
+	dbus_message_iter_close_container(iter, &dict);
 
 	return TRUE;
 }
 
-static gboolean get_framing(const GDBusPropertyTable *property,
+static gboolean get_location(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
-	dbus_bool_t val = bap->framing;
+	uint32_t location = bt_bap_stream_get_location(bap->stream);
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &location);
 
 	return TRUE;
 }
 
-static gboolean get_sdu(const GDBusPropertyTable *property,
+static gboolean get_metadata(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
+	struct iovec *meta = bt_bap_stream_get_metadata(bap->stream);
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	if (meta)
+		dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+							&meta->iov_base,
+							meta->iov_len);
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->sdu);
+	dbus_message_iter_close_container(iter, &array);
 
 	return TRUE;
 }
 
-static gboolean get_retransmissions(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static gboolean links_exists(const GDBusPropertyTable *property, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->rtn);
+	return bap->linked;
+}
 
-	return TRUE;
+static void append_link(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	DBusMessageIter *array = user_data;
+	struct media_transport *transport;
+
+	if (!stream)
+		return;
+
+	transport = find_transport_by_bap_stream(stream);
+	if (!transport) {
+		error("Unable to find transport");
+		return;
+	}
+
+	dbus_message_iter_append_basic(array, DBUS_TYPE_OBJECT_PATH,
+					&transport->path);
 }
 
-static gboolean get_latency(const GDBusPropertyTable *property,
+static gboolean get_links(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
+	struct queue *links = bt_bap_stream_io_get_links(bap->stream);
+	DBusMessageIter array;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->latency);
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_OBJECT_PATH_AS_STRING,
+					&array);
+
+	queue_foreach(links, append_link, &array);
+
+	dbus_message_iter_close_container(iter, &array);
 
 	return TRUE;
 }
 
-static gboolean get_delay(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static struct media_transport *find_transport_by_path(const char *path)
 {
-	struct media_transport *transport = data;
+	GSList *l;
+
+	for (l = transports; l; l = g_slist_next(l)) {
+		struct media_transport *transport = l->data;
+
+		if (g_str_equal(path, transport->path))
+			return transport;
+	}
+
+	return NULL;
+}
+
+static void set_links(const GDBusPropertyTable *property,
+				DBusMessageIter *iter,
+				GDBusPendingPropertySet id, void *user_data)
+{
+	struct media_transport *transport = user_data;
 	struct bap_transport *bap = transport->data;
+	DBusMessageIter array;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->delay);
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
+		return;
+	}
 
-	return TRUE;
+	dbus_message_iter_recurse(iter, &array);
+
+	while (dbus_message_iter_get_arg_type(&array) ==
+						DBUS_TYPE_OBJECT_PATH) {
+		struct media_transport *link;
+		struct bap_transport *bap_link;
+		const char *path;
+
+		dbus_message_iter_get_basic(&array, &path);
+
+		link = find_transport_by_path(path);
+		if (!link) {
+			g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Invalid arguments in method call");
+			return;
+		}
+
+		bap_link = link->data;
+
+		/* Link stream */
+		bt_bap_stream_io_link(bap->stream, bap_link->stream);
+
+		dbus_message_iter_next(&array);
+	}
+
+	g_dbus_pending_property_success(id);
 }
 
-static gboolean get_location(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static gboolean qos_ucast_exists(const GDBusPropertyTable *property, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
-	uint32_t location = bt_bap_stream_get_location(bap->stream);
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &location);
-
-	return TRUE;
+	return bap->qos.ucast.io_qos.phy != 0x00;
 }
 
-static gboolean get_metadata(const GDBusPropertyTable *property,
+static const GDBusPropertyTable transport_bap_uc_properties[] = {
+	{ "Device", "o", get_device },
+	{ "UUID", "s", get_uuid },
+	{ "Codec", "y", get_codec },
+	{ "Configuration", "ay", get_configuration },
+	{ "State", "s", get_state },
+	{ "QoS", "a{sv}", get_ucast_qos, NULL, qos_ucast_exists },
+	{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
+	{ "Location", "u", get_location },
+	{ "Metadata", "ay", get_metadata },
+	{ "Links", "ao", get_links, NULL, links_exists },
+	{ }
+};
+
+static gboolean get_bcast_qos(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
-	struct iovec *meta = bt_bap_stream_get_metadata(bap->stream);
-	DBusMessageIter array;
+	DBusMessageIter dict;
 
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-					DBUS_TYPE_BYTE_AS_STRING, &array);
-
-	if (meta)
-		dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
-							&meta->iov_base,
-							meta->iov_len);
-
-	dbus_message_iter_close_container(iter, &array);
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&dict);
+
+	dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.big);
+	dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.bis);
+	dict_append_entry(&dict, "SyncFactor", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.sync_factor);
+	dict_append_entry(&dict, "Packing", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.packing);
+	dict_append_entry(&dict, "Framing", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.framing);
+	dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.encryption);
+	if (bap->qos.bcast.bcode)
+		dict_append_array(&dict, "BCode", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.bcode->iov_base,
+					bap->qos.bcast.bcode->iov_len);
+	dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.options);
+	dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16,
+					&bap->qos.bcast.skip);
+	dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16,
+					&bap->qos.bcast.sync_timeout);
+	dict_append_entry(&dict, "SyncType", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.sync_cte_type);
+	dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE,
+					&bap->qos.bcast.mse);
+	dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16,
+					&bap->qos.bcast.timeout);
+
+	append_io_qos(&dict, &bap->qos.bcast.io_qos);
+
+	dbus_message_iter_close_container(iter, &dict);
 
 	return TRUE;
 }
 
-static gboolean links_exists(const GDBusPropertyTable *property, void *data)
+static gboolean qos_bcast_exists(const GDBusPropertyTable *property, void *data)
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	return bap->linked;
+	return bap->qos.bcast.io_qos.phy != 0x00;
 }
 
-static void append_links(void *data, void *user_data)
+static void bcast_qos_set(void *user_data, int err)
 {
-	struct bt_bap_stream *stream = data;
-	DBusMessageIter *array = user_data;
-	struct media_transport *transport;
-
-	transport = find_transport_by_bap_stream(stream);
-	if (!transport) {
-		error("Unable to find transport");
-		return;
-	}
+	GDBusPendingPropertySet id = GPOINTER_TO_UINT(user_data);
 
-	dbus_message_iter_append_basic(array, DBUS_TYPE_OBJECT_PATH,
-					&transport->path);
+	if (!err)
+		g_dbus_pending_property_success(id);
+	else
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".Failed",
+					"Failed to set Broadcast Code");
 }
 
-static gboolean get_links(const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static void set_bcast_qos(const GDBusPropertyTable *property,
+			DBusMessageIter *dict, GDBusPendingPropertySet id,
+			void *data)
 {
+	DBusMessageIter array, entry, value;
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
-	struct queue *links = bt_bap_stream_io_get_links(bap->stream);
-	DBusMessageIter array;
+	struct bt_bap_qos *bap_qos = bt_bap_stream_get_qos(bap->stream);
+	char *key;
 
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-					DBUS_TYPE_OBJECT_PATH_AS_STRING,
-					&array);
+	dbus_message_iter_recurse(dict, &array);
 
-	queue_foreach(links, append_links, &array);
+	dbus_message_iter_recurse(&array, &entry);
+	dbus_message_iter_get_basic(&entry, &key);
 
-	dbus_message_iter_close_container(iter, &array);
+	dbus_message_iter_next(&entry);
+	dbus_message_iter_recurse(&entry, &value);
 
-	return TRUE;
+	if (!strcasecmp(key, "BCode")) {
+		uint8_t *val;
+		int len;
+		DBusMessageIter array;
+		uint8_t empty_bcode[BT_BASS_BCAST_CODE_SIZE] = {0};
+
+		dbus_message_iter_recurse(&value, &array);
+		dbus_message_iter_get_fixed_array(&array, &val, &len);
+
+		if (len > BT_BASS_BCAST_CODE_SIZE) {
+			g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Invalid arguments in method call");
+			return;
+		}
+
+		if (!memcmp(val, empty_bcode, len)) {
+			/* If the user did not provide a Broadcast Code
+			 * for the encrypted stream, request the code from
+			 * Broadcast Assistants, if any are available.
+			 */
+			bass_req_bcode(bap->stream, bcast_qos_set,
+						GUINT_TO_POINTER(id));
+			return;
+		}
+
+		bap_qos->bcast.bcode = util_iov_new(val, len);
+	}
+
+	bt_bap_stream_qos(bap->stream, bap_qos, NULL, NULL);
+	g_dbus_pending_property_success(id);
 }
 
-static const GDBusPropertyTable bap_properties[] = {
+static const GDBusPropertyTable transport_bap_bc_properties[] = {
 	{ "Device", "o", get_device },
 	{ "UUID", "s", get_uuid },
 	{ "Codec", "y", get_codec },
 	{ "Configuration", "ay", get_configuration },
 	{ "State", "s", get_state },
-	{ "Interval", "u", get_interval },
-	{ "Framing", "b", get_framing },
-	{ "SDU", "q", get_sdu },
-	{ "Retransmissions", "y", get_retransmissions },
-	{ "Latency", "q", get_latency },
-	{ "Delay", "u", get_delay },
+	{ "QoS", "a{sv}", get_bcast_qos, set_bcast_qos, qos_bcast_exists },
 	{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
 	{ "Location", "u", get_location },
 	{ "Metadata", "ay", get_metadata },
-	{ "Links", "ao", get_links, NULL, links_exists },
+	{ "Links", "ao", get_links, set_links, NULL },
+	{ }
+};
+
+static gboolean get_asha_delay(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bt_asha_device *asha_dev = transport->data;
+	uint16_t delay;
+
+	// Delay property is in 1/10ths of ms, while ASHA RenderDelay is in ms
+	delay = bt_asha_device_get_render_delay(asha_dev) * 10;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &delay);
+
+	return TRUE;
+}
+
+static const GDBusPropertyTable transport_asha_properties[] = {
+	{ "Device", "o", get_device },
+	{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
+	{ "UUID", "s", get_uuid },
+	{ "Codec", "y", get_codec },
+	{ "State", "s", get_state },
+	{ "Delay", "q", get_asha_delay },
+	{ "Volume", "q", get_volume, set_volume, volume_exists },
 	{ }
 };
 
-static void destroy_a2dp(void *data)
+static void transport_a2dp_destroy(void *data)
 {
 	struct a2dp_transport *a2dp = data;
 
 	if (a2dp->session)
 		avdtp_unref(a2dp->session);
 
-	g_free(a2dp);
+	free(a2dp);
+}
+
+static void transport_a2dp_src_destroy(void *data)
+{
+	struct a2dp_transport *a2dp = data;
+
+	if (a2dp->watch)
+		sink_remove_state_cb(a2dp->watch);
+
+	transport_a2dp_destroy(data);
+}
+
+static void transport_a2dp_snk_destroy(void *data)
+{
+	struct a2dp_transport *a2dp = data;
+
+	if (a2dp->watch)
+		source_remove_state_cb(a2dp->watch);
+
+	transport_a2dp_destroy(data);
 }
 
 static void media_transport_free(void *data)
@@ -996,9 +1513,10 @@ static void media_transport_free(void *data)
 	if (transport->owner)
 		media_transport_remove_owner(transport);
 
-	if (transport->destroy != NULL)
-		transport->destroy(transport->data);
+	if (transport->ops && transport->ops->destroy)
+		transport->ops->destroy(transport->data);
 
+	g_free(transport->remote_endpoint);
 	g_free(transport->configuration);
 	g_free(transport->path);
 	g_free(transport);
@@ -1011,15 +1529,63 @@ static void transport_update_playing(struct media_transport *transport,
 					str_state[transport->state], playing);
 
 	if (playing == FALSE) {
-		if (transport->state == TRANSPORT_STATE_PENDING)
-			transport_set_state(transport, TRANSPORT_STATE_IDLE);
-		else if (transport->state == TRANSPORT_STATE_ACTIVE) {
-			/* Remove owner */
-			if (transport->owner != NULL)
-				media_transport_remove_owner(transport);
+		if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID)) {
+			if ((transport->state ==
+				TRANSPORT_STATE_BROADCASTING) ||
+				(transport->state == TRANSPORT_STATE_ACTIVE))
+				transport_set_state(transport,
+						TRANSPORT_STATE_IDLE);
+		} else {
+			if (transport->state == TRANSPORT_STATE_PENDING)
+				transport_set_state(transport,
+						TRANSPORT_STATE_IDLE);
+			else if (transport->state == TRANSPORT_STATE_ACTIVE) {
+				/* Remove owner */
+				if (transport->owner != NULL)
+					media_transport_remove_owner(transport);
+			}
 		}
-	} else if (transport->state == TRANSPORT_STATE_IDLE)
-		transport_set_state(transport, TRANSPORT_STATE_PENDING);
+	} else if (transport->state == TRANSPORT_STATE_IDLE) {
+		if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID))
+			transport_set_state(transport,
+						TRANSPORT_STATE_BROADCASTING);
+		else
+			transport_set_state(transport, TRANSPORT_STATE_PENDING);
+	}
+}
+
+static DBusMessage *select_transport(DBusConnection *conn, DBusMessage *msg,
+					void *data)
+{
+	struct media_transport *transport = data;
+
+	if (transport->owner != NULL)
+		return btd_error_not_authorized(msg);
+
+	if (transport->state >= TRANSPORT_STATE_REQUESTING)
+		return btd_error_not_authorized(msg);
+
+	if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID)) {
+		transport_update_playing(transport, TRUE);
+	}
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unselect_transport(DBusConnection *conn, DBusMessage *msg,
+					void *data)
+{
+	struct media_transport *transport = data;
+
+	if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID)) {
+		transport_update_playing(transport, FALSE);
+	}
+
+	return dbus_message_new_method_return(msg);
 }
 
 static void sink_state_changed(struct btd_service *service,
@@ -1048,53 +1614,39 @@ static void source_state_changed(struct btd_service *service,
 		transport_update_playing(transport, FALSE);
 }
 
-static int media_transport_init_source(struct media_transport *transport)
+static void *transport_a2dp_src_init(struct media_transport *transport,
+					void *stream)
 {
 	struct btd_service *service;
 	struct a2dp_transport *a2dp;
 
 	service = btd_device_get_service(transport->device, A2DP_SINK_UUID);
-	if (service == NULL)
-		return -EINVAL;
-
-	a2dp = g_new0(struct a2dp_transport, 1);
-
-	transport->resume = resume_a2dp;
-	transport->suspend = suspend_a2dp;
-	transport->cancel = cancel_a2dp;
-	transport->data = a2dp;
-	transport->destroy = destroy_a2dp;
+	if (!service)
+		return NULL;
 
+	a2dp = new0(struct a2dp_transport, 1);
 	a2dp->volume = -1;
-	transport->sink_watch = sink_add_state_cb(service, sink_state_changed,
-								transport);
+	a2dp->watch = sink_add_state_cb(service, sink_state_changed, transport);
 
-	return 0;
+	return a2dp;
 }
 
-static int media_transport_init_sink(struct media_transport *transport)
+static void *transport_a2dp_snk_init(struct media_transport *transport,
+					void *stream)
 {
 	struct btd_service *service;
 	struct a2dp_transport *a2dp;
 
 	service = btd_device_get_service(transport->device, A2DP_SOURCE_UUID);
-	if (service == NULL)
-		return -EINVAL;
-
-	a2dp = g_new0(struct a2dp_transport, 1);
-
-	transport->resume = resume_a2dp;
-	transport->suspend = suspend_a2dp;
-	transport->cancel = cancel_a2dp;
-	transport->data = a2dp;
-	transport->destroy = destroy_a2dp;
+	if (!service)
+		return NULL;
 
+	a2dp = new0(struct a2dp_transport, 1);
 	a2dp->volume = 127;
-	transport->source_watch = source_add_state_cb(service,
-							source_state_changed,
-							transport);
+	a2dp->watch = source_add_state_cb(service, source_state_changed,
+						transport);
 
-	return 0;
+	return a2dp;
 }
 
 static void bap_enable_complete(struct bt_bap_stream *stream,
@@ -1107,17 +1659,27 @@ static void bap_enable_complete(struct bt_bap_stream *stream,
 		media_transport_remove_owner(owner->transport);
 }
 
-static gboolean resume_complete(void *data)
+static void bap_resume_complete(struct media_transport *transport)
 {
-	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
 	struct media_owner *owner = transport->owner;
 
+	DBG("stream %p owner %p resume complete", bap->stream, owner);
+
+	if (bap->resume_id) {
+		g_source_remove(bap->resume_id);
+		bap->resume_id = 0;
+	}
+
 	if (!owner)
-		return FALSE;
+		return;
+
+	if (owner->pending)
+		owner->pending->id = 0;
 
 	if (transport->fd < 0) {
 		media_transport_remove_owner(transport);
-		return FALSE;
+		return;
 	}
 
 	if (owner->pending) {
@@ -1131,15 +1693,13 @@ static gboolean resume_complete(void *data)
 						DBUS_TYPE_INVALID);
 		if (!ret) {
 			media_transport_remove_owner(transport);
-			return FALSE;
+			return;
 		}
 	}
 
 	media_owner_remove(owner);
 
 	transport_set_state(transport, TRANSPORT_STATE_ACTIVE);
-
-	return FALSE;
 }
 
 static void bap_update_links(const struct media_transport *transport);
@@ -1158,7 +1718,8 @@ static bool match_link_transport(const void *data, const void *user_data)
 	return true;
 }
 
-static void bap_update_links(const struct media_transport *transport)
+static void transport_bap_update_links_uc(
+	const struct media_transport *transport)
 {
 	struct bap_transport *bap = transport->data;
 	struct queue *links = bt_bap_stream_io_get_links(bap->stream);
@@ -1181,28 +1742,122 @@ static void bap_update_links(const struct media_transport *transport)
 	DBG("stream %p linked %s", bap->stream, bap->linked ? "true" : "false");
 }
 
-static guint resume_bap(struct media_transport *transport,
+static void transport_bap_update_links_bc(
+	const struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+	struct queue *links = bt_bap_stream_io_get_links(bap->stream);
+
+	if (!queue_isempty(links))
+		bap->linked = true;
+	else
+		bap->linked = false;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Links");
+
+	DBG("stream %p linked %s", bap->stream, bap->linked ? "true" : "false");
+}
+
+static void bap_update_links(const struct media_transport *transport)
+{
+	if (transport->ops && transport->ops->update_links)
+		transport->ops->update_links(transport);
+}
+
+static void bap_update_qos(const struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+	struct bt_bap_qos *qos;
+
+	qos = bt_bap_stream_get_qos(bap->stream);
+
+	if (!memcmp(qos, &bap->qos, sizeof(struct bt_bap_qos)))
+		return;
+
+	bap->qos = *qos;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"QoS");
+}
+
+static gboolean bap_resume_complete_cb(void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	bap->resume_id = 0;
+	bap_resume_complete(transport);
+	return FALSE;
+}
+
+static gboolean bap_resume_wait_cb(void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+	struct media_owner *owner = transport->owner;
+
+	/* bap_state_changed will call completion callback when ready */
+	DBG("stream %p owner %p resume wait", bap->stream, owner);
+
+	bap->resume_id = 0;
+	if (owner && owner->pending)
+		owner->pending->id = 0;
+
+	return FALSE;
+}
+
+static void bap_update_bcast_qos(const struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+	struct bt_bap_qos *qos;
+
+	qos = bt_bap_stream_get_qos(bap->stream);
+
+	if (!memcmp(qos, &bap->qos, sizeof(struct bt_bap_qos)))
+		return;
+
+	bap->qos = *qos;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"QoS");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Codec");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Configuration");
+}
+
+static guint transport_bap_resume(struct media_transport *transport,
 				struct media_owner *owner)
 {
 	struct bap_transport *bap = transport->data;
+	struct iovec *meta;
 	guint id;
 
 	if (!bap->stream)
 		return 0;
+	if (bap->resume_id)
+		return 0;
 
 	bap_update_links(transport);
 
 	switch (bt_bap_stream_get_state(bap->stream)) {
 	case BT_BAP_STREAM_STATE_ENABLING:
 		bap_enable_complete(bap->stream, 0x00, 0x00, owner);
-		if (owner->pending)
-			return owner->pending->id;
-		return 0;
+		bap->resume_id = g_idle_add(bap_resume_wait_cb, transport);
+		return bap->resume_id;
 	case BT_BAP_STREAM_STATE_STREAMING:
-		return g_idle_add(resume_complete, transport);
+		bap->resume_id = g_idle_add(bap_resume_complete_cb, transport);
+		return bap->resume_id;
 	}
 
-	id = bt_bap_stream_enable(bap->stream, bap->linked, NULL,
+	meta = bt_bap_stream_get_metadata(bap->stream);
+	id = bt_bap_stream_enable(bap->stream, bap->linked, meta,
 					bap_enable_complete, owner);
 	if (!id)
 		return 0;
@@ -1213,37 +1868,47 @@ static guint resume_bap(struct media_transport *transport,
 	return id;
 }
 
-static void bap_stop_complete(struct bt_bap_stream *stream,
-					uint8_t code, uint8_t reason,
-					void *user_data)
+static void update_links(void *data, void *user_data)
 {
-	struct media_owner *owner = user_data;
-	struct media_request *req = owner->pending;
-	struct media_transport *transport = owner->transport;
+	struct bt_bap_stream *link = data;
+	struct media_transport *transport;
 
-	/* Release always succeeds */
-	if (req) {
-		req->id = 0;
-		media_request_reply(req, 0);
-		media_owner_remove(owner);
+	transport = find_transport_by_bap_stream(link);
+	if (!transport) {
+		error("Unable to find transport");
+		return;
 	}
 
-	transport_set_state(transport, TRANSPORT_STATE_IDLE);
-	media_transport_remove_owner(transport);
+	bap_update_links(transport);
 }
 
-static void bap_disable_complete(struct bt_bap_stream *stream,
-					uint8_t code, uint8_t reason,
-					void *user_data)
+static void transport_unlink(void *data, void *user_data)
 {
-	bap_stop_complete(stream, code, reason, user_data);
+	struct bt_bap_stream *link = data;
+	struct bt_bap_stream *stream = user_data;
+	struct media_transport *transport;
+
+	transport = find_transport_by_bap_stream(link);
+	if (!transport) {
+		error("Unable to find transport");
+		return;
+	}
+
+	bt_bap_stream_io_unlink(link, stream);
+
+	bap_update_links(transport);
+
+	/* Emit property changed for all remaining links */
+	queue_foreach(bt_bap_stream_io_get_links(link), update_links, NULL);
 }
 
-static guint suspend_bap(struct media_transport *transport,
+static guint transport_bap_suspend(struct media_transport *transport,
 				struct media_owner *owner)
 {
 	struct bap_transport *bap = transport->data;
+	struct queue *links = bt_bap_stream_io_get_links(bap->stream);
 	bt_bap_stream_func_t func = NULL;
+	guint id;
 
 	if (!bap->stream)
 		return 0;
@@ -1253,15 +1918,33 @@ static guint suspend_bap(struct media_transport *transport,
 	else
 		transport_set_state(transport, TRANSPORT_STATE_IDLE);
 
+	if (bt_bap_stream_get_type(bap->stream) == BT_BAP_STREAM_TYPE_BCAST)
+		/* Unlink stream from all its links */
+		queue_foreach(links, transport_unlink, bap->stream);
+
 	bap_update_links(transport);
 
-	return bt_bap_stream_disable(bap->stream, bap->linked, func, owner);
+	id = bt_bap_stream_disable(bap->stream, bap->linked, func, owner);
+
+	if (bt_bap_stream_get_type(bap->stream) == BT_BAP_STREAM_TYPE_BCAST) {
+		if (transport->owner == owner)
+			bap_disable_complete(bap->stream, 0x00, 0x00, owner);
+		return 0;
+	}
+
+	return id;
 }
 
-static void cancel_bap(struct media_transport *transport, guint id)
+static void transport_bap_cancel(struct media_transport *transport, guint id)
 {
 	struct bap_transport *bap = transport->data;
 
+	if (id == bap->resume_id && bap->resume_id) {
+		g_source_remove(bap->resume_id);
+		bap->resume_id = 0;
+		return;
+	}
+
 	if (!bap->stream)
 		return;
 
@@ -1283,7 +1966,7 @@ static void link_set_state(void *data, void *user_data)
 	transport_set_state(transport, state);
 }
 
-static void set_state_bap(struct media_transport *transport,
+static void transport_bap_set_state(struct media_transport *transport,
 					transport_state_t state)
 {
 	struct bap_transport *bap = transport->data;
@@ -1323,6 +2006,10 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
 		if (owner && owner->pending)
 			return;
 		bap_update_links(transport);
+		if (!media_endpoint_is_broadcast(transport->endpoint))
+			bap_update_qos(transport);
+		else if (bt_bap_stream_io_dir(stream) != BT_BAP_BCAST_SOURCE)
+			bap_update_bcast_qos(transport);
 		transport_update_playing(transport, FALSE);
 		return;
 	case BT_BAP_STREAM_STATE_DISABLING:
@@ -1332,6 +2019,13 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
 			return;
 		break;
 	case BT_BAP_STREAM_STATE_STREAMING:
+		if ((bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE) ||
+			(bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SINK))
+			bap_update_bcast_qos(transport);
+		break;
+	case BT_BAP_STREAM_STATE_RELEASING:
+		if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SINK)
+			return;
 		break;
 	}
 
@@ -1363,7 +2057,7 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
 	transport_update_playing(transport, TRUE);
 
 done:
-	resume_complete(transport);
+	bap_resume_complete(transport);
 }
 
 static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
@@ -1378,7 +2072,7 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
 	bap_update_links(transport);
 }
 
-static void free_bap(void *data)
+static void transport_bap_destroy(void *data)
 {
 	struct bap_transport *bap = data;
 
@@ -1387,8 +2081,7 @@ static void free_bap(void *data)
 	free(bap);
 }
 
-static int media_transport_init_bap(struct media_transport *transport,
-							void *stream)
+static void *transport_bap_init(struct media_transport *transport, void *stream)
 {
 	struct bt_bap_qos *qos;
 	struct bap_transport *bap;
@@ -1397,25 +2090,257 @@ static int media_transport_init_bap(struct media_transport *transport,
 
 	bap = new0(struct bap_transport, 1);
 	bap->stream = stream;
-	bap->interval = qos->interval;
-	bap->framing = qos->framing;
-	bap->phy = qos->phy;
-	bap->rtn = qos->rtn;
-	bap->latency = qos->latency;
-	bap->delay = qos->delay;
+	bap->qos = *qos;
 	bap->state_id = bt_bap_state_register(bt_bap_stream_get_session(stream),
 						bap_state_changed,
 						bap_connecting,
 						transport, NULL);
 
-	transport->data = bap;
-	transport->resume = resume_bap;
-	transport->suspend = suspend_bap;
-	transport->cancel = cancel_bap;
-	transport->set_state = set_state_bap;
-	transport->destroy = free_bap;
+	return bap;
+}
 
-	return 0;
+static void asha_transport_sync_state(struct media_transport *transport,
+						struct bt_asha_device *asha_dev)
+{
+	switch (bt_asha_device_get_state(asha_dev)) {
+	case ASHA_STOPPED:
+		transport_set_state(transport, TRANSPORT_STATE_IDLE);
+		break;
+	case ASHA_STARTING:
+		transport_set_state(transport, TRANSPORT_STATE_REQUESTING);
+		break;
+	case ASHA_STARTED:
+		transport_set_state(transport, TRANSPORT_STATE_ACTIVE);
+		break;
+	case ASHA_STOPPING:
+		transport_set_state(transport, TRANSPORT_STATE_SUSPENDING);
+		break;
+	}
+}
+
+static void asha_transport_state_cb(int status, void *user_data)
+{
+	struct media_owner *owner = user_data;
+	struct media_transport *transport = owner->transport;
+	struct bt_asha_device *asha_dev;
+	enum bt_asha_state_t state;
+
+	if (!transport) {
+		DBG("Lost owner while connecting, bailing");
+		return;
+	}
+
+	asha_dev = transport->data;
+	state = bt_asha_device_get_state(asha_dev);
+
+	if (state == ASHA_STARTED) {
+		int fd;
+		uint16_t imtu, omtu;
+		gboolean ret;
+
+		fd = bt_asha_device_get_fd(asha_dev);
+		imtu = bt_asha_device_get_imtu(asha_dev);
+		omtu = bt_asha_device_get_omtu(asha_dev);
+
+		media_transport_set_fd(transport, fd, imtu, omtu);
+
+		owner->pending->id = 0;
+		ret = g_dbus_send_reply(btd_get_dbus_connection(),
+				owner->pending->msg,
+				DBUS_TYPE_UNIX_FD, &fd,
+				DBUS_TYPE_UINT16, &imtu,
+				DBUS_TYPE_UINT16, &omtu,
+				DBUS_TYPE_INVALID);
+		if (!ret) {
+			media_transport_remove_owner(transport);
+			return;
+		}
+
+		media_owner_remove(owner);
+	} else if (state == ASHA_STOPPED) {
+		if (owner->pending) {
+			owner->pending->id = 0;
+			media_request_reply(owner->pending, 0);
+			media_owner_remove(owner);
+		}
+
+		media_transport_remove_owner(transport);
+	}
+
+	asha_transport_sync_state(transport, asha_dev);
+}
+
+static guint transport_asha_resume(struct media_transport *transport,
+						struct media_owner *owner)
+{
+	struct bt_asha_device *asha_dev = transport->data;
+	guint ret;
+
+	ret = bt_asha_device_start(asha_dev, asha_transport_state_cb, owner);
+	asha_transport_sync_state(transport, asha_dev);
+
+	return ret > 0 ? ret : 0;
+}
+
+static guint transport_asha_suspend(struct media_transport *transport,
+						struct media_owner *owner)
+{
+	struct bt_asha_device *asha_dev = transport->data;
+	guint ret = 0;
+
+	if (owner) {
+		ret = bt_asha_device_stop(asha_dev, asha_transport_state_cb,
+									owner);
+		asha_transport_sync_state(transport, asha_dev);
+	} else {
+		ret = bt_asha_device_stop(asha_dev, NULL, NULL);
+		/* We won't have a callback to set the final state */
+		transport_set_state(transport, TRANSPORT_STATE_IDLE);
+	}
+
+	return ret;
+}
+
+static void transport_asha_cancel(struct media_transport *transport, guint id)
+{
+	struct bt_asha_device *asha_dev = transport->data;
+	enum bt_asha_state_t state = bt_asha_device_get_state(asha_dev);
+
+	if (id != bt_asha_device_device_get_resume_id(asha_dev)) {
+		/* Not current, ignore */
+		DBG("Ignoring cancel request for id %d", id);
+		return;
+	}
+
+	if (state == ASHA_STARTING || state == ASHA_STARTED) {
+		DBG("Cancel requested, stopping");
+		bt_asha_device_stop(asha_dev, NULL, NULL);
+		/* We won't have a callback to set the final state */
+		transport_set_state(transport, TRANSPORT_STATE_IDLE);
+	} else if (state == ASHA_STOPPING) {
+		DBG("Cancel requested, resetting transport state");
+		/* We already dispatched a stop, just reset our state */
+		bt_asha_device_state_reset(asha_dev);
+		transport_set_state(transport, TRANSPORT_STATE_IDLE);
+	}
+}
+
+static int8_t transport_asha_get_volume(struct media_transport *transport)
+{
+	struct bt_asha_device *asha_dev = transport->data;
+	int8_t volume;
+	int scaled_volume;
+
+	volume = bt_asha_device_get_volume(asha_dev);
+
+	/* Convert -128-0 to 0-127 */
+	scaled_volume = ((((int) volume) + 128) * 127) / 128;
+
+	return scaled_volume;
+}
+
+static int transport_asha_set_volume(struct media_transport *transport,
+								int8_t volume)
+{
+	struct bt_asha_device *asha_dev = transport->data;
+	int scaled_volume;
+
+	/* Convert 0-127 to -128-0 */
+	scaled_volume = ((((int) volume) * 128) / 127) - 128;
+
+	return bt_asha_device_set_volume(asha_dev, scaled_volume) ? 0 : -EIO;
+}
+
+static void *transport_asha_init(struct media_transport *transport, void *data)
+{
+	/* We just store the struct asha_device on the transport */
+	return data;
+}
+
+#define TRANSPORT_OPS(_uuid, _props, _set_owner, _remove_owner, _init, \
+		      _resume, _suspend, _cancel, _set_state, _get_stream, \
+		      _get_volume, _set_volume, _set_delay, _update_links, \
+		      _destroy) \
+{ \
+	.uuid = _uuid, \
+	.properties = _props, \
+	.set_owner = _set_owner, \
+	.remove_owner = _remove_owner, \
+	.init = _init, \
+	.resume = _resume, \
+	.suspend = _suspend, \
+	.cancel = _cancel, \
+	.set_state = _set_state, \
+	.get_stream = _get_stream, \
+	.get_volume = _get_volume, \
+	.set_volume = _set_volume, \
+	.set_delay = _set_delay, \
+	.update_links = _update_links, \
+	.destroy = _destroy \
+}
+
+#define A2DP_OPS(_uuid, _init, _set_volume, _set_delay, _destroy) \
+	TRANSPORT_OPS(_uuid, transport_a2dp_properties, NULL, NULL, _init, \
+			transport_a2dp_resume, transport_a2dp_suspend, \
+			transport_a2dp_cancel, NULL, \
+			transport_a2dp_get_stream, transport_a2dp_get_volume, \
+			_set_volume, _set_delay, NULL, _destroy)
+
+#define BAP_OPS(_uuid, _props, _set_owner, _remove_owner, _update_links, \
+		_set_state) \
+	TRANSPORT_OPS(_uuid, _props, _set_owner, _remove_owner,\
+			transport_bap_init, \
+			transport_bap_resume, transport_bap_suspend, \
+			transport_bap_cancel, _set_state, \
+			transport_bap_get_stream, NULL, NULL, NULL, \
+			_update_links, transport_bap_destroy)
+
+#define BAP_UC_OPS(_uuid) \
+	BAP_OPS(_uuid, transport_bap_uc_properties, \
+			transport_bap_set_owner, transport_bap_remove_owner, \
+			transport_bap_update_links_uc, transport_bap_set_state)
+
+#define BAP_BC_OPS(_uuid) \
+	BAP_OPS(_uuid, transport_bap_bc_properties, NULL, NULL, \
+			transport_bap_update_links_bc, NULL)
+
+#define ASHA_OPS(_uuid) \
+	TRANSPORT_OPS(_uuid, transport_asha_properties, NULL, NULL, \
+			transport_asha_init, \
+			transport_asha_resume, transport_asha_suspend, \
+			transport_asha_cancel, NULL, NULL, \
+			transport_asha_get_volume, transport_asha_set_volume, \
+			NULL, NULL, NULL)
+
+static const struct media_transport_ops transport_ops[] = {
+	A2DP_OPS(A2DP_SOURCE_UUID, transport_a2dp_src_init,
+			transport_a2dp_src_set_volume,
+			NULL,
+			transport_a2dp_src_destroy),
+	A2DP_OPS(A2DP_SINK_UUID, transport_a2dp_snk_init,
+			transport_a2dp_snk_set_volume,
+			transport_a2dp_snk_set_delay,
+			transport_a2dp_snk_destroy),
+	BAP_UC_OPS(PAC_SOURCE_UUID),
+	BAP_UC_OPS(PAC_SINK_UUID),
+	BAP_BC_OPS(BCAA_SERVICE_UUID),
+	BAP_BC_OPS(BAA_SERVICE_UUID),
+	ASHA_OPS(ASHA_PROFILE_UUID),
+};
+
+static const struct media_transport_ops *
+media_transport_find_ops(const char *uuid)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(transport_ops); i++) {
+		const struct media_transport_ops *ops = &transport_ops[i];
+
+		if (!strcasecmp(uuid, ops->uuid))
+			return ops;
+	}
+
+	return NULL;
 }
 
 struct media_transport *media_transport_create(struct btd_device *device,
@@ -1426,42 +2351,46 @@ struct media_transport *media_transport_create(struct btd_device *device,
 {
 	struct media_endpoint *endpoint = data;
 	struct media_transport *transport;
-	const char *uuid;
+	const struct media_transport_ops *ops;
 	static int fd = 0;
-	const GDBusPropertyTable *properties;
 
 	transport = g_new0(struct media_transport, 1);
-	transport->device = device;
+	if (device)
+		transport->device = device;
+	else
+		transport->adapter = media_endpoint_get_btd_adapter(endpoint);
+
 	transport->endpoint = endpoint;
-	transport->configuration = g_new(uint8_t, size);
-	memcpy(transport->configuration, configuration, size);
+	transport->configuration = util_memdup(configuration, size);
 	transport->size = size;
-	transport->remote_endpoint = remote_endpoint;
-	transport->path = g_strdup_printf("%s/fd%d",
-				remote_endpoint ? remote_endpoint :
-				device_get_path(device), fd++);
+	transport->remote_endpoint = g_strdup(remote_endpoint);
+
+	if (device)
+		transport->path = g_strdup_printf("%s/fd%d",
+					remote_endpoint ? remote_endpoint :
+					device_get_path(device), fd++);
+	else
+		transport->path = g_strdup_printf("%s/fd%d",
+					remote_endpoint ? remote_endpoint :
+					adapter_get_path(transport->adapter),
+					fd++);
 	transport->fd = -1;
 
-	uuid = media_endpoint_get_uuid(endpoint);
-	if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
-		if (media_transport_init_source(transport) < 0)
-			goto fail;
-		properties = a2dp_properties;
-	} else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
-		if (media_transport_init_sink(transport) < 0)
-			goto fail;
-		properties = a2dp_properties;
-	} else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
-				!strcasecmp(uuid, PAC_SOURCE_UUID)) {
-		if (media_transport_init_bap(transport, stream) < 0)
-			goto fail;
-		properties = bap_properties;
-	} else
+	ops = media_transport_find_ops(media_endpoint_get_uuid(endpoint));
+	if (!ops)
 		goto fail;
 
+	transport->ops = ops;
+
+	if (ops->init) {
+		transport->data = ops->init(transport, stream);
+		if (!transport->data)
+			goto fail;
+	}
+
 	if (g_dbus_register_interface(btd_get_dbus_connection(),
 				transport->path, MEDIA_TRANSPORT_INTERFACE,
-				transport_methods, NULL, properties,
+				transport_methods, NULL, ops->properties,
 				transport, media_transport_free) == FALSE) {
 		error("Could not register transport %s", transport->path);
 		goto fail;
@@ -1481,6 +2410,14 @@ const char *media_transport_get_path(struct media_transport *transport)
 	return transport->path;
 }
 
+void *media_transport_get_stream(struct media_transport *transport)
+{
+	if (transport->ops && transport->ops->get_stream)
+		return transport->ops->get_stream(transport);
+
+	return NULL;
+}
+
 void media_transport_update_delay(struct media_transport *transport,
 							uint16_t delay)
 {
@@ -1502,12 +2439,6 @@ struct btd_device *media_transport_get_dev(struct media_transport *transport)
 	return transport->device;
 }
 
-int8_t media_transport_get_volume(struct media_transport *transport)
-{
-	struct a2dp_transport *a2dp = transport->data;
-	return a2dp->volume;
-}
-
 void media_transport_update_volume(struct media_transport *transport,
 								int8_t volume)
 {
@@ -1541,8 +2472,14 @@ int8_t media_transport_get_device_volume(struct btd_device *dev)
 			continue;
 
 		/* Volume is A2DP only */
-		if (media_endpoint_get_sep(transport->endpoint))
-			return media_transport_get_volume(transport);
+		if (media_endpoint_get_sep(transport->endpoint)) {
+			int8_t volume;
+
+			if (!media_transport_get_volume(transport, &volume))
+				return volume;
+
+			return -1;
+		}
 	}
 
 	/* If transport volume doesn't exists use device_volume */
diff --git a/profiles/audio/transport.h b/profiles/audio/transport.h
index 102fc3c..b46bc80 100644
--- a/profiles/audio/transport.h
+++ b/profiles/audio/transport.h
@@ -19,8 +19,10 @@ struct media_transport *media_transport_create(struct btd_device *device,
 
 void media_transport_destroy(struct media_transport *transport);
 const char *media_transport_get_path(struct media_transport *transport);
+void *media_transport_get_stream(struct media_transport *transport);
 struct btd_device *media_transport_get_dev(struct media_transport *transport);
-int8_t media_transport_get_volume(struct media_transport *transport);
+int media_transport_get_volume(struct media_transport *transport,
+					int8_t *volume);
 void media_transport_update_delay(struct media_transport *transport,
 							uint16_t delay);
 void media_transport_update_volume(struct media_transport *transport,
diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
index b42b0a4..175275f 100644
--- a/profiles/audio/vcp.c
+++ b/profiles/audio/vcp.c
@@ -289,18 +289,20 @@ static struct btd_profile vcp_profile = {
 
 	.adapter_probe = vcp_server_probe,
 	.adapter_remove = vcp_server_remove,
+
+	.experimental	= true,
 };
 
 static unsigned int vcp_id = 0;
 
 static int vcp_init(void)
 {
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
-		warn("D-Bus experimental not enabled");
-		return -ENOTSUP;
-	}
+	int err;
+
+	err = btd_profile_register(&vcp_profile);
+	if (err)
+		return err;
 
-	btd_profile_register(&vcp_profile);
 	vcp_id = bt_vcp_register(vcp_attached, vcp_detached, NULL);
 
 	return 0;
@@ -308,10 +310,8 @@ static int vcp_init(void)
 
 static void vcp_exit(void)
 {
-	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
-		btd_profile_unregister(&vcp_profile);
-		bt_vcp_unregister(vcp_id);
-	}
+	btd_profile_unregister(&vcp_profile);
+	bt_vcp_unregister(vcp_id);
 }
 
 BLUETOOTH_PLUGIN_DEFINE(vcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
diff --git a/profiles/gap/gas.c b/profiles/gap/gas.c
index 400818d..08aaf19 100644
--- a/profiles/gap/gas.c
+++ b/profiles/gap/gas.c
@@ -50,10 +50,18 @@ struct gas {
 	struct gatt_db_attribute *attr;
 };
 
-static void gas_free(struct gas *gas)
+static void gas_reset(struct gas *gas)
 {
+	gas->attr = NULL;
 	gatt_db_unref(gas->db);
+	gas->db = NULL;
 	bt_gatt_client_unref(gas->client);
+	gas->client = NULL;
+}
+
+static void gas_free(struct gas *gas)
+{
+	gas_reset(gas);
 	btd_device_unref(gas->device);
 	g_free(gas);
 }
@@ -152,7 +160,76 @@ static void handle_appearance(struct gas *gas, uint16_t value_handle)
 		DBG("Failed to send request to read appearance");
 }
 
-static bool uuid_cmp(uint16_t u16, const bt_uuid_t *uuid)
+static void read_ppcp_cb(bool success, uint8_t att_ecode,
+			const uint8_t *value, uint16_t length,
+			void *user_data)
+{
+	struct gas *gas = user_data;
+	uint16_t min_interval, max_interval, latency, timeout, max_latency;
+
+	if (!success) {
+		DBG("Reading PPCP failed with ATT error: %u", att_ecode);
+		return;
+	}
+
+	if (length != 8) {
+		DBG("Malformed PPCP value");
+		return;
+	}
+
+	min_interval = get_le16(&value[0]);
+	max_interval = get_le16(&value[2]);
+	latency = get_le16(&value[4]);
+	timeout = get_le16(&value[6]);
+
+	/* 0xffff indicates no specific min/max */
+	if (min_interval == 0xffff)
+		min_interval = 0x0018; /* 30.0ms */
+
+	if (max_interval == 0xffff)
+		max_interval = 0x0028; /* 50.0ms */
+
+	DBG("GAP Peripheral Preferred Connection Parameters:");
+	DBG("\tMinimum connection interval: %u", min_interval);
+	DBG("\tMaximum connection interval: %u", max_interval);
+	DBG("\tSlave latency: %u", latency);
+	DBG("\tConnection Supervision timeout multiplier: %u", timeout);
+
+	/* avoid persisting connection parameters that are not valid */
+	if (min_interval > max_interval ||
+	    min_interval < 6 || max_interval > 3200) {
+		warn("GAS PPCP: Invalid Connection Parameters values");
+		return;
+	}
+
+	if (timeout < 10 || timeout > 3200) {
+		warn("GAS PPCP: Invalid Connection Parameters values");
+		return;
+	}
+
+	if (max_interval >= timeout * 8) {
+		warn("GAS PPCP: Invalid Connection Parameters values");
+		return;
+	}
+
+	max_latency = (timeout * 4 / max_interval) - 1;
+	if (latency > 499 || latency > max_latency) {
+		warn("GAS PPCP: Invalid Connection Parameters values");
+		return;
+	}
+
+	btd_device_set_conn_param(gas->device, min_interval, max_interval,
+					latency, timeout);
+}
+
+static void handle_ppcp(struct gas *gas, uint16_t value_handle)
+{
+	if (!bt_gatt_client_read_value(gas->client, value_handle,
+						read_ppcp_cb, gas, NULL))
+		DBG("Failed to send request to read PPCP");
+}
+
+static inline bool uuid_cmp(uint16_t u16, const bt_uuid_t *uuid)
 {
 	bt_uuid_t lhs;
 
@@ -178,6 +255,8 @@ static void handle_characteristic(struct gatt_db_attribute *attr,
 		handle_device_name(gas, value_handle);
 	else if (uuid_cmp(GATT_CHARAC_APPEARANCE, &uuid))
 		handle_appearance(gas, value_handle);
+	else if (uuid_cmp(GATT_CHARAC_PERIPHERAL_PREF_CONN, &uuid))
+		handle_ppcp(gas, value_handle);
 	else {
 		char uuid_str[MAX_LEN_UUID_STR];
 
@@ -188,11 +267,6 @@ static void handle_characteristic(struct gatt_db_attribute *attr,
 	}
 }
 
-static void handle_gap_service(struct gas *gas)
-{
-	gatt_db_service_foreach_char(gas->attr, handle_characteristic, gas);
-}
-
 static int gap_probe(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
@@ -246,16 +320,7 @@ static void foreach_gap_service(struct gatt_db_attribute *attr, void *user_data)
 	}
 
 	gas->attr = attr;
-	handle_gap_service(gas);
-}
-
-static void gas_reset(struct gas *gas)
-{
-	gas->attr = NULL;
-	gatt_db_unref(gas->db);
-	gas->db = NULL;
-	bt_gatt_client_unref(gas->client);
-	gas->client = NULL;
+	gatt_db_service_foreach_char(gas->attr, handle_characteristic, gas);
 }
 
 static int gap_accept(struct btd_service *service)
@@ -266,15 +331,21 @@ static int gap_accept(struct btd_service *service)
 	struct gas *gas = btd_service_get_user_data(service);
 	char addr[18];
 	bt_uuid_t gap_uuid;
+	int err = 0;
 
 	ba2str(device_get_address(device), addr);
 	DBG("GAP profile accept (%s)", addr);
 
 	if (!gas) {
 		error("GAP service not handled by profile");
-		return -1;
+		err = -1;
+		goto _finish;
 	}
 
+	/* Check if attribute already has been discovered */
+	if (gas->attr)
+		goto _finish;
+
 	gas->db = gatt_db_ref(db);
 	gas->client = bt_gatt_client_clone(client);
 
@@ -285,20 +356,18 @@ static int gap_accept(struct btd_service *service)
 	if (!gas->attr) {
 		error("GAP attribute not found");
 		gas_reset(gas);
-		return -1;
+		err = -1;
 	}
 
-	btd_service_connecting_complete(service, 0);
+_finish:
 
-	return 0;
+	btd_service_connecting_complete(service, err);
+
+	return err;
 }
 
 static int gap_disconnect(struct btd_service *service)
 {
-	struct gas *gas = btd_service_get_user_data(service);
-
-	gas_reset(gas);
-
 	btd_service_disconnecting_complete(service, 0);
 
 	return 0;
diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c
index ab3b78f..ad3702f 100644
--- a/profiles/health/hdp_util.c
+++ b/profiles/health/hdp_util.c
@@ -42,7 +42,7 @@ typedef gboolean (*parse_item_f)(DBusMessageIter *iter, gpointer user_data,
 								GError **err);
 
 struct dict_entry_func {
-	char		*key;
+	const char	*key;
 	parse_item_f	func;
 };
 
@@ -67,7 +67,7 @@ struct get_dcpsm_data {
 	GDestroyNotify		destroy;
 };
 
-static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
+static gboolean parse_dict_entry(const struct dict_entry_func dict_context[],
 							DBusMessageIter *iter,
 							GError **err,
 							gpointer user_data)
@@ -75,7 +75,6 @@ static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
 	DBusMessageIter entry;
 	char *key;
 	int ctype, i;
-	struct dict_entry_func df;
 
 	dbus_message_iter_recurse(iter, &entry);
 	ctype = dbus_message_iter_get_arg_type(&entry);
@@ -88,9 +87,9 @@ static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
 	dbus_message_iter_get_basic(&entry, &key);
 	dbus_message_iter_next(&entry);
 	/* Find function and call it */
-	for (i = 0, df = dict_context[0]; df.key; i++, df = dict_context[i]) {
-		if (g_ascii_strcasecmp(df.key, key) == 0)
-			return df.func(&entry, user_data, err);
+	for (i = 0; dict_context[i].key; i++) {
+		if (g_ascii_strcasecmp(dict_context[i].key, key) == 0)
+			return dict_context[i].func(&entry, user_data, err);
 	}
 
 	g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
@@ -98,7 +97,7 @@ static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
 	return FALSE;
 }
 
-static gboolean parse_dict(struct dict_entry_func dict_context[],
+static gboolean parse_dict(const struct dict_entry_func dict_context[],
 							DBusMessageIter *iter,
 							GError **err,
 							gpointer user_data)
@@ -273,7 +272,7 @@ static gboolean parse_chan_type(DBusMessageIter *iter, gpointer data,
 	return TRUE;
 }
 
-static struct dict_entry_func dict_parser[] = {
+static const struct dict_entry_func dict_parser[] = {
 	{"DataType",		parse_data_type},
 	{"Role",		parse_role},
 	{"Description",		parse_desc},
diff --git a/profiles/health/mcap.c b/profiles/health/mcap.c
index 5d2bac3..2e4214a 100644
--- a/profiles/health/mcap.c
+++ b/profiles/health/mcap.c
@@ -336,6 +336,9 @@ static void mcap_notify_error(struct mcap_mcl *mcl, GError *err)
 	case MCAP_MD_CREATE_MDL_REQ:
 		st = MDL_WAITING;
 		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
+		if (!l)
+			return;
+
 		mdl = l->data;
 		mcl->mdls = g_slist_remove(mcl->mdls, mdl);
 		mcap_mdl_unref(mdl);
@@ -345,6 +348,9 @@ static void mcap_notify_error(struct mcap_mcl *mcl, GError *err)
 	case MCAP_MD_ABORT_MDL_REQ:
 		st = MDL_WAITING;
 		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
+		if (!l)
+			return;
+
 		shutdown_mdl(l->data);
 		update_mcl_state(mcl);
 		con->cb.notify(err, con->user_data);
@@ -362,6 +368,9 @@ static void mcap_notify_error(struct mcap_mcl *mcl, GError *err)
 	case MCAP_MD_RECONNECT_MDL_REQ:
 		st = MDL_WAITING;
 		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
+		if (!l)
+			return;
+
 		shutdown_mdl(l->data);
 		update_mcl_state(mcl);
 		con->cb.op(NULL, err, con->user_data);
@@ -1907,6 +1916,7 @@ gboolean mcap_create_mcl(struct mcap_instance *mi,
 		set_default_cb(mcl);
 		if (util_getrandom(&val, sizeof(val), 0) < 0) {
 			mcap_instance_unref(mcl->mi);
+			g_free(mcl->cb);
 			g_free(mcl);
 			return FALSE;
 		}
@@ -2051,6 +2061,7 @@ static void connect_mcl_event_cb(GIOChannel *chan, GError *gerr,
 		set_default_cb(mcl);
 		if (util_getrandom(&val, sizeof(val), 0) < 0) {
 			mcap_instance_unref(mcl->mi);
+			g_free(mcl->cb);
 			g_free(mcl);
 			goto drop;
 		}
diff --git a/profiles/iap/main.c b/profiles/iap/main.c
index 9a04f5c..054ff60 100644
--- a/profiles/iap/main.c
+++ b/profiles/iap/main.c
@@ -398,7 +398,7 @@ static guint setup_signalfd(void)
 
 static gboolean option_version = FALSE;
 
-static GOptionEntry options[] = {
+static const GOptionEntry options[] = {
 	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
 				"Show version information and exit" },
 	{ NULL },
diff --git a/profiles/input/device.c b/profiles/input/device.c
index e2ac6ea..8cf8e5e 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -20,6 +20,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
+#include <sys/uio.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hidp.h"
@@ -41,6 +42,8 @@
 #include "src/sdp-client.h"
 #include "src/shared/timeout.h"
 #include "src/shared/uhid.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
 
 #include "device.h"
 #include "hidp_defs.h"
@@ -54,13 +57,18 @@ enum reconnect_mode_t {
 	RECONNECT_ANY
 };
 
+struct hidp_msg {
+	uint8_t hdr;
+	struct iovec *iov;
+};
+
 struct input_device {
 	struct btd_service	*service;
 	struct btd_device	*device;
 	char			*path;
 	bdaddr_t		src;
 	bdaddr_t		dst;
-	uint32_t		handle;
+	const sdp_record_t	*rec;
 	GIOChannel		*ctrl_io;
 	GIOChannel		*intr_io;
 	guint			ctrl_watch;
@@ -72,25 +80,40 @@ struct input_device {
 	unsigned int		reconnect_timer;
 	uint32_t		reconnect_attempt;
 	struct bt_uhid		*uhid;
-	bool			uhid_created;
 	uint8_t			report_req_pending;
 	unsigned int		report_req_timer;
 	uint32_t		report_rsp_id;
 	bool			virtual_cable_unplug;
+	uint8_t			type;
+	unsigned int		idle_timer;
 };
 
 static int idle_timeout = 0;
-static bool uhid_enabled = false;
-static bool classic_bonded_only = false;
+static uhid_state_t uhid_state = UHID_ENABLED;
+static bool classic_bonded_only = true;
 
 void input_set_idle_timeout(int timeout)
 {
 	idle_timeout = timeout;
 }
 
-void input_enable_userspace_hid(bool state)
+void input_set_userspace_hid(char *state)
+{
+	if (!strcasecmp(state, "false") || !strcasecmp(state, "no") ||
+			!strcasecmp(state, "off"))
+		uhid_state = UHID_DISABLED;
+	else if (!strcasecmp(state, "true") || !strcasecmp(state, "yes") ||
+			!strcasecmp(state, "on"))
+		uhid_state = UHID_ENABLED;
+	else if (!strcasecmp(state, "persist"))
+		uhid_state = UHID_PERSIST;
+	else
+		error("Unknown value '%s'", state);
+}
+
+uint8_t input_get_userspace_hid(void)
 {
-	uhid_enabled = state;
+	return uhid_state;
 }
 
 void input_set_classic_bonded_only(bool state)
@@ -105,7 +128,6 @@ bool input_get_classic_bonded_only(void)
 
 static void input_device_enter_reconnect_mode(struct input_device *idev);
 static int connection_disconnect(struct input_device *idev, uint32_t flags);
-static int uhid_disconnect(struct input_device *idev);
 
 static bool input_device_bonded(struct input_device *idev)
 {
@@ -140,6 +162,9 @@ static void input_device_free(struct input_device *idev)
 		g_free(idev->req);
 	}
 
+	if (idev->idle_timer)
+		timeout_remove(idev->idle_timer);
+
 	if (idev->reconnect_timer > 0)
 		timeout_remove(idev->reconnect_timer);
 
@@ -157,40 +182,93 @@ static void virtual_cable_unplug(struct input_device *idev)
 	idev->virtual_cable_unplug = false;
 }
 
-static bool hidp_send_message(GIOChannel *chan, uint8_t hdr,
-					const uint8_t *data, size_t size)
+static int uhid_disconnect(struct input_device *idev, bool force)
+{
+	int err;
+
+	if (!bt_uhid_created(idev->uhid))
+		return 0;
+
+	/* Force destroy the node if virtual cable unplug flag has been set */
+	if (idev->virtual_cable_unplug && !force)
+		force = true;
+
+	if (!force && uhid_state != UHID_PERSIST)
+		force = true;
+
+	err = bt_uhid_destroy(idev->uhid, force);
+	if (err < 0) {
+		error("bt_uhid_destroy: %s", strerror(-err));
+		return err;
+	}
+
+	if (!bt_uhid_created(idev->uhid))
+		bt_uhid_unregister_all(idev->uhid);
+
+	return err;
+}
+
+static bool input_device_idle_timeout(gpointer user_data)
+{
+	struct input_device *idev = user_data;
+
+	idev->idle_timer = 0;
+
+	DBG("path=%s", idev->path);
+
+	uhid_disconnect(idev, true);
+	connection_disconnect(idev, 0);
+
+	return false;
+}
+
+static void input_device_idle_reset(struct input_device *idev)
+{
+	timeout_remove(idev->idle_timer);
+
+	if (idle_timeout)
+		idev->idle_timer = timeout_add_seconds(idle_timeout,
+					input_device_idle_timeout, idev,
+					NULL);
+}
+
+static bool hidp_send_message(struct input_device *idev, GIOChannel *chan,
+				uint8_t hdr, const uint8_t *data, size_t size)
 {
 	int fd;
 	ssize_t len;
-	uint8_t msg[size + 1];
+	struct iovec iov[2];
 
 	if (!chan) {
 		error("BT socket not connected");
 		return false;
 	}
 
+	iov[0].iov_base = &hdr;
+	iov[0].iov_len = sizeof(hdr);
+
 	if (data == NULL)
 		size = 0;
 
-	msg[0] = hdr;
-	if (size > 0)
-		memcpy(&msg[1], data, size);
-	++size;
+	iov[1].iov_base = (void *)data;
+	iov[1].iov_len = size;
 
 	fd = g_io_channel_unix_get_fd(chan);
 
-	len = write(fd, msg, size);
+	len = writev(fd, iov, 2);
 	if (len < 0) {
 		error("BT socket write error: %s (%d)", strerror(errno), errno);
 		return false;
 	}
 
-	if ((size_t) len < size) {
+	if ((size_t) len < size + 1) {
 		error("BT socket write error: partial write (%zd of %zu bytes)",
-								len, size);
+								len, size + 1);
 		return false;
 	}
 
+	input_device_idle_reset(idev);
+
 	return true;
 }
 
@@ -200,45 +278,33 @@ static bool hidp_send_ctrl_message(struct input_device *idev, uint8_t hdr,
 	if (hdr == (HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG))
 		idev->virtual_cable_unplug = true;
 
-	return hidp_send_message(idev->ctrl_io, hdr, data, size);
+	return hidp_send_message(idev, idev->ctrl_io, hdr, data, size);
 }
 
 static bool hidp_send_intr_message(struct input_device *idev, uint8_t hdr,
 					const uint8_t *data, size_t size)
 {
-	return hidp_send_message(idev->intr_io, hdr, data, size);
+	return hidp_send_message(idev, idev->intr_io, hdr, data, size);
 }
 
 static bool uhid_send_get_report_reply(struct input_device *idev,
 					const uint8_t *data, size_t size,
 					uint32_t id, uint16_t err)
 {
-	struct uhid_event ev;
 	int ret;
 
 	if (data == NULL)
 		size = 0;
 
-	if (size > sizeof(ev.u.get_report_reply.data))
-		size = sizeof(ev.u.get_report_reply.data);
-
-	if (!idev->uhid_created) {
+	if (!bt_uhid_created(idev->uhid)) {
 		DBG("HID report (%zu bytes) dropped", size);
 		return false;
 	}
 
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_GET_REPORT_REPLY;
-	ev.u.get_report_reply.id = id;
-	ev.u.get_report_reply.err = err;
-	ev.u.get_report_reply.size = size;
-
-	if (size > 0)
-		memcpy(ev.u.get_report_reply.data, data, size);
-
-	ret = bt_uhid_send(idev->uhid, &ev);
+	ret = bt_uhid_get_report_reply(idev->uhid, id, 0, err, data, size);
 	if (ret < 0) {
-		error("bt_uhid_send: %s (%d)", strerror(-ret), -ret);
+		error("bt_uhid_get_report_reply: %s (%d)", strerror(-ret),
+			-ret);
 		return false;
 	}
 
@@ -250,20 +316,15 @@ static bool uhid_send_get_report_reply(struct input_device *idev,
 static bool uhid_send_set_report_reply(struct input_device *idev,
 					uint32_t id, uint16_t err)
 {
-	struct uhid_event ev;
 	int ret;
 
-	if (!idev->uhid_created)
+	if (!bt_uhid_created(idev->uhid))
 		return false;
 
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_SET_REPORT_REPLY;
-	ev.u.set_report_reply.id = id;
-	ev.u.set_report_reply.err = err;
-
-	ret = bt_uhid_send(idev->uhid, &ev);
+	ret = bt_uhid_set_report_reply(idev->uhid, id, err);
 	if (ret < 0) {
-		error("bt_uhid_send: %s (%d)", strerror(-ret), -ret);
+		error("bt_uhid_set_report_reply: %s (%d)", strerror(-ret),
+			-ret);
 		return false;
 	}
 
@@ -273,30 +334,19 @@ static bool uhid_send_set_report_reply(struct input_device *idev,
 static bool uhid_send_input_report(struct input_device *idev,
 					const uint8_t *data, size_t size)
 {
-	struct uhid_event ev;
 	int err;
 
 	if (data == NULL)
 		size = 0;
 
-	if (size > sizeof(ev.u.input.data))
-		size = sizeof(ev.u.input.data);
-
-	if (!idev->uhid_created) {
+	if (!bt_uhid_created(idev->uhid)) {
 		DBG("HID report (%zu bytes) dropped", size);
 		return false;
 	}
 
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_INPUT;
-	ev.u.input.size = size;
-
-	if (size > 0)
-		memcpy(ev.u.input.data, data, size);
-
-	err = bt_uhid_send(idev->uhid, &ev);
+	err = bt_uhid_input(idev->uhid, 0, data, size);
 	if (err < 0) {
-		error("bt_uhid_send: %s (%d)", strerror(-err), -err);
+		error("bt_uhid_input: %s (%d)", strerror(-err), -err);
 		return false;
 	}
 
@@ -325,6 +375,8 @@ static bool hidp_recv_intr_data(GIOChannel *chan, struct input_device *idev)
 		return true;
 	}
 
+	input_device_idle_reset(idev);
+
 	hdr = data[0];
 	if (hdr != (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
 		DBG("unsupported HIDP protocol header 0x%02x", hdr);
@@ -383,8 +435,7 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 		virtual_cable_unplug(idev);
 
 	/* If connection abruptly ended, uhid might be not yet disconnected */
-	if (idev->uhid_created)
-		uhid_disconnect(idev);
+	uhid_disconnect(idev, false);
 
 	return FALSE;
 }
@@ -443,6 +494,7 @@ static void hidp_recv_ctrl_handshake(struct input_device *idev, uint8_t param)
 			timeout_remove(idev->report_req_timer);
 			idev->report_req_timer = 0;
 		}
+		uhid_send_set_report_reply(idev, idev->report_rsp_id, 0);
 		idev->report_rsp_id = 0;
 	}
 }
@@ -526,6 +578,8 @@ static bool hidp_recv_ctrl_message(GIOChannel *chan, struct input_device *idev)
 		return true;
 	}
 
+	input_device_idle_reset(idev);
+
 	hdr = data[0];
 	type = hdr & HIDP_HEADER_TRANS_MASK;
 	param = hdr & HIDP_HEADER_PARAM_MASK;
@@ -623,7 +677,7 @@ static bool hidp_report_req_timeout(gpointer data)
 		break;
 	}
 
-	DBG("Device %s HIDP %s request timed out", address, req_type_str);
+	error("Device %s HIDP %s request timed out", address, req_type_str);
 
 	idev->report_req_pending = 0;
 	idev->report_req_timer = 0;
@@ -636,11 +690,14 @@ static void hidp_send_output(struct uhid_event *ev, void *user_data)
 {
 	struct input_device *idev = user_data;
 	uint8_t hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUTPUT;
+	bool sent;
 
 	DBG("");
 
-	hidp_send_intr_message(idev, hdr, ev->u.output.data,
+	sent = hidp_send_intr_message(idev, hdr, ev->u.output.data,
 						ev->u.output.size);
+	if (!sent)
+		uhid_disconnect(idev, true);
 }
 
 static void hidp_send_set_report(struct uhid_event *ev, void *user_data)
@@ -680,8 +737,11 @@ static void hidp_send_set_report(struct uhid_event *ev, void *user_data)
 			timeout_add_seconds(REPORT_REQ_TIMEOUT,
 					hidp_report_req_timeout, idev, NULL);
 		idev->report_rsp_id = ev->u.set_report.id;
-	} else
+	} else {
 		uhid_send_set_report_reply(idev, ev->u.set_report.id, EIO);
+		/* Force UHID_DESTROY on error */
+		uhid_disconnect(idev, true);
+	}
 }
 
 static void hidp_send_get_report(struct uhid_event *ev, void *user_data)
@@ -724,9 +784,12 @@ static void hidp_send_get_report(struct uhid_event *ev, void *user_data)
 						hidp_report_req_timeout, idev,
 						NULL);
 		idev->report_rsp_id = ev->u.get_report.id;
-	} else
+	} else {
 		uhid_send_get_report_reply(idev, NULL, 0, ev->u.get_report.id,
 									EIO);
+		/* Force UHID_DESTROY on error */
+		uhid_disconnect(idev, true);
+	}
 }
 
 static void epox_endian_quirk(unsigned char *data, int size)
@@ -754,7 +817,8 @@ static void epox_endian_quirk(unsigned char *data, int size)
 	}
 }
 
-static int create_hid_dev_name(sdp_record_t *rec, struct hidp_connadd_req *req)
+static int create_hid_dev_name(const sdp_record_t *rec,
+					struct hidp_connadd_req *req)
 {
 	char sdesc[sizeof(req->name) / 2];
 
@@ -776,7 +840,7 @@ static int create_hid_dev_name(sdp_record_t *rec, struct hidp_connadd_req *req)
 
 /* See HID profile specification v1.0, "7.11.6 HIDDescriptorList" for details
  * on the attribute format. */
-static int extract_hid_desc_data(sdp_record_t *rec,
+static int extract_hid_desc_data(const sdp_record_t *rec,
 						struct hidp_connadd_req *req)
 {
 	sdp_data_t *d;
@@ -817,36 +881,40 @@ invalid_desc:
 	return -EINVAL;
 }
 
-static int extract_hid_record(sdp_record_t *rec, struct hidp_connadd_req *req)
+static int extract_hid_record(struct input_device *idev,
+					struct hidp_connadd_req *req)
 {
 	sdp_data_t *pdlist;
 	uint8_t attr_val;
 	int err;
 
-	err = create_hid_dev_name(rec, req);
+	if (!idev->rec)
+		return -ENOENT;
+
+	err = create_hid_dev_name(idev->rec, req);
 	if (err < 0)
 		DBG("No valid Service Name or Service Description found");
 
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_PARSER_VERSION);
+	pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_PARSER_VERSION);
 	req->parser = pdlist ? pdlist->val.uint16 : 0x0100;
 
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_DEVICE_SUBCLASS);
+	pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_DEVICE_SUBCLASS);
 	req->subclass = pdlist ? pdlist->val.uint8 : 0;
 
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_COUNTRY_CODE);
+	pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_COUNTRY_CODE);
 	req->country = pdlist ? pdlist->val.uint8 : 0;
 
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_VIRTUAL_CABLE);
+	pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_VIRTUAL_CABLE);
 	attr_val = pdlist ? pdlist->val.uint8 : 0;
 	if (attr_val)
 		req->flags |= (1 << HIDP_VIRTUAL_CABLE_UNPLUG);
 
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_BOOT_DEVICE);
+	pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_BOOT_DEVICE);
 	attr_val = pdlist ? pdlist->val.uint8 : 0;
 	if (attr_val)
 		req->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
 
-	err = extract_hid_desc_data(rec, req);
+	err = extract_hid_desc_data(idev->rec, req);
 	if (err < 0)
 		return err;
 
@@ -934,28 +1002,16 @@ static int ioctl_disconnect(struct input_device *idev, uint32_t flags)
 static int uhid_connadd(struct input_device *idev, struct hidp_connadd_req *req)
 {
 	int err;
-	struct uhid_event ev;
 
-	if (idev->uhid_created)
-		return 0;
+	if (bt_uhid_created(idev->uhid))
+		return bt_uhid_replay(idev->uhid);
 
-	/* create uHID device */
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_CREATE;
-	strncpy((char *) ev.u.create.name, req->name, sizeof(ev.u.create.name));
-	ba2strlc(&idev->src, (char *) ev.u.create.phys);
-	ba2strlc(&idev->dst, (char *) ev.u.create.uniq);
-	ev.u.create.vendor = req->vendor;
-	ev.u.create.product = req->product;
-	ev.u.create.version = req->version;
-	ev.u.create.country = req->country;
-	ev.u.create.bus = BUS_BLUETOOTH;
-	ev.u.create.rd_data = req->rd_data;
-	ev.u.create.rd_size = req->rd_size;
-
-	err = bt_uhid_send(idev->uhid, &ev);
+	err = bt_uhid_create(idev->uhid, req->name, &idev->src, &idev->dst,
+				req->vendor, req->product, req->version,
+				req->country, idev->type,
+				req->rd_data, req->rd_size);
 	if (err < 0) {
-		error("bt_uhid_send: %s", strerror(-err));
+		error("bt_uhid_create: %s", strerror(-err));
 		return err;
 	}
 
@@ -965,32 +1021,6 @@ static int uhid_connadd(struct input_device *idev, struct hidp_connadd_req *req)
 	bt_uhid_register(idev->uhid, UHID_SET_REPORT, hidp_send_set_report,
 									idev);
 
-	idev->uhid_created = true;
-
-	return err;
-}
-
-static int uhid_disconnect(struct input_device *idev)
-{
-	int err;
-	struct uhid_event ev;
-
-	if (!idev->uhid_created)
-		return 0;
-
-	bt_uhid_unregister_all(idev->uhid);
-
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_DESTROY;
-
-	err = bt_uhid_send(idev->uhid, &ev);
-	if (err < 0) {
-		error("bt_uhid_send: %s", strerror(-err));
-		return err;
-	}
-
-	idev->uhid_created = false;
-
 	return err;
 }
 
@@ -1035,11 +1065,6 @@ static gboolean encrypt_notify(GIOChannel *io, GIOCondition condition,
 static int hidp_add_connection(struct input_device *idev)
 {
 	struct hidp_connadd_req *req;
-	sdp_record_t *rec;
-	char src_addr[18], dst_addr[18];
-	char filename[PATH_MAX];
-	GKeyFile *key_file;
-	char handle[11], *str;
 	GError *gerr = NULL;
 	int err;
 
@@ -1049,33 +1074,7 @@ static int hidp_add_connection(struct input_device *idev)
 	req->flags     = 0;
 	req->idle_to   = idle_timeout;
 
-	ba2str(&idev->src, src_addr);
-	ba2str(&idev->dst, dst_addr);
-
-	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr,
-								dst_addr);
-	sprintf(handle, "0x%8.8X", idev->handle);
-
-	key_file = g_key_file_new();
-	if (!g_key_file_load_from_file(key_file, filename, 0, &gerr)) {
-		error("Unable to load key file from %s: (%s)", filename,
-								gerr->message);
-		g_clear_error(&gerr);
-	}
-	str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL);
-	g_key_file_free(key_file);
-
-	if (!str) {
-		error("Rejected connection from unknown device %s", dst_addr);
-		err = -EPERM;
-		goto cleanup;
-	}
-
-	rec = record_from_string(str);
-	g_free(str);
-
-	err = extract_hid_record(rec, req);
-	sdp_record_free(rec);
+	err = extract_hid_record(idev, req);
 	if (err < 0) {
 		error("Could not parse HID SDP record: %s (%d)", strerror(-err),
 									-err);
@@ -1091,7 +1090,7 @@ static int hidp_add_connection(struct input_device *idev)
 
 	/* Make sure the device is bonded if required */
 	if (classic_bonded_only && !input_device_bonded(idev)) {
-		error("Rejected connection from !bonded device %s", dst_addr);
+		error("Rejected connection from !bonded device %s", idev->path);
 		goto cleanup;
 	}
 
@@ -1099,7 +1098,7 @@ static int hidp_add_connection(struct input_device *idev)
 	/* Some platforms may choose to require encryption for all devices */
 	/* Note that this only matters for pre 2.1 devices as otherwise the */
 	/* device is encrypted by default by the lower layers */
-	if (classic_bonded_only || req->subclass & 0x40) {
+	if (classic_bonded_only || idev->type == BT_UHID_KEYBOARD) {
 		if (!bt_io_set(idev->intr_io, &gerr,
 					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
 					BT_IO_OPT_INVALID)) {
@@ -1156,11 +1155,73 @@ static int connection_disconnect(struct input_device *idev, uint32_t flags)
 		idev->virtual_cable_unplug = true;
 
 	if (idev->uhid)
-		return uhid_disconnect(idev);
+		return uhid_disconnect(idev, false);
 	else
 		return ioctl_disconnect(idev, flags);
 }
 
+static bool is_device_sdp_disable(const sdp_record_t *rec)
+{
+	sdp_data_t *data;
+
+	data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE);
+
+	return data && data->val.uint8;
+}
+
+static enum reconnect_mode_t hid_reconnection_mode(bool reconnect_initiate,
+						bool normally_connectable)
+{
+	if (!reconnect_initiate && !normally_connectable)
+		return RECONNECT_NONE;
+	else if (!reconnect_initiate && normally_connectable)
+		return RECONNECT_HOST;
+	else if (reconnect_initiate && !normally_connectable)
+		return RECONNECT_DEVICE;
+	else /* (reconnect_initiate && normally_connectable) */
+		return RECONNECT_ANY;
+}
+
+static void extract_hid_props(struct input_device *idev,
+					const sdp_record_t *rec)
+{
+	/* Extract HID connectability */
+	bool reconnect_initiate, normally_connectable;
+	sdp_data_t *pdlist;
+
+	/* HIDNormallyConnectable is optional and assumed FALSE if not
+	 * present.
+	 */
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_RECONNECT_INITIATE);
+	reconnect_initiate = pdlist ? pdlist->val.uint8 : TRUE;
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_NORMALLY_CONNECTABLE);
+	normally_connectable = pdlist ? pdlist->val.uint8 : FALSE;
+
+	/* Update local values */
+	idev->reconnect_mode =
+		hid_reconnection_mode(reconnect_initiate, normally_connectable);
+}
+
+static void input_device_update_rec(struct input_device *idev)
+{
+	struct btd_profile *p = btd_service_get_profile(idev->service);
+	const sdp_record_t *rec;
+
+	rec = btd_device_get_record(idev->device, p->remote_uuid);
+	if (!rec || idev->rec == rec)
+		return;
+
+	idev->rec = rec;
+	idev->disable_sdp = is_device_sdp_disable(rec);
+
+	/* Initialize device properties */
+	extract_hid_props(idev, rec);
+
+	if (idev->disable_sdp)
+		device_set_refresh_discovery(idev->device, false);
+}
+
 static int input_device_connected(struct input_device *idev)
 {
 	int err;
@@ -1168,6 +1229,9 @@ static int input_device_connected(struct input_device *idev)
 	if (idev->intr_io == NULL || idev->ctrl_io == NULL)
 		return -ENOTCONN;
 
+	/* Attempt to update SDP record if it had changed */
+	input_device_update_rec(idev);
+
 	err = hidp_add_connection(idev);
 	if (err < 0)
 		return err;
@@ -1411,74 +1475,22 @@ int input_device_disconnect(struct btd_service *service)
 	return 0;
 }
 
-static bool is_device_sdp_disable(const sdp_record_t *rec)
-{
-	sdp_data_t *data;
-
-	data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE);
-
-	return data && data->val.uint8;
-}
-
-static enum reconnect_mode_t hid_reconnection_mode(bool reconnect_initiate,
-						bool normally_connectable)
-{
-	if (!reconnect_initiate && !normally_connectable)
-		return RECONNECT_NONE;
-	else if (!reconnect_initiate && normally_connectable)
-		return RECONNECT_HOST;
-	else if (reconnect_initiate && !normally_connectable)
-		return RECONNECT_DEVICE;
-	else /* (reconnect_initiate && normally_connectable) */
-		return RECONNECT_ANY;
-}
-
-static void extract_hid_props(struct input_device *idev,
-					const sdp_record_t *rec)
-{
-	/* Extract HID connectability */
-	bool reconnect_initiate, normally_connectable;
-	sdp_data_t *pdlist;
-
-	/* HIDNormallyConnectable is optional and assumed FALSE
-	* if not present. */
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_RECONNECT_INITIATE);
-	reconnect_initiate = pdlist ? pdlist->val.uint8 : TRUE;
-
-	pdlist = sdp_data_get(rec, SDP_ATTR_HID_NORMALLY_CONNECTABLE);
-	normally_connectable = pdlist ? pdlist->val.uint8 : FALSE;
-
-	/* Update local values */
-	idev->reconnect_mode =
-		hid_reconnection_mode(reconnect_initiate, normally_connectable);
-}
-
 static struct input_device *input_device_new(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
-	struct btd_profile *p = btd_service_get_profile(service);
 	const char *path = device_get_path(device);
-	const sdp_record_t *rec = btd_device_get_record(device, p->remote_uuid);
 	struct btd_adapter *adapter = device_get_adapter(device);
 	struct input_device *idev;
 
-	if (!rec)
-		return NULL;
-
 	idev = g_new0(struct input_device, 1);
 	bacpy(&idev->src, btd_adapter_get_address(adapter));
 	bacpy(&idev->dst, device_get_address(device));
 	idev->service = btd_service_ref(service);
 	idev->device = btd_device_ref(device);
 	idev->path = g_strdup(path);
-	idev->handle = rec->handle;
-	idev->disable_sdp = is_device_sdp_disable(rec);
+	idev->type = bt_uhid_icon_to_type(btd_device_get_icon(device));
 
-	/* Initialize device properties */
-	extract_hid_props(idev, rec);
-
-	if (idev->disable_sdp)
-		device_set_refresh_discovery(device, false);
+	input_device_update_rec(idev);
 
 	return idev;
 }
@@ -1512,7 +1524,7 @@ int input_device_register(struct btd_service *service)
 	if (!idev)
 		return -EINVAL;
 
-	if (uhid_enabled) {
+	if (uhid_state) {
 		idev->uhid = bt_uhid_new_default();
 		if (!idev->uhid) {
 			error("bt_uhid_new_default: failed");
@@ -1610,7 +1622,7 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
 	if (!idev)
 		return -ENOENT;
 
-	if (uhid_enabled)
+	if (uhid_state)
 		cond |= G_IO_IN;
 
 	switch (psm) {
diff --git a/profiles/input/device.h b/profiles/input/device.h
index cf03894..7b87ce5 100644
--- a/profiles/input/device.h
+++ b/profiles/input/device.h
@@ -11,11 +11,18 @@
 #define L2CAP_PSM_HIDP_CTRL	0x11
 #define L2CAP_PSM_HIDP_INTR	0x13
 
+typedef enum {
+	UHID_DISABLED = 0,
+	UHID_ENABLED,
+	UHID_PERSIST
+} uhid_state_t;
+
 struct input_device;
 struct input_conn;
 
 void input_set_idle_timeout(int timeout);
-void input_enable_userspace_hid(bool state);
+void input_set_userspace_hid(char *state);
+uint8_t input_get_userspace_hid(void);
 void input_set_classic_bonded_only(bool state);
 bool input_get_classic_bonded_only(void);
 void input_set_auto_sec(bool state);
diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 021db38..22599f7 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -73,14 +73,13 @@ struct bt_hog {
 	uint16_t		vendor;
 	uint16_t		product;
 	uint16_t		version;
+	uint8_t			type;
 	struct gatt_db_attribute *attr;
 	struct gatt_primary	*primary;
 	GAttrib			*attrib;
 	GSList			*reports;
 	struct bt_uhid		*uhid;
 	int			uhid_fd;
-	bool			uhid_created;
-	bool			uhid_start;
 	uint64_t		uhid_flags;
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
@@ -99,7 +98,6 @@ struct bt_hog {
 	struct queue		*gatt_op;
 	struct gatt_db		*gatt_db;
 	struct gatt_db_attribute	*report_map_attr;
-	struct queue		*input;
 };
 
 struct report {
@@ -326,8 +324,6 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
 {
 	struct report *report = user_data;
 	struct bt_hog *hog = report->hog;
-	struct uhid_event ev;
-	uint8_t *buf;
 	int err;
 
 	if (len < ATT_NOTIFICATION_HEADER_SIZE) {
@@ -338,40 +334,19 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
 	pdu += ATT_NOTIFICATION_HEADER_SIZE;
 	len -= ATT_NOTIFICATION_HEADER_SIZE;
 
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_INPUT;
-	buf = ev.u.input.data;
+	err = bt_uhid_input(hog->uhid, report->numbered ? report->id : 0, pdu,
+				len);
+	if (err < 0)
+		error("bt_uhid_input: %s (%d)", strerror(-err), -err);
+}
 
-	/* BLUETOOTH SPECIFICATION Page 16 of 26
-	 * HID Service Specification
-	 *
-	 * Report ID shall be nonzero in a Report Reference characteristic
-	 * descriptor where there is more than one instance of the Report
-	 * characteristic for any given Report Type.
-	 */
-	if (report->numbered && report->id) {
-		buf[0] = report->id;
-		len = MIN(len, sizeof(ev.u.input.data) - 1);
-		memcpy(buf + 1, pdu, len);
-		ev.u.input.size = ++len;
-	} else {
-		len = MIN(len, sizeof(ev.u.input.data));
-		memcpy(buf, pdu, len);
-		ev.u.input.size = len;
-	}
-
-	/* If uhid had not sent UHID_START yet queue up the input */
-	if (!hog->uhid_created || !hog->uhid_start) {
-		if (!hog->input)
-			hog->input = queue_new();
-
-		queue_push_tail(hog->input, util_memdup(&ev, sizeof(ev)));
-		return;
-	}
+static void report_notify_destroy(void *user_data)
+{
+	struct report *report = user_data;
 
-	err = bt_uhid_send(hog->uhid, &ev);
-	if (err < 0)
-		error("bt_uhid_send: %s (%d)", strerror(-err), -err);
+	DBG("");
+
+	report->notifyid = 0;
 }
 
 static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
@@ -393,7 +368,13 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
 	report->notifyid = g_attrib_register(hog->attrib,
 					ATT_OP_HANDLE_NOTIFY,
 					report->value_handle,
-					report_value_cb, report, NULL);
+					report_value_cb, report,
+					report_notify_destroy);
+	if (!report->notifyid) {
+		error("Unable to register report notification: handle 0x%04x",
+					report->value_handle);
+		goto remove;
+	}
 
 	DBG("Report characteristic descriptor written: notifications enabled");
 
@@ -817,56 +798,48 @@ static void set_numbered(void *data, void *user_data)
 	}
 }
 
-static bool input_dequeue(const void *data, const void *match_data)
-{
-	const struct uhid_event *ev = data;
-	const struct bt_hog *hog = match_data;
-	int err;
-
-	err = bt_uhid_send(hog->uhid, ev);
-	if (err < 0) {
-		error("bt_uhid_send: %s (%d)", strerror(-err), -err);
-		return false;
-	}
-
-	return true;
-}
-
 static void start_flags(struct uhid_event *ev, void *user_data)
 {
 	struct bt_hog *hog = user_data;
 
-	hog->uhid_start = true;
 	hog->uhid_flags = ev->u.start.dev_flags;
 
 	DBG("uHID device flags: 0x%16" PRIx64, hog->uhid_flags);
 
 	if (hog->uhid_flags)
 		g_slist_foreach(hog->reports, set_numbered, hog);
-
-	queue_remove_all(hog->input, input_dequeue, hog, free);
 }
 
 static void set_report_cb(guint8 status, const guint8 *pdu,
 					guint16 plen, gpointer user_data)
 {
 	struct bt_hog *hog = user_data;
-	struct uhid_event rsp;
 	int err;
 
 	hog->setrep_att = 0;
 
-	memset(&rsp, 0, sizeof(rsp));
-	rsp.type = UHID_SET_REPORT_REPLY;
-	rsp.u.set_report_reply.id = hog->setrep_id;
-	rsp.u.set_report_reply.err = status;
-
 	if (status != 0)
 		error("Error setting Report value: %s", att_ecode2str(status));
 
-	err = bt_uhid_send(hog->uhid, &rsp);
+	err = bt_uhid_set_report_reply(hog->uhid, hog->setrep_id, status);
 	if (err < 0)
-		error("bt_uhid_send: %s", strerror(-err));
+		error("bt_uhid_set_report_reply: %s", strerror(-err));
+}
+
+static void uhid_destroy(struct bt_hog *hog, bool force)
+{
+	int err;
+
+	if (!hog->uhid)
+		return;
+
+	bt_uhid_unregister_all(hog->uhid);
+
+	err = bt_uhid_destroy(hog->uhid, force);
+	if (err < 0) {
+		error("bt_uhid_destroy: %s", strerror(-err));
+		return;
+	}
 }
 
 static void set_report(struct uhid_event *ev, void *user_data)
@@ -877,6 +850,14 @@ static void set_report(struct uhid_event *ev, void *user_data)
 	int size;
 	int err;
 
+	/* Destroy input device if there is an attempt to communicate with it
+	 * while disconnected.
+	 */
+	if (hog->attrib == NULL) {
+		uhid_destroy(hog, true);
+		return;
+	}
+
 	/* uhid never sends reqs in parallel; if there's a req, it timed out */
 	if (hog->setrep_att) {
 		g_attrib_cancel(hog->attrib, hog->setrep_att);
@@ -903,9 +884,6 @@ static void set_report(struct uhid_event *ev, void *user_data)
 	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
 				report->id, report->value_handle);
 
-	if (hog->attrib == NULL)
-		return;
-
 	hog->setrep_att = gatt_write_char(hog->attrib,
 						report->value_handle,
 						data, size, set_report_cb,
@@ -922,34 +900,16 @@ fail:
 }
 
 static void report_reply(struct bt_hog *hog, uint8_t status, uint8_t id,
-			bool numbered, uint16_t len, const uint8_t *data)
+			uint16_t len, const uint8_t *data)
 {
-	struct uhid_event rsp;
 	int err;
 
 	hog->getrep_att = 0;
 
-	memset(&rsp, 0, sizeof(rsp));
-	rsp.type = UHID_GET_REPORT_REPLY;
-	rsp.u.get_report_reply.id = hog->getrep_id;
-
-	if (status)
-		goto done;
-
-	if (numbered && len > 0) {
-		rsp.u.get_report_reply.size = len + 1;
-		rsp.u.get_report_reply.data[0] = id;
-		memcpy(&rsp.u.get_report_reply.data[1], data, len);
-	} else {
-		rsp.u.get_report_reply.size = len;
-		memcpy(rsp.u.get_report_reply.data, data, len);
-	}
-
-done:
-	rsp.u.get_report_reply.err = status;
-	err = bt_uhid_send(hog->uhid, &rsp);
+	err = bt_uhid_get_report_reply(hog->uhid, hog->getrep_id, id, status,
+					data, len);
 	if (err < 0)
-		error("bt_uhid_send: %s", strerror(-err));
+		error("bt_uhid_get_report_reply: %s", strerror(-err));
 }
 
 static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
@@ -979,7 +939,7 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
 	++pdu;
 
 exit:
-	report_reply(hog, status, report->id, report->numbered, len, pdu);
+	report_reply(hog, status, report->numbered ? report->id : 0, len, pdu);
 }
 
 static void get_report(struct uhid_event *ev, void *user_data)
@@ -988,6 +948,14 @@ static void get_report(struct uhid_event *ev, void *user_data)
 	struct report *report;
 	guint8 err;
 
+	/* Destroy input device if there is an attempt to communicate with it
+	 * while disconnected.
+	 */
+	if (hog->attrib == NULL) {
+		uhid_destroy(hog, true);
+		return;
+	}
+
 	/* uhid never sends reqs in parallel; if there's a req, it timed out */
 	if (hog->getrep_att) {
 		g_attrib_cancel(hog->attrib, hog->getrep_att);
@@ -1015,61 +983,33 @@ static void get_report(struct uhid_event *ev, void *user_data)
 
 fail:
 	/* reply with an error on failure */
-	report_reply(hog, err, 0, false, 0, NULL);
+	report_reply(hog, err, 0, 0, NULL);
 }
 
 static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
 							size_t report_map_len)
 {
 	uint8_t *value = report_map;
-	struct uhid_event ev;
 	size_t vlen = report_map_len;
-	int i, err;
+	int err;
 	GError *gerr = NULL;
-
-	if (vlen > sizeof(ev.u.create2.rd_data)) {
-		error("Report MAP too big: %zu > %zu", vlen,
-					sizeof(ev.u.create2.rd_data));
-		return;
-	}
-
-	/* create uHID device */
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_CREATE2;
+	bdaddr_t src, dst;
 
 	bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
-			BT_IO_OPT_SOURCE, ev.u.create2.phys,
-			BT_IO_OPT_DEST, ev.u.create2.uniq,
+			BT_IO_OPT_SOURCE_BDADDR, &src,
+			BT_IO_OPT_DEST_BDADDR, &dst,
 			BT_IO_OPT_INVALID);
-
 	if (gerr) {
 		error("Failed to connection details: %s", gerr->message);
 		g_error_free(gerr);
 		return;
 	}
 
-	/* Phys + uniq are the same size (hw address type) */
-	for (i = 0;
-	    i < (int)sizeof(ev.u.create2.phys) && ev.u.create2.phys[i] != 0;
-	    ++i) {
-		ev.u.create2.phys[i] = tolower(ev.u.create2.phys[i]);
-		ev.u.create2.uniq[i] = tolower(ev.u.create2.uniq[i]);
-	}
-
-	strncpy((char *) ev.u.create2.name, hog->name,
-						sizeof(ev.u.create2.name) - 1);
-	ev.u.create2.vendor = hog->vendor;
-	ev.u.create2.product = hog->product;
-	ev.u.create2.version = hog->version;
-	ev.u.create2.country = hog->bcountrycode;
-	ev.u.create2.bus = BUS_BLUETOOTH;
-	ev.u.create2.rd_size = vlen;
-
-	memcpy(ev.u.create2.rd_data, value, vlen);
-
-	err = bt_uhid_send(hog->uhid, &ev);
+	err = bt_uhid_create(hog->uhid, hog->name, &src, &dst,
+				hog->vendor, hog->product, hog->version,
+				hog->bcountrycode, hog->type, value, vlen);
 	if (err < 0) {
-		error("bt_uhid_send: %s", strerror(-err));
+		error("bt_uhid_create: %s", strerror(-err));
 		return;
 	}
 
@@ -1078,9 +1018,6 @@ static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
 	bt_uhid_register(hog->uhid, UHID_GET_REPORT, get_report, hog);
 	bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
 
-	hog->uhid_created = true;
-	hog->uhid_start = false;
-
 	DBG("HoG created uHID device");
 }
 
@@ -1131,7 +1068,8 @@ static void read_report_map(struct bt_hog *hog)
 {
 	uint16_t handle;
 
-	if (!hog->report_map_attr || hog->uhid_created || hog->report_map_id)
+	if (!hog->report_map_attr || bt_uhid_created(hog->uhid) ||
+			hog->report_map_id)
 		return;
 
 	handle = gatt_db_attribute_get_handle(hog->report_map_attr);
@@ -1298,9 +1236,9 @@ static void hog_free(void *data)
 {
 	struct bt_hog *hog = data;
 
-	bt_hog_detach(hog);
+	bt_hog_detach(hog, true);
+	uhid_destroy(hog, true);
 
-	queue_destroy(hog->input, free);
 	queue_destroy(hog->bas, (void *) bt_bas_unref);
 	g_slist_free_full(hog->instances, hog_free);
 
@@ -1318,9 +1256,9 @@ static void hog_free(void *data)
 
 struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					struct gatt_db *db)
+					uint8_t type, struct gatt_db *db)
 {
-	return bt_hog_new(-1, name, vendor, product, version, db);
+	return bt_hog_new(-1, name, vendor, product, version, type, db);
 }
 
 static void foreach_hog_report(struct gatt_db_attribute *attr, void *user_data)
@@ -1480,25 +1418,32 @@ static void foreach_hog_chrc(struct gatt_db_attribute *attr, void *user_data)
 
 static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
+					uint8_t type,
 					struct gatt_db_attribute *attr)
 {
+	struct bt_uhid *uhid;
 	struct bt_hog *hog;
 
+	if (fd < 0)
+		uhid = bt_uhid_new_default();
+	else
+		uhid = bt_uhid_new(fd);
+
+	if (!uhid) {
+		DBG("Unable to create UHID");
+		return NULL;
+	}
+
 	hog = g_try_new0(struct bt_hog, 1);
 	if (!hog)
 		return NULL;
 
 	hog->gatt_op = queue_new();
 	hog->bas = queue_new();
-
-	if (fd < 0)
-		hog->uhid = bt_uhid_new_default();
-	else
-		hog->uhid = bt_uhid_new(fd);
-
 	hog->uhid_fd = fd;
+	hog->uhid = uhid;
 
-	if (!hog->gatt_op || !hog->bas || !hog->uhid) {
+	if (!hog->gatt_op || !hog->bas) {
 		hog_free(hog);
 		return NULL;
 	}
@@ -1507,6 +1452,7 @@ static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
 	hog->vendor = vendor;
 	hog->product = product;
 	hog->version = version;
+	hog->type = type;
 	hog->attr = attr;
 
 	return hog;
@@ -1522,8 +1468,8 @@ static void hog_attach_instance(struct bt_hog *hog,
 		return;
 	}
 
-	instance = hog_new(hog->uhid_fd, hog->name, hog->vendor,
-					hog->product, hog->version, attr);
+	instance = hog_new(hog->uhid_fd, hog->name, hog->vendor, hog->product,
+				hog->version, hog->type, attr);
 	if (!instance)
 		return;
 
@@ -1559,11 +1505,11 @@ static void dis_notify(uint8_t source, uint16_t vendor, uint16_t product,
 
 struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					struct gatt_db *db)
+					uint8_t type, struct gatt_db *db)
 {
 	struct bt_hog *hog;
 
-	hog = hog_new(fd, name, vendor, product, version, NULL);
+	hog = hog_new(fd, name, vendor, product, version, type, NULL);
 	if (!hog)
 		return NULL;
 
@@ -1686,7 +1632,7 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
 
 	instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
 					hog->product, hog->version,
-					hog->gatt_db);
+					hog->type, hog->gatt_db);
 	if (!instance)
 		return;
 
@@ -1771,7 +1717,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 		bt_hog_attach(instance, gatt);
 	}
 
-	if (!hog->uhid_created) {
+	if (!bt_uhid_created(hog->uhid)) {
 		DBG("HoG discovering characteristics");
 		if (hog->attr)
 			gatt_db_service_foreach_char(hog->attr,
@@ -1783,7 +1729,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 					char_discovered_cb, hog);
 	}
 
-	if (!hog->uhid_created)
+	if (!bt_uhid_created(hog->uhid))
 		return true;
 
 	/* If UHID is already created, set up the report value handlers to
@@ -1798,48 +1744,37 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 		r->notifyid = g_attrib_register(hog->attrib,
 					ATT_OP_HANDLE_NOTIFY,
 					r->value_handle,
-					report_value_cb, r, NULL);
+					report_value_cb, r,
+					report_notify_destroy);
+		if (!r->notifyid)
+			error("Unable to register report notification: "
+				"handle 0x%04x", r->value_handle);
 	}
 
+	/* Attempt to replay get/set report messages since the driver might not
+	 * be aware the device has been disconnected in the meantime.
+	 */
+	bt_uhid_replay(hog->uhid);
+
 	return true;
 }
 
-static void uhid_destroy(struct bt_hog *hog)
+void bt_hog_detach(struct bt_hog *hog, bool force)
 {
-	int err;
-	struct uhid_event ev;
-
-	if (!hog->uhid_created)
-		return;
-
-	bt_uhid_unregister_all(hog->uhid);
-
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_DESTROY;
-
-	err = bt_uhid_send(hog->uhid, &ev);
+	GSList *l;
 
-	if (err < 0) {
-		error("bt_uhid_send: %s", strerror(-err));
+	if (!hog)
 		return;
-	}
-
-	hog->uhid_created = false;
-}
-
-void bt_hog_detach(struct bt_hog *hog)
-{
-	GSList *l;
 
 	if (!hog->attrib)
-		return;
+		goto done;
 
 	queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
 
 	for (l = hog->instances; l; l = l->next) {
 		struct bt_hog *instance = l->data;
 
-		bt_hog_detach(instance);
+		bt_hog_detach(instance, force);
 	}
 
 	for (l = hog->reports; l; l = l->next) {
@@ -1860,7 +1795,9 @@ void bt_hog_detach(struct bt_hog *hog)
 	queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);
 	g_attrib_unref(hog->attrib);
 	hog->attrib = NULL;
-	uhid_destroy(hog);
+
+done:
+	uhid_destroy(hog, force);
 }
 
 int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
diff --git a/profiles/input/hog-lib.h b/profiles/input/hog-lib.h
index a796489..41e4546 100644
--- a/profiles/input/hog-lib.h
+++ b/profiles/input/hog-lib.h
@@ -12,17 +12,17 @@ struct bt_hog;
 
 struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					struct gatt_db *db);
+					uint8_t type, struct gatt_db *db);
 
 struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					struct gatt_db *db);
+					uint8_t type, struct gatt_db *db);
 
 struct bt_hog *bt_hog_ref(struct bt_hog *hog);
 void bt_hog_unref(struct bt_hog *hog);
 
 bool bt_hog_attach(struct bt_hog *hog, void *gatt);
-void bt_hog_detach(struct bt_hog *hog);
+void bt_hog_detach(struct bt_hog *hog, bool force);
 
 int bt_hog_set_control_point(struct bt_hog *hog, bool suspend);
 int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type);
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index d50b823..017e320 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -50,6 +50,7 @@
 struct hog_device {
 	struct btd_device	*device;
 	struct bt_hog		*hog;
+	uint8_t			type;
 };
 
 static gboolean suspend_supported = FALSE;
@@ -64,7 +65,7 @@ void input_set_auto_sec(bool state)
 static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
 {
 	char name[248];
-	uint16_t vendor, product, version;
+	uint16_t vendor, product, version, type;
 
 	if (dev->hog)
 		return;
@@ -77,11 +78,12 @@ static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
 	vendor = btd_device_get_vendor(dev->device);
 	product = btd_device_get_product(dev->device);
 	version = btd_device_get_version(dev->device);
+	type = bt_uhid_icon_to_type(btd_device_get_icon(dev->device));
 
 	DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
 							product, version);
 
-	dev->hog = bt_hog_new_default(name, vendor, product, version, db);
+	dev->hog = bt_hog_new_default(name, vendor, product, version, type, db);
 }
 
 static struct hog_device *hog_device_new(struct btd_device *device)
@@ -206,7 +208,10 @@ static int hog_disconnect(struct btd_service *service)
 {
 	struct hog_device *dev = btd_service_get_user_data(service);
 
-	bt_hog_detach(dev->hog);
+	if (input_get_userspace_hid() == UHID_PERSIST)
+		bt_hog_detach(dev->hog, false);
+	else
+		bt_hog_detach(dev->hog, true);
 
 	btd_service_disconnecting_complete(service, 0);
 
diff --git a/profiles/input/input.conf b/profiles/input/input.conf
index 4c70bc5..d555d42 100644
--- a/profiles/input/input.conf
+++ b/profiles/input/input.conf
@@ -4,12 +4,17 @@
 # particular interface
 [General]
 
-# Set idle timeout (in minutes) before the connection will
-# be disconnect (defaults to 0 for no timeout)
-#IdleTimeout=30
+# Set idle timeout (in seconds) before the connection will be disconnect and
+# the input device is removed.
+# Defaults: 0 (disabled)
+#IdleTimeout=0
 
 # Enable HID protocol handling in userspace input profile
-# Defaults to false (HIDP handled in HIDP kernel module)
+# Possible values:
+#  - persist: Use UHID in persistent mode (keyboard only)
+#  - true: Use UHID instead
+#  - false: User kernel HIDP
+# Defaults to true
 #UserspaceHID=true
 
 # Limit HID connections to bonded devices
@@ -17,7 +22,7 @@
 # platforms may want to make sure that input connections only come from bonded
 # device connections. Several older mice have been known for not supporting
 # pairing/encryption.
-# Defaults to false to maximize device compatibility.
+# Defaults to true for security.
 #ClassicBondedOnly=true
 
 # LE upgrade security
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 92789a0..d1accc2 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -14,6 +14,7 @@
 
 #include <errno.h>
 #include <stdbool.h>
+#include <stdlib.h>
 
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
@@ -83,22 +84,23 @@ static int input_init(void)
 	config = load_config_file(CONFIGDIR "/input.conf");
 	if (config) {
 		int idle_timeout;
-		gboolean uhid_enabled, classic_bonded_only, auto_sec;
+		gboolean classic_bonded_only, auto_sec;
+		char *uhid_enabled;
 
 		idle_timeout = g_key_file_get_integer(config, "General",
 							"IdleTimeout", &err);
 		if (!err) {
 			DBG("input.conf: IdleTimeout=%d", idle_timeout);
-			input_set_idle_timeout(idle_timeout * 60);
+			input_set_idle_timeout(idle_timeout);
 		} else
 			g_clear_error(&err);
 
-		uhid_enabled = g_key_file_get_boolean(config, "General",
+		uhid_enabled = g_key_file_get_string(config, "General",
 							"UserspaceHID", &err);
 		if (!err) {
-			DBG("input.conf: UserspaceHID=%s", uhid_enabled ?
-							"true" : "false");
-			input_enable_userspace_hid(uhid_enabled);
+			DBG("input.conf: UserspaceHID=%s", uhid_enabled);
+			input_set_userspace_hid(uhid_enabled);
+			free(uhid_enabled);
 		} else
 			g_clear_error(&err);
 
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
deleted file mode 100644
index ea1835e..0000000
--- a/profiles/input/suspend-dummy.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012  Nordic Semiconductor Inc.
- *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include "src/log.h"
-#include "suspend.h"
-
-#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
-
-static suspend_event suspend_cb = NULL;
-static resume_event resume_cb = NULL;
-static guint watch = 0;
-
-static int fifo_open(void);
-
-static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
-{
-	char buffer[12];
-	gsize offset, left, bread;
-	GIOStatus iostatus;
-
-	if (cond & (G_IO_ERR | G_IO_HUP)) {
-		/*
-		 * Both ends needs to be open simultaneously before proceeding
-		 * any input or output operation. When the remote closes the
-		 * channel, hup signal is received on this end.
-		 */
-		fifo_open();
-		return FALSE;
-	}
-
-	offset = 0;
-	left = sizeof(buffer) - 1;
-	memset(buffer, 0, sizeof(buffer));
-
-	do {
-		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
-								&bread, NULL);
-
-		offset += bread;
-		left -= bread;
-		if (left == 0)
-			break;
-	} while (iostatus == G_IO_STATUS_NORMAL);
-
-	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
-		suspend_cb();
-	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
-		resume_cb();
-
-	return TRUE;
-}
-
-static int fifo_open(void)
-{
-	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
-	GIOChannel *fifoio;
-	int fd;
-
-	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		int err = -errno;
-		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	fifoio = g_io_channel_unix_new(fd);
-	g_io_channel_set_close_on_unref(fifoio, TRUE);
-
-	watch = g_io_add_watch(fifoio, condition, read_fifo, NULL);
-
-	g_io_channel_unref(fifoio);
-
-	return 0;
-}
-
-int suspend_init(suspend_event suspend, resume_event resume)
-{
-	struct stat st;
-	int ret;
-
-	DBG("");
-
-	suspend_cb = suspend;
-	resume_cb = resume;
-
-	if (stat(HOG_SUSPEND_FIFO, &st) == 0) {
-		if (!S_ISFIFO(st.st_mode)) {
-			error("Unexpected non-FIFO %s file", HOG_SUSPEND_FIFO);
-			return -EIO;
-		}
-
-		if (unlink(HOG_SUSPEND_FIFO) < 0) {
-			int err = -errno;
-			error("Failed to remove FIFO (%s): %s (%d)",
-				HOG_SUSPEND_FIFO, strerror(-err), -err);
-			return err;
-		}
-	}
-
-	if (mkfifo(HOG_SUSPEND_FIFO, 0600) < 0) {
-		int err = -errno;
-
-		error("Can't create FIFO (%s): %s (%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	DBG("Created suspend-dummy FIFO on %s", HOG_SUSPEND_FIFO);
-
-	ret = fifo_open();
-	if (ret < 0)
-		unlink(HOG_SUSPEND_FIFO);
-
-	return ret;
-}
-
-void suspend_exit(void)
-{
-	if (watch > 0) {
-		g_source_remove(watch);
-		watch = 0;
-	}
-
-	unlink(HOG_SUSPEND_FIFO);
-}
diff --git a/profiles/midi/midi.c b/profiles/midi/midi.c
index 40064df..bab309b 100644
--- a/profiles/midi/midi.c
+++ b/profiles/midi/midi.c
@@ -53,20 +53,21 @@ struct midi {
 	struct midi_write_parser midi_out;
 };
 
+static void foreach_cb(const struct midi_write_parser *parser, void *user_data)
+{
+	struct midi *midi = user_data;
+
+	bt_gatt_client_write_without_response(midi->client,
+						midi->midi_io_handle, false,
+						midi_write_data(parser),
+						midi_write_data_size(parser));
+}
+
 static bool midi_write_cb(struct io *io, void *user_data)
 {
 	struct midi *midi = user_data;
 	int err;
 
-	void foreach_cb(const struct midi_write_parser *parser, void *user_data) {
-		struct midi *midi = user_data;
-		bt_gatt_client_write_without_response(midi->client,
-		                                      midi->midi_io_handle,
-		                                      false,
-		                                      midi_write_data(parser),
-		                                      midi_write_data_size(parser));
-	};
-
 	do {
 		snd_seq_event_t *event = NULL;
 
@@ -81,10 +82,10 @@ static bool midi_write_cb(struct io *io, void *user_data)
 
 	if (midi_write_has_data(&midi->midi_out))
 		bt_gatt_client_write_without_response(midi->client,
-		                                      midi->midi_io_handle,
-		                                      false,
-		                                      midi_write_data(&midi->midi_out),
-		                                      midi_write_data_size(&midi->midi_out));
+					midi->midi_io_handle,
+					false,
+					midi_write_data(&midi->midi_out),
+					midi_write_data_size(&midi->midi_out));
 
 	midi_write_reset(&midi->midi_out);
 
diff --git a/src/adapter.c b/src/adapter.c
index 8fb2acd..2bb94cf 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -24,6 +24,7 @@
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <dirent.h>
+#include <limits.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -170,6 +171,7 @@ static GSList *conn_fail_list = NULL;
 
 struct link_key_info {
 	bdaddr_t bdaddr;
+	uint8_t bdaddr_type;
 	unsigned char key[16];
 	uint8_t type;
 	uint8_t pin_len;
@@ -239,6 +241,11 @@ struct btd_adapter_pin_cb_iter {
 	/* When the iterator reaches the end, it is NULL and attempt is 0 */
 };
 
+struct exp_pending {
+	struct btd_adapter *adapter;
+	unsigned int id;
+};
+
 enum {
 	ADAPTER_POWER_STATE_OFF,
 	ADAPTER_POWER_STATE_ON,
@@ -255,6 +262,7 @@ struct btd_adapter {
 
 	bdaddr_t bdaddr;		/* controller Bluetooth address */
 	uint8_t bdaddr_type;		/* address type */
+	uint8_t version;                /* controller core spec version */
 	uint32_t dev_class;		/* controller class of device */
 	char *name;			/* controller device name */
 	char *short_name;		/* controller short name */
@@ -331,6 +339,7 @@ struct btd_adapter {
 
 	bool is_default;		/* true if adapter is default one */
 
+	struct queue *exp_pending;
 	struct queue *exps;
 };
 
@@ -1340,6 +1349,10 @@ int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec)
 void adapter_service_remove(struct btd_adapter *adapter, uint32_t handle)
 {
 	sdp_record_t *rec;
+
+	if (!adapter)
+		return;
+
 	/*
 	 * If the controller does not support BR/EDR operation,
 	 * there is no point in trying to remote SDP records.
@@ -1407,8 +1420,6 @@ static void adapter_remove_device(struct btd_adapter *adapter,
 void btd_adapter_remove_device(struct btd_adapter *adapter,
 				struct btd_device *dev)
 {
-	GList *l;
-
 	adapter->connect_list = g_slist_remove(adapter->connect_list, dev);
 
 	adapter_remove_device(adapter, dev);
@@ -1422,22 +1433,7 @@ void btd_adapter_remove_device(struct btd_adapter *adapter,
 	if (adapter->connect_le == dev)
 		adapter->connect_le = NULL;
 
-	l = adapter->auths->head;
-	while (l != NULL) {
-		struct service_auth *auth = l->data;
-		GList *next = g_list_next(l);
-
-		if (auth->device != dev) {
-			l = next;
-			continue;
-		}
-
-		g_queue_delete_link(adapter->auths, l);
-		l = next;
-
-		service_auth_cancel(auth);
-	}
-
+	btd_adapter_cancel_service_auth(adapter, dev);
 	device_remove(dev, TRUE);
 }
 
@@ -1721,7 +1717,8 @@ static void discovery_cleanup(struct btd_adapter *adapter, int timeout)
 
 		next = g_slist_next(l);
 
-		if (device_is_temporary(dev) && !device_is_connectable(dev))
+		if (device_is_temporary(dev) && !device_is_connectable(dev)
+			&& !btd_device_is_connected(dev))
 			btd_adapter_remove_device(adapter, dev);
 	}
 }
@@ -2192,6 +2189,7 @@ static int merge_discovery_filters(struct btd_adapter *adapter, int *rssi,
 	bool empty_uuid = false;
 	bool has_regular_discovery = false;
 	bool has_filtered_discovery = false;
+	uint8_t adapter_scan_type = get_scan_type(adapter);
 
 	for (l = adapter->discovery_list; l != NULL; l = g_slist_next(l)) {
 		struct discovery_client *client = l->data;
@@ -2202,6 +2200,20 @@ static int merge_discovery_filters(struct btd_adapter *adapter, int *rssi,
 			continue;
 		}
 
+		/*
+		 * Detect empty filter with only discoverable
+		 * (which does not require a kernel filter) set.
+		 */
+		if (item->uuids == NULL &&
+		    item->pathloss == DISTANCE_VAL_INVALID &&
+		    item->rssi == DISTANCE_VAL_INVALID &&
+		    item->type == adapter_scan_type &&
+		    item->duplicate == false &&
+		    item->pattern == NULL) {
+			has_regular_discovery = true;
+			continue;
+		}
+
 		has_filtered_discovery = true;
 
 		*transport |= item->type;
@@ -2251,7 +2263,7 @@ static int merge_discovery_filters(struct btd_adapter *adapter, int *rssi,
 		 * It there is both regular and filtered scan running, then
 		 * clear whole fitler to report all devices.
 		 */
-		*transport = get_scan_type(adapter);
+		*transport = adapter_scan_type;
 		*rssi = HCI_RSSI_INVALID;
 		g_slist_free(*uuids);
 		*uuids = NULL;
@@ -2382,7 +2394,7 @@ static int update_discovery_filter(struct btd_adapter *adapter)
 	 * starting discovery.
 	 */
 	if (filters_equal(adapter->current_discovery_filter, sd_cp) &&
-	    adapter->discovering != 0) {
+	    adapter->discovering != false) {
 		DBG("filters were equal, deciding to not restart the scan.");
 		g_free(sd_cp);
 		return 0;
@@ -2624,10 +2636,13 @@ static bool parse_transport(DBusMessageIter *value,
 static bool parse_duplicate_data(DBusMessageIter *value,
 					struct discovery_filter *filter)
 {
+	dbus_bool_t duplicate = false;
+
 	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
 		return false;
 
-	dbus_message_iter_get_basic(value, &filter->duplicate);
+	dbus_message_iter_get_basic(value, &duplicate);
+	filter->duplicate = duplicate;
 
 	return true;
 }
@@ -2635,10 +2650,13 @@ static bool parse_duplicate_data(DBusMessageIter *value,
 static bool parse_discoverable(DBusMessageIter *value,
 					struct discovery_filter *filter)
 {
+	dbus_bool_t discoverable = false;
+
 	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
 		return false;
 
-	dbus_message_iter_get_basic(value, &filter->discoverable);
+	dbus_message_iter_get_basic(value, &discoverable);
+	filter->discoverable = discoverable;
 
 	return true;
 }
@@ -3146,6 +3164,11 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting,
 		param = &mode;
 		len = sizeof(mode);
 		break;
+	case MGMT_SETTING_CONNECTABLE:
+		opcode = MGMT_OP_SET_CONNECTABLE;
+		param = &mode;
+		len = sizeof(mode);
+		break;
 	default:
 		goto failed;
 	}
@@ -3519,6 +3542,47 @@ static gboolean property_experimental_exists(const GDBusPropertyTable *property,
 	return !queue_isempty(adapter->exps);
 }
 
+static gboolean property_get_manufacturer(const GDBusPropertyTable *property,
+					  DBusMessageIter *iter,
+					  void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	dbus_uint16_t val = adapter->manufacturer;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &val);
+
+	return TRUE;
+}
+
+static gboolean property_get_version(const GDBusPropertyTable *property,
+				     DBusMessageIter *iter, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	uint8_t val = adapter->version;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &val);
+
+	return TRUE;
+}
+
+static gboolean property_get_connectable(const GDBusPropertyTable *property,
+					 DBusMessageIter *iter, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	return property_get_mode(adapter, MGMT_SETTING_CONNECTABLE, iter);
+}
+
+static void property_set_connectable(const GDBusPropertyTable *property,
+				     DBusMessageIter *iter,
+				     GDBusPendingPropertySet id,
+				     void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	property_set_mode(adapter, MGMT_SETTING_CONNECTABLE, iter, id);
+}
+
 static DBusMessage *remove_device(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -3748,9 +3812,6 @@ static DBusMessage *connect_device(DBusConnection *conn,
 	if (!bacmp(&addr, BDADDR_ANY))
 		return btd_error_invalid_args(msg);
 
-	if (btd_adapter_find_device(adapter, &addr, addr_type))
-		return btd_error_already_exists(msg);
-
 	device_connect(adapter, &addr, addr_type, msg);
 	return NULL;
 }
@@ -3863,9 +3924,10 @@ static const GDBusPropertyTable adapter_properties[] = {
 	{ "Name", "s", property_get_name },
 	{ "Alias", "s", property_get_alias, property_set_alias },
 	{ "Class", "u", property_get_class },
+	{ "Connectable", "b", property_get_connectable,
+					property_set_connectable },
 	{ "Powered", "b", property_get_powered, property_set_powered },
-	{ "PowerState", "s", property_get_power_state, NULL, NULL,
-			     G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "PowerState", "s", property_get_power_state },
 	{ "Discoverable", "b", property_get_discoverable,
 					property_set_discoverable },
 	{ "DiscoverableTimeout", "u", property_get_discoverable_timeout,
@@ -3880,6 +3942,8 @@ static const GDBusPropertyTable adapter_properties[] = {
 	{ "Roles", "as", property_get_roles },
 	{ "ExperimentalFeatures", "as", property_get_experimental, NULL,
 					property_experimental_exists },
+	{ "Manufacturer", "q", property_get_manufacturer },
+	{ "Version", "y", property_get_version },
 	{ }
 };
 
@@ -3914,7 +3978,9 @@ static bool is_blocked_key(uint8_t key_type, uint8_t *key_value)
 	return false;
 }
 
-static struct link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
+static struct link_key_info *get_key_info(GKeyFile *key_file, const char *peer,
+					uint8_t bdaddr_type)
+
 {
 	struct link_key_info *info = NULL;
 	char *str;
@@ -3926,6 +3992,7 @@ static struct link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
 	info = g_new0(struct link_key_info, 1);
 
 	str2ba(peer, &info->bdaddr);
+	info->bdaddr_type = bdaddr_type;
 
 	if (!strncmp(str, "0x", 2))
 		str2buf(&str[2], info->key, sizeof(info->key));
@@ -4133,6 +4200,7 @@ static int generate_and_write_irk(uint8_t *irk, GKeyFile *key_file,
 
 	g_key_file_set_string(key_file, "General", "IdentityResolvingKey",
 								str_irk_out);
+	create_file(filename, S_IRUSR | S_IWUSR);
 	str = g_key_file_to_data(key_file, &length, NULL);
 	if (!g_file_set_contents(filename, str, length, &gerr)) {
 		error("Unable set contents for %s: (%s)", filename,
@@ -4292,7 +4360,7 @@ static void load_link_keys(struct btd_adapter *adapter, GSList *keys,
 		struct link_key_info *info = l->data;
 
 		bacpy(&key->addr.bdaddr, &info->bdaddr);
-		key->addr.type = BDADDR_BREDR;
+		key->addr.type = info->bdaddr_type;
 		key->type = info->type;
 		memcpy(key->val, info->key, 16);
 		key->pin_len = info->pin_len;
@@ -4387,8 +4455,8 @@ static void load_ltks(struct btd_adapter *adapter, GSList *keys)
 		if (dev) {
 			device_set_paired(dev, info->bdaddr_type);
 			device_set_bonded(dev, info->bdaddr_type);
-			device_set_ltk_enc_size(dev, info->enc_size);
-			device_set_ltk_enc_size(dev, info->enc_size);
+			device_set_ltk(dev, info->val, info->central,
+						info->enc_size);
 		}
 	}
 
@@ -4547,14 +4615,42 @@ static void load_conn_params(struct btd_adapter *adapter, GSList *params)
 		btd_error(adapter->dev_id, "Load connection parameters failed");
 }
 
-static uint8_t get_le_addr_type(GKeyFile *keyfile)
+void btd_adapter_load_conn_param(struct btd_adapter *adapter,
+				const bdaddr_t *peer, uint8_t bdaddr_type,
+				uint16_t min_interval, uint16_t max_interval,
+				uint16_t latency, uint16_t timeout)
+{
+	GSList *params = NULL;
+	struct conn_param param;
+
+	/* Only versions >= 1.23 support updating connection parameters */
+	if (MGMT_VERSION(mgmt_version, mgmt_revision) < MGMT_VERSION(1, 23))
+		return;
+
+	bacpy(&param.bdaddr, peer);
+	param.bdaddr_type = bdaddr_type;
+	param.max_interval = max_interval;
+	param.min_interval = min_interval;
+	param.latency = latency;
+	param.timeout = timeout;
+
+	params = g_slist_append(params, &param);
+	load_conn_params(adapter, params);
+	g_slist_free(params);
+}
+
+static uint8_t get_addr_type(GKeyFile *keyfile)
 {
 	uint8_t addr_type;
 	char *type;
 
+	/* The AddressType is written to file only When dev->le is
+	 * set to true, as referenced in the update_technologies().
+	 * Therefore, When type is NULL, it default to BDADDR_BREDR.
+	 */
 	type = g_key_file_get_string(keyfile, "General", "AddressType", NULL);
 	if (!type)
-		return BDADDR_LE_PUBLIC;
+		return BDADDR_BREDR;
 
 	if (g_str_equal(type, "public"))
 		addr_type = BDADDR_LE_PUBLIC;
@@ -4863,9 +4959,9 @@ static void load_devices(struct btd_adapter *adapter)
 			g_clear_error(&gerr);
 		}
 
-		key_info = get_key_info(key_file, entry->d_name);
+		bdaddr_type = get_addr_type(key_file);
 
-		bdaddr_type = get_le_addr_type(key_file);
+		key_info = get_key_info(key_file, entry->d_name, bdaddr_type);
 
 		ltk_info = get_ltk_info(key_file, entry->d_name, bdaddr_type);
 
@@ -4904,11 +5000,27 @@ static void load_devices(struct btd_adapter *adapter)
 			goto free;
 		}
 
-		if (key_info)
+		if (key_info) {
+			/* Fix up address type if it was stored with the wrong
+			 * address type since Load Link Keys are only meant to
+			 * work with BR/EDR addresses as per MGMT documentation.
+			 */
+			if (key_info->bdaddr_type != BDADDR_BREDR)
+				key_info->bdaddr_type = BDADDR_BREDR;
+
 			keys = g_slist_append(keys, key_info);
+		}
+
+		if (ltk_info) {
+			/* Fix up address type if it was stored with the wrong
+			 * address type since Load Long Term Keys are only meant
+			 * to work with LE addresses as per MGMT documentation.
+			 */
+			if (ltk_info->bdaddr_type == BDADDR_BREDR)
+				ltk_info->bdaddr_type = BDADDR_LE_PUBLIC;
 
-		if (ltk_info)
 			ltks = g_slist_append(ltks, ltk_info);
+		}
 
 		if (peripheral_ltk_info)
 			ltks = g_slist_append(ltks, peripheral_ltk_info);
@@ -5144,9 +5256,10 @@ static void adapter_remove_device(struct btd_adapter *adapter,
 
 static void adapter_add_connection(struct btd_adapter *adapter,
 						struct btd_device *device,
-						uint8_t bdaddr_type)
+						uint8_t bdaddr_type,
+						uint32_t flags)
 {
-	device_add_connection(device, bdaddr_type);
+	device_add_connection(device, bdaddr_type, flags);
 
 	if (g_slist_find(adapter->connections, device)) {
 		btd_error(adapter->dev_id,
@@ -5199,7 +5312,7 @@ static void get_connections_complete(uint8_t status, uint16_t length,
 		device = btd_adapter_get_device(adapter, &addr->bdaddr,
 								addr->type);
 		if (device)
-			adapter_add_connection(adapter, device, addr->type);
+			adapter_add_connection(adapter, device, addr->type, 0);
 	}
 }
 
@@ -5455,6 +5568,7 @@ void adapter_accept_list_remove(struct btd_adapter *adapter,
 static void set_device_privacy_complete(uint8_t status, uint16_t length,
 					 const void *param, void *user_data)
 {
+	struct btd_device *dev = user_data;
 	const struct mgmt_rp_set_device_flags *rp = param;
 
 	if (status != MGMT_STATUS_SUCCESS) {
@@ -5467,6 +5581,9 @@ static void set_device_privacy_complete(uint8_t status, uint16_t length,
 		error("Too small Set Device Flags complete event: %d", length);
 		return;
 	}
+
+	btd_device_flags_changed(dev, btd_device_get_supported_flags(dev),
+					btd_device_get_pending_flags(dev));
 }
 
 static void add_device_complete(uint8_t status, uint16_t length,
@@ -5512,7 +5629,7 @@ static void add_device_complete(uint8_t status, uint16_t length,
 			adapter_set_device_flags(adapter, dev, flags |
 						DEVICE_FLAG_DEVICE_PRIVACY,
 						set_device_privacy_complete,
-						NULL);
+						dev);
 		}
 	}
 }
@@ -5562,6 +5679,7 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
 {
 	struct mgmt_cp_set_device_flags cp;
 	uint32_t supported = btd_device_get_supported_flags(device);
+	uint32_t pending = btd_device_get_pending_flags(device);
 	const bdaddr_t *bdaddr;
 	uint8_t bdaddr_type;
 
@@ -5569,6 +5687,14 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
 				(supported | flags) != supported)
 		return;
 
+	/* Check if changing flags are pending */
+	if (flags == (flags & pending))
+		return;
+
+	/* Set Device Privacy Mode if it has not set the flag yet. */
+	if (btd_opts.device_privacy && !(flags & DEVICE_FLAG_DEVICE_PRIVACY))
+		flags |= DEVICE_FLAG_DEVICE_PRIVACY & supported & ~pending;
+
 	bdaddr = device_get_address(device);
 	bdaddr_type = btd_device_get_bdaddr_type(device);
 
@@ -5577,8 +5703,9 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
 	cp.addr.type = bdaddr_type;
 	cp.current_flags = cpu_to_le32(flags);
 
-	mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
-		  sizeof(cp), &cp, func, user_data, NULL);
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
+		  sizeof(cp), &cp, func, user_data, NULL))
+		btd_device_set_pending_flags(device, flags);
 }
 
 static void device_flags_changed_callback(uint16_t index, uint16_t length,
@@ -5741,6 +5868,16 @@ static void remove_discovery_list(struct btd_adapter *adapter)
 	adapter->discovery_list = NULL;
 }
 
+static void cancel_exp_pending(void *data)
+{
+	struct exp_pending *pending = data;
+	struct btd_adapter *adapter = pending->adapter;
+
+	pending->adapter = NULL;
+	mgmt_cancel(adapter->mgmt, pending->id);
+	g_free(pending);
+}
+
 static void adapter_free(gpointer user_data)
 {
 	struct btd_adapter *adapter = user_data;
@@ -5769,6 +5906,8 @@ static void adapter_free(gpointer user_data)
 	g_queue_free(adapter->auths);
 	queue_destroy(adapter->exps, NULL);
 
+	queue_destroy(adapter->exp_pending, cancel_exp_pending);
+
 	/*
 	 * Unregister all handlers for this specific index since
 	 * the adapter bound to them is no longer valid.
@@ -6835,6 +6974,7 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
 
 	adapter->auths = g_queue_new();
 	adapter->exps = queue_new();
+	adapter->exp_pending = queue_new();
 
 	return btd_adapter_ref(adapter);
 }
@@ -6882,6 +7022,8 @@ static void adapter_remove(struct btd_adapter *adapter)
 
 	g_slist_free(adapter->msd_callbacks);
 	adapter->msd_callbacks = NULL;
+
+	queue_remove_all(adapter->exp_pending, NULL, NULL, cancel_exp_pending);
 }
 
 const char *adapter_get_path(struct btd_adapter *adapter)
@@ -7073,12 +7215,10 @@ static bool device_is_discoverable(struct btd_adapter *adapter,
 	return discoverable;
 }
 
-void btd_adapter_update_found_device(struct btd_adapter *adapter,
+void btd_adapter_device_found(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
-					bool confirm, bool legacy,
-					bool not_connectable,
-					bool name_resolve_failed,
+					uint32_t flags,
 					const uint8_t *data, uint8_t data_len,
 					bool monitoring)
 {
@@ -7087,9 +7227,20 @@ void btd_adapter_update_found_device(struct btd_adapter *adapter,
 	struct eir_data eir_data;
 	bool name_known, discoverable;
 	char addr[18];
+	bool confirm;
+	bool legacy;
+	bool not_connectable;
+	bool name_resolve_failed;
+	bool scan_rsp;
 	bool duplicate = false;
 	struct queue *matched_monitors = NULL;
 
+	confirm = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
+	legacy = (flags & MGMT_DEV_FOUND_LEGACY_PAIRING);
+	not_connectable = (flags & MGMT_DEV_FOUND_NOT_CONNECTABLE);
+	name_resolve_failed = (flags & MGMT_DEV_FOUND_NAME_REQUEST_FAILED);
+	scan_rsp = (flags & MGMT_DEV_FOUND_SCAN_RSP);
+
 	if (!btd_adv_monitor_offload_enabled(adapter->adv_monitor_manager) ||
 				(MGMT_VERSION(mgmt_version, mgmt_revision) <
 							MGMT_VERSION(1, 22))) {
@@ -7122,7 +7273,23 @@ void btd_adapter_update_found_device(struct btd_adapter *adapter,
 
 	dev = btd_adapter_find_device(adapter, bdaddr, bdaddr_type);
 	if (!dev) {
-		if (!discoverable && !monitoring) {
+		/* In case of being just a scan response don't attempt to create
+		 * the device.
+		 */
+		if (scan_rsp) {
+			eir_data_free(&eir_data);
+			return;
+		}
+
+		/* Monitor Devices advertising Broadcast Announcements if the
+		 * adapter is capable of synchronizing to it.
+		 */
+		if (eir_get_service_data(&eir_data, BCAA_SERVICE_UUID) &&
+				btd_adapter_has_settings(adapter,
+				MGMT_SETTING_ISO_SYNC_RECEIVER))
+			monitoring = true;
+
+		if (!discoverable && !monitoring && not_connectable) {
 			eir_data_free(&eir_data);
 			return;
 		}
@@ -7169,7 +7336,7 @@ void btd_adapter_update_found_device(struct btd_adapter *adapter,
 	/* If there is no matched Adv monitors, don't continue if not
 	 * discoverable or if active discovery filter don't match.
 	 */
-	if (!monitoring && (!discoverable ||
+	if (!eir_data.rsi && !monitoring && (!discoverable ||
 		(adapter->filtered_discovery && !is_filter_match(
 				adapter->discovery_list, &eir_data, rssi)))) {
 		eir_data_free(&eir_data);
@@ -7302,10 +7469,6 @@ static void device_found_callback(uint16_t index, uint16_t length,
 	const uint8_t *eir;
 	uint16_t eir_len;
 	uint32_t flags;
-	bool confirm_name;
-	bool legacy;
-	bool not_connectable;
-	bool name_resolve_failed;
 	char addr[18];
 
 	if (length < sizeof(*ev)) {
@@ -7327,22 +7490,15 @@ static void device_found_callback(uint16_t index, uint16_t length,
 	else
 		eir = ev->eir;
 
-	flags = btohl(ev->flags);
+	flags = le32_to_cpu(ev->flags);
 
 	ba2str(&ev->addr.bdaddr, addr);
 	DBG("hci%u addr %s, rssi %d flags 0x%04x eir_len %u",
 			index, addr, ev->rssi, flags, eir_len);
 
-	confirm_name = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
-	legacy = (flags & MGMT_DEV_FOUND_LEGACY_PAIRING);
-	not_connectable = (flags & MGMT_DEV_FOUND_NOT_CONNECTABLE);
-	name_resolve_failed = (flags & MGMT_DEV_FOUND_NAME_REQUEST_FAILED);
-
-	btd_adapter_update_found_device(adapter, &ev->addr.bdaddr,
-					ev->addr.type, ev->rssi, confirm_name,
-					legacy, not_connectable,
-					name_resolve_failed, eir, eir_len,
-					false);
+	btd_adapter_device_found(adapter, &ev->addr.bdaddr,
+					ev->addr.type, ev->rssi, flags,
+					eir, eir_len, false);
 }
 
 struct agent *adapter_get_agent(struct btd_adapter *adapter)
@@ -7365,11 +7521,10 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
 
 	device_remove_connection(device, bdaddr_type, &remove_device);
 
-	if (device_is_authenticating(device))
-		device_cancel_authentication(device, TRUE);
+	device_cancel_authentication(device, TRUE);
 
 	/* If another bearer is still connected */
-	if (btd_device_is_connected(device))
+	if (btd_device_bearer_is_connected(device))
 		return;
 
 	adapter->connections = g_slist_remove(adapter->connections, device);
@@ -7432,6 +7587,12 @@ static void adapter_stop(struct btd_adapter *adapter)
 
 int btd_register_adapter_driver(struct btd_adapter_driver *driver)
 {
+	if (driver->experimental && !(g_dbus_get_flags() &
+					G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+		DBG("D-Bus experimental not enabled");
+		return -ENOTSUP;
+	}
+
 	adapter_drivers = g_slist_append(adapter_drivers, driver);
 
 	if (driver->probe == NULL)
@@ -8657,80 +8818,11 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
 		device_set_bonded(device, addr->type);
 	}
 
-	device_set_ltk_enc_size(device, ev->key.enc_size);
+	device_set_ltk(device, ev->key.val, ev->key.central, ev->key.enc_size);
 
 	bonding_complete(adapter, &addr->bdaddr, addr->type, 0);
 }
 
-static void store_csrk(struct btd_adapter *adapter, const bdaddr_t *peer,
-				uint8_t bdaddr_type, const unsigned char *key,
-				uint32_t counter, uint8_t type)
-{
-	const char *group;
-	char device_addr[18];
-	char filename[PATH_MAX];
-	GKeyFile *key_file;
-	GError *gerr = NULL;
-	char key_str[33];
-	gsize length = 0;
-	gboolean auth;
-	char *str;
-	int i;
-
-	switch (type) {
-	case 0x00:
-		group = "LocalSignatureKey";
-		auth = FALSE;
-		break;
-	case 0x01:
-		group = "RemoteSignatureKey";
-		auth = FALSE;
-		break;
-	case 0x02:
-		group = "LocalSignatureKey";
-		auth = TRUE;
-		break;
-	case 0x03:
-		group = "RemoteSignatureKey";
-		auth = TRUE;
-		break;
-	default:
-		warn("Unsupported CSRK type %u", type);
-		return;
-	}
-
-	ba2str(peer, device_addr);
-
-	create_filename(filename, PATH_MAX, "/%s/%s/info",
-			btd_adapter_get_storage_dir(adapter), device_addr);
-
-	key_file = g_key_file_new();
-	if (!g_key_file_load_from_file(key_file, filename, 0, &gerr)) {
-		error("Unable to load key file from %s: (%s)", filename,
-								gerr->message);
-		g_clear_error(&gerr);
-	}
-
-	for (i = 0; i < 16; i++)
-		sprintf(key_str + (i * 2), "%2.2X", key[i]);
-
-	g_key_file_set_string(key_file, group, "Key", key_str);
-	g_key_file_set_integer(key_file, group, "Counter", counter);
-	g_key_file_set_boolean(key_file, group, "Authenticated", auth);
-
-	create_file(filename, 0600);
-
-	str = g_key_file_to_data(key_file, &length, NULL);
-	if (!g_file_set_contents(filename, str, length, &gerr)) {
-		error("Unable set contents for %s: (%s)", filename,
-								gerr->message);
-		g_error_free(gerr);
-	}
-	g_free(str);
-
-	g_key_file_free(key_file);
-}
-
 static void new_csrk_callback(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -8758,13 +8850,7 @@ static void new_csrk_callback(uint16_t index, uint16_t length,
 		return;
 	}
 
-	if (!ev->store_hint)
-		return;
-
-	store_csrk(adapter, &key->addr.bdaddr, key->addr.type, key->val, 0,
-								key->type);
-
-	btd_device_set_temporary(device, false);
+	device_set_csrk(device, key->val, 0, key->type, ev->store_hint);
 }
 
 static void store_irk(struct btd_adapter *adapter, const bdaddr_t *peer,
@@ -8864,10 +8950,10 @@ static void new_irk_callback(uint16_t index, uint16_t length,
 	btd_device_set_temporary(device, false);
 }
 
-static void store_conn_param(struct btd_adapter *adapter, const bdaddr_t *peer,
-				uint8_t bdaddr_type, uint16_t min_interval,
-				uint16_t max_interval, uint16_t latency,
-				uint16_t timeout)
+void btd_adapter_store_conn_param(struct btd_adapter *adapter,
+				const bdaddr_t *peer, uint8_t bdaddr_type,
+				uint16_t min_interval, uint16_t max_interval,
+				uint16_t latency, uint16_t timeout)
 {
 	char device_addr[18];
 	char filename[PATH_MAX];
@@ -8947,7 +9033,7 @@ static void new_conn_param(uint16_t index, uint16_t length,
 	if (!ev->store_hint)
 		return;
 
-	store_conn_param(adapter, &ev->addr.bdaddr, ev->addr.type,
+	btd_adapter_store_conn_param(adapter, &ev->addr.bdaddr, ev->addr.type,
 					ev->min_interval, ev->max_interval,
 					ev->latency, ev->timeout);
 }
@@ -9205,10 +9291,8 @@ static int adapter_register(struct btd_adapter *adapter)
 		agent_unref(agent);
 	}
 
-	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
-		adapter->battery_provider_manager =
-			btd_battery_provider_manager_create(adapter);
-	}
+	adapter->battery_provider_manager =
+		btd_battery_provider_manager_create(adapter);
 
 	/* Don't start GATT database and advertising managers on
 	 * non-LE controllers.
@@ -9372,7 +9456,8 @@ static void connected_callback(uint16_t index, uint16_t length,
 	if (eir_data.class != 0)
 		device_set_class(device, eir_data.class);
 
-	adapter_add_connection(adapter, device, ev->addr.type);
+	adapter_add_connection(adapter, device, ev->addr.type,
+					le32_to_cpu(ev->flags));
 
 	name_known = device_name_known(device);
 
@@ -9791,10 +9876,38 @@ static bool set_blocked_keys(struct btd_adapter *adapter)
 	.func = _func, \
 }
 
+static void exp_complete(void *user_data);
+
+static bool exp_mgmt_send(struct btd_adapter *adapter, uint16_t opcode,
+			uint16_t index, uint16_t length, const void *param,
+			mgmt_request_func_t callback)
+{
+	struct exp_pending *pending;
+
+	pending = g_new0(struct exp_pending, 1);
+	pending->adapter = adapter;
+
+	if (!queue_push_tail(adapter->exp_pending, pending)) {
+		g_free(pending);
+		return false;
+	}
+
+	pending->id = mgmt_send(adapter->mgmt, opcode, index, length, param,
+					callback, pending, exp_complete);
+	if (!pending->id) {
+		queue_remove(adapter->exp_pending, pending);
+		g_free(pending);
+		return false;
+	}
+
+	return true;
+}
+
 static void set_exp_debug_complete(uint8_t status, uint16_t len,
 					const void *param, void *user_data)
 {
-	struct btd_adapter *adapter = user_data;
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
 	uint8_t action;
 
 	if (status != 0) {
@@ -9819,9 +9932,9 @@ static void exp_debug_func(struct btd_adapter *adapter, uint8_t action)
 	memcpy(cp.uuid, debug_uuid.val, 16);
 	cp.action = action;
 
-	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+	if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
 			adapter->dev_id, sizeof(cp), &cp,
-			set_exp_debug_complete, adapter, NULL) > 0)
+			set_exp_debug_complete))
 		return;
 
 	btd_error(adapter->dev_id, "Failed to set exp debug");
@@ -9844,7 +9957,8 @@ static void quality_report_func(struct btd_adapter *adapter, uint8_t action)
 static void set_rpa_resolution_complete(uint8_t status, uint16_t len,
 					const void *param, void *user_data)
 {
-	struct btd_adapter *adapter = user_data;
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
 	uint8_t action;
 
 	if (status != 0) {
@@ -9869,9 +9983,9 @@ static void rpa_resolution_func(struct btd_adapter *adapter, uint8_t action)
 	memcpy(cp.uuid, rpa_resolution_uuid.val, 16);
 	cp.action = action;
 
-	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+	if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
 			adapter->dev_id, sizeof(cp), &cp,
-			set_rpa_resolution_complete, adapter, NULL) > 0)
+			set_rpa_resolution_complete))
 		return;
 
 	btd_error(adapter->dev_id, "Failed to set RPA Resolution");
@@ -9880,7 +9994,8 @@ static void rpa_resolution_func(struct btd_adapter *adapter, uint8_t action)
 static void codec_offload_complete(uint8_t status, uint16_t len,
 					const void *param, void *user_data)
 {
-	struct btd_adapter *adapter = user_data;
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
 	uint8_t action;
 
 	if (status != 0) {
@@ -9905,9 +10020,9 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action)
 	memcpy(cp.uuid, codec_offload_uuid.val, 16);
 	cp.action = action;
 
-	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+	if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
 			adapter->dev_id, sizeof(cp), &cp,
-			codec_offload_complete, adapter, NULL) > 0)
+			codec_offload_complete))
 		return;
 
 	btd_error(adapter->dev_id, "Failed to set Codec Offload");
@@ -9916,7 +10031,8 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action)
 static void iso_socket_complete(uint8_t status, uint16_t len,
 				const void *param, void *user_data)
 {
-	struct btd_adapter *adapter = user_data;
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
 	uint8_t action;
 
 	if (status != 0) {
@@ -9941,9 +10057,9 @@ static void iso_socket_func(struct btd_adapter *adapter, uint8_t action)
 	memcpy(cp.uuid, iso_socket_uuid.val, 16);
 	cp.action = action;
 
-	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+	if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
 			MGMT_INDEX_NONE, sizeof(cp), &cp,
-			iso_socket_complete, adapter, NULL) > 0)
+			iso_socket_complete))
 		return;
 
 	btd_error(adapter->dev_id, "Failed to set ISO Socket");
@@ -9968,7 +10084,8 @@ static const struct exp_feat {
 static void read_exp_features_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
-	struct btd_adapter *adapter = user_data;
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
 	const struct mgmt_rp_read_exp_features_info *rp = param;
 	size_t feature_count = 0;
 	size_t i = 0;
@@ -10028,9 +10145,8 @@ static void read_exp_features_complete(uint8_t status, uint16_t length,
 
 static void read_exp_features(struct btd_adapter *adapter)
 {
-	if (mgmt_send(adapter->mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
-			adapter->dev_id, 0, NULL, read_exp_features_complete,
-			adapter, NULL) > 0)
+	if (exp_mgmt_send(adapter, MGMT_OP_READ_EXP_FEATURES_INFO,
+			adapter->dev_id, 0, NULL, read_exp_features_complete))
 		return;
 
 	btd_error(adapter->dev_id, "Failed to read exp features info");
@@ -10077,6 +10193,8 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	adapter->supported_settings = btohl(rp->supported_settings);
 	adapter->current_settings = btohl(rp->current_settings);
 
+	adapter->version = rp->version;
+
 	clear_uuids(adapter);
 	clear_devices(adapter);
 
@@ -10110,12 +10228,12 @@ static void read_info_complete(uint8_t status, uint16_t length,
 
 	switch (btd_opts.mode) {
 	case BT_MODE_DUAL:
-		if (missing_settings & MGMT_SETTING_SSP)
-			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
 		if (missing_settings & MGMT_SETTING_LE)
 			set_mode(adapter, MGMT_OP_SET_LE, 0x01);
 		if (missing_settings & MGMT_SETTING_BREDR)
 			set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
+		if (missing_settings & MGMT_SETTING_SSP)
+			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
 		break;
 	case BT_MODE_BREDR:
 		if (!(adapter->supported_settings & MGMT_SETTING_BREDR)) {
@@ -10124,10 +10242,10 @@ static void read_info_complete(uint8_t status, uint16_t length,
 			goto failed;
 		}
 
-		if (missing_settings & MGMT_SETTING_SSP)
-			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
 		if (missing_settings & MGMT_SETTING_BREDR)
 			set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
+		if (missing_settings & MGMT_SETTING_SSP)
+			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
 		if (adapter->current_settings & MGMT_SETTING_LE)
 			set_mode(adapter, MGMT_OP_SET_LE, 0x00);
 		break;
@@ -10146,7 +10264,11 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	}
 
 	if (missing_settings & MGMT_SETTING_SECURE_CONN)
-		set_mode(adapter, MGMT_OP_SET_SECURE_CONN, 0x01);
+		set_mode(adapter, MGMT_OP_SET_SECURE_CONN,
+					btd_opts.secure_conn);
+
+	if (missing_settings & MGMT_SETTING_WIDEBAND_SPEECH)
+		set_mode(adapter, MGMT_OP_SET_WIDEBAND_SPEECH, 0x01);
 
 	if (adapter->supported_settings & MGMT_SETTING_PRIVACY)
 		set_privacy(adapter, btd_opts.privacy);
@@ -10355,6 +10477,43 @@ static void reset_adv_monitors(uint16_t index)
 	error("Failed to reset Adv Monitors");
 }
 
+static void read_info(struct btd_adapter *adapter)
+{
+	DBG("sending read info command for index %u", adapter->dev_id);
+
+	if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, adapter->dev_id, 0, NULL,
+					read_info_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to read controller info for index %u",
+			adapter->dev_id);
+
+	adapter_list = g_list_remove(adapter_list, adapter);
+
+	btd_adapter_unref(adapter);
+}
+
+static void exp_complete(void *user_data)
+{
+	struct exp_pending *pending = user_data;
+	struct btd_adapter *adapter = pending->adapter;
+
+	if (!adapter)
+		return;  /* canceled */
+
+	queue_remove(adapter->exp_pending, pending);
+	g_free(pending);
+
+	if (queue_isempty(adapter->exp_pending)) {
+		read_info(adapter);
+		return;
+	}
+
+	DBG("index %u has %u pending MGMT EXP requests", adapter->dev_id,
+					queue_length(adapter->exp_pending));
+}
+
 static void index_added(uint16_t index, uint16_t length, const void *param,
 							void *user_data)
 {
@@ -10401,18 +10560,8 @@ static void index_added(uint16_t index, uint16_t length, const void *param,
 	 */
 	adapter_list = g_list_append(adapter_list, adapter);
 
-	DBG("sending read info command for index %u", index);
-
-	if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, index, 0, NULL,
-					read_info_complete, adapter, NULL) > 0)
-		return;
-
-	btd_error(adapter->dev_id,
-			"Failed to read controller info for index %u", index);
-
-	adapter_list = g_list_remove(adapter_list, adapter);
-
-	btd_adapter_unref(adapter);
+	if (queue_isempty(adapter->exp_pending))
+		read_info(adapter);
 }
 
 static void index_removed(uint16_t index, uint16_t length, const void *param,
@@ -10711,6 +10860,14 @@ bool btd_le_connect_before_pairing(void)
 	return false;
 }
 
+bool btd_adapter_has_settings(struct btd_adapter *adapter, uint32_t settings)
+{
+	if (!adapter)
+		return false;
+
+	return (adapter->current_settings & settings) ? true : false;
+}
+
 bool btd_has_kernel_features(uint32_t features)
 {
 	return (kernel_features & features) ? true : false;
@@ -10730,3 +10887,25 @@ bool btd_adapter_has_exp_feature(struct btd_adapter *adapter, uint32_t feature)
 
 	return false;
 }
+
+void btd_adapter_cancel_service_auth(struct btd_adapter *adapter,
+			struct btd_device *device)
+{
+	GList *l;
+
+	l = adapter->auths->head;
+	while (l != NULL) {
+		struct service_auth *auth = l->data;
+		GList *next = g_list_next(l);
+
+		if (auth->device != device) {
+			l = next;
+			continue;
+		}
+
+		g_queue_delete_link(adapter->auths, l);
+		l = next;
+
+		service_auth_cancel(auth);
+	}
+}
diff --git a/src/adapter.h b/src/adapter.h
index 78eb069..8dfbe76 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -88,14 +88,12 @@ struct btd_device *btd_adapter_find_device_by_path(struct btd_adapter *adapter,
 						   const char *path);
 struct btd_device *btd_adapter_find_device_by_fd(int fd);
 
-void btd_adapter_update_found_device(struct btd_adapter *adapter,
+void btd_adapter_device_found(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
-					bool confirm, bool legacy,
-					bool not_connectable,
-					bool name_resolve_failed,
+					uint32_t flags,
 					const uint8_t *data, uint8_t data_len,
-					bool monitored);
+					bool monitoring);
 
 const char *adapter_get_path(struct btd_adapter *adapter);
 const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter);
@@ -127,6 +125,11 @@ struct btd_adapter_driver {
 						struct btd_device *device);
 	void (*device_resolved)(struct btd_adapter *adapter,
 						struct btd_device *device);
+
+	/* Indicates the driver is experimental and shall only be registered
+	 * when experimental has been enabled (see: main.conf:Experimental).
+	 */
+	bool experimental;
 };
 
 void device_resolved_drivers(struct btd_adapter *adapter,
@@ -256,6 +259,8 @@ void btd_adapter_for_each_device(struct btd_adapter *adapter,
 
 bool btd_le_connect_before_pairing(void);
 
+bool btd_adapter_has_settings(struct btd_adapter *adapter, uint32_t settings);
+
 enum experimental_features {
 	EXP_FEAT_DEBUG			= 1 << 0,
 	EXP_FEAT_LE_SIMULT_ROLES	= 1 << 1,
@@ -283,3 +288,15 @@ bool btd_adapter_set_allowed_uuids(struct btd_adapter *adapter,
 							struct queue *uuids);
 bool btd_adapter_is_uuid_allowed(struct btd_adapter *adapter,
 							const char *uuid_str);
+
+void btd_adapter_load_conn_param(struct btd_adapter *adapter,
+				const bdaddr_t *peer, uint8_t bdaddr_type,
+				uint16_t min_interval, uint16_t max_interval,
+				uint16_t latency, uint16_t timeout);
+
+void btd_adapter_store_conn_param(struct btd_adapter *adapter,
+				const bdaddr_t *peer, uint8_t bdaddr_type,
+				uint16_t min_interval, uint16_t max_interval,
+				uint16_t latency, uint16_t timeout);
+void btd_adapter_cancel_service_auth(struct btd_adapter *adapter,
+				struct btd_device *device);
diff --git a/src/adv_monitor.c b/src/adv_monitor.c
index 33f4d96..cb38916 100644
--- a/src/adv_monitor.c
+++ b/src/adv_monitor.c
@@ -1583,10 +1583,6 @@ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
 	const uint8_t *ad_data = NULL;
 	uint16_t ad_data_len;
 	uint32_t flags;
-	bool confirm_name;
-	bool legacy;
-	bool not_connectable;
-	bool name_resolve_failed;
 	char addr[18];
 
 	if (length < sizeof(*ev)) {
@@ -1605,21 +1601,14 @@ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
 	if (ad_data_len > 0)
 		ad_data = ev->ad_data;
 
-	flags = btohl(ev->flags);
+	flags = le32_to_cpu(ev->flags);
 
 	ba2str(&ev->addr.bdaddr, addr);
 	DBG("hci%u addr %s, rssi %d flags 0x%04x ad_data_len %u",
 			index, addr, ev->rssi, flags, ad_data_len);
 
-	confirm_name = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
-	legacy = (flags & MGMT_DEV_FOUND_LEGACY_PAIRING);
-	not_connectable = (flags & MGMT_DEV_FOUND_NOT_CONNECTABLE);
-	name_resolve_failed = (flags & MGMT_DEV_FOUND_NAME_REQUEST_FAILED);
-
-	btd_adapter_update_found_device(adapter, &ev->addr.bdaddr,
-					ev->addr.type, ev->rssi, confirm_name,
-					legacy, not_connectable,
-					name_resolve_failed, ad_data,
+	btd_adapter_device_found(adapter, &ev->addr.bdaddr,
+					ev->addr.type, ev->rssi, flags, ad_data,
 					ad_data_len, true);
 
 	if (handle) {
diff --git a/src/advertising.c b/src/advertising.c
index f9748b1..bd121e5 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -29,11 +29,13 @@
 #include "error.h"
 #include "log.h"
 #include "eir.h"
+#include "btd.h"
 #include "src/shared/ad.h"
 #include "src/shared/mgmt.h"
 #include "src/shared/queue.h"
 #include "src/shared/timeout.h"
 #include "src/shared/util.h"
+#include "src/shared/crypto.h"
 #include "advertising.h"
 
 #define LE_ADVERTISING_MGR_IFACE "org.bluez.LEAdvertisingManager1"
@@ -459,13 +461,50 @@ fail:
 	return false;
 }
 
+static bool set_rsi(struct btd_adv_client *client)
+{
+	struct bt_crypto *crypto;
+	uint8_t zero[16] = {};
+	struct bt_ad_data rsi = { .type = BT_AD_CSIP_RSI };
+	uint8_t data[6];
+	bool ret;
+
+	/* Check if a valid SIRK has been set */
+	if (!memcmp(btd_opts.csis.sirk, zero, sizeof(zero)))
+		return false;
+
+	/* Check if RSI needs to be set or data already contains RSI data */
+	if (!client || bt_ad_has_data(client->data, &rsi))
+		return true;
+
+	crypto = bt_crypto_new();
+	if (!crypto)
+		return false;
+
+	ret = bt_crypto_random_bytes(crypto, data + 3, sizeof(data) - 3);
+	if (!ret)
+		goto done;
+
+	ret = bt_crypto_sih(crypto, btd_opts.csis.sirk, data + 3, data);
+	if (!ret)
+		goto done;
+
+	ret = bt_ad_add_data(client->data, BT_AD_CSIP_RSI, data, sizeof(data));
+
+done:
+	bt_crypto_unref(crypto);
+	return ret;
+}
+
 static struct adv_include {
 	uint8_t flag;
 	const char *name;
+	bool (*set)(struct btd_adv_client *client);
 } includes[] = {
 	{ MGMT_ADV_FLAG_TX_POWER, "tx-power" },
 	{ MGMT_ADV_FLAG_APPEARANCE, "appearance" },
 	{ MGMT_ADV_FLAG_LOCAL_NAME, "local-name" },
+	{ 0 , "rsi", set_rsi },
 	{ },
 };
 
@@ -497,6 +536,11 @@ static bool parse_includes(DBusMessageIter *iter,
 			if (strcmp(str, inc->name))
 				continue;
 
+			if (inc->set && inc->set(client)) {
+				DBG("Including Feature: %s", str);
+				continue;
+			}
+
 			if (!(client->manager->supported_flags & inc->flag))
 				continue;
 
@@ -683,11 +727,6 @@ fail:
 
 static bool set_flags(struct btd_adv_client *client, uint8_t flags)
 {
-	if (!flags) {
-		bt_ad_clear_flags(client->data);
-		return true;
-	}
-
 	/* Set BR/EDR Not Supported for LE only */
 	if (!btd_adapter_get_bredr(client->manager->adapter))
 		flags |= BT_AD_FLAG_NO_BREDR;
@@ -695,8 +734,7 @@ static bool set_flags(struct btd_adv_client *client, uint8_t flags)
 	/* Set BR/EDR Not Supported if adapter is not discoverable but the
 	 * instance is.
 	 */
-	if ((flags & (BT_AD_FLAG_GENERAL | BT_AD_FLAG_LIMITED)) &&
-			!btd_adapter_get_discoverable(client->manager->adapter))
+	if (!btd_adapter_get_discoverable(client->manager->adapter))
 		flags |= BT_AD_FLAG_NO_BREDR;
 
 	if (!bt_ad_add_flags(client->data, &flags, 1))
@@ -845,12 +883,18 @@ static int get_adv_flags(struct btd_adv_client *client)
 
 	flags |= client->flags;
 
+	/* Detect if the length is bigger that legacy and secondary is not set
+	 * then force it to be set to ensure the kernel uses EA.
+	 */
+	if (bt_ad_length(client->data) > BT_AD_MAX_DATA_LEN &&
+			!(flags & MGMT_ADV_FLAG_SEC_MASK))
+		flags |= MGMT_ADV_FLAG_SEC_1M;
+
 	return flags;
 }
 
 static int refresh_legacy_adv(struct btd_adv_client *client,
-				mgmt_request_func_t func,
-				unsigned int *mgmt_id)
+				mgmt_request_func_t func)
 {
 	struct mgmt_cp_add_advertising *cp;
 	uint8_t param_len;
@@ -895,7 +939,9 @@ static int refresh_legacy_adv(struct btd_adv_client *client,
 	cp->adv_data_len = adv_data_len;
 	cp->scan_rsp_len = scan_rsp_len;
 	memcpy(cp->data, adv_data, adv_data_len);
-	memcpy(cp->data + adv_data_len, scan_rsp, scan_rsp_len);
+
+	if (scan_rsp)
+		memcpy(cp->data + adv_data_len, scan_rsp, scan_rsp_len);
 
 	free(adv_data);
 	free(scan_rsp);
@@ -909,8 +955,8 @@ static int refresh_legacy_adv(struct btd_adv_client *client,
 		free(cp);
 		return -EINVAL;
 	}
-	if (mgmt_id)
-		*mgmt_id = mgmt_ret;
+	if (func)
+		client->add_adv_id = mgmt_ret;
 
 	free(cp);
 
@@ -921,7 +967,7 @@ static void add_adv_params_callback(uint8_t status, uint16_t length,
 				    const void *param, void *user_data);
 
 static int refresh_extended_adv(struct btd_adv_client *client,
-				mgmt_request_func_t func, unsigned int *mgmt_id)
+				mgmt_request_func_t func)
 {
 	struct mgmt_cp_add_ext_adv_params cp;
 	uint32_t flags = 0;
@@ -974,21 +1020,18 @@ static int refresh_extended_adv(struct btd_adv_client *client,
 
 	/* Store callback, called after we set advertising data */
 	client->refresh_done_func = func;
-
-	if (mgmt_id)
-		*mgmt_id = mgmt_ret;
-
+	client->add_adv_id = mgmt_ret;
 
 	return 0;
 }
 
 static int refresh_advertisement(struct btd_adv_client *client,
-			mgmt_request_func_t func, unsigned int *mgmt_id)
+					mgmt_request_func_t func)
 {
 	if (client->manager->extended_add_cmds)
-		return refresh_extended_adv(client, func, mgmt_id);
+		return refresh_extended_adv(client, func);
 
-	return refresh_legacy_adv(client, func, mgmt_id);
+	return refresh_legacy_adv(client, func);
 }
 
 static bool client_discoverable_timeout(void *user_data)
@@ -1001,7 +1044,7 @@ static bool client_discoverable_timeout(void *user_data)
 
 	bt_ad_clear_flags(client->data);
 
-	refresh_advertisement(client, NULL, NULL);
+	refresh_advertisement(client, NULL);
 
 	return FALSE;
 }
@@ -1024,7 +1067,9 @@ static bool parse_discoverable_timeout(DBusMessageIter *iter,
 	if (client->disc_to_id)
 		timeout_remove(client->disc_to_id);
 
-	client->disc_to_id = timeout_add_seconds(client->discoverable_to,
+	if (client->discoverable_to > 0)
+		client->disc_to_id = timeout_add_seconds(
+						client->discoverable_to,
 						client_discoverable_timeout,
 						client, NULL);
 
@@ -1083,10 +1128,6 @@ static bool parse_min_interval(DBusMessageIter *iter,
 {
 	uint32_t min_interval_ms;
 
-	/* Only consider this property if experimental setting is applied */
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL))
-		return true;
-
 	if (!iter) {
 		client->min_interval = 0;
 		return false;
@@ -1116,10 +1157,6 @@ static bool parse_max_interval(DBusMessageIter *iter,
 {
 	uint32_t max_interval_ms;
 
-	/* Only consider this property if experimental setting is applied */
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL))
-		return true;
-
 	if (!iter) {
 		client->max_interval = 0;
 		return false;
@@ -1149,10 +1186,6 @@ static bool parse_tx_power(DBusMessageIter *iter,
 {
 	int16_t val;
 
-	/* Only consider this property if experimental setting is applied */
-	if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL))
-		return true;
-
 	if (!iter) {
 		client->tx_power = ADV_TX_POWER_NO_PREFERENCE;
 		return false;
@@ -1209,7 +1242,7 @@ static void properties_changed(GDBusProxy *proxy, const char *name,
 			continue;
 
 		if (parser->func(iter, client)) {
-			refresh_advertisement(client, NULL, NULL);
+			refresh_advertisement(client, NULL);
 
 			break;
 		}
@@ -1220,9 +1253,18 @@ static void add_client_complete(struct btd_adv_client *client, uint8_t status)
 {
 	DBusMessage *reply;
 
-	if (status) {
+	if (status)
 		error("Failed to add advertisement: %s (0x%02x)",
 						mgmt_errstr(status), status);
+
+	/* If the advertising request was not started by a direct call from
+	 * the client, but rather by a refresh due to properties update or
+	 * our internal timer, there is nothing to reply to.
+	 */
+	if (!client->reg)
+		return;
+
+	if (status) {
 		reply = btd_error_failed(client->reg,
 					"Failed to register advertisement");
 		queue_remove(client->manager->clients, client);
@@ -1288,6 +1330,8 @@ static void add_adv_params_callback(uint8_t status, uint16_t length,
 	unsigned int mgmt_ret;
 	dbus_int16_t tx_power;
 
+	client->add_adv_id = 0;
+
 	if (status)
 		goto fail;
 
@@ -1350,6 +1394,9 @@ static void add_adv_params_callback(uint8_t status, uint16_t length,
 			     client->manager->mgmt_index, param_len, cp,
 			     client->refresh_done_func, client, NULL);
 
+	if (mgmt_ret && client->refresh_done_func)
+		client->add_adv_id = mgmt_ret;
+
 	/* Clear the callback */
 	client->refresh_done_func = NULL;
 
@@ -1358,9 +1405,6 @@ static void add_adv_params_callback(uint8_t status, uint16_t length,
 		goto fail;
 	}
 
-	if (client->add_adv_id)
-		client->add_adv_id = mgmt_ret;
-
 	free(cp);
 	cp = NULL;
 
@@ -1401,7 +1445,8 @@ static DBusMessage *parse_advertisement(struct btd_adv_client *client)
 		}
 	}
 
-	if (bt_ad_has_flags(client->data)) {
+	if (bt_ad_get_flags(client->data) &
+			(BT_AD_FLAG_GENERAL | BT_AD_FLAG_LIMITED)) {
 		/* BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part C
 		 * page 2042:
 		 * A device in the broadcast mode shall not set the
@@ -1441,8 +1486,7 @@ static DBusMessage *parse_advertisement(struct btd_adv_client *client)
 		goto fail;
 	}
 
-	err = refresh_advertisement(client, add_adv_callback,
-					&client->add_adv_id);
+	err = refresh_advertisement(client, add_adv_callback);
 
 	if (!err)
 		return NULL;
@@ -1512,10 +1556,14 @@ static struct btd_adv_client *client_create(struct btd_adv_manager *manager,
 	if (!client->data)
 		goto fail;
 
+	bt_ad_set_max_len(client->data, manager->max_adv_len);
+
 	client->scan = bt_ad_new();
 	if (!client->scan)
 		goto fail;
 
+	bt_ad_set_max_len(client->scan, manager->max_scan_rsp_len);
+
 	client->manager = manager;
 	client->appearance = UINT16_MAX;
 	client->tx_power = ADV_TX_POWER_NO_PREFERENCE;
@@ -1644,7 +1692,8 @@ static void append_include(struct btd_adv_manager *manager,
 	struct adv_include *inc;
 
 	for (inc = includes; inc && inc->name; inc++) {
-		if (manager->supported_flags & inc->flag)
+		if ((inc->set && inc->set(NULL)) ||
+				(manager->supported_flags & inc->flag))
 			dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
 								&inc->name);
 	}
@@ -1779,10 +1828,8 @@ static const GDBusPropertyTable properties[] = {
 	{ "SupportedIncludes", "as", get_supported_includes, NULL, NULL },
 	{ "SupportedSecondaryChannels", "as", get_supported_secondary, NULL,
 							secondary_exists },
-	{ "SupportedFeatures", "as", get_supported_features, NULL, NULL,
-					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
-	{ "SupportedCapabilities", "a{sv}", get_supported_cap, NULL, NULL,
-					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
+	{ "SupportedFeatures", "as", get_supported_features, NULL, NULL },
+	{ "SupportedCapabilities", "a{sv}", get_supported_cap, NULL, NULL },
 	{ }
 };
 
@@ -1844,6 +1891,19 @@ static void read_adv_features_callback(uint8_t status, uint16_t length,
 	/* Reset existing instances */
 	if (feat->num_instances)
 		remove_advertising(manager, 0);
+
+	/* Emit property update */
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+		adapter_get_path(manager->adapter),
+		LE_ADVERTISING_MGR_IFACE, "SupportedFeatures");
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+		adapter_get_path(manager->adapter),
+		LE_ADVERTISING_MGR_IFACE, "SupportedIncludes");
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+		adapter_get_path(manager->adapter),
+		LE_ADVERTISING_MGR_IFACE, "SupportedSecondaryChannels");
 }
 
 static void read_controller_cap_complete(uint8_t status, uint16_t length,
@@ -1923,8 +1983,7 @@ static struct btd_adv_manager *manager_create(struct btd_adapter *adapter,
 	/* Query controller capabilities. This will be used to display valid
 	 * advertising tx power range to the client.
 	 */
-	if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL &&
-			btd_has_kernel_features(KERNEL_HAS_CONTROLLER_CAP_CMD))
+	if (btd_has_kernel_features(KERNEL_HAS_CONTROLLER_CAP_CMD))
 		mgmt_send(manager->mgmt, MGMT_OP_READ_CONTROLLER_CAP,
 			manager->mgmt_index, 0, NULL,
 			read_controller_cap_complete, manager, NULL);
@@ -1970,7 +2029,7 @@ static void manager_refresh(void *data, void *user_data)
 {
 	struct btd_adv_client *client = data;
 
-	refresh_advertisement(client, user_data, NULL);
+	refresh_advertisement(client, NULL);
 }
 
 void btd_adv_manager_refresh(struct btd_adv_manager *manager)
diff --git a/src/battery.c b/src/battery.c
index 88a53e8..59e4fc5 100644
--- a/src/battery.c
+++ b/src/battery.c
@@ -152,8 +152,7 @@ static gboolean property_source_exists(const GDBusPropertyTable *property,
 static const GDBusPropertyTable battery_properties[] = {
 	{ "Percentage", "y", property_percentage_get, NULL,
 	  property_percentage_exists },
-	{ "Source", "s", property_source_get, NULL, property_source_exists,
-	  G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Source", "s", property_source_get, NULL, property_source_exists },
 	{}
 };
 
@@ -288,6 +287,10 @@ static void provided_battery_added_cb(GDBusProxy *proxy, void *user_data)
 	uint8_t percentage;
 	DBusMessageIter iter;
 
+	if (strcmp(g_dbus_proxy_get_interface(proxy),
+		   BATTERY_PROVIDER_INTERFACE) != 0)
+		return;
+
 	if (g_dbus_proxy_get_property(proxy, "Device", &iter) == FALSE) {
 		warn("Battery object %s does not specify device path", path);
 		return;
@@ -295,10 +298,6 @@ static void provided_battery_added_cb(GDBusProxy *proxy, void *user_data)
 
 	dbus_message_iter_get_basic(&iter, &export_path);
 
-	if (strcmp(g_dbus_proxy_get_interface(proxy),
-		   BATTERY_PROVIDER_INTERFACE) != 0)
-		return;
-
 	device = btd_adapter_find_device_by_path(provider->manager->adapter,
 						 export_path);
 	if (!device || device_is_temporary(device)) {
@@ -341,15 +340,15 @@ static void provided_battery_removed_cb(GDBusProxy *proxy, void *user_data)
 	const char *export_path;
 	DBusMessageIter iter;
 
+	if (strcmp(g_dbus_proxy_get_interface(proxy),
+		   BATTERY_PROVIDER_INTERFACE) != 0)
+		return;
+
 	if (g_dbus_proxy_get_property(proxy, "Device", &iter) == FALSE)
 		return;
 
 	dbus_message_iter_get_basic(&iter, &export_path);
 
-	if (strcmp(g_dbus_proxy_get_interface(proxy),
-		   BATTERY_PROVIDER_INTERFACE) != 0)
-		return;
-
 	DBG("provided battery removed %s", g_dbus_proxy_get_path(proxy));
 
 	battery = find_battery_by_path(export_path);
@@ -523,10 +522,10 @@ static DBusMessage *unregister_battery_provider(DBusConnection *conn,
 }
 
 static const GDBusMethodTable methods[] = {
-	{ GDBUS_EXPERIMENTAL_METHOD("RegisterBatteryProvider",
+	{ GDBUS_METHOD("RegisterBatteryProvider",
 				    GDBUS_ARGS({ "provider", "o" }), NULL,
 				    register_battery_provider) },
-	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterBatteryProvider",
+	{ GDBUS_METHOD("UnregisterBatteryProvider",
 				    GDBUS_ARGS({ "provider", "o" }), NULL,
 				    unregister_battery_provider) },
 	{}
diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in
index beb98ce..8ebe89b 100644
--- a/src/bluetooth.service.in
+++ b/src/bluetooth.service.in
@@ -6,7 +6,7 @@ ConditionPathIsDirectory=/sys/class/bluetooth
 [Service]
 Type=dbus
 BusName=org.bluez
-ExecStart=@pkglibexecdir@/bluetoothd
+ExecStart=@PKGLIBEXECDIR@/bluetoothd
 NotifyAccess=main
 #WatchdogSec=10
 #Restart=on-failure
diff --git a/src/bluetooth.ver b/src/bluetooth.ver
index 214fa8a..a96fda2 100644
--- a/src/bluetooth.ver
+++ b/src/bluetooth.ver
@@ -7,6 +7,14 @@
 		debug;
 		baswap;
 		ba2str;
+		/* Don't break LLVM sanitizers */
+		__asan*;
+		__dfsan*;
+		__lsan*;
+		__msan*;
+		__sanitizer*;
+		__tsan*;
+		__ubsan*;
 	local:
 		*;
 };
diff --git a/src/bluetoothd.8 b/src/bluetoothd.8
new file mode 100644
index 0000000..2b37a8d
--- /dev/null
+++ b/src/bluetoothd.8
@@ -0,0 +1,120 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BLUETOOTHD" "8" "March, 2004" "BlueZ" "System management commands"
+.SH NAME
+bluetoothd \- Bluetooth daemon
+.SH SYNOPSIS
+.sp
+\fBbluetoothd\fP [\-\-version] | [\-\-help]
+.sp
+\fBbluetoothd\fP  [\-\-nodetach]  [\-\-compat] [\-\-experimental] [\-\-debug=<\fIfiles\fP>]
+[\-\-plugin=<\fIplugins\fP>] [\-\-noplugin=<\fIplugins\fP>]
+.SH DESCRIPTION
+.sp
+This manual page documents briefly the \fBbluetoothd\fP daemon, which manages
+all the Bluetooth devices. \fBbluetoothd\fP can also provide a number of services
+via the D\-Bus message bus system.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-v\fP,\fB  \-\-version
+Print bluetoothd version and exit.
+.TP
+.B  \-h\fP,\fB  \-\-help
+Print bluetoothd options and exit.
+.TP
+.B  \-n\fP,\fB  \-\-nodetach
+Enable logging in foreground. Directs log output to the
+controlling terminal in addition to syslog.
+.TP
+.B  \-f\fP,\fB  \-\-configfile
+Specifies an explicit config file path instead of relying
+on the default path(\fI/usr/local/etc/bluetooth/main.conf\fP)
+for the config file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-d, \-\-debug=<file1>:<file2>:...
+Sets how much information bluetoothd sends to the log destination (usually
+syslog\(aqs \(dqdaemon\(dq facility). If the file options are omitted, then
+debugging information from all the source files are printed. If file
+options are present, then only debug prints from that source file are
+printed. The option can be a pattern containing \(dq*\(dq and \(dq?\(dq characters.
+.sp
+Example: \-\-debug=src/adapter.c:src/agent.c
+.TP
+.B \-p, \-\-plugin=<plugin1>,<plugin2>,..
+Load these plugins only. The option can be a pattern containing  \(dq*\(dq and
+\(dq?\(dq characters.
+.TP
+.B \-P, \-\-noplugin=<plugin1>,<plugin2>,..
+Never load these plugins. The option can be a pattern containing \(dq*\(dq and
+\(dq?\(dq  characters.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B  \-C\fP,\fB  \-\-compat
+Provide deprecated command line interfaces.
+.TP
+.B  \-E\fP,\fB  \-\-experimental
+Enable D\-Bus experimental interfaces.
+These interfaces are not guaranteed to be compatible or present in future
+releases.
+.TP
+.B  \-T\fP,\fB  \-\-testing
+Enable D\-Bus testing interfaces.
+These interfaces are only meant for test validation of the internals of
+bluetoothd and shall not never be used by anything other than that.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-K, \-\-kernel=<uuid1>,<uuid2>,...
+Enable Kernel experimental features. Kernel experimental features are
+considered unstable and may be removed from future kernel releases.
+.UNINDENT
+.SH FILES
+.INDENT 0.0
+.TP
+.B \fI/usr/local/etc/bluetooth/main.conf\fP
+Location of the global configuration file.
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann, Philipp Matthias Hahn, Fredrik Noring
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/src/bluetoothd.rst b/src/bluetoothd.rst
new file mode 100644
index 0000000..d507cfa
--- /dev/null
+++ b/src/bluetoothd.rst
@@ -0,0 +1,93 @@
+==========
+bluetoothd
+==========
+
+----------------
+Bluetooth daemon
+----------------
+
+:Authors: - Marcel Holtmann
+          - Philipp Matthias Hahn
+          - Fredrik Noring
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: March, 2004
+:Manual section: 8
+:Manual group: System management commands
+
+SYNOPSIS
+========
+
+**bluetoothd** [--version] | [--help]
+
+**bluetoothd**  [--nodetach]  [--compat] [--experimental] [--debug=<*files*>]
+[--plugin=<*plugins*>] [--noplugin=<*plugins*>]
+
+DESCRIPTION
+===========
+
+This manual page documents briefly the **bluetoothd** daemon, which manages
+all the Bluetooth devices. **bluetoothd** can also provide a number of services
+via the D-Bus message bus system.
+
+OPTIONS
+=======
+
+-v, --version       Print bluetoothd version and exit.
+
+-h, --help          Print bluetoothd options and exit.
+
+-n, --nodetach      Enable logging in foreground. Directs log output to the
+                    controlling terminal in addition to syslog.
+
+-f, --configfile    Specifies an explicit config file path instead of relying
+                    on the default path(*/usr/local/etc/bluetooth/main.conf*)
+                    for the config file.
+
+-d, --debug=<file1>:<file2>:...
+    Sets how much information bluetoothd sends to the log destination (usually
+    syslog's "daemon" facility). If the file options are omitted, then
+    debugging information from all the source files are printed. If file
+    options are present, then only debug prints from that source file are
+    printed. The option can be a pattern containing "*" and "?" characters.
+
+    Example: --debug=src/adapter.c:src/agent.c
+
+-p, --plugin=<plugin1>,<plugin2>,..
+    Load these plugins only. The option can be a pattern containing  "*" and
+    "?" characters.
+
+-P, --noplugin=<plugin1>,<plugin2>,..
+    Never load these plugins. The option can be a pattern containing "*" and
+    "?"  characters.
+
+-C, --compat        Provide deprecated command line interfaces.
+
+-E, --experimental  Enable D-Bus experimental interfaces.
+    These interfaces are not guaranteed to be compatible or present in future
+    releases.
+
+-T, --testing  Enable D-Bus testing interfaces.
+    These interfaces are only meant for test validation of the internals of
+    bluetoothd and shall not never be used by anything other than that.
+
+-K, --kernel=<uuid1>,<uuid2>,...
+    Enable Kernel experimental features. Kernel experimental features are
+    considered unstable and may be removed from future kernel releases.
+
+FILES
+=====
+
+*/usr/local/etc/bluetooth/main.conf*
+    Location of the global configuration file.
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/src/bluetoothd.rst.in b/src/bluetoothd.rst.in
index 7a0fa1b..0b998f6 100644
--- a/src/bluetoothd.rst.in
+++ b/src/bluetoothd.rst.in
@@ -64,8 +64,13 @@ OPTIONS
 
 -C, --compat        Provide deprecated command line interfaces.
 
--E, --experimental  Enable experimental interfaces. Those interfaces are not
-                    guaranteed to be compatible or present in future releases.
+-E, --experimental  Enable D-Bus experimental interfaces.
+    These interfaces are not guaranteed to be compatible or present in future
+    releases.
+
+-T, --testing  Enable D-Bus testing interfaces.
+    These interfaces are only meant for test validation of the internals of
+    bluetoothd and shall not never be used by anything other than that.
 
 -K, --kernel=<uuid1>,<uuid2>,...
     Enable Kernel experimental features. Kernel experimental features are
diff --git a/src/btd.h b/src/btd.h
index 63be6d8..07205aa 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -36,6 +36,12 @@ enum mps_mode_t {
 	MPS_MULTIPLE,
 };
 
+enum sc_mode_t {
+	SC_OFF,
+	SC_ON,
+	SC_ONLY,
+};
+
 struct btd_br_defaults {
 	uint16_t	page_scan_type;
 	uint16_t	page_scan_interval;
@@ -86,11 +92,23 @@ struct btd_defaults {
 	struct btd_le_defaults le;
 };
 
+struct btd_csis {
+	bool    encrypt;
+	uint8_t sirk[16];
+	uint8_t size;
+	uint8_t rank;
+};
+
 struct btd_avdtp_opts {
 	uint8_t  session_mode;
 	uint8_t  stream_mode;
 };
 
+struct btd_avrcp_opts {
+	bool		volume_without_target;
+	bool		volume_category;
+};
+
 struct btd_advmon_opts {
 	uint8_t		rssi_sampling_period;
 };
@@ -98,22 +116,24 @@ struct btd_advmon_opts {
 struct btd_opts {
 	char		*name;
 	uint32_t	class;
-	gboolean	pairable;
+	bool		pairable;
 	uint32_t	pairto;
 	uint32_t	discovto;
 	uint32_t	tmpto;
 	uint8_t		privacy;
 	bool		device_privacy;
 	uint32_t	name_request_retry_delay;
+	uint8_t		secure_conn;
 
 	struct btd_defaults defaults;
 
-	gboolean	reverse_discovery;
-	gboolean	name_resolv;
-	gboolean	debug_keys;
-	gboolean	fast_conn;
-	gboolean	refresh_discovery;
-	gboolean	experimental;
+	bool		reverse_discovery;
+	bool		name_resolv;
+	bool		debug_keys;
+	bool		fast_conn;
+	bool		refresh_discovery;
+	bool		experimental;
+	bool		testing;
 	struct queue	*kernel;
 
 	uint16_t	did_source;
@@ -126,20 +146,24 @@ struct btd_opts {
 	bt_gatt_cache_t gatt_cache;
 	uint16_t	gatt_mtu;
 	uint8_t		gatt_channels;
+	bool		gatt_client;
 	enum mps_mode_t	mps;
 
 	struct btd_avdtp_opts avdtp;
+	struct btd_avrcp_opts avrcp;
 
 	uint8_t		key_size;
 
 	enum jw_repairing_t jw_repairing;
 
 	struct btd_advmon_opts	advmon;
+
+	struct btd_csis csis;
 };
 
 extern struct btd_opts btd_opts;
 
-gboolean plugin_init(const char *enable, const char *disable);
+void plugin_init(const char *enable, const char *disable);
 void plugin_cleanup(void);
 
 void rfkill_init(void);
diff --git a/src/device.c b/src/device.c
index 995d39f..2b3d19f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
+ *  Copyright 2024 NXP
  *
  */
 
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <dirent.h>
 #include <time.h>
+#include <limits.h>
 #include <sys/stat.h>
 
 #include <glib.h>
@@ -64,6 +65,7 @@
 #include "storage.h"
 #include "eir.h"
 #include "settings.h"
+#include "set.h"
 
 #define DISCONNECT_TIMER	2
 #define DISCOVERY_TIMER		1
@@ -159,9 +161,24 @@ struct bearer_state {
 	time_t last_seen;
 };
 
+struct ltk_info {
+	uint8_t key[16];
+	bool central;
+	uint8_t enc_size;
+};
+
 struct csrk_info {
 	uint8_t key[16];
 	uint32_t counter;
+	bool auth;
+};
+
+struct sirk_info {
+	struct btd_device_set *set;
+	uint8_t encrypted;
+	uint8_t key[16];
+	uint8_t size;
+	uint8_t rank;
 };
 
 enum {
@@ -198,6 +215,7 @@ struct btd_device {
 	GDBusPendingPropertySet wake_id;
 
 	uint32_t	supported_flags;
+	uint32_t	pending_flags;
 	uint32_t	current_flags;
 	GSList		*svc_callbacks;
 	GSList		*eir_uuids;
@@ -253,7 +271,8 @@ struct btd_device {
 
 	struct csrk_info *local_csrk;
 	struct csrk_info *remote_csrk;
-	uint8_t ltk_enc_size;
+	struct ltk_info *ltk;
+	struct queue	*sirks;
 
 	sdp_list_t	*tmp_records;
 
@@ -294,11 +313,11 @@ static struct bearer_state *get_state(struct btd_device *dev,
 		return &dev->le_state;
 }
 
-static bool get_initiator(struct btd_device *dev)
+bool btd_device_is_initiator(struct btd_device *dev)
 {
 	if (dev->le_state.connected)
 		return dev->le_state.initiator;
-	if (dev->bredr_state.connected)
+	else if (dev->bredr_state.connected)
 		return dev->bredr_state.initiator;
 
 	return dev->att_io ? true : false;
@@ -384,6 +403,25 @@ static void store_csrk(struct csrk_info *csrk, GKeyFile *key_file,
 
 	g_key_file_set_string(key_file, group, "Key", key);
 	g_key_file_set_integer(key_file, group, "Counter", csrk->counter);
+	g_key_file_set_boolean(key_file, group, "Authenticated", csrk->auth);
+}
+
+static void store_sirk(struct sirk_info *sirk, GKeyFile *key_file,
+						uint8_t index)
+{
+	char group[28];
+	char key[33];
+	int i;
+
+	sprintf(group, "SetIdentityResolvingKey#%u", index);
+
+	for (i = 0; i < 16; i++)
+		sprintf(key + (i * 2), "%2.2X", sirk->key[i]);
+
+	g_key_file_set_boolean(key_file, group, "Encrypted", sirk->encrypted);
+	g_key_file_set_string(key_file, group, "Key", key);
+	g_key_file_set_integer(key_file, group, "Size", sirk->size);
+	g_key_file_set_integer(key_file, group, "Rank", sirk->rank);
 }
 
 static gboolean store_device_info_cb(gpointer user_data)
@@ -483,6 +521,18 @@ static gboolean store_device_info_cb(gpointer user_data)
 	if (device->remote_csrk)
 		store_csrk(device->remote_csrk, key_file, "RemoteSignatureKey");
 
+	if (!queue_isempty(device->sirks)) {
+		const struct queue_entry *entry;
+		int i;
+
+		for (entry = queue_get_entries(device->sirks), i = 0; entry;
+						entry = entry->next, i++) {
+			struct sirk_info *sirk = entry->data;
+
+			store_sirk(sirk, key_file, i);
+		}
+	}
+
 	str = g_key_file_to_data(key_file, &length, NULL);
 	if (!g_file_set_contents(filename, str, length, &gerr)) {
 		error("Unable set contents for %s: (%s)", filename,
@@ -804,8 +854,11 @@ static void device_free(gpointer user_data)
 	if (device->eir_uuids)
 		g_slist_free_full(device->eir_uuids, g_free);
 
+	queue_destroy(device->sirks, free);
+
 	g_free(device->local_csrk);
 	g_free(device->remote_csrk);
+	free(device->ltk);
 	g_free(device->path);
 	g_free(device->alias);
 	free(device->modalias);
@@ -1001,16 +1054,14 @@ static gboolean dev_property_get_appearance(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
-static const char *get_icon(const GDBusPropertyTable *property, void *data)
+const char *btd_device_get_icon(struct btd_device *device)
 {
-	struct btd_device *device = data;
 	const char *icon = NULL;
-	uint16_t appearance;
 
 	if (device->class != 0)
 		icon = class_to_icon(device->class);
-	else if (get_appearance(property, data, &appearance))
-		icon = gap_appearance_to_icon(appearance);
+	else if (device->appearance != 0)
+		icon = gap_appearance_to_icon(device->appearance);
 
 	return icon;
 }
@@ -1018,7 +1069,7 @@ static const char *get_icon(const GDBusPropertyTable *property, void *data)
 static gboolean dev_property_exists_icon(
 			const GDBusPropertyTable *property, void *data)
 {
-	return get_icon(property, data) != NULL;
+	return btd_device_get_icon(data) != NULL;
 }
 
 static gboolean dev_property_get_icon(const GDBusPropertyTable *property,
@@ -1026,7 +1077,7 @@ static gboolean dev_property_get_icon(const GDBusPropertyTable *property,
 {
 	const char *icon;
 
-	icon = get_icon(property, data);
+	icon = btd_device_get_icon(data);
 	if (icon == NULL)
 		return FALSE;
 
@@ -1520,7 +1571,7 @@ static void set_wake_allowed_complete(uint8_t status, uint16_t length,
 		return;
 	}
 
-	device_set_wake_allowed_complete(dev);
+	btd_device_flags_changed(dev, dev->supported_flags, dev->pending_flags);
 }
 
 void device_set_wake_allowed(struct btd_device *device, bool wake_allowed,
@@ -1607,6 +1658,67 @@ static gboolean dev_property_wake_allowed_exist(
 	return device_get_wake_support(device);
 }
 
+static void append_set(void *data, void *user_data)
+{
+	struct sirk_info *info = data;
+	const char *path;
+	DBusMessageIter *iter = user_data;
+	DBusMessageIter entry, dict;
+
+	if (!info->set)
+		return;
+
+	path = btd_set_get_path(info->set);
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
+								&entry);
+
+	dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
+				DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+				DBUS_TYPE_STRING_AS_STRING
+				DBUS_TYPE_VARIANT_AS_STRING
+				DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	g_dbus_dict_append_entry(&dict, "Rank", DBUS_TYPE_BYTE, &info->rank);
+
+	dbus_message_iter_close_container(&entry, &dict);
+	dbus_message_iter_close_container(iter, &entry);
+}
+
+static gboolean dev_property_get_set(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device *device = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_OBJECT_PATH_AS_STRING
+					DBUS_TYPE_ARRAY_AS_STRING
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&array);
+
+	queue_foreach(device->sirks, append_set, &array);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static gboolean dev_property_set_exists(const GDBusPropertyTable *property,
+						void *data)
+{
+	struct btd_device *device = data;
+
+	return !queue_isempty(device->sirks);
+}
+
 static bool disconnect_all(gpointer user_data)
 {
 	struct btd_device *device = user_data;
@@ -1792,17 +1904,167 @@ bool device_is_disconnecting(struct btd_device *device)
 	return device->disconn_timer > 0;
 }
 
-void device_set_ltk_enc_size(struct btd_device *device, uint8_t enc_size)
+static void add_set(void *data, void *user_data)
 {
-	device->ltk_enc_size = enc_size;
-	bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
+	struct sirk_info *sirk = data;
+	struct btd_device *device = user_data;
+	struct btd_device_set *set;
+
+	if (!sirk->encrypted)
+		return;
+
+	set = btd_set_add_device(device, device->ltk->key, sirk->key,
+							sirk->size);
+	if (!set)
+		return;
+
+	if (sirk->set != set) {
+		sirk->set = set;
+		g_dbus_emit_property_changed(dbus_conn, device->path,
+					     DEVICE_INTERFACE, "Sets");
+	}
+}
+
+void device_set_ltk(struct btd_device *device, const uint8_t val[16],
+				bool central, uint8_t enc_size)
+{
+	if (!device->ltk)
+		device->ltk = new0(struct ltk_info, 1);
+
+	memcpy(device->ltk->key, val, sizeof(device->ltk->key));
+	device->ltk->central = central;
+	device->ltk->enc_size = enc_size;
+	bt_att_set_enc_key_size(device->att, enc_size);
+
+	/* Check if there is any set/sirk that needs decryption */
+	queue_foreach(device->sirks, add_set, device);
+}
+
+bool btd_device_get_ltk(struct btd_device *device, uint8_t key[16],
+				bool *central, uint8_t *enc_size)
+{
+	if (!device || !device->ltk || !key)
+		return false;
+
+	memcpy(key, device->ltk->key, sizeof(device->ltk->key));
+
+	if (central)
+		*central = device->ltk->central;
+
+	if (enc_size)
+		*enc_size = device->ltk->enc_size;
+
+	return true;
+}
+
+void device_set_csrk(struct btd_device *device, const uint8_t val[16],
+				uint32_t counter, uint8_t type,
+				bool store_hint)
+{
+	struct csrk_info **handle;
+	struct csrk_info *csrk;
+	bool auth;
+
+	switch (type) {
+	case 0x00:
+		handle = &device->local_csrk;
+		auth = FALSE;
+		break;
+	case 0x01:
+		handle = &device->remote_csrk;
+		auth = FALSE;
+		break;
+	case 0x02:
+		handle = &device->local_csrk;
+		auth = TRUE;
+		break;
+	case 0x03:
+		handle = &device->remote_csrk;
+		auth = TRUE;
+		break;
+	default:
+		warn("Unsupported CSRK type %u", type);
+		return;
+	}
+
+	if (!*handle)
+		*handle = g_new0(struct csrk_info, 1);
+
+	csrk = *handle;
+	memcpy(csrk->key, val, sizeof(csrk->key));
+	csrk->counter = counter;
+	csrk->auth = auth;
+
+	if (!store_hint)
+		return;
+
+	store_device_info(device);
+
+	btd_device_set_temporary(device, false);
+}
+
+static bool match_sirk(const void *data, const void *match_data)
+{
+	const struct sirk_info *sirk = data;
+	const uint8_t *key = match_data;
+
+	return !memcmp(sirk->key, key, sizeof(sirk->key));
+}
+
+static struct sirk_info *device_add_sirk_info(struct btd_device *device,
+					      bool encrypted, uint8_t key[16],
+					      uint8_t size, uint8_t rank)
+{
+	struct sirk_info *sirk;
+
+	sirk = queue_find(device->sirks, match_sirk, key);
+	if (sirk)
+		return sirk;
+
+	sirk = new0(struct sirk_info, 1);
+	sirk->encrypted = encrypted;
+	memcpy(sirk->key, key, sizeof(sirk->key));
+	sirk->size = size;
+	sirk->rank = rank;
+
+	queue_push_tail(device->sirks, sirk);
+	store_device_info(device);
+
+	return sirk;
+}
+
+bool btd_device_add_set(struct btd_device *device, bool encrypted,
+				uint8_t key[16], uint8_t size, uint8_t rank)
+{
+	struct btd_device_set *set;
+	struct sirk_info *sirk;
+
+	if (encrypted && !device->ltk)
+		return false;
+
+	sirk = device_add_sirk_info(device, encrypted, key, size, rank);
+	if (!sirk)
+		return false;
+
+	set = btd_set_add_device(device, encrypted ? device->ltk->key : NULL,
+						key, size);
+	if (!set)
+		return false;
+
+	if (sirk->set != set) {
+		sirk->set = set;
+		g_dbus_emit_property_changed(dbus_conn, device->path,
+					     DEVICE_INTERFACE, "Sets");
+	}
+
+	return true;
 }
 
 static void device_set_auto_connect(struct btd_device *device, gboolean enable)
 {
 	char addr[18];
 
-	if (!device || !device->le)
+	if (!device || !device->le || device_address_is_private(device))
 		return;
 
 	ba2str(&device->bdaddr, addr);
@@ -1952,7 +2214,7 @@ done:
 void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
 {
 	GSList *l;
-	bool added = false;
+	GSList *added = NULL;
 
 	if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
 		return;
@@ -1961,13 +2223,11 @@ void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
 		const char *str = l->data;
 		if (g_slist_find_custom(dev->eir_uuids, str, bt_uuid_strcmp))
 			continue;
-		added = true;
+		added = g_slist_append(added, (void *)str);
 		dev->eir_uuids = g_slist_append(dev->eir_uuids, g_strdup(str));
 	}
 
-	if (added)
-		g_dbus_emit_property_changed(dbus_conn, dev->path,
-						DEVICE_INTERFACE, "UUIDs");
+	device_probe_profiles(dev, added);
 }
 
 static void add_manufacturer_data(void *data, void *user_data)
@@ -1997,6 +2257,7 @@ static void add_service_data(void *data, void *user_data)
 	struct eir_sd *sd = data;
 	struct btd_device *dev = user_data;
 	bt_uuid_t uuid;
+	GSList *l;
 
 	if (bt_string_to_uuid(&uuid, sd->uuid) < 0)
 		return;
@@ -2004,6 +2265,10 @@ static void add_service_data(void *data, void *user_data)
 	if (!bt_ad_add_service_data(dev->ad, &uuid, sd->data, sd->data_len))
 		return;
 
+	l = g_slist_append(NULL, sd->uuid);
+	device_add_eir_uuids(dev, l);
+	g_slist_free(l);
+
 	g_dbus_emit_property_changed(dbus_conn, dev->path,
 					DEVICE_INTERFACE, "ServiceData");
 }
@@ -2272,13 +2537,13 @@ static uint8_t select_conn_bearer(struct btd_device *dev)
 	if (dev->bdaddr_type == BDADDR_LE_RANDOM)
 		return dev->bdaddr_type;
 
-	if (dev->bredr_state.last_seen) {
+	if (dev->bredr_state.connectable && dev->bredr_state.last_seen) {
 		bredr_last = current - dev->bredr_state.last_seen;
 		if (bredr_last > SEEN_TRESHHOLD)
 			bredr_last = NVAL_TIME;
 	}
 
-	if (dev->le_state.last_seen) {
+	if (dev->le_state.connectable && dev->le_state.last_seen) {
 		le_last = current - dev->le_state.last_seen;
 		if (le_last > SEEN_TRESHHOLD)
 			le_last = NVAL_TIME;
@@ -2812,12 +3077,25 @@ static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
 	if (device->bonding)
 		return btd_error_in_progress(msg);
 
-	if (device->bredr_state.bonded)
+	/* Only use this selection algorithms when device is combo
+	 * chip. Ohterwise, it will use the wrong bearer to establish
+	 * a connection if the device is already paired, which will
+	 * stall the pairing procedure. For example, for a BLE only
+	 * device, if the device is already paired, and upper layer
+	 * issue the pair device again, it will set bdaddr_type to
+	 * BDADDR_BREDR since LE is bonded, then it goes with BR/EDR
+	 * bearer.
+	 */
+	if (device->bredr && device->le) {
+		if (device->bredr_state.bonded)
+			bdaddr_type = device->bdaddr_type;
+		else if (device->le_state.bonded)
+			bdaddr_type = BDADDR_BREDR;
+		else
+			bdaddr_type = select_conn_bearer(device);
+	} else {
 		bdaddr_type = device->bdaddr_type;
-	else if (device->le_state.bonded)
-		bdaddr_type = BDADDR_BREDR;
-	else
-		bdaddr_type = select_conn_bearer(device);
+	}
 
 	state = get_state(device, bdaddr_type);
 
@@ -2850,6 +3128,11 @@ static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
 	 * this in the ATT connect callback)
 	 */
 	if (bdaddr_type != BDADDR_BREDR) {
+		if (device->disable_auto_connect) {
+			device->disable_auto_connect = FALSE;
+			device_set_auto_connect(device, TRUE);
+		}
+
 		if (!state->connected && btd_le_connect_before_pairing())
 			err = device_connect_le(device);
 		else
@@ -2946,6 +3229,86 @@ static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg,
 	return dbus_message_new_method_return(msg);
 }
 
+static sdp_list_t *read_device_records(struct btd_device *device);
+
+static DBusMessage *get_service_records(DBusConnection *conn, DBusMessage *msg,
+					void *data)
+{
+	DBusMessage *reply;
+	DBusMessageIter records_arr, record;
+	struct btd_device *device = data;
+	sdp_list_t *cur;
+
+	if (!btd_adapter_get_powered(device->adapter))
+		return btd_error_not_ready(msg);
+
+	if (!btd_device_is_connected(device))
+		return btd_error_not_connected(msg);
+
+	if (!device->bredr_state.svc_resolved)
+		return btd_error_not_ready(msg);
+
+	if (!device->tmp_records) {
+		device->tmp_records = read_device_records(device);
+		if (!device->tmp_records)
+			return btd_error_does_not_exist(msg);
+	}
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return btd_error_failed(msg, "Could not create method reply");
+
+	dbus_message_iter_init_append(reply, &records_arr);
+	if (!dbus_message_iter_open_container(&records_arr, DBUS_TYPE_ARRAY,
+					      "ay", &record)) {
+		dbus_message_unref(reply);
+		return btd_error_failed(msg, "Could not initialize iterator");
+	}
+
+	for (cur = device->tmp_records; cur; cur = cur->next) {
+		DBusMessageIter record_bytes;
+		sdp_record_t *rec = cur->data;
+		sdp_buf_t buf;
+		int result;
+
+		result = sdp_gen_record_pdu(rec, &buf);
+		if (result) {
+			dbus_message_iter_abandon_container(&records_arr,
+							    &record);
+			dbus_message_unref(reply);
+			return btd_error_failed(
+				msg, "Could not marshal service record");
+		}
+		if (!dbus_message_iter_open_container(&record, DBUS_TYPE_ARRAY,
+						      "y", &record_bytes)) {
+			bt_free(buf.data);
+			dbus_message_iter_abandon_container(&records_arr,
+							    &record);
+			dbus_message_unref(reply);
+			return btd_error_failed(
+				msg, "Could not initialize iterator");
+		}
+		if (!dbus_message_iter_append_fixed_array(
+			    &record_bytes, DBUS_TYPE_BYTE, &buf.data,
+			    buf.data_size)) {
+			bt_free(buf.data);
+			dbus_message_iter_abandon_container(&record,
+							    &record_bytes);
+			dbus_message_iter_abandon_container(&records_arr,
+							    &record);
+			dbus_message_unref(reply);
+			return btd_error_failed(
+				msg, "Could not append record data to reply");
+		}
+		dbus_message_iter_close_container(&record, &record_bytes);
+		bt_free(buf.data);
+	}
+
+	dbus_message_iter_close_container(&records_arr, &record);
+
+	return reply;
+}
+
 static const GDBusMethodTable device_methods[] = {
 	{ GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, dev_disconnect) },
 	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, dev_connect) },
@@ -2955,6 +3318,9 @@ static const GDBusMethodTable device_methods[] = {
 						NULL, disconnect_profile) },
 	{ GDBUS_ASYNC_METHOD("Pair", NULL, NULL, pair_device) },
 	{ GDBUS_METHOD("CancelPairing", NULL, NULL, cancel_pairing) },
+	{ GDBUS_EXPERIMENTAL_METHOD("GetServiceRecords", NULL,
+				    GDBUS_ARGS({ "Records", "aay" }),
+				    get_service_records) },
 	{ }
 };
 
@@ -2988,14 +3354,14 @@ static const GDBusPropertyTable device_properties[] = {
 					dev_property_exists_tx_power },
 	{ "ServicesResolved", "b", dev_property_get_svc_resolved, NULL, NULL },
 	{ "AdvertisingFlags", "ay", dev_property_get_flags, NULL,
-					dev_property_flags_exist,
-					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
+					dev_property_flags_exist },
 	{ "AdvertisingData", "a{yv}", dev_property_get_advertising_data,
-				NULL, dev_property_advertising_data_exist,
-				G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+				NULL, dev_property_advertising_data_exist },
 	{ "WakeAllowed", "b", dev_property_get_wake_allowed,
 				dev_property_set_wake_allowed,
 				dev_property_wake_allowed_exist },
+	{ "Sets", "a{oa{sv}}", dev_property_get_set, NULL,
+				dev_property_set_exists },
 	{ }
 };
 
@@ -3005,6 +3371,15 @@ uint8_t btd_device_get_bdaddr_type(struct btd_device *dev)
 }
 
 bool btd_device_is_connected(struct btd_device *dev)
+{
+	if (btd_device_bearer_is_connected(dev))
+		return true;
+
+	return find_service_with_state(dev->services,
+						BTD_SERVICE_STATE_CONNECTED);
+}
+
+bool btd_device_bearer_is_connected(struct btd_device *dev)
 {
 	return dev->bredr_state.connected || dev->le_state.connected;
 }
@@ -3017,7 +3392,8 @@ static void clear_temporary_timer(struct btd_device *dev)
 	}
 }
 
-void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
+void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
+							uint32_t flags)
 {
 	struct bearer_state *state = get_state(dev, bdaddr_type);
 
@@ -3040,6 +3416,7 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
 		device_set_le_support(dev, bdaddr_type);
 
 	state->connected = true;
+	state->initiator = flags & BIT(3);
 
 	if (dev->le_state.connected && dev->bredr_state.connected)
 		return;
@@ -3051,10 +3428,26 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
 								"Connected");
 }
 
+static bool device_service_connected(struct btd_device *dev)
+{
+	if (find_service_with_state(dev->services,
+					BTD_SERVICE_STATE_CONNECTING))
+		return true;
+
+	return find_service_with_state(dev->services,
+					BTD_SERVICE_STATE_CONNECTED);
+}
+
 static bool device_disappeared(gpointer user_data)
 {
 	struct btd_device *dev = user_data;
 
+	/* If there are services connected restart the timer to give more time
+	 * for the service to either complete the connection or disconnect.
+	 */
+	if (device_service_connected(dev))
+		return TRUE;
+
 	dev->temporary_timer = 0;
 
 	btd_adapter_remove_device(dev->adapter, dev);
@@ -3108,18 +3501,6 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 		device->connect = NULL;
 	}
 
-	while (device->disconnects) {
-		DBusMessage *msg = device->disconnects->data;
-
-		if (dbus_message_is_method_call(msg, ADAPTER_INTERFACE,
-								"RemoveDevice"))
-			remove_device = true;
-
-		g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
-		device->disconnects = g_slist_remove(device->disconnects, msg);
-		dbus_message_unref(msg);
-	}
-
 	/* Check paired status of both bearers since it's possible to be
 	 * paired but not connected via link key to LTK conversion.
 	 */
@@ -3159,6 +3540,19 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 	g_dbus_emit_property_changed(dbus_conn, device->path,
 						DEVICE_INTERFACE, "Connected");
 
+	/* remove device only if both bearers are disconnected */
+	while (device->disconnects) {
+		DBusMessage *msg = device->disconnects->data;
+
+		if (dbus_message_is_method_call(msg, ADAPTER_INTERFACE,
+								"RemoveDevice"))
+			remove_device = true;
+
+		g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
+		device->disconnects = g_slist_remove(device->disconnects, msg);
+		dbus_message_unref(msg);
+	}
+
 	if (remove_device)
 		*remove = remove_device;
 }
@@ -3290,6 +3684,63 @@ fail:
 	return NULL;
 }
 
+static struct sirk_info *load_sirk(GKeyFile *key_file, uint8_t index)
+{
+	char group[28];
+	struct sirk_info *sirk;
+	char *str;
+	int i;
+
+	sprintf(group, "SetIdentityResolvingKey#%u", index);
+
+	str = g_key_file_get_string(key_file, group, "Key", NULL);
+	if (!str)
+		return NULL;
+
+	sirk = g_new0(struct sirk_info, 1);
+
+	for (i = 0; i < 16; i++) {
+		if (sscanf(str + (i * 2), "%2hhx", &sirk->key[i]) != 1)
+			goto fail;
+	}
+
+
+	sirk->encrypted = g_key_file_get_boolean(key_file, group, "Encrypted",
+									NULL);
+	sirk->size = g_key_file_get_integer(key_file, group, "Size", NULL);
+	sirk->rank = g_key_file_get_integer(key_file, group, "Rank", NULL);
+	g_free(str);
+
+	return sirk;
+
+fail:
+	g_free(str);
+	g_free(sirk);
+	return NULL;
+}
+
+static void load_sirks(struct btd_device *device, GKeyFile *key_file)
+{
+	struct sirk_info *sirk;
+	uint8_t i;
+
+	for (i = 0; i < UINT8_MAX; i++) {
+		sirk = load_sirk(key_file, i);
+		if (!sirk)
+			break;
+
+		queue_push_tail(device->sirks, sirk);
+
+		/* Only add DeviceSet object if sirk does need
+		 * decryption otherwise it has to wait for the LTK in
+		 * order to decrypt.
+		 */
+		if (!sirk->encrypted)
+			btd_set_add_device(device, NULL, sirk->key,
+							sirk->size);
+	}
+}
+
 static void load_services(struct btd_device *device, char **uuids)
 {
 	char **uuid;
@@ -3430,6 +3881,8 @@ static void load_info(struct btd_device *device, const char *local,
 
 		device->local_csrk = load_csrk(key_file, "LocalSignatureKey");
 		device->remote_csrk = load_csrk(key_file, "RemoteSignatureKey");
+
+		load_sirks(device, key_file);
 	}
 
 	g_strfreev(techno);
@@ -3662,11 +4115,13 @@ static bool device_match_profile(struct btd_device *device,
 					struct btd_profile *profile,
 					GSList *uuids)
 {
+	GSList *l;
+
 	if (profile->remote_uuid == NULL)
 		return false;
 
-	if (g_slist_find_custom(uuids, profile->remote_uuid,
-							bt_uuid_strcmp) == NULL)
+	l = g_slist_find_custom(uuids, profile->remote_uuid, bt_uuid_strcmp);
+	if (!l)
 		return false;
 
 	return true;
@@ -3711,7 +4166,7 @@ done:
 	}
 
 	/* Notify driver about the new connection */
-	service_accept(service, get_initiator(device));
+	service_accept(service, btd_device_is_initiator(device));
 }
 
 static void device_add_gatt_services(struct btd_device *device)
@@ -3731,7 +4186,7 @@ static void device_add_gatt_services(struct btd_device *device)
 static void device_accept_gatt_profiles(struct btd_device *device)
 {
 	GSList *l;
-	bool initiator = get_initiator(device);
+	bool initiator = btd_device_is_initiator(device);
 
 	DBG("initiator %s", initiator ? "true" : "false");
 
@@ -3945,6 +4400,7 @@ static struct btd_device *device_new(struct btd_adapter *adapter,
 	}
 
 	device->adapter = adapter;
+	device->sirks = queue_new();
 	device->temporary = true;
 
 	device->db_id = gatt_db_register(device->db, gatt_service_added,
@@ -4158,7 +4614,10 @@ void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
 	bacpy(&device->bdaddr, bdaddr);
 	device->bdaddr_type = bdaddr_type;
 
-	store_device_info(device);
+	if (device->temporary)
+		btd_device_set_temporary(device, false);
+	else
+		store_device_info(device);
 
 	g_dbus_emit_property_changed(dbus_conn, device->path,
 						DEVICE_INTERFACE, "Address");
@@ -4186,6 +4645,9 @@ void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type)
 	device->le = true;
 	device->bdaddr_type = bdaddr_type;
 
+	g_dbus_emit_property_changed(dbus_conn, device->path,
+					DEVICE_INTERFACE, "AddressType");
+
 	store_device_info(device);
 }
 
@@ -4206,6 +4668,11 @@ void device_update_last_seen(struct btd_device *device, uint8_t bdaddr_type,
 	set_temporary_timer(device, btd_opts.tmpto);
 }
 
+void btd_device_set_connectable(struct btd_device *device, bool connectable)
+{
+	device_update_last_seen(device, device->bdaddr_type, connectable);
+}
+
 /* It is possible that we have two device objects for the same device in
  * case it has first been discovered over BR/EDR and has a private
  * address when discovered over LE for the first time. In such a case we
@@ -4553,8 +5020,15 @@ static struct btd_service *probe_service(struct btd_device *device,
 	/* Only set auto connect if profile has set the flag and can really
 	 * accept connections.
 	 */
-	if (profile->auto_connect && profile->accept)
-		device_set_auto_connect(device, TRUE);
+	if (profile->auto_connect && profile->accept) {
+		/* If temporary mark auto_connect as disabled so when the
+		 * device is connected it attempts to enable it.
+		 */
+		if (device->temporary)
+			device->disable_auto_connect = TRUE;
+		else
+			device_set_auto_connect(device, TRUE);
+	}
 
 	return service;
 }
@@ -4615,6 +5089,9 @@ void device_probe_profiles(struct btd_device *device, GSList *uuids)
 	struct probe_data d = { device, uuids };
 	char addr[18];
 
+	if (!uuids)
+		return;
+
 	ba2str(&device->bdaddr, addr);
 
 	if (device->blocked) {
@@ -4622,8 +5099,6 @@ void device_probe_profiles(struct btd_device *device, GSList *uuids)
 		goto add_uuids;
 	}
 
-	DBG("Probing profiles for device %s", addr);
-
 	btd_profile_foreach(dev_probe, &d);
 
 add_uuids:
@@ -5143,6 +5618,10 @@ static void gatt_client_init(struct btd_device *device)
 		DBG("Reverse service discovery disabled: skipping GATT client");
 		return;
 	}
+	if (!device->connect && !btd_opts.gatt_client) {
+		DBG("GATT client disabled: skipping GATT client");
+		return;
+	}
 
 	device->client = bt_gatt_client_new(device->db, device->att,
 							device->att_mtu, 0);
@@ -5152,12 +5631,14 @@ static void gatt_client_init(struct btd_device *device)
 	}
 
 	bt_gatt_client_set_debug(device->client, gatt_debug, NULL, NULL);
+	g_attrib_attach_client(device->attrib, device->client);
 
 	/*
-	 * Notify notify existing service about the new connection so they can
-	 * react to notifications while discovering services
+	 * If we have cache, notify existing service about the new connection
+	 * so they can react to notifications while discovering services
 	 */
-	device_accept_gatt_profiles(device);
+	if (!gatt_db_isempty(device->db))
+		device_accept_gatt_profiles(device);
 
 	device->gatt_ready_id = bt_gatt_client_ready_register(device->client,
 							gatt_client_ready_cb,
@@ -5205,7 +5686,9 @@ static void gatt_server_init(struct btd_device *device,
 		return;
 	}
 
-	bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
+	if (device->ltk)
+		bt_att_set_enc_key_size(device->att, device->ltk->enc_size);
+
 	bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL);
 
 	btd_gatt_database_server_connected(database, device->server);
@@ -5420,7 +5903,7 @@ int device_connect_le(struct btd_device *dev)
 	char addr[18];
 
 	/* There is one connection attempt going on */
-	if (dev->att_io)
+	if (dev->att_io || dev->att)
 		return -EALREADY;
 
 	ba2str(&dev->bdaddr, addr);
@@ -5468,6 +5951,10 @@ int device_connect_le(struct btd_device *dev)
 	/* Keep this, so we can cancel the connection */
 	dev->att_io = io;
 
+	/* Restart temporary timer to give it time to connect/pair, etc. */
+	if (dev->temporary)
+		set_temporary_timer(dev, btd_opts.tmpto);
+
 	return 0;
 }
 
@@ -6043,7 +6530,8 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
 		/* Put the device back to the temporary state so that it will be
 		 * treated as a newly discovered device.
 		 */
-		if (!device_is_paired(device, bdaddr_type) &&
+		if (!btd_device_bearer_is_connected(device) &&
+				!device_is_paired(device, bdaddr_type) &&
 				!btd_device_is_trusted(device))
 			btd_device_set_temporary(device, true);
 
@@ -6564,6 +7052,9 @@ void device_cancel_authentication(struct btd_device *device, gboolean aborted)
 	struct authentication_req *auth = device->authr;
 	char addr[18];
 
+	if (device->adapter)
+		btd_adapter_cancel_service_auth(device->adapter, device);
+
 	if (!auth)
 		return;
 
@@ -6609,6 +7100,27 @@ struct gatt_db *btd_device_get_gatt_db(struct btd_device *device)
 	return device->db;
 }
 
+bool btd_device_set_gatt_db(struct btd_device *device, struct gatt_db *db)
+{
+	struct gatt_db *clone;
+
+	if (!device)
+		return false;
+
+	clone = gatt_db_clone(db);
+	if (clone)
+		return false;
+
+	gatt_db_unregister(device->db, device->db_id);
+	gatt_db_unref(device->db);
+
+	device->db = clone;
+	device->db_id = gatt_db_register(device->db, gatt_service_added,
+					gatt_service_removed, device, NULL);
+
+	return true;
+}
+
 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device)
 {
 	if (!device)
@@ -6647,9 +7159,6 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
 	GSList *uuid_list;
 	char *new_uuid;
 
-	if (g_slist_find_custom(device->uuids, uuid, bt_uuid_strcmp))
-		return;
-
 	new_uuid = g_strdup(uuid);
 	uuid_list = g_slist_append(NULL, new_uuid);
 
@@ -6657,11 +7166,6 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
 
 	g_free(new_uuid);
 	g_slist_free(uuid_list);
-
-	store_device_info(device);
-
-	g_dbus_emit_property_changed(dbus_conn, device->path,
-						DEVICE_INTERFACE, "UUIDs");
 }
 
 static sdp_list_t *read_device_records(struct btd_device *device)
@@ -6758,6 +7262,14 @@ struct btd_device *btd_device_ref(struct btd_device *device)
 	return device;
 }
 
+static void remove_sirk_info(void *data, void *user_data)
+{
+	struct sirk_info *info = data;
+	struct btd_device *device = user_data;
+
+	btd_set_remove_device(info->set, device);
+}
+
 void btd_device_unref(struct btd_device *device)
 {
 	if (__sync_sub_and_fetch(&device->ref_count, 1))
@@ -6768,6 +7280,9 @@ void btd_device_unref(struct btd_device *device)
 		return;
 	}
 
+	if (!queue_isempty(device->sirks))
+		queue_foreach(device->sirks, remove_sirk_info, device);
+
 	DBG("Freeing device %s", device->path);
 
 	g_dbus_unregister_interface(dbus_conn, device->path, DEVICE_INTERFACE);
@@ -6833,6 +7348,22 @@ uint32_t btd_device_get_supported_flags(struct btd_device *dev)
 	return dev->supported_flags;
 }
 
+void btd_device_set_pending_flags(struct btd_device *dev, uint32_t flags)
+{
+	if (!dev)
+		return;
+
+	dev->pending_flags = flags;
+}
+
+uint32_t btd_device_get_pending_flags(struct btd_device *dev)
+{
+	if (!dev)
+		return 0;
+
+	return dev->pending_flags;
+}
+
 /* This event is sent immediately after add device on all mgmt sockets.
  * Afterwards, it is only sent to mgmt sockets other than the one which called
  * set_device_flags.
@@ -6845,11 +7376,12 @@ void btd_device_flags_changed(struct btd_device *dev, uint32_t supported_flags,
 
 	dev->supported_flags = supported_flags;
 	dev->current_flags = current_flags;
+	dev->pending_flags = 0;
 
 	if (!changed_flags)
 		return;
 
-	if (changed_flags & DEVICE_FLAG_REMOTE_WAKEUP) {
+	if (changed_flags & DEVICE_FLAG_REMOTE_WAKEUP && dev->wake_support) {
 		flag_value = !!(current_flags & DEVICE_FLAG_REMOTE_WAKEUP);
 		dev->pending_wake_allowed = flag_value;
 
@@ -6926,3 +7458,29 @@ int8_t btd_device_get_volume(struct btd_device *device)
 {
 	return device->volume;
 }
+
+void btd_device_foreach_ad(struct btd_device *dev, bt_ad_func_t func,
+							void *data)
+{
+	bt_ad_foreach_data(dev->ad, func, data);
+}
+
+void btd_device_set_conn_param(struct btd_device *device, uint16_t min_interval,
+					uint16_t max_interval, uint16_t latency,
+					uint16_t timeout)
+{
+	/* Attempt to load the new connection parameters, in case it is
+	 * successful the MGMT_EV_NEW_CONN_PARAM will be generated which will
+	 * then trigger btd_adapter_store_conn_param.
+	 */
+	btd_adapter_load_conn_param(device->adapter, &device->bdaddr,
+					device->bdaddr_type, min_interval,
+					max_interval, latency,
+					timeout);
+}
+
+void btd_device_foreach_service_data(struct btd_device *dev, bt_ad_func_t func,
+							void *data)
+{
+	bt_ad_foreach_service_data(dev->ad, func, data);
+}
diff --git a/src/device.h b/src/device.h
index 9e81fda..9753677 100644
--- a/src/device.h
+++ b/src/device.h
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
+ *  Copyright 2024 NXP
  *
  */
 
@@ -41,6 +41,7 @@ uint16_t btd_device_get_vendor(struct btd_device *device);
 uint16_t btd_device_get_vendor_src(struct btd_device *device);
 uint16_t btd_device_get_product(struct btd_device *device);
 uint16_t btd_device_get_version(struct btd_device *device);
+const char *btd_device_get_icon(struct btd_device *device);
 void device_remove_bonding(struct btd_device *device, uint8_t bdaddr_type);
 void device_remove(struct btd_device *device, gboolean remove_stored);
 int device_address_cmp(gconstpointer a, gconstpointer b);
@@ -65,8 +66,10 @@ struct gatt_primary *btd_device_get_primary(struct btd_device *device,
 							const char *uuid);
 GSList *btd_device_get_primaries(struct btd_device *device);
 struct gatt_db *btd_device_get_gatt_db(struct btd_device *device);
+bool btd_device_set_gatt_db(struct btd_device *device, struct gatt_db *db);
 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device);
 struct bt_gatt_server *btd_device_get_gatt_server(struct btd_device *device);
+bool btd_device_is_initiator(struct btd_device *device);
 void *btd_device_get_attrib(struct btd_device *device);
 void btd_device_gatt_set_service_changed(struct btd_device *device,
 						uint16_t start, uint16_t end);
@@ -94,6 +97,7 @@ void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type);
 void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type);
 void btd_device_set_temporary(struct btd_device *device, bool temporary);
 void btd_device_set_trusted(struct btd_device *device, gboolean trusted);
+void btd_device_set_connectable(struct btd_device *device, bool connectable);
 void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type);
 void device_set_legacy(struct btd_device *device, bool legacy);
 void device_set_rssi_with_delta(struct btd_device *device, int8_t rssi,
@@ -102,6 +106,7 @@ void device_set_rssi(struct btd_device *device, int8_t rssi);
 void device_set_tx_power(struct btd_device *device, int8_t tx_power);
 void device_set_flags(struct btd_device *device, uint8_t flags);
 bool btd_device_is_connected(struct btd_device *dev);
+bool btd_device_bearer_is_connected(struct btd_device *dev);
 uint8_t btd_device_get_bdaddr_type(struct btd_device *dev);
 bool device_is_retrying(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
@@ -123,13 +128,21 @@ int device_notify_pincode(struct btd_device *device, gboolean secure,
 							const char *pincode);
 void device_cancel_authentication(struct btd_device *device, gboolean aborted);
 gboolean device_is_authenticating(struct btd_device *device);
-void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type);
+void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
+							uint32_t flags);
 void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 								bool *remove);
 void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
 bool device_is_disconnecting(struct btd_device *device);
-void device_set_ltk_enc_size(struct btd_device *device, uint8_t enc_size);
-
+void device_set_ltk(struct btd_device *device, const uint8_t val[16],
+				bool central, uint8_t enc_size);
+bool btd_device_get_ltk(struct btd_device *device, uint8_t val[16],
+				bool *central, uint8_t *enc_size);
+void device_set_csrk(struct btd_device *device, const uint8_t val[16],
+				uint32_t counter, uint8_t type,
+				bool store_hint);
+bool btd_device_add_set(struct btd_device *device, bool encrypted,
+				uint8_t sirk[16], uint8_t size, uint8_t rank);
 void device_store_svc_chng_ccc(struct btd_device *device, uint8_t bdaddr_type,
 								uint16_t value);
 void device_load_svc_chng_ccc(struct btd_device *device, uint16_t *ccc_le,
@@ -178,6 +191,8 @@ int btd_device_connect_services(struct btd_device *dev, GSList *services);
 
 uint32_t btd_device_get_current_flags(struct btd_device *dev);
 uint32_t btd_device_get_supported_flags(struct btd_device *dev);
+uint32_t btd_device_get_pending_flags(struct btd_device *dev);
+void btd_device_set_pending_flags(struct btd_device *dev, uint32_t flags);
 void btd_device_flags_changed(struct btd_device *dev, uint32_t supported_flags,
 			      uint32_t current_flags);
 
@@ -188,3 +203,14 @@ void btd_device_cleanup(void);
 
 void btd_device_set_volume(struct btd_device *dev, int8_t volume);
 int8_t btd_device_get_volume(struct btd_device *dev);
+
+typedef void (*bt_device_ad_func_t)(void *data, void *user_data);
+
+void btd_device_foreach_ad(struct btd_device *dev, bt_device_ad_func_t func,
+							void *data);
+void btd_device_set_conn_param(struct btd_device *device, uint16_t min_interval,
+					uint16_t max_interval, uint16_t latency,
+					uint16_t timeout);
+void btd_device_foreach_service_data(struct btd_device *dev,
+					bt_device_ad_func_t func,
+					void *data);
diff --git a/src/eir.c b/src/eir.c
index 2f9ee03..3e3ee28 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -236,6 +236,9 @@ static void eir_parse_data(struct eir_data *eir, uint8_t type,
 	memcpy(ad->data, data, len);
 
 	eir->data_list = g_slist_append(eir->data_list, ad);
+
+	if (type == EIR_CSIP_RSI)
+		eir->rsi = true;
 }
 
 void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
@@ -599,3 +602,25 @@ int eir_create_oob(const bdaddr_t *addr, const char *name, uint32_t cod,
 
 	return eir_total_len;
 }
+
+static int match_sd_uuid(const void *data, const void *user_data)
+{
+	const struct eir_sd *sd = data;
+	const char *uuid = user_data;
+
+	return strcmp(sd->uuid, uuid);
+}
+
+struct eir_sd *eir_get_service_data(struct eir_data *eir, const char *uuid)
+{
+	GSList *l;
+
+	if (!eir || !uuid)
+		return NULL;
+
+	l = g_slist_find_custom(eir->sd_list, uuid, match_sd_uuid);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
diff --git a/src/eir.h b/src/eir.h
index 6154e23..f342919 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -12,6 +12,7 @@
 #include <glib.h>
 
 #include "lib/sdp.h"
+#include "lib/uuid.h"
 
 #define EIR_FLAGS                   0x01  /* flags */
 #define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
@@ -37,6 +38,7 @@
 #define EIR_SVC_DATA32              0x20  /* LE: Service data, 32-bit UUID */
 #define EIR_SVC_DATA128             0x21  /* LE: Service data, 128-bit UUID */
 #define EIR_TRANSPORT_DISCOVERY     0x26  /* Transport Discovery Service */
+#define EIR_CSIP_RSI                0x2e  /* Resolvable Set Identifier */
 #define EIR_MANUFACTURER_DATA       0xFF  /* Manufacturer Specific Data */
 
 /* Flags Descriptions */
@@ -76,6 +78,7 @@ struct eir_data {
 	uint32_t class;
 	uint16_t appearance;
 	bool name_complete;
+	bool rsi;
 	int8_t tx_power;
 	uint8_t *hash;
 	uint8_t *randomizer;
@@ -97,3 +100,4 @@ int eir_create_oob(const bdaddr_t *addr, const char *name, uint32_t cod,
 			uint16_t did_vendor, uint16_t did_product,
 			uint16_t did_version, uint16_t did_source,
 			sdp_list_t *uuids, uint8_t *data);
+struct eir_sd *eir_get_service_data(struct eir_data *eir, const char *uuid);
diff --git a/src/error.c b/src/error.c
index 29c0710..f179e6c 100644
--- a/src/error.c
+++ b/src/error.c
@@ -171,6 +171,8 @@ const char *btd_error_bredr_conn_from_errno(int errno_code)
 		return ERR_BREDR_CONN_ABORT_BY_LOCAL;
 	case EPROTO:
 		return ERR_BREDR_CONN_LMP_PROTO_ERROR;
+	case EBADE:
+		return ERR_BREDR_CONN_KEY_MISSING;
 	default:
 		return ERR_BREDR_CONN_UNKNOWN;
 	}
@@ -209,6 +211,8 @@ const char *btd_error_le_conn_from_errno(int errno_code)
 		return ERR_LE_CONN_ABORT_BY_LOCAL;
 	case EPROTO:
 		return ERR_LE_CONN_LL_PROTO_ERROR;
+	case EBADE:
+		return ERR_LE_CONN_KEY_MISSING;
 	default:
 		return ERR_LE_CONN_UNKNOWN;
 	}
diff --git a/src/error.h b/src/error.h
index cc7790a..83206cb 100644
--- a/src/error.h
+++ b/src/error.h
@@ -43,6 +43,7 @@
 #define ERR_BREDR_CONN_LMP_PROTO_ERROR		"br-connection-lmp-protocol-"\
 						"error"
 #define ERR_BREDR_CONN_CANCELED			"br-connection-canceled"
+#define ERR_BREDR_CONN_KEY_MISSING		"br-connection-key-missing"
 #define ERR_BREDR_CONN_UNKNOWN			"br-connection-unknown"
 
 /* LE connection failure reasons */
@@ -63,6 +64,7 @@
 #define ERR_LE_CONN_LL_PROTO_ERROR	"le-connection-link-layer-protocol-"\
 					"error"
 #define ERR_LE_CONN_GATT_BROWSE		"le-connection-gatt-browsing"
+#define ERR_LE_CONN_KEY_MISSING		"le-connection-key-missing"
 #define ERR_LE_CONN_UNKNOWN		"le-connection-unknown"
 
 DBusMessage *btd_error_invalid_args(DBusMessage *msg);
diff --git a/src/gatt-client.c b/src/gatt-client.c
index b2fc16b..8d83a95 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -137,6 +137,17 @@ static bool uuid_cmp(const bt_uuid_t *uuid, uint16_t u16)
 	return bt_uuid_cmp(uuid, &uuid16) == 0;
 }
 
+static gboolean descriptor_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct service *desc = data;
+	uint16_t handle = desc->start_handle;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &handle);
+
+	return TRUE;
+}
+
 static gboolean descriptor_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -635,6 +646,7 @@ static DBusMessage *descriptor_write_value(DBusConnection *conn,
 }
 
 static const GDBusPropertyTable descriptor_properties[] = {
+	{ "Handle", "q", descriptor_get_handle },
 	{ "UUID", "s", descriptor_get_uuid },
 	{ "Characteristic", "o", descriptor_get_characteristic, },
 	{ "Value", "ay", descriptor_get_value, NULL, descriptor_value_exists },
@@ -713,6 +725,17 @@ static void unregister_descriptor(void *data)
 							GATT_DESCRIPTOR_IFACE);
 }
 
+static gboolean characteristic_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct characteristic *chrc = data;
+	uint16_t handle = chrc->handle;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &handle);
+
+	return TRUE;
+}
+
 static gboolean characteristic_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1104,6 +1127,11 @@ static bool sock_read(struct io *io, void *user_data)
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
 
+	if (fd < 0) {
+		error("io_get_fd() returned %d\n", fd);
+		return false;
+	}
+
 	bytes_read = recvmsg(fd, &msg, MSG_DONTWAIT);
 	if (bytes_read < 0) {
 		error("recvmsg: %s", strerror(errno));
@@ -1660,6 +1688,7 @@ static DBusMessage *characteristic_stop_notify(DBusConnection *conn,
 }
 
 static const GDBusPropertyTable characteristic_properties[] = {
+	{ "Handle", "q", characteristic_get_handle },
 	{ "UUID", "s", characteristic_get_uuid, NULL, NULL },
 	{ "Service", "o", characteristic_get_service, NULL, NULL },
 	{ "Value", "ay", characteristic_get_value, NULL,
@@ -1821,6 +1850,17 @@ static void unregister_characteristic(void *data)
 						GATT_CHARACTERISTIC_IFACE);
 }
 
+static gboolean service_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct service *service = data;
+	uint16_t handle = service->start_handle;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &handle);
+
+	return TRUE;
+}
+
 static gboolean service_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1884,6 +1924,7 @@ static gboolean service_get_includes(const GDBusPropertyTable *property,
 }
 
 static const GDBusPropertyTable service_properties[] = {
+	{ "Handle", "q", service_get_handle },
 	{ "UUID", "s", service_get_uuid },
 	{ "Device", "o", service_get_device },
 	{ "Primary", "b", service_get_primary },
@@ -2255,7 +2296,8 @@ void btd_gatt_client_eatt_connect(struct btd_gatt_client *client)
 	char addr[18];
 	int i;
 
-	if (!(client->features & BT_GATT_CHRC_CLI_FEAT_EATT))
+	if (!(client->features & BT_GATT_CHRC_CLI_FEAT_EATT) ||
+				!btd_device_is_initiator(dev))
 		return;
 
 	if (bt_att_get_channels(att) == btd_opts.gatt_channels)
diff --git a/src/gatt-database.c b/src/gatt-database.c
index ea282d4..a86e528 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
@@ -110,6 +111,13 @@ struct external_profile {
 	struct queue *profiles; /* btd_profile list */
 };
 
+struct client_io {
+	struct bt_att *att;
+	struct external_chrc *chrc;
+	unsigned int disconn_id;
+	struct io *io;
+};
+
 struct external_chrc {
 	struct external_service *service;
 	char *path;
@@ -119,8 +127,8 @@ struct external_chrc {
 	uint32_t perm;
 	uint32_t ccc_perm;
 	uint16_t mtu;
-	struct io *write_io;
-	struct io *notify_io;
+	struct queue *write_ios;
+	struct queue *notify_ios;
 	struct gatt_db_attribute *attrib;
 	struct gatt_db_attribute *ccc;
 	struct queue *pending_reads;
@@ -463,12 +471,22 @@ static void cancel_pending_write(void *data)
 	op->owner_queue = NULL;
 }
 
+static void client_io_free(void *data)
+{
+	struct client_io *client = data;
+
+	bt_att_unregister_disconnect(client->att, client->disconn_id);
+	bt_att_unref(client->att);
+	io_destroy(client->io);
+	free(client);
+}
+
 static void chrc_free(void *data)
 {
 	struct external_chrc *chrc = data;
 
-	io_destroy(chrc->write_io);
-	io_destroy(chrc->notify_io);
+	queue_destroy(chrc->write_ios, client_io_free);
+	queue_destroy(chrc->notify_ios, client_io_free);
 
 	queue_destroy(chrc->pending_reads, cancel_pending_read);
 	queue_destroy(chrc->pending_writes, cancel_pending_write);
@@ -2231,6 +2249,9 @@ static uint8_t dbus_error_to_att_ecode(const char *name, const char *msg,
 	if (strcmp(name, ERROR_INTERFACE ".InProgress") == 0)
 		return BT_ERROR_ALREADY_IN_PROGRESS;
 
+	if (!strcmp(name, ERROR_INTERFACE ".ImproperlyConfigured"))
+		return BT_ERROR_CCC_IMPROPERLY_CONFIGURED;
+
 	if (strcmp(name, ERROR_INTERFACE ".NotPermitted") == 0)
 		return perm_err;
 
@@ -2543,39 +2564,52 @@ static void flush_pending_writes(GDBusProxy *proxy,
 	queue_remove_all(owner_queue, NULL, NULL, NULL);
 }
 
+static bool match_client_io(const void *data, const void *user_data)
+{
+	const struct client_io *client = data;
+	const struct io *io = user_data;
+
+	return client->io == io;
+}
+
 static bool sock_hup(struct io *io, void *user_data)
 {
 	struct external_chrc *chrc = user_data;
+	struct client_io *client;
 
 	DBG("%p closed\n", io);
 
-	if (io == chrc->write_io)
-		chrc->write_io = NULL;
-	else
-		chrc->notify_io = NULL;
+	client = queue_remove_if(chrc->write_ios, match_client_io, io);
+	if (!client) {
+		client = queue_remove_if(chrc->notify_ios, match_client_io, io);
+		if (!client)
+			return false;
+	}
 
-	io_destroy(io);
+	client_io_free(client);
 
 	return false;
 }
 
 static bool sock_io_read(struct io *io, void *user_data)
 {
-	struct external_chrc *chrc = user_data;
+	struct client_io *client = user_data;
+	struct external_chrc *chrc = client->chrc;
 	uint8_t buf[512];
 	int fd = io_get_fd(io);
 	ssize_t bytes_read;
 
+	if (fd < 0) {
+		error("io_get_fd() returned %d\n", fd);
+		return false;
+	}
+
 	bytes_read = read(fd, buf, sizeof(buf));
 	if (bytes_read <= 0)
 		return false;
 
-	send_notification_to_devices(chrc->service->app->database,
-				gatt_db_attribute_get_handle(chrc->attrib),
-				buf, bytes_read,
-				gatt_db_attribute_get_handle(chrc->ccc),
-				conf_cb,
-				chrc->proxy);
+	gatt_notify_cb(chrc->attrib, chrc->ccc, buf, bytes_read, client->att,
+				client->chrc->service->app->database);
 
 	return true;
 }
@@ -2597,6 +2631,7 @@ static int sock_io_send(struct io *io, const void *data, size_t len)
 {
 	struct msghdr msg;
 	struct iovec iov;
+	int fd;
 
 	iov.iov_base = (void *) data;
 	iov.iov_len = len;
@@ -2605,13 +2640,78 @@ static int sock_io_send(struct io *io, const void *data, size_t len)
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
 
-	return sendmsg(io_get_fd(io), &msg, MSG_NOSIGNAL);
+	fd = io_get_fd(io);
+	if (fd < 0) {
+		error("io_get_fd() returned %d\n", fd);
+		return fd;
+	}
+
+	return sendmsg(fd, &msg, MSG_NOSIGNAL);
+}
+
+static void att_disconnect_cb(int err, void *user_data)
+{
+	struct client_io *client = user_data;
+
+	/* If ATT is disconnected shutdown correspondent client IO so sock_hup
+	 * is triggered and the server socket is closed.
+	 */
+	io_shutdown(client->io);
+}
+
+static struct client_io *
+client_io_new(struct external_chrc *chrc, int fd, struct bt_att *att)
+{
+	struct client_io *client;
+
+	client = new0(struct client_io, 1);
+	client->att = bt_att_ref(att);
+	client->chrc = chrc;
+	client->disconn_id = bt_att_register_disconnect(att, att_disconnect_cb,
+							client, NULL);
+	client->io = sock_io_new(fd, chrc);
+
+	return client;
+}
+
+static bool match_client_att(const void *data, const void *user_data)
+{
+	const struct client_io *client = data;
+	const struct bt_att *att = user_data;
+
+	/* Always match if ATT instance is not set since that is used by
+	 * clear_cc_state to clear all instances.
+	 */
+	if (!att)
+		return true;
+
+	return client->att == att;
+}
+
+static struct client_io *
+client_write_io_get(struct external_chrc *chrc, int fd, struct bt_att *att)
+{
+	struct client_io *client;
+
+	client = queue_find(chrc->write_ios, match_client_att, att);
+	if (client)
+		return client;
+
+	client = client_io_new(chrc, fd, att);
+
+	if (!chrc->write_ios)
+		chrc->write_ios = queue_new();
+
+	queue_push_tail(chrc->write_ios, client);
+
+	return client;
 }
 
 static void acquire_write_reply(DBusMessage *message, void *user_data)
 {
 	struct pending_op *op = user_data;
 	struct external_chrc *chrc;
+	struct client_io *client;
 	DBusError err;
 	int fd;
 	uint16_t mtu;
@@ -2636,6 +2736,7 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
 		if (ecode != BT_ATT_ERROR_UNLIKELY) {
 			gatt_db_attribute_write_result(op->attrib, op->id,
 								ecode);
+			pending_op_free(op);
 			return;
 		}
 
@@ -2651,10 +2752,12 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
 
 	DBG("AcquireWrite success: fd %d MTU %u\n", fd, mtu);
 
-	chrc->write_io = sock_io_new(fd, chrc);
+	client = client_write_io_get(chrc, fd, op->att);
+	if (!client)
+		goto retry;
 
 	while ((op = queue_peek_head(chrc->pending_writes)) != NULL) {
-		if (sock_io_send(chrc->write_io, op->data.iov_base,
+		if (sock_io_send(client->io, op->data.iov_base,
 					op->data.iov_len) < 0)
 			goto retry;
 
@@ -2711,10 +2814,32 @@ static struct pending_op *acquire_write(struct external_chrc *chrc,
 	return NULL;
 }
 
+static struct client_io *
+client_notify_io_get(struct external_chrc *chrc, int fd, struct bt_att *att)
+{
+	struct client_io *client;
+
+	client = queue_find(chrc->notify_ios, match_client_att, att);
+	if (client)
+		return client;
+
+	client = client_io_new(chrc, fd, att);
+
+	io_set_read_handler(client->io, sock_io_read, client, NULL);
+
+	if (!chrc->notify_ios)
+		chrc->notify_ios = queue_new();
+
+	queue_push_tail(chrc->notify_ios, client);
+
+	return client;
+}
+
 static void acquire_notify_reply(DBusMessage *message, void *user_data)
 {
 	struct pending_op *op = user_data;
 	struct external_chrc *chrc = (void *) op->data.iov_base;
+	struct client_io *client;
 	DBusError err;
 	int fd;
 	uint16_t mtu;
@@ -2748,8 +2873,9 @@ static void acquire_notify_reply(DBusMessage *message, void *user_data)
 
 	DBG("AcquireNotify success: fd %d MTU %u\n", fd, mtu);
 
-	chrc->notify_io = sock_io_new(fd, chrc);
-	io_set_read_handler(chrc->notify_io, sock_io_read, chrc, NULL);
+	client = client_notify_io_get(chrc, fd, op->att);
+	if (!client)
+		goto retry;
 
 	__sync_fetch_and_add(&chrc->ntfy_cnt, 1);
 
@@ -2782,6 +2908,7 @@ static void acquire_notify_setup(DBusMessageIter *iter, void *user_data)
 static uint8_t ccc_write_cb(struct pending_op *op, void *user_data)
 {
 	struct external_chrc *chrc = user_data;
+	struct client_io *client;
 	DBusMessageIter iter;
 	uint16_t value;
 
@@ -2794,14 +2921,16 @@ static uint8_t ccc_write_cb(struct pending_op *op, void *user_data)
 		if (!chrc->ntfy_cnt)
 			goto done;
 
-		if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
+		client = queue_remove_if(chrc->notify_ios, match_client_att,
+							op ? op->att : NULL);
+		if (client) {
+			client_io_free(client);
+			__sync_sub_and_fetch(&chrc->ntfy_cnt, 1);
 			goto done;
+		}
 
-		if (chrc->notify_io) {
-			io_destroy(chrc->notify_io);
-			chrc->notify_io = NULL;
+		if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
 			goto done;
-		}
 
 		/*
 		 * Send request to stop notifying. This is best-effort
@@ -2822,7 +2951,8 @@ static uint8_t ccc_write_cb(struct pending_op *op, void *user_data)
 		(value == 2 && !(chrc->props & BT_GATT_CHRC_PROP_INDICATE)))
 		return BT_ERROR_CCC_IMPROPERLY_CONFIGURED;
 
-	if (chrc->notify_io) {
+	client = queue_find(chrc->notify_ios, match_client_att, op->att);
+	if (client) {
 		__sync_fetch_and_add(&chrc->ntfy_cnt, 1);
 		goto done;
 	}
@@ -3123,6 +3253,7 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
 					void *user_data)
 {
 	struct external_chrc *chrc = user_data;
+	struct client_io *client;
 	struct btd_device *device;
 	struct queue *queue;
 	DBusMessageIter iter;
@@ -3158,8 +3289,9 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
 	if (opcode == BT_ATT_OP_EXEC_WRITE_REQ)
 		chrc->prep_authorized = false;
 
-	if (chrc->write_io) {
-		if (sock_io_send(chrc->write_io, value, len) < 0) {
+	client = queue_find(chrc->write_ios, match_client_att, att);
+	if (client) {
+		if (sock_io_send(client->io, value, len) < 0) {
 			error("Unable to write: %s", strerror(errno));
 			goto fail;
 		}
@@ -3215,12 +3347,12 @@ static void database_add_includes(struct external_service *service)
 static bool database_add_chrc(struct external_service *service,
 						struct external_chrc *chrc)
 {
-	uint16_t handle;
+	uint16_t handle = 0, value_handle;
 	bt_uuid_t uuid;
 	char str[MAX_LEN_UUID_STR];
 	const struct queue_entry *entry;
 
-	if (!parse_handle(chrc->proxy, &handle)) {
+	if (!parse_handle(chrc->proxy, &value_handle)) {
 		error("Failed to read \"Handle\" property of characteristic");
 		return false;
 	}
@@ -3235,10 +3367,14 @@ static bool database_add_chrc(struct external_service *service,
 		return false;
 	}
 
+	if (value_handle)
+		handle = value_handle - 1;
+
 	chrc->attrib = gatt_db_service_insert_characteristic(service->attrib,
-						handle, &uuid, chrc->perm,
-						chrc->props, chrc_read_cb,
-						chrc_write_cb, chrc);
+						handle, value_handle, &uuid,
+						chrc->perm, chrc->props,
+						chrc_read_cb, chrc_write_cb,
+						chrc);
 	if (!chrc->attrib) {
 		error("Failed to create characteristic entry in database");
 		return false;
@@ -3788,6 +3924,70 @@ static uint8_t server_authorize(struct bt_att *att, uint8_t opcode,
 	return BT_ATT_ERROR_DB_OUT_OF_SYNC;
 }
 
+static void eatt_confirm_cb(GIOChannel *io, gpointer data)
+{
+	char address[18];
+	uint8_t dst_type;
+	bdaddr_t src, dst;
+	GError *gerr = NULL;
+	struct btd_device *device;
+	struct bt_gatt_server *server;
+	struct bt_att *att;
+
+	bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
+				BT_IO_OPT_DEST_BDADDR, &dst,
+				BT_IO_OPT_DEST_TYPE, &dst_type,
+				BT_IO_OPT_DEST, address,
+				BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("bt_io_get: %s", gerr->message);
+		g_error_free(gerr);
+		goto drop;
+	}
+
+	DBG("New incoming EATT connection");
+
+	/* Confirm the device exists before accepting the connection, if the
+	 * device is using an RPA it could be that the MGMT event has not been
+	 * processed yet which would lead to create a second copy of the same
+	 * device using its identity address.
+	 */
+	device = btd_adapter_find_device(adapter_find(&src), &dst, dst_type);
+	if (!device) {
+		error("Unable to find device: %s", address);
+		goto drop;
+	}
+
+	/* Only allow EATT connection from central */
+	if (btd_device_is_initiator(device)) {
+		warn("EATT connection from peripheral may cause collisions");
+		goto drop;
+	}
+
+	server = btd_device_get_gatt_server(device);
+	if (!server) {
+		error("Unable to resolve bt_server");
+		goto drop;
+	}
+
+	att = bt_gatt_server_get_att(server);
+	if (bt_att_get_channels(att) == btd_opts.gatt_channels) {
+		DBG("EATT channel limit reached");
+		goto drop;
+	}
+
+	if (!bt_io_accept(io, connect_cb, NULL, NULL, &gerr)) {
+		error("bt_io_accept: %s", gerr->message);
+		g_error_free(gerr);
+		goto drop;
+	}
+
+	return;
+
+drop:
+	g_io_channel_shutdown(io, TRUE, NULL);
+}
+
 struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
 {
 	struct btd_gatt_database *database;
@@ -3824,14 +4024,14 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
 	if (btd_opts.gatt_channels == 1)
 		goto bredr;
 
-	/* EATT socket */
-	database->eatt_io = bt_io_listen(connect_cb, NULL, NULL, NULL,
+	/* EATT socket, encryption is required */
+	database->eatt_io = bt_io_listen(NULL, eatt_confirm_cb, NULL, NULL,
 					&gerr,
 					BT_IO_OPT_SOURCE_BDADDR, addr,
 					BT_IO_OPT_SOURCE_TYPE,
 					btd_adapter_get_address_type(adapter),
 					BT_IO_OPT_PSM, BT_ATT_EATT_PSM,
-					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
 					BT_IO_OPT_MTU, btd_opts.gatt_mtu,
 					BT_IO_OPT_INVALID);
 	if (!database->eatt_io) {
diff --git a/src/genbuiltin b/src/genbuiltin
index 8b6f047..010e4ed 100755
--- a/src/genbuiltin
+++ b/src/genbuiltin
@@ -2,11 +2,11 @@
 
 for i in $*
 do
-	echo "extern struct bluetooth_plugin_desc __bluetooth_builtin_$i;"
+	echo "extern const struct bluetooth_plugin_desc __bluetooth_builtin_$i;"
 done
 
 echo
-echo "static struct bluetooth_plugin_desc *__bluetooth_builtin[] = {"
+echo "static const struct bluetooth_plugin_desc *__bluetooth_builtin[] = {"
 
 for i in $*
 do
diff --git a/src/log.c b/src/log.c
index 0155a6b..ca8ae2d 100644
--- a/src/log.c
+++ b/src/log.c
@@ -123,7 +123,7 @@ extern struct btd_debug_desc __stop___debug[];
 
 static char **enabled = NULL;
 
-static gboolean is_enabled(struct btd_debug_desc *desc)
+static gboolean is_enabled(const struct btd_debug_desc *desc)
 {
 	int i;
 
diff --git a/src/main.c b/src/main.c
index 1d35716..41c3271 100644
--- a/src/main.c
+++ b/src/main.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <signal.h>
 #include <stdbool.h>
+#include <limits.h>
 #include <sys/signalfd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -43,6 +44,7 @@
 #include "shared/mainloop.h"
 #include "shared/timeout.h"
 #include "shared/queue.h"
+#include "shared/crypto.h"
 #include "lib/uuid.h"
 #include "shared/util.h"
 #include "btd.h"
@@ -77,13 +79,16 @@ static const char *supported_options[] = {
 	"NameResolving",
 	"DebugKeys",
 	"ControllerMode",
-	"MaxControllers"
+	"MaxControllers",
 	"MultiProfile",
 	"FastConnectable",
+	"SecureConnections",
 	"Privacy",
 	"JustWorksRepairing",
 	"TemporaryTimeout",
+	"RefreshDiscovery",
 	"Experimental",
+	"Testing",
 	"KernelExperimental",
 	"RemoteNameRequestRetryDelay",
 	NULL
@@ -142,6 +147,15 @@ static const char *gatt_options[] = {
 	"KeySize",
 	"ExchangeMTU",
 	"Channels",
+	"Client",
+	NULL
+};
+
+static const char *csip_options[] = {
+	"SIRK",
+	"Encryption",
+	"Size",
+	"Rank",
 	NULL
 };
 
@@ -151,6 +165,12 @@ static const char *avdtp_options[] = {
 	NULL
 };
 
+static const char *avrcp_options[] = {
+	"VolumeWithoutTarget",
+	"VolumeCategory",
+	NULL
+};
+
 static const char *advmon_options[] = {
 	"RSSISamplingPeriod",
 	NULL
@@ -165,11 +185,56 @@ static const struct group_table {
 	{ "LE",		le_options },
 	{ "Policy",	policy_options },
 	{ "GATT",	gatt_options },
+	{ "CSIS",	csip_options },
 	{ "AVDTP",	avdtp_options },
+	{ "AVRCP",	avrcp_options },
 	{ "AdvMon",	advmon_options },
 	{ }
 };
 
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
+static int8_t check_sirk_alpha_numeric(char *str)
+{
+	int8_t val = 0;
+	char *s = str;
+
+	if (strlen(s) != 32) /* 32 Bytes of Alpha numeric string */
+		return 0;
+
+	for ( ; *s; s++) {
+		if (((*s >= '0') & (*s <= '9'))
+			|| ((*s >= 'a') && (*s <= 'z'))
+			|| ((*s >= 'A') && (*s <= 'Z'))) {
+			val = 1;
+		} else {
+			val = 0;
+			break;
+		}
+	}
+
+	return val;
+}
+
+static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
+{
+	size_t i, len;
+
+	if (!hexstr)
+		return 0;
+
+	len = MIN((strlen(hexstr) / 2), buflen);
+	memset(buf, 0, len);
+
+	for (i = 0; i < len; i++) {
+		if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1)
+			continue;
+	}
+
+	return len;
+}
 
 GKeyFile *btd_get_main_conf(void)
 {
@@ -257,7 +322,7 @@ done:
 	btd_opts.did_version = version;
 }
 
-static bt_gatt_cache_t parse_gatt_cache(const char *cache)
+static bt_gatt_cache_t parse_gatt_cache_str(const char *cache)
 {
 	if (!strcmp(cache, "always")) {
 		return BT_GATT_CACHE_ALWAYS;
@@ -359,6 +424,69 @@ static int get_mode(const char *str)
 	return BT_MODE_DUAL;
 }
 
+static bool parse_config_string(GKeyFile *config, const char *group,
+					const char *key, char **val)
+{
+	GError *err = NULL;
+	char *tmp;
+
+	tmp = g_key_file_get_string(config, group, key, &err);
+	if (err) {
+		if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
+			DBG("%s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
+	DBG("%s.%s = %s", group, key, tmp);
+
+	if (val) {
+		g_free(*val);
+		*val = tmp;
+	}
+
+	return true;
+}
+
+static bool parse_config_int(GKeyFile *config, const char *group,
+					const char *key, int *val,
+					size_t min, size_t max)
+{
+	size_t tmp;
+	char *str = NULL;
+	char *endptr = NULL;
+
+	if (!parse_config_string(config, group, key, &str))
+		return false;
+
+	tmp = strtol(str, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		error("%s.%s = %s is not integer", group, key, str);
+		g_free(str);
+		return false;
+	}
+
+	if (tmp < min) {
+		g_free(str);
+		warn("%s.%s = %zu is out of range (< %zu)", group, key, tmp,
+									min);
+		return false;
+	}
+
+	if (tmp > max) {
+		g_free(str);
+		warn("%s.%s = %zu is out of range (> %zu)", group, key, tmp,
+									max);
+		return false;
+	}
+
+	g_free(str);
+	if (val)
+		*val = tmp;
+
+	return true;
+}
+
 struct config_param {
 	const char * const val_name;
 	void * const val;
@@ -377,31 +505,15 @@ static void parse_mode_config(GKeyFile *config, const char *group,
 		return;
 
 	for (i = 0; i < params_len; ++i) {
-		GError *err = NULL;
-		char *str;
-
-		str = g_key_file_get_string(config, group, params[i].val_name,
-									&err);
-		if (err) {
-			DBG("%s", err->message);
-			g_clear_error(&err);
-		} else {
-			char *endptr = NULL;
-			int val;
-
-			val = strtol(str, &endptr, 0);
-			if (!endptr || *endptr != '\0')
-				continue;
-
-			info("%s=%s(%d)", params[i].val_name, str, val);
-
-			val = MAX(val, params[i].min);
-			val = MIN(val, params[i].max);
+		int val;
 
+		if (parse_config_int(config, group, params[i].val_name,
+					&val, params[i].min, params[i].max)) {
 			val = htobl(val);
 			memcpy(params[i].val, &val, params[i].size);
-			++btd_opts.defaults.num_entries;
 		}
+
+		++btd_opts.defaults.num_entries;
 	}
 }
 
@@ -651,330 +763,425 @@ static void btd_parse_kernel_experimental(char **list)
 	}
 }
 
-static void parse_config(GKeyFile *config)
+static bool gen_sirk(const char *str)
 {
-	GError *err = NULL;
-	char *str, **strlist;
-	int val;
-	gboolean boolean;
+	struct bt_crypto *crypto;
+	int ret;
 
-	if (!config)
-		return;
+	crypto = bt_crypto_new();
+	if (!crypto) {
+		error("Failed to open crypto");
+		return false;
+	}
 
-	check_config(config);
+	ret = bt_crypto_sirk(crypto, str, btd_opts.did_vendor,
+			   btd_opts.did_product, btd_opts.did_version,
+			   btd_opts.did_source, btd_opts.csis.sirk);
+	if (!ret)
+		error("Failed to generate SIRK");
 
-	DBG("parsing %s", main_conf_file_path);
+	bt_crypto_unref(crypto);
+	return ret;
+}
 
-	val = g_key_file_get_integer(config, "General",
-						"DiscoverableTimeout", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("discovto=%d", val);
-		btd_opts.discovto = val;
-	}
+static bool parse_config_u32(GKeyFile *config, const char *group,
+					const char *key, uint32_t *val,
+					uint32_t min, uint32_t max)
+{
+	int tmp;
 
-	boolean = g_key_file_get_boolean(config, "General",
-						"AlwaysPairable", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("pairable=%s", boolean ? "true" : "false");
-		btd_opts.pairable = boolean;
-	}
+	if (!parse_config_int(config, group, key, &tmp, min, max))
+		return false;
+
+	if (val)
+		*val = tmp;
+
+	return true;
+}
+
+static bool parse_config_u16(GKeyFile *config, const char *group,
+					const char *key, uint16_t *val,
+					uint16_t min, uint16_t max)
+{
+	int tmp;
+
+	if (!parse_config_int(config, group, key, &tmp, min, max))
+		return false;
+
+	if (val)
+		*val = tmp;
+
+	return true;
+}
+
+static bool parse_config_u8(GKeyFile *config, const char *group,
+					const char *key, uint8_t *val,
+					uint8_t min, uint8_t max)
+{
+	int tmp;
+
+	if (!parse_config_int(config, group, key, &tmp, min, max))
+		return false;
+
+	if (val)
+		*val = tmp;
+
+	return true;
+}
+
+static bool parse_config_bool(GKeyFile *config, const char *group,
+					const char *key, bool *val)
+{
+	GError *err = NULL;
+	gboolean tmp;
 
-	val = g_key_file_get_integer(config, "General",
-						"PairableTimeout", &err);
+	tmp = g_key_file_get_boolean(config, group, key, &err);
 	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("pairto=%d", val);
-		btd_opts.pairto = val;
+		if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
+			DBG("%s", err->message);
+		g_error_free(err);
+		return false;
 	}
 
-	str = g_key_file_get_string(config, "General", "Privacy", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
+	DBG("%s.%s = %s", group, key, tmp ? "true" : "false");
+
+	if (val)
+		*val = tmp;
+
+	return true;
+}
+
+static void parse_privacy(GKeyFile *config)
+{
+	char *str = NULL;
+
+	if (!parse_config_string(config, "General", "Privacy", &str)) {
 		btd_opts.privacy = 0x00;
 		btd_opts.device_privacy = true;
-	} else {
-		DBG("privacy=%s", str);
-
-		if (!strcmp(str, "network") || !strcmp(str, "on")) {
-			btd_opts.privacy = 0x01;
-		} else if (!strcmp(str, "device")) {
-			btd_opts.privacy = 0x01;
-			btd_opts.device_privacy = true;
-		} else if (!strcmp(str, "limited-network")) {
-			if (btd_opts.mode != BT_MODE_DUAL) {
-				DBG("Invalid privacy option: %s", str);
-				btd_opts.privacy = 0x00;
-			}
-			btd_opts.privacy = 0x01;
-		} else if (!strcmp(str, "limited-device")) {
-			if (btd_opts.mode != BT_MODE_DUAL) {
-				DBG("Invalid privacy option: %s", str);
-				btd_opts.privacy = 0x00;
-			}
-			btd_opts.privacy = 0x02;
-			btd_opts.device_privacy = true;
-		} else if (!strcmp(str, "off")) {
+		return;
+	}
+
+	if (!strcmp(str, "network") || !strcmp(str, "on")) {
+		btd_opts.privacy = 0x01;
+	} else if (!strcmp(str, "device")) {
+		btd_opts.privacy = 0x01;
+		btd_opts.device_privacy = true;
+	} else if (!strcmp(str, "limited-network")) {
+		if (btd_opts.mode != BT_MODE_DUAL) {
+			DBG("Invalid privacy option: %s", str);
 			btd_opts.privacy = 0x00;
-			btd_opts.device_privacy = true;
-		} else {
+		}
+		btd_opts.privacy = 0x01;
+	} else if (!strcmp(str, "limited-device")) {
+		if (btd_opts.mode != BT_MODE_DUAL) {
 			DBG("Invalid privacy option: %s", str);
 			btd_opts.privacy = 0x00;
 		}
-
-		g_free(str);
+		btd_opts.privacy = 0x02;
+		btd_opts.device_privacy = true;
+	} else if (!strcmp(str, "off")) {
+		btd_opts.privacy = 0x00;
+		btd_opts.device_privacy = true;
+	} else {
+		DBG("Invalid privacy option: %s", str);
+		btd_opts.privacy = 0x00;
 	}
 
-	str = g_key_file_get_string(config, "General",
-						"JustWorksRepairing", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
+	g_free(str);
+}
+
+static void parse_repairing(GKeyFile *config)
+{
+	char *str = NULL;
+
+	if (!parse_config_string(config, "General", "JustWorksRepairing",
+						&str)) {
 		btd_opts.jw_repairing = JW_REPAIRING_NEVER;
-	} else {
-		DBG("just_works_repairing=%s", str);
-		btd_opts.jw_repairing = parse_jw_repairing(str);
-		g_free(str);
+		return;
 	}
 
-	val = g_key_file_get_integer(config, "General",
-						"TemporaryTimeout", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("tmpto=%d", val);
-		btd_opts.tmpto = val;
-	}
+	btd_opts.jw_repairing = parse_jw_repairing(str);
+	g_free(str);
+}
 
-	str = g_key_file_get_string(config, "General", "Name", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("name=%s", str);
-		g_free(btd_opts.name);
-		btd_opts.name = str;
-	}
+static bool parse_config_hex(GKeyFile *config, char *group,
+					const char *key, uint32_t *val)
+{
+	char *str = NULL;
 
-	str = g_key_file_get_string(config, "General", "Class", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("class=%s", str);
-		btd_opts.class = strtol(str, NULL, 16);
-		g_free(str);
-	}
+	if (!parse_config_string(config, group, key, &str))
+		return false;
 
-	str = g_key_file_get_string(config, "General", "DeviceID", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("deviceid=%s", str);
-		parse_did(str);
-		g_free(str);
-	}
+	if (val)
+		*val = strtol(str, NULL, 16);
 
-	boolean = g_key_file_get_boolean(config, "General",
-						"ReverseServiceDiscovery", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else
-		btd_opts.reverse_discovery = boolean;
-
-	boolean = g_key_file_get_boolean(config, "General",
-						"NameResolving", &err);
-	if (err)
-		g_clear_error(&err);
-	else
-		btd_opts.name_resolv = boolean;
+	g_free(str);
+	return true;
+}
 
-	boolean = g_key_file_get_boolean(config, "General",
-						"DebugKeys", &err);
-	if (err)
-		g_clear_error(&err);
-	else
-		btd_opts.debug_keys = boolean;
+static void parse_device_id(GKeyFile *config)
+{
+	char *str = NULL;
 
-	str = g_key_file_get_string(config, "General", "ControllerMode", &err);
-	if (err) {
-		g_clear_error(&err);
-	} else {
-		DBG("ControllerMode=%s", str);
-		btd_opts.mode = get_mode(str);
-		g_free(str);
-	}
+	parse_config_string(config, "General", "DeviceID", &str);
+	if (!str)
+		return;
 
-	val = g_key_file_get_integer(config, "General", "MaxControllers", &err);
-	if (err) {
-		g_clear_error(&err);
-	} else {
-		DBG("MaxControllers=%d", val);
-		btd_opts.max_adapters = val;
-	}
+	parse_did(str);
+	g_free(str);
+}
 
-	str = g_key_file_get_string(config, "General", "MultiProfile", &err);
-	if (err) {
-		g_clear_error(&err);
-	} else {
-		DBG("MultiProfile=%s", str);
+static void parse_ctrl_mode(GKeyFile *config)
+{
+	char *str = NULL;
 
-		if (!strcmp(str, "single"))
-			btd_opts.mps = MPS_SINGLE;
-		else if (!strcmp(str, "multiple"))
-			btd_opts.mps = MPS_MULTIPLE;
-		else
-			btd_opts.mps = MPS_OFF;
+	parse_config_string(config, "General", "ControllerMode", &str);
+	if (!str)
+		return;
 
-		g_free(str);
-	}
+	btd_opts.mode = get_mode(str);
+	g_free(str);
+}
 
-	boolean = g_key_file_get_boolean(config, "General",
-						"FastConnectable", &err);
-	if (err)
-		g_clear_error(&err);
-	else
-		btd_opts.fast_conn = boolean;
+static void parse_multi_profile(GKeyFile *config)
+{
+	char *str = NULL;
 
-	boolean = g_key_file_get_boolean(config, "General",
-						"RefreshDiscovery", &err);
-	if (err)
-		g_clear_error(&err);
-	else
-		btd_opts.refresh_discovery = boolean;
+	parse_config_string(config, "General", "MultiProfile", &str);
+	if (!str)
+		return;
 
-	boolean = g_key_file_get_boolean(config, "General", "Experimental",
-						&err);
-	if (err)
-		g_clear_error(&err);
+	if (!strcmp(str, "single"))
+		btd_opts.mps = MPS_SINGLE;
+	else if (!strcmp(str, "multiple"))
+		btd_opts.mps = MPS_MULTIPLE;
 	else
-		btd_opts.experimental = boolean;
+		btd_opts.mps = MPS_OFF;
 
-	strlist = g_key_file_get_string_list(config, "General",
-						"KernelExperimental",
-						NULL, &err);
-	if (err)
-		g_clear_error(&err);
-	else {
+	g_free(str);
+}
+
+static gboolean parse_kernel_experimental(const char *key, const char *value,
+					gpointer user_data, GError **error)
+{
+	char **strlist;
+
+	if (value && value[0] != '*') {
+		strlist = g_strsplit(value, ",", -1);
 		btd_parse_kernel_experimental(strlist);
 		g_strfreev(strlist);
-	}
-
-	val = g_key_file_get_integer(config, "General",
-					"RemoteNameRequestRetryDelay", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
 	} else {
-		DBG("RemoteNameRequestRetryDelay=%d", val);
-		btd_opts.name_request_retry_delay = val;
+		if (!btd_opts.kernel)
+			btd_opts.kernel = queue_new();
+		queue_push_head(btd_opts.kernel, strdup("*"));
 	}
 
-	str = g_key_file_get_string(config, "GATT", "Cache", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		btd_opts.gatt_cache = parse_gatt_cache(str);
-		g_free(str);
-	}
+	return TRUE;
+}
 
-	val = g_key_file_get_integer(config, "GATT", "KeySize", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("KeySize=%d", val);
+static void parse_kernel_exp(GKeyFile *config)
+{
+	char *str = NULL;
 
-		if (val >=7 && val <= 16)
-			btd_opts.key_size = val;
-	}
+	if (!parse_config_string(config, "General", "KernelExperimental",
+						&str))
+		return;
 
-	val = g_key_file_get_integer(config, "GATT", "ExchangeMTU", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		/* Ensure the mtu is within a valid range. */
-		val = MIN(val, BT_ATT_MAX_LE_MTU);
-		val = MAX(val, BT_ATT_DEFAULT_LE_MTU);
-		DBG("ExchangeMTU=%d", val);
-		btd_opts.gatt_mtu = val;
-	}
+	parse_kernel_experimental(NULL, str, NULL, NULL);
 
-	val = g_key_file_get_integer(config, "GATT", "Channels", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("Channels=%d", val);
-		/* Ensure the channels is within a valid range. */
-		val = MIN(val, 5);
-		val = MAX(val, 1);
-		btd_opts.gatt_channels = val;
-	}
+	g_free(str);
+}
 
-	str = g_key_file_get_string(config, "AVDTP", "SessionMode", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("SessionMode=%s", str);
-
-		if (!strcmp(str, "basic"))
-			btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
-		else if (!strcmp(str, "ertm"))
-			btd_opts.avdtp.session_mode = BT_IO_MODE_ERTM;
-		else {
-			DBG("Invalid mode option: %s", str);
-			btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
-		}
-		g_free(str);
-	}
+static void parse_secure_conns(GKeyFile *config)
+{
+	char *str = NULL;
 
-	str = g_key_file_get_string(config, "AVDTP", "StreamMode", &err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		DBG("StreamMode=%s", str);
-
-		if (!strcmp(str, "basic"))
-			btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
-		else if (!strcmp(str, "streaming"))
-			btd_opts.avdtp.stream_mode = BT_IO_MODE_STREAMING;
-		else {
-			DBG("Invalid mode option: %s", str);
-			btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
-		}
-		g_free(str);
+	if (!parse_config_string(config, "General", "SecureConnections",
+								&str))
+		return;
+
+	if (!strcmp(str, "off"))
+		btd_opts.secure_conn = SC_OFF;
+	else if (!strcmp(str, "on"))
+		btd_opts.secure_conn = SC_ON;
+	else if (!strcmp(str, "only"))
+		btd_opts.secure_conn = SC_ONLY;
+
+	g_free(str);
+}
+
+static void parse_general(GKeyFile *config)
+{
+	parse_config_string(config, "General", "Name", &btd_opts.name);
+	parse_config_hex(config, "General", "Class", &btd_opts.class);
+	parse_config_u32(config, "General", "DiscoverableTimeout",
+						&btd_opts.discovto,
+						0, UINT32_MAX);
+	parse_config_bool(config, "General", "AlwaysPairable",
+						&btd_opts.pairable);
+	parse_config_u32(config, "General", "PairableTimeout",
+						&btd_opts.pairto,
+						0, UINT32_MAX);
+	parse_device_id(config);
+	parse_config_bool(config, "General", "ReverseServiceDiscovery",
+						&btd_opts.reverse_discovery);
+	parse_config_bool(config, "General", "NameResolving",
+						&btd_opts.name_resolv);
+	parse_config_bool(config, "General", "DebugKeys",
+						&btd_opts.debug_keys);
+	parse_ctrl_mode(config);
+	parse_config_u16(config, "General", "MaxControllers",
+						&btd_opts.max_adapters,
+						0, UINT16_MAX);
+	parse_multi_profile(config);
+	parse_config_bool(config, "General", "FastConnectable",
+						&btd_opts.fast_conn);
+	parse_privacy(config);
+	parse_repairing(config);
+	parse_config_u32(config, "General", "TemporaryTimeout",
+						&btd_opts.tmpto,
+						0, UINT32_MAX);
+	parse_config_bool(config, "General", "RefreshDiscovery",
+						&btd_opts.refresh_discovery);
+	parse_secure_conns(config);
+	parse_config_bool(config, "General", "Experimental",
+						&btd_opts.experimental);
+	parse_config_bool(config, "General", "Testing",
+						&btd_opts.testing);
+	parse_kernel_exp(config);
+	parse_config_u32(config, "General", "RemoteNameRequestRetryDelay",
+					&btd_opts.name_request_retry_delay,
+					0, UINT32_MAX);
+}
+
+static void parse_gatt_cache(GKeyFile *config)
+{
+	char *str = NULL;
+
+	parse_config_string(config, "GATT", "Cache", &str);
+	if (!str)
+		return;
+
+	btd_opts.gatt_cache = parse_gatt_cache_str(str);
+	g_free(str);
+}
+
+static void parse_gatt(GKeyFile *config)
+{
+	parse_gatt_cache(config);
+	parse_config_u8(config, "GATT", "KeySize", &btd_opts.key_size, 7, 16);
+	parse_config_u16(config, "GATT", "ExchangeMTU", &btd_opts.gatt_mtu,
+				BT_ATT_DEFAULT_LE_MTU, BT_ATT_MAX_LE_MTU);
+	parse_config_u8(config, "GATT", "Channels", &btd_opts.gatt_channels,
+				1, 5);
+	parse_config_bool(config, "GATT", "Client", &btd_opts.gatt_client);
+}
+
+static void parse_csis_sirk(GKeyFile *config)
+{
+	char *str = NULL;
+
+	if (!parse_config_string(config, "CSIS", "SIRK", &str))
+		return;
+
+	if (strlen(str) == 32 && check_sirk_alpha_numeric(str))
+		hex2bin(str, btd_opts.csis.sirk, sizeof(btd_opts.csis.sirk));
+	else if (!gen_sirk(str))
+		DBG("Unable to generate SIRK from string");
+
+	g_free(str);
+}
+
+static void parse_csis(GKeyFile *config)
+{
+	parse_csis_sirk(config);
+	parse_config_bool(config, "CSIS", "Encryption",
+					&btd_opts.csis.encrypt);
+	parse_config_u8(config, "CSIS", "Size", &btd_opts.csis.size,
+					0, UINT8_MAX);
+	parse_config_u8(config, "CSIS", "Rank", &btd_opts.csis.rank,
+					0, UINT8_MAX);
+}
+
+static void parse_avdtp_session_mode(GKeyFile *config)
+{
+	char *str = NULL;
+
+	if (!parse_config_string(config, "AVDTP", "SessionMode", &str))
+		return;
+
+	if (!strcmp(str, "basic"))
+		btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
+	else if (!strcmp(str, "ertm"))
+		btd_opts.avdtp.session_mode = BT_IO_MODE_ERTM;
+	else {
+		DBG("Invalid mode option: %s", str);
+		btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
 	}
 
-	val = g_key_file_get_integer(config, "AdvMon", "RSSISamplingPeriod",
-									&err);
-	if (err) {
-		DBG("%s", err->message);
-		g_clear_error(&err);
-	} else {
-		val = MIN(val, 0xFF);
-		val = MAX(val, 0);
-		DBG("RSSISamplingPeriod=%d", val);
-		btd_opts.advmon.rssi_sampling_period = val;
+	g_free(str);
+}
+
+static void parse_avdtp_stream_mode(GKeyFile *config)
+{
+	char *str = NULL;
+
+	if (!parse_config_string(config, "AVDTP", "StreamMode", &str))
+		return;
+
+	if (!strcmp(str, "basic"))
+		btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
+	else if (!strcmp(str, "streaming"))
+		btd_opts.avdtp.stream_mode = BT_IO_MODE_STREAMING;
+	else {
+		DBG("Invalid mode option: %s", str);
+		btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
 	}
 
+	g_free(str);
+}
+
+static void parse_avdtp(GKeyFile *config)
+{
+	parse_avdtp_session_mode(config);
+	parse_avdtp_stream_mode(config);
+}
+
+static void parse_avrcp(GKeyFile *config)
+{
+	parse_config_bool(config, "AVRCP",
+		"VolumeWithoutTarget",
+		&btd_opts.avrcp.volume_without_target);
+	parse_config_bool(config, "AVRCP",
+		"VolumeCategory",
+		&btd_opts.avrcp.volume_category);
+}
+
+static void parse_advmon(GKeyFile *config)
+{
+	parse_config_u8(config, "AdvMon", "RSSISamplingPeriod",
+				&btd_opts.advmon.rssi_sampling_period,
+				0, UINT8_MAX);
+}
+
+static void parse_config(GKeyFile *config)
+{
+	if (!config)
+		return;
+
+	check_config(config);
+
+	DBG("parsing %s", main_conf_file_path);
+
+	/* Parse Groups */
+	parse_general(config);
 	parse_br_config(config);
 	parse_le_config(config);
+	parse_gatt(config);
+	parse_csis(config);
+	parse_avdtp(config);
+	parse_avrcp(config);
+	parse_advmon(config);
 }
 
 static void init_defaults(void)
@@ -993,6 +1200,7 @@ static void init_defaults(void)
 	btd_opts.debug_keys = FALSE;
 	btd_opts.refresh_discovery = TRUE;
 	btd_opts.name_request_retry_delay = DEFAULT_NAME_REQUEST_RETRY_DELAY;
+	btd_opts.secure_conn = SC_ON;
 
 	btd_opts.defaults.num_entries = 0;
 	btd_opts.defaults.br.page_scan_type = 0xFFFF;
@@ -1009,12 +1217,17 @@ static void init_defaults(void)
 
 	btd_opts.gatt_cache = BT_GATT_CACHE_ALWAYS;
 	btd_opts.gatt_mtu = BT_ATT_MAX_LE_MTU;
-	btd_opts.gatt_channels = 3;
+	btd_opts.gatt_channels = 1;
+	btd_opts.gatt_client = true;
 
 	btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
 	btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
 
+	btd_opts.avrcp.volume_without_target = false;
+	btd_opts.avrcp.volume_category = true;
+
 	btd_opts.advmon.rssi_sampling_period = 0xFF;
+	btd_opts.csis.encrypt = true;
 }
 
 static void log_handler(const gchar *log_domain, GLogLevelFlags log_level,
@@ -1109,6 +1322,11 @@ static void disconnected_dbus(DBusConnection *conn, void *data)
 	mainloop_quit();
 }
 
+static void dbus_debug(const char *str, void *data)
+{
+	DBG_IDX(0xffff, "%s", str);
+}
+
 static int connect_dbus(void)
 {
 	DBusConnection *conn;
@@ -1130,6 +1348,7 @@ static int connect_dbus(void)
 
 	g_dbus_set_disconnect_function(conn, disconnected_dbus, NULL, NULL);
 	g_dbus_attach_object_manager(conn);
+	g_dbus_set_debug(dbus_debug, NULL, NULL);
 
 	return 0;
 }
@@ -1145,24 +1364,6 @@ static gboolean parse_debug(const char *key, const char *value,
 	return TRUE;
 }
 
-static gboolean parse_kernel_experimental(const char *key, const char *value,
-					gpointer user_data, GError **error)
-{
-	char **strlist;
-
-	if (value) {
-		strlist = g_strsplit(value, ",", -1);
-		btd_parse_kernel_experimental(strlist);
-		g_strfreev(strlist);
-	} else {
-		if (!btd_opts.kernel)
-			btd_opts.kernel = queue_new();
-		queue_push_head(btd_opts.kernel, strdup("*"));
-	}
-
-	return TRUE;
-}
-
 static GOptionEntry options[] = {
 	{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
 				G_OPTION_ARG_CALLBACK, parse_debug,
@@ -1177,6 +1378,8 @@ static GOptionEntry options[] = {
 				"Provide deprecated command line interfaces" },
 	{ "experimental", 'E', 0, G_OPTION_ARG_NONE, &btd_opts.experimental,
 				"Enable experimental D-Bus interfaces" },
+	{ "testing", 'T', 0, G_OPTION_ARG_NONE, &btd_opts.testing,
+				"Enable testing D-Bus interfaces" },
 	{ "kernel", 'K', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
 				parse_kernel_experimental,
 				"Enable kernel experimental features" },
@@ -1243,6 +1446,9 @@ int main(int argc, char *argv[])
 	if (btd_opts.experimental)
 		gdbus_flags = G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
 
+	if (btd_opts.testing)
+		gdbus_flags |= G_DBUS_FLAG_ENABLE_TESTING;
+
 	g_dbus_set_flags(gdbus_flags);
 
 	if (adapter_init() < 0) {
diff --git a/src/main.conf b/src/main.conf
index 2796f15..fff13ed 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -33,7 +33,7 @@
 # us. For BR/EDR this option is really only needed for qualification since the
 # BITE tester doesn't like us doing reverse SDP for some test cases, for LE
 # this disables the GATT client functionally so it can be used in system which
-# can only operate as peripheral.
+# can only operate as peripheral (see also GATT Client option).
 # Defaults to 'true'.
 #ReverseServiceDiscovery = true
 
@@ -111,10 +111,25 @@
 # profile is connected. Defaults to true.
 #RefreshDiscovery = true
 
+# Default Secure Connections setting.
+# Enables the Secure Connections setting for adapters that support it. It
+# provides better crypto algorithms for BT links and also enables CTKD (cross
+# transport key derivation) during pairing on any link.
+# Possible values: "off", "on", "only"
+# - "off": Secure Connections are disabled
+# - "on": Secure Connections are enabled when peer device supports them
+# - "only": we allow only Secure Connections
+# Defaults to "on"
+#SecureConnections = on
+
 # Enables D-Bus experimental interfaces
 # Possible values: true or false
 #Experimental = false
 
+# Enables D-Bus testing interfaces
+# Possible values: true or false
+#Testing = false
+
 # Enables kernel experimental features, alternatively a list of UUIDs
 # can be given.
 # Possible values: true,false,<UUID List>
@@ -244,8 +259,38 @@
 
 # Number of ATT channels
 # Possible values: 1-5 (1 disables EATT)
-# Default to 3
-#Channels = 3
+# Default to 1
+#Channels = 1
+
+[CSIS]
+# SIRK - Set Identification Resolution Key which is common for all the
+# sets. They SIRK key is used to identify its sets. This can be any
+# 128 bit value or a string value (e.g. product name) which is then hashed.
+# Possible Values:
+# 16 byte hexadecimal value: 861FAE703ED681F0C50B34155B6434FB
+# String value: "My Product Name"
+# Defaults to none
+#SIRK =
+
+# SIRK Encryption
+# Possible values:
+# true: Encrypt SIRK when read
+# false: Do not encrypt SIRK when read. (plaintext)
+# Defaults to true
+#Encryption = true
+
+# Total no of sets belongs to this Profile
+# Defaults to 0
+#Size = 0
+
+# Rank for the device
+# Defaults to 0
+#Rank = 0
+
+# This enables the GATT client functionally, so it can be disabled in system
+# which can only operate as a peripheral.
+# Defaults to 'true'.
+#Client = true
 
 [AVDTP]
 # AVDTP L2CAP Signalling Channel Mode.
@@ -260,6 +305,17 @@
 # streaming: Use L2CAP Streaming Mode
 #StreamMode = basic
 
+[AVRCP]
+# Allow SetAbsoluteVolume calls to a peer device that does not advertise the
+# AVRCP remote control target profile.  If it does advertise this profile, the
+# version is ignored.
+#VolumeWithoutTarget = false
+
+# Validate that remote AVRCP profiles advertise the category-2 bit before
+# allowing SetAbsoluteVolume calls or registering for EVENT_VOLUME_CHANGED
+# notifications.
+#VolumeCategory = true
+
 [Policy]
 #
 # The ReconnectUUIDs defines the set of remote services that should try
diff --git a/src/oui.c b/src/oui.c
index c434f41..7b3040f 100644
--- a/src/oui.c
+++ b/src/oui.c
@@ -16,7 +16,7 @@
 #include "lib/bluetooth.h"
 #include "oui.h"
 
-#ifdef HAVE_UDEV_HWDB_NEW
+#ifdef HAVE_UDEV
 #include <libudev.h>
 
 char *batocomp(const bdaddr_t *ba)
diff --git a/src/plugin.c b/src/plugin.c
index dd7b406..e6d05be 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -26,12 +26,13 @@
 #include "src/log.h"
 #include "src/btd.h"
 
+#define IS_ENABLED(x) (x)
+
 static GSList *plugins = NULL;
 
 struct bluetooth_plugin {
 	void *handle;
-	gboolean active;
-	struct bluetooth_plugin_desc *desc;
+	const struct bluetooth_plugin_desc *desc;
 };
 
 static int compare_priority(gconstpointer a, gconstpointer b)
@@ -42,7 +43,24 @@ static int compare_priority(gconstpointer a, gconstpointer b)
 	return plugin2->desc->priority - plugin1->desc->priority;
 }
 
-static gboolean add_plugin(void *handle, struct bluetooth_plugin_desc *desc)
+static int init_plugin(const struct bluetooth_plugin_desc *desc)
+{
+	int err;
+
+	err = desc->init();
+	if (err < 0) {
+		if (err == -ENOSYS || err == -ENOTSUP)
+			warn("System does not support %s plugin",
+						desc->name);
+		else
+			error("Failed to init %s plugin",
+						desc->name);
+	}
+	return err;
+}
+
+static gboolean add_external_plugin(void *handle,
+				const struct bluetooth_plugin_desc *desc)
 {
 	struct bluetooth_plugin *plugin;
 
@@ -54,23 +72,47 @@ static gboolean add_plugin(void *handle, struct bluetooth_plugin_desc *desc)
 		return FALSE;
 	}
 
-	DBG("Loading %s plugin", desc->name);
-
 	plugin = g_try_new0(struct bluetooth_plugin, 1);
 	if (plugin == NULL)
 		return FALSE;
 
 	plugin->handle = handle;
-	plugin->active = FALSE;
 	plugin->desc = desc;
 
+	if (init_plugin(desc) < 0) {
+		g_free(plugin);
+		return FALSE;
+	}
+
 	__btd_enable_debug(desc->debug_start, desc->debug_stop);
 
 	plugins = g_slist_insert_sorted(plugins, plugin, compare_priority);
+	DBG("Plugin %s loaded", desc->name);
 
 	return TRUE;
 }
 
+static void add_plugin(const struct bluetooth_plugin_desc *desc)
+{
+	struct bluetooth_plugin *plugin;
+
+	DBG("Loading %s plugin", desc->name);
+
+	plugin = g_try_new0(struct bluetooth_plugin, 1);
+	if (plugin == NULL)
+		return;
+
+	plugin->desc = desc;
+
+	if (init_plugin(desc) < 0) {
+		g_free(plugin);
+		return;
+	}
+
+	plugins = g_slist_insert_sorted(plugins, plugin, compare_priority);
+	DBG("Plugin %s loaded", desc->name);
+}
+
 static gboolean enable_plugin(const char *name, char **cli_enable,
 							char **cli_disable)
 {
@@ -97,51 +139,26 @@ static gboolean enable_plugin(const char *name, char **cli_enable,
 	return TRUE;
 }
 
-#include "src/builtin.h"
 
-gboolean plugin_init(const char *enable, const char *disable)
+static void external_plugin_init(char **cli_disabled, char **cli_enabled)
 {
-	GSList *list;
 	GDir *dir;
 	const char *file;
-	char **cli_disabled, **cli_enabled;
-	unsigned int i;
 
-	/* Make a call to BtIO API so its symbols got resolved before the
-	 * plugins are loaded. */
-	bt_io_error_quark();
-
-	if (enable)
-		cli_enabled = g_strsplit_set(enable, ", ", -1);
-	else
-		cli_enabled = NULL;
-
-	if (disable)
-		cli_disabled = g_strsplit_set(disable, ", ", -1);
-	else
-		cli_disabled = NULL;
-
-	DBG("Loading builtin plugins");
-
-	for (i = 0; __bluetooth_builtin[i]; i++) {
-		if (!enable_plugin(__bluetooth_builtin[i]->name, cli_enabled,
-								cli_disabled))
-			continue;
-
-		add_plugin(NULL,  __bluetooth_builtin[i]);
-	}
+	info("Using external plugins is not officially supported.\n");
+	info("Consider upstreaming your plugins into the BlueZ project.");
 
 	if (strlen(PLUGINDIR) == 0)
-		goto start;
+		return;
 
 	DBG("Loading plugins %s", PLUGINDIR);
 
 	dir = g_dir_open(PLUGINDIR, 0, NULL);
 	if (!dir)
-		goto start;
+		return;
 
 	while ((file = g_dir_read_name(dir)) != NULL) {
-		struct bluetooth_plugin_desc *desc;
+		const struct bluetooth_plugin_desc *desc;
 		void *handle;
 		char *filename;
 
@@ -173,35 +190,46 @@ gboolean plugin_init(const char *enable, const char *disable)
 			continue;
 		}
 
-		if (add_plugin(handle, desc) == FALSE)
+		if (add_external_plugin(handle, desc) == FALSE)
 			dlclose(handle);
 	}
 
 	g_dir_close(dir);
+}
 
-start:
-	for (list = plugins; list; list = list->next) {
-		struct bluetooth_plugin *plugin = list->data;
-		int err;
-
-		err = plugin->desc->init();
-		if (err < 0) {
-			if (err == -ENOSYS)
-				warn("System does not support %s plugin",
-							plugin->desc->name);
-			else
-				error("Failed to init %s plugin",
-							plugin->desc->name);
+#include "src/builtin.h"
+
+void plugin_init(const char *enable, const char *disable)
+{
+	char **cli_disabled = NULL;
+	char **cli_enabled = NULL;
+	unsigned int i;
+
+	/* Make a call to BtIO API so its symbols got resolved before the
+	 * plugins are loaded. */
+	bt_io_error_quark();
+
+	if (enable)
+		cli_enabled = g_strsplit_set(enable, ", ", -1);
+
+	if (disable)
+		cli_disabled = g_strsplit_set(disable, ", ", -1);
+
+	DBG("Loading builtin plugins");
+
+	for (i = 0; __bluetooth_builtin[i]; i++) {
+		if (!enable_plugin(__bluetooth_builtin[i]->name, cli_enabled,
+								cli_disabled))
 			continue;
-		}
 
-		plugin->active = TRUE;
+		add_plugin(__bluetooth_builtin[i]);
 	}
 
+	if IS_ENABLED(EXTERNAL_PLUGINS)
+		external_plugin_init(cli_enabled, cli_disabled);
+
 	g_strfreev(cli_enabled);
 	g_strfreev(cli_disabled);
-
-	return TRUE;
 }
 
 void plugin_cleanup(void)
@@ -213,7 +241,7 @@ void plugin_cleanup(void)
 	for (list = plugins; list; list = list->next) {
 		struct bluetooth_plugin *plugin = list->data;
 
-		if (plugin->active == TRUE && plugin->desc->exit)
+		if (plugin->desc->exit)
 			plugin->desc->exit();
 
 		if (plugin->handle != NULL)
diff --git a/src/plugin.h b/src/plugin.h
index a5f92a5..b484ed3 100644
--- a/src/plugin.h
+++ b/src/plugin.h
@@ -23,19 +23,25 @@ struct bluetooth_plugin_desc {
 
 #ifdef BLUETOOTH_PLUGIN_BUILTIN
 #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \
-		struct bluetooth_plugin_desc __bluetooth_builtin_ ## name = { \
+		const struct bluetooth_plugin_desc \
+		__bluetooth_builtin_ ## name = { \
 			#name, version, priority, init, exit \
 		};
 #else
+#if EXTERNAL_PLUGINS
 #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \
 		extern struct btd_debug_desc __start___debug[] \
 				__attribute__ ((weak, visibility("hidden"))); \
 		extern struct btd_debug_desc __stop___debug[] \
 				__attribute__ ((weak, visibility("hidden"))); \
-		extern struct bluetooth_plugin_desc bluetooth_plugin_desc \
+		extern const struct bluetooth_plugin_desc \
+				bluetooth_plugin_desc \
 				__attribute__ ((visibility("default"))); \
-		struct bluetooth_plugin_desc bluetooth_plugin_desc = { \
+		const struct bluetooth_plugin_desc bluetooth_plugin_desc = { \
 			#name, version, priority, init, exit, \
 			__start___debug, __stop___debug \
 		};
+#else
+#error "Requested non built-in plugin, while external plugins is disabled"
+#endif
 #endif
diff --git a/src/profile.c b/src/profile.c
index e1bebf1..c62224a 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -775,6 +775,18 @@ static struct btd_profile *btd_profile_find_uuid(const char *uuid)
 
 int btd_profile_register(struct btd_profile *profile)
 {
+	if (profile->experimental && !(g_dbus_get_flags() &
+					G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+		DBG("D-Bus experimental not enabled");
+		return -ENOTSUP;
+	}
+
+	if (profile->testing && !(g_dbus_get_flags() &
+					G_DBUS_FLAG_ENABLE_TESTING)) {
+		DBG("D-Bus testing not enabled");
+		return -ENOTSUP;
+	}
+
 	profiles = g_slist_append(profiles, profile);
 	return 0;
 }
diff --git a/src/profile.h b/src/profile.h
index 6827f84..424ce55 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -28,6 +28,16 @@ struct btd_profile {
 	 */
 	bool external;
 
+	/* Indicates the profile is experimental and shall only be registered
+	 * when experimental has been enabled (see: main.conf:Experimental).
+	 */
+	bool experimental;
+
+	/* Indicates the profile for testing only and shall only be registered
+	 * when testing has been enabled (see: main.conf:Testing).
+	 */
+	bool testing;
+
 	int (*device_probe) (struct btd_service *service);
 	void (*device_remove) (struct btd_service *service);
 
diff --git a/src/rfkill.c b/src/rfkill.c
index a0a50d9..88cad1c 100644
--- a/src/rfkill.c
+++ b/src/rfkill.c
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #include <glib.h>
 
@@ -55,7 +56,7 @@ struct rfkill_event {
 };
 #define RFKILL_EVENT_SIZE_V1    8
 
-static int get_adapter_id_for_rfkill(int rfkill_id)
+static int get_adapter_id_for_rfkill(uint32_t rfkill_id)
 {
 	char sysname[PATH_MAX];
 	int namefd;
diff --git a/src/set.c b/src/set.c
new file mode 100644
index 0000000..4ca2f78
--- /dev/null
+++ b/src/set.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  Intel Corporation
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "gdbus/gdbus.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
+#include "src/shared/ad.h"
+#include "src/shared/crypto.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+
+#include "log.h"
+#include "error.h"
+#include "adapter.h"
+#include "device.h"
+#include "dbus-common.h"
+#include "set.h"
+
+static struct queue *set_list;
+
+struct btd_device_set {
+	struct btd_adapter *adapter;
+	char *path;
+	uint8_t sirk[16];
+	uint8_t size;
+	bool auto_connect;
+	struct queue *devices;
+	struct btd_device *device;
+};
+
+static DBusMessage *set_disconnect(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	/* TODO */
+	return NULL;
+}
+
+static DBusMessage *set_connect(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	/* TODO */
+	return NULL;
+}
+
+static const GDBusMethodTable set_methods[] = {
+	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("Disconnect", NULL, NULL,
+						set_disconnect) },
+	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("Connect", NULL, NULL,
+						set_connect) },
+	{}
+};
+
+static gboolean get_adapter(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device_set *set = data;
+	const char *path = adapter_get_path(set->adapter);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	return TRUE;
+}
+
+static gboolean get_auto_connect(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device_set *set = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
+						&set->auto_connect);
+
+	return TRUE;
+}
+
+static void set_auto_connect(const GDBusPropertyTable *property,
+					DBusMessageIter *iter,
+					 GDBusPendingPropertySet id, void *data)
+{
+	struct btd_device_set *set = data;
+	dbus_bool_t b;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) {
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
+		return;
+	}
+
+	dbus_message_iter_get_basic(iter, &b);
+
+	set->auto_connect = b ? true : false;
+
+	g_dbus_pending_property_success(id);
+}
+
+static void append_device(void *data, void *user_data)
+{
+	struct btd_device *device = data;
+	const char *path = device_get_path(device);
+	DBusMessageIter *entry = user_data;
+
+	dbus_message_iter_append_basic(entry, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static gboolean get_devices(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device_set *set = data;
+	DBusMessageIter entry;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_OBJECT_PATH_AS_STRING,
+					&entry);
+
+	queue_foreach(set->devices, append_device, &entry);
+
+	dbus_message_iter_close_container(iter, &entry);
+
+	return TRUE;
+}
+
+static gboolean get_size(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device_set *set = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &set->size);
+
+	return TRUE;
+}
+
+static const GDBusPropertyTable set_properties[] = {
+	{ "Adapter", "o", get_adapter, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "AutoConnect", "b", get_auto_connect, set_auto_connect, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Devices", "ao", get_devices, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Size", "y", get_size, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{}
+};
+
+static void set_free(void *data)
+{
+	struct btd_device_set *set = data;
+
+	queue_destroy(set->devices, NULL);
+	g_free(set->path);
+	free(set);
+}
+
+static struct btd_device_set *set_new(struct btd_device *device,
+					const uint8_t sirk[16], uint8_t size)
+{
+	struct btd_device_set *set;
+
+	set = new0(struct btd_device_set, 1);
+	set->adapter = device_get_adapter(device);
+	memcpy(set->sirk, sirk, sizeof(set->sirk));
+	set->size = size;
+	set->auto_connect = true;
+	set->devices = queue_new();
+	queue_push_tail(set->devices, device);
+	set->path = g_strdup_printf("%s/set_%02x%02x%02x%02x%02x%02x%02x%02x"
+					"%02x%02x%02x%02x%02x%02x%02x%02x",
+					adapter_get_path(set->adapter),
+					sirk[15], sirk[14], sirk[13], sirk[12],
+					sirk[11], sirk[10], sirk[9], sirk[8],
+					sirk[7], sirk[6], sirk[5], sirk[4],
+					sirk[3], sirk[2], sirk[1], sirk[0]);
+
+	DBG("Creating set %s", set->path);
+
+	if (g_dbus_register_interface(btd_get_dbus_connection(),
+					set->path, BTD_DEVICE_SET_INTERFACE,
+					set_methods, NULL,
+					set_properties, set,
+					set_free) == FALSE) {
+		error("Unable to register set interface");
+		set_free(set);
+		return NULL;
+	}
+
+	return set;
+}
+
+static struct btd_device_set *set_find(struct btd_device *device,
+						const uint8_t sirk[16])
+{
+	struct btd_adapter *adapter = device_get_adapter(device);
+	const struct queue_entry *entry;
+
+	for (entry = queue_get_entries(set_list); entry; entry = entry->next) {
+		struct btd_device_set *set = entry->data;
+
+		if (set->adapter != adapter)
+			continue;
+
+		if (!memcmp(set->sirk, sirk, sizeof(set->sirk)))
+			return set;
+	}
+
+	return NULL;
+}
+
+static void set_connect_next(struct btd_device_set *set)
+{
+	const struct queue_entry *entry;
+
+	for (entry = queue_get_entries(set->devices); entry;
+					entry = entry->next) {
+		struct btd_device *device = entry->data;
+
+		/* Only connect one at time(?) */
+		if (!device_connect_le(device))
+			return;
+	}
+}
+
+static void set_add(struct btd_device_set *set, struct btd_device *device)
+{
+	/* Check if device is already part of the set then skip to connect */
+	if (queue_find(set->devices, NULL, device))
+		goto done;
+
+	DBG("set %s device %s", set->path, device_get_path(device));
+
+	queue_push_tail(set->devices, device);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), set->path,
+					BTD_DEVICE_SET_INTERFACE, "Devices");
+
+done:
+	/* Check if set is marked to auto-connect */
+	if (btd_device_is_connected(device) && set->auto_connect)
+		set_connect_next(set);
+}
+
+static void foreach_rsi(void *data, void *user_data)
+{
+	struct bt_ad_data *ad = data;
+	struct btd_device_set *set = user_data;
+	struct bt_crypto *crypto;
+	uint8_t res[3];
+
+	if (ad->type != BT_AD_CSIP_RSI || ad->len < 6)
+		return;
+
+	crypto = bt_crypto_new();
+	if (!crypto)
+		return;
+
+	if (!bt_crypto_sih(crypto, set->sirk, ad->data + 3, res)) {
+		bt_crypto_unref(crypto);
+		return;
+	}
+
+	bt_crypto_unref(crypto);
+
+	if (memcmp(ad->data, res, sizeof(res)))
+		return;
+
+	/* Attempt to use existing gatt_db from set if device has never been
+	 * connected before.
+	 *
+	 * If dbs don't really match bt_gatt_client will attempt to rediscover
+	 * the ranges that don't match.
+	 */
+	if (gatt_db_isempty(btd_device_get_gatt_db(set->device))) {
+		struct btd_device *device;
+
+		device = queue_get_entries(set->devices)->data;
+		btd_device_set_gatt_db(set->device,
+					btd_device_get_gatt_db(device));
+	}
+
+	device_connect_le(set->device);
+}
+
+static void foreach_device(struct btd_device *device, void *data)
+{
+	struct btd_device_set *set = data;
+
+	/* Check if device is already part of the set then skip */
+	if (queue_find(set->devices, NULL, device))
+		return;
+
+	set->device = device;
+
+	btd_device_foreach_ad(device, foreach_rsi, set);
+}
+
+struct btd_device_set *btd_set_add_device(struct btd_device *device,
+						const uint8_t *key,
+						const uint8_t sirk_value[16],
+						uint8_t size)
+{
+	struct btd_device_set *set;
+	uint8_t sirk[16];
+
+	memcpy(sirk, sirk_value, sizeof(sirk));
+
+	/* In case key has been set it means SIRK is encrypted */
+	if (key) {
+		struct bt_crypto *crypto = bt_crypto_new();
+
+		if (!crypto)
+			return NULL;
+
+		/* sef and sdf are symmetric */
+		bt_crypto_sef(crypto, key, sirk, sirk);
+
+		bt_crypto_unref(crypto);
+	}
+
+	/* Check if DeviceSet already exists */
+	set = set_find(device, sirk);
+	if (set) {
+		set_add(set, device);
+		/* Check if there are new devices with RSI found */
+		goto done;
+	}
+
+	set = set_new(device, sirk, size);
+	if (!set)
+		return NULL;
+
+	if (!set_list)
+		set_list = queue_new();
+
+	queue_push_tail(set_list, set);
+
+done:
+	/* Attempt to add devices which have matching RSI */
+	btd_adapter_for_each_device(device_get_adapter(device), foreach_device,
+									set);
+
+	return set;
+}
+
+bool btd_set_remove_device(struct btd_device_set *set,
+						struct btd_device *device)
+{
+	if (!set || !device)
+		return false;
+
+	if (!queue_remove_if(set->devices, NULL, device))
+		return false;
+
+	if (!queue_isempty(set->devices)) {
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						set->path,
+						BTD_DEVICE_SET_INTERFACE,
+						"Devices");
+		return true;
+	}
+
+	if (!queue_remove(set_list, set))
+		return false;
+
+	/* Unregister if there are no devices left in the set */
+	g_dbus_unregister_interface(btd_get_dbus_connection(), set->path,
+						BTD_DEVICE_SET_INTERFACE);
+
+	return true;
+}
+
+const char *btd_set_get_path(struct btd_device_set *set)
+{
+	return set->path;
+}
diff --git a/src/set.h b/src/set.h
new file mode 100644
index 0000000..2307218
--- /dev/null
+++ b/src/set.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  Intel Corporation
+ *
+ *
+ */
+
+#define BTD_DEVICE_SET_INTERFACE	"org.bluez.DeviceSet1"
+
+struct btd_device_set;
+
+struct btd_device_set *btd_set_add_device(struct btd_device *device,
+						const uint8_t *ltk,
+						const uint8_t sirk[16],
+						uint8_t size);
+bool btd_set_remove_device(struct btd_device_set *set,
+						struct btd_device *device);
+const char *btd_set_get_path(struct btd_device_set *set);
diff --git a/src/settings.c b/src/settings.c
index 85534f2..3716493 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -58,13 +58,17 @@ static int load_desc(struct gatt_db *db, char *handle, char *value,
 	uint16_t val;
 	bt_uuid_t uuid, ext_uuid;
 
-	if (sscanf(handle, "%04hx", &handle_int) != 1)
+	if (sscanf(handle, "%04hx", &handle_int) != 1) {
+		DBG("Failed to parse handle: %s", handle);
 		return -EIO;
+	}
 
 	/* Check if there is any value stored, otherwise it is just the UUID */
 	if (sscanf(value, "%04hx:%36s", &val, uuid_str) != 2) {
-		if (sscanf(value, "%36s", uuid_str) != 1)
+		if (sscanf(value, "%36s", uuid_str) != 1) {
+			DBG("Failed to parse value: %s", value);
 			return -EIO;
+		}
 		val = 0;
 	}
 
@@ -104,8 +108,10 @@ static int load_chrc(struct gatt_db *db, char *handle, char *value,
 	size_t val_len;
 	bt_uuid_t uuid;
 
-	if (sscanf(handle, "%04hx", &handle_int) != 1)
+	if (sscanf(handle, "%04hx", &handle_int) != 1) {
+		DBG("Failed to parse handle: %s", handle);
 		return -EIO;
+	}
 
 	/* Check if there is any value stored */
 	if (sscanf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hx:%32s:%36s",
@@ -125,7 +131,8 @@ static int load_chrc(struct gatt_db *db, char *handle, char *value,
 				handle_int, value_handle,
 				properties, val_len ? val_str : "", uuid_str);
 
-	att = gatt_db_service_insert_characteristic(service, value_handle,
+	att = gatt_db_service_insert_characteristic(service, handle_int,
+							value_handle,
 							&uuid, 0, properties,
 							NULL, NULL, NULL);
 	if (!att || gatt_db_attribute_get_handle(att) != value_handle)
@@ -147,12 +154,16 @@ static int load_incl(struct gatt_db *db, char *handle, char *value,
 	struct gatt_db_attribute *att;
 	uint16_t start, end;
 
-	if (sscanf(handle, "%04hx", &start) != 1)
+	if (sscanf(handle, "%04hx", &start) != 1) {
+		DBG("Failed to parse handle: %s", handle);
 		return -EIO;
+	}
 
 	if (sscanf(value, GATT_INCLUDE_UUID_STR ":%04hx:%04hx:%36s", &start,
-							&end, uuid_str) != 3)
+							&end, uuid_str) != 3) {
+		DBG("Failed to parse value: %s", value);
 		return -EIO;
+	}
 
 	/* Log debug message. */
 	DBG("loading included service: 0x%04x, end: 0x%04x, uuid: %s",
@@ -177,11 +188,15 @@ static int load_service(struct gatt_db *db, char *handle, char *value)
 	bt_uuid_t uuid;
 	bool primary;
 
-	if (sscanf(handle, "%04hx", &start) != 1)
+	if (sscanf(handle, "%04hx", &start) != 1) {
+		DBG("Failed to parse handle: %s", handle);
 		return -EIO;
+	}
 
-	if (sscanf(value, "%[^:]:%04hx:%36s", type, &end, uuid_str) != 3)
+	if (sscanf(value, "%36[^:]:%04hx:%36s", type, &end, uuid_str) != 3) {
+		DBG("Failed to parse value: %s", value);
 		return -EIO;
+	}
 
 	if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR))
 		primary = true;
@@ -217,7 +232,7 @@ static int gatt_db_load(struct gatt_db *db, GKeyFile *key_file, char **keys)
 		value = g_key_file_get_string(key_file, "Attributes", *handle,
 									NULL);
 
-		if (sscanf(value, "%[^:]:", type) != 1) {
+		if (!value || sscanf(value, "%36[^:]:", type) != 1) {
 			g_free(value);
 			return -EIO;
 		}
@@ -240,7 +255,7 @@ static int gatt_db_load(struct gatt_db *db, GKeyFile *key_file, char **keys)
 		value = g_key_file_get_string(key_file, "Attributes", *handle,
 									NULL);
 
-		if (sscanf(value, "%[^:]:", type) != 1) {
+		if (!value || sscanf(value, "%36[^:]:", type) != 1) {
 			g_free(value);
 			return -EIO;
 		}
diff --git a/src/shared/ad.c b/src/shared/ad.c
index 27b76dc..d08ce7a 100644
--- a/src/shared/ad.c
+++ b/src/shared/ad.c
@@ -14,6 +14,11 @@
 
 #define _GNU_SOURCE
 
+#include <ctype.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+
 #include "src/shared/ad.h"
 
 #include "src/eir.h"
@@ -22,6 +27,7 @@
 
 struct bt_ad {
 	int ref_count;
+	uint8_t max_len;
 	char *name;
 	uint16_t appearance;
 	struct queue *service_uuids;
@@ -42,6 +48,7 @@ struct bt_ad *bt_ad_new(void)
 	struct bt_ad *ad;
 
 	ad = new0(struct bt_ad, 1);
+	ad->max_len = BT_EA_MAX_DATA_LEN;
 	ad->service_uuids = queue_new();
 	ad->manufacturer_data = queue_new();
 	ad->solicit_uuids = queue_new();
@@ -52,6 +59,16 @@ struct bt_ad *bt_ad_new(void)
 	return bt_ad_ref(ad);
 }
 
+bool bt_ad_set_max_len(struct bt_ad *ad, uint8_t len)
+{
+	if (!ad || len < BT_AD_MAX_DATA_LEN)
+		return false;
+
+	ad->max_len = len;
+
+	return true;
+}
+
 static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
 							size_t len);
 
@@ -68,7 +85,11 @@ static bool ad_is_type_valid(uint8_t type)
 struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data)
 {
 	struct bt_ad *ad;
-	uint16_t parsed_len = 0;
+	struct iovec iov = {
+		.iov_base = (void *)data,
+		.iov_len = len,
+	};
+	uint8_t elen;
 
 	if (data == NULL || !len)
 		return NULL;
@@ -77,31 +98,29 @@ struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data)
 	if (!ad)
 		return NULL;
 
-	while (parsed_len < len - 1) {
-		uint8_t d_len;
-		uint8_t d_type;
-		const uint8_t *d;
-		uint8_t field_len = data[0];
-
-		if (field_len == 0)
-			break;
+	bt_ad_set_max_len(ad, len);
 
-		parsed_len += field_len + 1;
+	while (util_iov_pull_u8(&iov, &elen)) {
+		uint8_t type;
+		void *data;
 
-		if (parsed_len > len)
+		if (elen == 0 || elen > iov.iov_len)
 			break;
 
-		d = &data[2];
-		d_type = data[1];
-		d_len = field_len - 1;
+		if (!util_iov_pull_u8(&iov, &type))
+			goto failed;
+
+		elen--;
 
-		if (!ad_is_type_valid(d_type))
+		if (!ad_is_type_valid(type))
 			goto failed;
 
-		if (!ad_replace_data(ad, d_type, d, d_len))
+		data = util_iov_pull_mem(&iov, elen);
+		if (!data)
 			goto failed;
 
-		data += field_len + 1;
+		if (!ad_replace_data(ad, type, data, elen))
+			goto failed;
 	}
 
 	return ad;
@@ -191,10 +210,181 @@ static bool data_type_match(const void *data, const void *user_data)
 	return a->type == type;
 }
 
+static bool ad_replace_uuid16(struct bt_ad *ad, struct iovec *iov)
+{
+	uint16_t value;
+
+	while ((util_iov_pull_le16(iov, &value))) {
+		bt_uuid_t uuid;
+
+		if (bt_uuid16_create(&uuid, value))
+			return false;
+
+		if (bt_ad_has_service_uuid(ad, &uuid))
+			continue;
+
+		if (!bt_ad_add_service_uuid(ad, &uuid))
+			return false;
+	}
+
+	return true;
+}
+
+static bool ad_replace_uuid32(struct bt_ad *ad, struct iovec *iov)
+{
+	uint32_t value;
+
+	while ((util_iov_pull_le32(iov, &value))) {
+		bt_uuid_t uuid;
+
+		if (bt_uuid32_create(&uuid, value))
+			return false;
+
+		if (bt_ad_has_service_uuid(ad, &uuid))
+			continue;
+
+		if (!bt_ad_add_service_uuid(ad, &uuid))
+			return false;
+	}
+
+	return true;
+}
+
+static bool ad_replace_uuid128(struct bt_ad *ad, struct iovec *iov)
+{
+	void *data;
+
+	while ((data = util_iov_pull_mem(iov, 16))) {
+		uint128_t value;
+		bt_uuid_t uuid;
+
+		bswap_128(data, &value);
+
+		if (bt_uuid128_create(&uuid, value))
+			return false;
+
+		if (bt_ad_has_service_uuid(ad, &uuid))
+			continue;
+
+		if (!bt_ad_add_service_uuid(ad, &uuid))
+			return false;
+	}
+
+	return true;
+}
+
+static bool ad_replace_name(struct bt_ad *ad, struct iovec *iov)
+{
+	char utf8_name[HCI_MAX_NAME_LENGTH + 2];
+	int i;
+
+	memset(utf8_name, 0, sizeof(utf8_name));
+	strncpy(utf8_name, (const char *)iov->iov_base, iov->iov_len);
+
+	if (strisutf8(utf8_name, iov->iov_len))
+		goto done;
+
+	/* Assume ASCII, and replace all non-ASCII with spaces */
+	for (i = 0; utf8_name[i] != '\0'; i++) {
+		if (!isascii(utf8_name[i]))
+			utf8_name[i] = ' ';
+	}
+
+	/* Remove leading and trailing whitespace characters */
+	strstrip(utf8_name);
+
+done:
+	return bt_ad_add_name(ad, utf8_name);
+}
+
+static bool ad_replace_uuid16_data(struct bt_ad *ad, struct iovec *iov)
+{
+	uint16_t value;
+	bt_uuid_t uuid;
+
+	if (!util_iov_pull_le16(iov, &value))
+		return false;
+
+	if (bt_uuid16_create(&uuid, value))
+		return false;
+
+	return bt_ad_add_service_data(ad, &uuid, iov->iov_base, iov->iov_len);
+}
+
+static bool ad_replace_uuid32_data(struct bt_ad *ad, struct iovec *iov)
+{
+	uint32_t value;
+	bt_uuid_t uuid;
+
+	if (!util_iov_pull_le32(iov, &value))
+		return false;
+
+	if (bt_uuid32_create(&uuid, value))
+		return false;
+
+	return bt_ad_add_service_data(ad, &uuid, iov->iov_base, iov->iov_len);
+}
+
+static bool ad_replace_uuid128_data(struct bt_ad *ad, struct iovec *iov)
+{
+	void *data;
+	uint128_t value;
+	bt_uuid_t uuid;
+
+	data = util_iov_pull_mem(iov, 16);
+	if (!data)
+		return false;
+
+	bswap_128(data, &value);
+
+	if (bt_uuid128_create(&uuid, value))
+		return false;
+
+	return bt_ad_add_service_data(ad, &uuid, iov->iov_base, iov->iov_len);
+}
+
+static bool ad_replace_manufacturer_data(struct bt_ad *ad, struct iovec *iov)
+{
+	uint16_t value;
+
+	if (!util_iov_pull_le16(iov, &value))
+		return false;
+
+	return bt_ad_add_manufacturer_data(ad, value, iov->iov_base,
+							iov->iov_len);
+}
+
 static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
 							size_t len)
 {
 	struct bt_ad_data *new_data;
+	struct iovec iov = {
+		.iov_base = (void *)data,
+		.iov_len = len,
+	};
+
+	switch (type) {
+	case BT_AD_UUID16_SOME:
+	case BT_AD_UUID16_ALL:
+		return ad_replace_uuid16(ad, &iov);
+	case BT_AD_UUID32_SOME:
+	case BT_AD_UUID32_ALL:
+		return ad_replace_uuid32(ad, &iov);
+	case BT_AD_UUID128_SOME:
+	case BT_AD_UUID128_ALL:
+		return ad_replace_uuid128(ad, &iov);
+	case BT_AD_NAME_SHORT:
+	case BT_AD_NAME_COMPLETE:
+		return ad_replace_name(ad, &iov);
+	case BT_AD_SERVICE_DATA16:
+		return ad_replace_uuid16_data(ad, &iov);
+	case BT_AD_SERVICE_DATA32:
+		return ad_replace_uuid32_data(ad, &iov);
+	case BT_AD_SERVICE_DATA128:
+		return ad_replace_uuid128_data(ad, &iov);
+	case BT_AD_MANUFACTURER_DATA:
+		return ad_replace_manufacturer_data(ad, &iov);
+	}
 
 	new_data = queue_find(ad->data, data_type_match, UINT_TO_PTR(type));
 	if (new_data) {
@@ -208,13 +398,12 @@ static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
 
 	new_data = new0(struct bt_ad_data, 1);
 	new_data->type = type;
-	new_data->data = malloc(len);
+	new_data->data = util_memdup(data, 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->data, new_data))
@@ -298,17 +487,17 @@ static size_t uuid_data_length(struct queue *uuid_data)
 	return length;
 }
 
-static size_t name_length(const char *name, size_t *pos)
+static size_t name_length(struct bt_ad *ad, size_t *pos)
 {
 	size_t len;
 
-	if (!name)
+	if (!ad->name)
 		return 0;
 
-	len = 2 + strlen(name);
+	len = 2 + strlen(ad->name);
 
-	if (len > BT_AD_MAX_DATA_LEN - *pos)
-		len = BT_AD_MAX_DATA_LEN - *pos;
+	if (len > ad->max_len - (*pos))
+		len = ad->max_len - (*pos);
 
 	return len;
 }
@@ -331,9 +520,14 @@ static size_t data_length(struct queue *queue)
 	return length;
 }
 
-static size_t calculate_length(struct bt_ad *ad)
+size_t bt_ad_length(struct bt_ad *ad)
 {
-	size_t length = 0;
+	size_t length;
+
+	if (!ad)
+		return 0;
+
+	length = 0;
 
 	length += uuid_list_length(ad->service_uuids);
 
@@ -343,7 +537,7 @@ static size_t calculate_length(struct bt_ad *ad)
 
 	length += uuid_data_length(ad->service_data);
 
-	length += name_length(ad->name, &length);
+	length += name_length(ad, &length);
 
 	length += ad->appearance != UINT16_MAX ? 4 : 0;
 
@@ -353,84 +547,80 @@ static size_t calculate_length(struct bt_ad *ad)
 }
 
 static void serialize_uuids(struct queue *uuids, uint8_t uuid_type,
-						uint8_t ad_type, uint8_t *buf,
-						uint8_t *pos)
+				uint8_t ad_type, struct iovec *iov)
 {
 	const struct queue_entry *entry = queue_get_entries(uuids);
-	bool added = false;
-	uint8_t length_pos = 0;
+	uint8_t *len = NULL;
 
 	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 (!len) {
+				len = iov->iov_base + iov->iov_len;
+				util_iov_push_u8(iov, 1);
+				util_iov_push_u8(iov, ad_type);
 			}
 
-			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);
+			switch (uuid->type) {
+			case BT_UUID16:
+				util_iov_push_le16(iov, uuid->value.u16);
+				*len += 2;
+				break;
+			case BT_UUID32:
+				util_iov_push_le32(iov, uuid->value.u32);
+				*len += 4;
+				break;
+			case BT_UUID128:
+				bt_uuid_to_le(uuid, util_iov_push(iov, 16));
+				*len += 16;
+				break;
+			case BT_UUID_UNSPEC:
+				break;
+			}
 		}
 
 		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)
+static void serialize_service_uuids(struct queue *uuids, struct iovec *iov)
 {
-	serialize_uuids(uuids, BT_UUID16, BT_AD_UUID16_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID16, BT_AD_UUID16_ALL, iov);
 
-	serialize_uuids(uuids, BT_UUID32, BT_AD_UUID32_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID32, BT_AD_UUID32_ALL, iov);
 
-	serialize_uuids(uuids, BT_UUID128, BT_AD_UUID128_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID128, BT_AD_UUID128_ALL, iov);
 }
 
-static void serialize_solicit_uuids(struct queue *uuids, uint8_t *buf,
-								uint8_t *pos)
+static void serialize_solicit_uuids(struct queue *uuids, struct iovec *iov)
 {
-	serialize_uuids(uuids, BT_UUID16, BT_AD_SOLICIT16, buf, pos);
+	serialize_uuids(uuids, BT_UUID16, BT_AD_SOLICIT16, iov);
 
-	serialize_uuids(uuids, BT_UUID32, BT_AD_SOLICIT32, buf, pos);
+	serialize_uuids(uuids, BT_UUID32, BT_AD_SOLICIT32, iov);
 
-	serialize_uuids(uuids, BT_UUID128, BT_AD_SOLICIT128, buf, pos);
+	serialize_uuids(uuids, BT_UUID128, BT_AD_SOLICIT128, iov);
 }
 
-static void serialize_manuf_data(struct queue *manuf_data, uint8_t *buf,
-								uint8_t *pos)
+static void serialize_manuf_data(struct queue *manuf_data, struct iovec *iov)
 {
 	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)++] = BT_AD_MANUFACTURER_DATA;
-
-		bt_put_le16(data->manufacturer_id, buf + (*pos));
-
-		*pos += 2;
-
-		memcpy(buf + *pos, data->data, data->len);
+		util_iov_push_u8(iov, data->len + 2 + 1);
+		util_iov_push_u8(iov, BT_AD_MANUFACTURER_DATA);
 
-		*pos += data->len;
+		util_iov_push_le16(iov, data->manufacturer_id);
+		util_iov_push_mem(iov, data->len, data->data);
 
 		entry = entry->next;
 	}
 }
 
-static void serialize_service_data(struct queue *service_data, uint8_t *buf,
-								uint8_t *pos)
+static void serialize_service_data(struct queue *service_data,
+					struct iovec *iov)
 {
 	const struct queue_entry *entry = queue_get_entries(service_data);
 
@@ -438,81 +628,69 @@ static void serialize_service_data(struct queue *service_data, uint8_t *buf,
 		struct bt_ad_service_data *data = entry->data;
 		int uuid_len = bt_uuid_len(&data->uuid);
 
-		buf[(*pos)++] =  uuid_len + data->len + 1;
+		util_iov_push_u8(iov, data->len + uuid_len + 1);
 
 		switch (uuid_len) {
 		case 2:
-			buf[(*pos)++] = BT_AD_SERVICE_DATA16;
+			util_iov_push_u8(iov, BT_AD_SERVICE_DATA16);
+			util_iov_push_le16(iov, data->uuid.value.u16);
 			break;
 		case 4:
-			buf[(*pos)++] = BT_AD_SERVICE_DATA32;
+			util_iov_push_u8(iov, BT_AD_SERVICE_DATA32);
+			util_iov_push_le32(iov, data->uuid.value.u32);
 			break;
 		case 16:
-			buf[(*pos)++] = BT_AD_SERVICE_DATA128;
+			util_iov_push_u8(iov, BT_AD_SERVICE_DATA128);
+			bt_uuid_to_le(&data->uuid,
+					util_iov_push(iov, uuid_len));
 			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;
+		util_iov_push_mem(iov, data->len, data->data);
 
 		entry = entry->next;
 	}
 }
 
-static void serialize_name(const char *name, uint8_t *buf, uint8_t *pos)
+static void serialize_name(struct bt_ad *ad, struct iovec *iov)
 {
-	int len;
+	size_t len;
 	uint8_t type = BT_AD_NAME_COMPLETE;
 
-	if (!name)
+	if (!ad->name)
 		return;
 
-	len = strlen(name);
-	if (len > BT_AD_MAX_DATA_LEN - (*pos + 2)) {
+	len = strlen(ad->name);
+	if (len > ad->max_len - (iov->iov_len + 2)) {
 		type = BT_AD_NAME_SHORT;
-		len = BT_AD_MAX_DATA_LEN - (*pos + 2);
+		len = ad->max_len - (iov->iov_len + 2);
 	}
 
-	buf[(*pos)++] = len + 1;
-	buf[(*pos)++] = type;
-
-	memcpy(buf + *pos, name, len);
-	*pos += len;
+	util_iov_push_u8(iov, len + 1);
+	util_iov_push_u8(iov, type);
+	util_iov_push_mem(iov, len, ad->name);
 }
 
-static void serialize_appearance(uint16_t value, uint8_t *buf, uint8_t *pos)
+static void serialize_appearance(struct bt_ad *ad, struct iovec *iov)
 {
-	if (value == UINT16_MAX)
+	if (ad->appearance == UINT16_MAX)
 		return;
 
-	buf[(*pos)++] = sizeof(value) + 1;
-	buf[(*pos)++] = BT_AD_GAP_APPEARANCE;
-
-	bt_put_le16(value, buf + (*pos));
-	*pos += 2;
+	util_iov_push_u8(iov, sizeof(ad->appearance) + 1);
+	util_iov_push_u8(iov, BT_AD_GAP_APPEARANCE);
+	util_iov_push_le16(iov, ad->appearance);
 }
 
-static void serialize_data(struct queue *queue, uint8_t *buf, uint8_t *pos)
+static void serialize_data(struct queue *queue, struct iovec *iov)
 {
 	const struct queue_entry *entry = queue_get_entries(queue);
 
 	while (entry) {
 		struct bt_ad_data *data = entry->data;
 
-		buf[(*pos)++] = data->len + 1;
-		buf[(*pos)++] = data->type;
-
-		memcpy(buf + *pos, data->data, data->len);
-
-		*pos += data->len;
+		util_iov_push_u8(iov, data->len + 1);
+		util_iov_push_u8(iov, data->type);
+		util_iov_push_mem(iov, data->len, data->data);
 
 		entry = entry->next;
 	}
@@ -520,36 +698,37 @@ static void serialize_data(struct queue *queue, uint8_t *buf, uint8_t *pos)
 
 uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
 {
-	uint8_t *adv_data;
-	uint8_t pos = 0;
+	struct iovec iov;
 
 	if (!ad)
 		return NULL;
 
-	*length = calculate_length(ad);
+	*length = bt_ad_length(ad);
 
-	if (*length > BT_AD_MAX_DATA_LEN)
+	if (*length > ad->max_len)
 		return NULL;
 
-	adv_data = malloc0(*length);
-	if (!adv_data)
+	iov.iov_base = malloc0(*length);
+	if (!iov.iov_base)
 		return NULL;
 
-	serialize_service_uuids(ad->service_uuids, adv_data, &pos);
+	iov.iov_len = 0;
 
-	serialize_solicit_uuids(ad->solicit_uuids, adv_data, &pos);
+	serialize_service_uuids(ad->service_uuids, &iov);
 
-	serialize_manuf_data(ad->manufacturer_data, adv_data, &pos);
+	serialize_solicit_uuids(ad->solicit_uuids, &iov);
 
-	serialize_service_data(ad->service_data, adv_data, &pos);
+	serialize_manuf_data(ad->manufacturer_data, &iov);
 
-	serialize_name(ad->name, adv_data, &pos);
+	serialize_service_data(ad->service_data, &iov);
 
-	serialize_appearance(ad->appearance, adv_data, &pos);
+	serialize_name(ad, &iov);
 
-	serialize_data(ad->data, adv_data, &pos);
+	serialize_appearance(ad, &iov);
 
-	return adv_data;
+	serialize_data(ad->data, &iov);
+
+	return iov.iov_base;
 }
 
 bool bt_ad_is_empty(struct bt_ad *ad)
@@ -593,7 +772,7 @@ 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);
+	return !bt_uuid_cmp(match_uuid, uuid);
 }
 
 static bool queue_remove_uuid(struct queue *queue, bt_uuid_t *uuid)
@@ -621,6 +800,14 @@ bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
 	return queue_add_uuid(ad->service_uuids, uuid);
 }
 
+bool bt_ad_has_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
+{
+	if (!ad)
+		return false;
+
+	return queue_find(ad->service_uuids, uuid_match, uuid);
+}
+
 bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid)
 {
 	if (!ad)
@@ -653,7 +840,7 @@ bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_id,
 	if (!ad)
 		return false;
 
-	if (len > (BT_AD_MAX_DATA_LEN - 2 - sizeof(uint16_t)))
+	if (len > (ad->max_len - 2 - sizeof(uint16_t)))
 		return false;
 
 	new_data = queue_find(ad->manufacturer_data, manufacturer_id_data_match,
@@ -790,7 +977,7 @@ bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void *data,
 	if (!ad)
 		return false;
 
-	if (len > (BT_AD_MAX_DATA_LEN - 2 - (size_t)bt_uuid_len(uuid)))
+	if (len > (ad->max_len - 2 - (size_t)bt_uuid_len(uuid)))
 		return false;
 
 	new_data = queue_find(ad->service_data, service_uuid_match, uuid);
@@ -897,6 +1084,14 @@ bool bt_ad_add_name(struct bt_ad *ad, const char *name)
 	return true;
 }
 
+const char *bt_ad_get_name(struct bt_ad *ad)
+{
+	if (!ad)
+		return false;
+
+	return ad->name;
+}
+
 void bt_ad_clear_name(struct bt_ad *ad)
 {
 	if (!ad)
@@ -936,6 +1131,20 @@ bool bt_ad_add_flags(struct bt_ad *ad, uint8_t *flags, size_t len)
 	return ad_replace_data(ad, BT_AD_FLAGS, flags, len);
 }
 
+uint8_t bt_ad_get_flags(struct bt_ad *ad)
+{
+	struct bt_ad_data *data;
+
+	if (!ad)
+		return 0;
+
+	data = queue_find(ad->data, data_type_match, UINT_TO_PTR(BT_AD_FLAGS));
+	if (!data || data->len != 1)
+		return 0;
+
+	return data->data[0];
+}
+
 bool bt_ad_has_flags(struct bt_ad *ad)
 {
 	struct bt_ad_data *data;
@@ -1009,7 +1218,7 @@ bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len)
 	if (!ad)
 		return false;
 
-	if (len > (BT_AD_MAX_DATA_LEN - 2))
+	if (len > (size_t)(ad->max_len - 2))
 		return false;
 
 	for (i = 0; i < sizeof(type_reject_list); i++) {
@@ -1028,6 +1237,9 @@ static bool data_match(const void *data, const void *user_data)
 	if (d1->type != d2->type)
 		return false;
 
+	if (!d2->len && !d2->data)
+		return true;
+
 	if (d1->len != d2->len)
 		return false;
 
@@ -1077,6 +1289,21 @@ void bt_ad_clear_data(struct bt_ad *ad)
 	queue_remove_all(ad->data, NULL, NULL, data_destroy);
 }
 
+int8_t bt_ad_get_tx_power(struct bt_ad *ad)
+{
+	struct bt_ad_data *data;
+
+	if (!ad)
+		return 0;
+
+	data = queue_find(ad->data, data_type_match,
+					UINT_TO_PTR(BT_AD_TX_POWER));
+	if (!data || data->len != 1)
+		return 127;
+
+	return data->data[0];
+}
+
 struct bt_ad_pattern *bt_ad_pattern_new(uint8_t type, size_t offset, size_t len,
 							const uint8_t *data)
 {
@@ -1102,36 +1329,110 @@ struct bt_ad_pattern *bt_ad_pattern_new(uint8_t type, size_t offset, size_t len,
 	return pattern;
 }
 
-static void pattern_ad_data_match(void *data, void *user_data)
+static bool match_manufacturer(const void *data, const void *user_data)
 {
-	struct bt_ad_data *ad_data = data;
-	struct pattern_match_info *info = user_data;
-	struct bt_ad_pattern *pattern;
+	const struct bt_ad_manufacturer_data *manufacturer_data = data;
+	const struct pattern_match_info *info = user_data;
+	const struct bt_ad_pattern *pattern;
+	uint8_t all_data[BT_AD_MAX_DATA_LEN];
+
+	if (!manufacturer_data || !info)
+		return false;
+
+	if (info->matched_pattern)
+		return false;
+
+	pattern = info->current_pattern;
+
+	if (!pattern || pattern->type != BT_AD_MANUFACTURER_DATA)
+		return false;
+
+	/* Take the manufacturer ID into account */
+	if (manufacturer_data->len + 2 < pattern->offset + pattern->len)
+		return false;
+
+	memcpy(&all_data[0], &manufacturer_data->manufacturer_id, 2);
+	memcpy(&all_data[2], manufacturer_data->data, manufacturer_data->len);
+
+	if (!memcmp(all_data + pattern->offset, pattern->data,
+							pattern->len)) {
+		return true;
+	}
+
+	return false;
+}
+
+static bool match_service(const void *data, const void *user_data)
+{
+	const struct bt_ad_service_data *service_data = data;
+	const struct pattern_match_info *info = user_data;
+	const struct bt_ad_pattern *pattern;
+
+	if (!service_data || !info)
+		return false;
+
+	if (info->matched_pattern)
+		return false;
+
+	pattern = info->current_pattern;
+
+	if (!pattern)
+		return false;
+
+	switch (pattern->type) {
+	case BT_AD_SERVICE_DATA16:
+	case BT_AD_SERVICE_DATA32:
+	case BT_AD_SERVICE_DATA128:
+		break;
+	default:
+		return false;
+	}
+
+	if (service_data->len < pattern->offset + pattern->len)
+		return false;
+
+	if (!memcmp(service_data->data + pattern->offset, pattern->data,
+							pattern->len)) {
+		return true;
+	}
+
+	return false;
+}
+
+static bool match_ad_data(const void *data, const void *user_data)
+{
+	const struct bt_ad_data *ad_data = data;
+	const struct pattern_match_info *info = user_data;
+	const struct bt_ad_pattern *pattern;
 
 	if (!ad_data || !info)
-		return;
+		return false;
 
 	if (info->matched_pattern)
-		return;
+		return false;
 
 	pattern = info->current_pattern;
 
 	if (!pattern || ad_data->type != pattern->type)
-		return;
+		return false;
 
 	if (ad_data->len < pattern->offset + pattern->len)
-		return;
+		return false;
 
 	if (!memcmp(ad_data->data + pattern->offset, pattern->data,
 								pattern->len)) {
-		info->matched_pattern = pattern;
+		return true;
 	}
+
+	return false;
 }
 
 static void pattern_match(void *data, void *user_data)
 {
 	struct bt_ad_pattern *pattern = data;
 	struct pattern_match_info *info = user_data;
+	struct bt_ad *ad;
+	void *matched = NULL;
 
 	if (!pattern || !info)
 		return;
@@ -1140,8 +1441,29 @@ static void pattern_match(void *data, void *user_data)
 		return;
 
 	info->current_pattern = pattern;
+	ad = info->ad;
+
+	if (!ad)
+		return;
+
+	switch (pattern->type) {
+	case BT_AD_MANUFACTURER_DATA:
+		matched = queue_find(ad->manufacturer_data, match_manufacturer,
+				user_data);
+		break;
+	case BT_AD_SERVICE_DATA16:
+	case BT_AD_SERVICE_DATA32:
+	case BT_AD_SERVICE_DATA128:
+		matched = queue_find(ad->service_data, match_service,
+				user_data);
+		break;
+	default:
+		matched = queue_find(ad->data, match_ad_data, user_data);
+		break;
+	}
 
-	bt_ad_foreach_data(info->ad, pattern_ad_data_match, info);
+	if (matched)
+		info->matched_pattern = info->current_pattern;
 }
 
 struct bt_ad_pattern *bt_ad_pattern_match(struct bt_ad *ad,
diff --git a/src/shared/ad.h b/src/shared/ad.h
index feb712f..90cc82d 100644
--- a/src/shared/ad.h
+++ b/src/shared/ad.h
@@ -15,6 +15,8 @@
 #include "lib/uuid.h"
 
 #define BT_AD_MAX_DATA_LEN		31
+#define BT_EA_MAX_DATA_LEN		251
+#define BT_PA_MAX_DATA_LEN		252
 
 #define BT_AD_FLAGS			0x01
 #define BT_AD_UUID16_SOME		0x02
@@ -57,6 +59,7 @@
 #define BT_AD_MESH_PROV			0x29
 #define BT_AD_MESH_DATA			0x2a
 #define BT_AD_MESH_BEACON		0x2b
+#define BT_AD_CSIP_RSI			0x2e
 #define BT_AD_3D_INFO_DATA		0x3d
 #define BT_AD_MANUFACTURER_DATA		0xff
 
@@ -97,23 +100,29 @@ struct bt_ad_pattern {
 
 struct bt_ad *bt_ad_new(void);
 
+bool bt_ad_set_max_len(struct bt_ad *ad, uint8_t len);
+
 struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data);
 
 struct bt_ad *bt_ad_ref(struct bt_ad *ad);
 
 void bt_ad_unref(struct bt_ad *ad);
 
+size_t bt_ad_length(struct bt_ad *ad);
+
 uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length);
 
 bool bt_ad_is_empty(struct bt_ad *ad);
 
 bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
 
+bool bt_ad_has_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,
+bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t id,
 						void *data, size_t len);
 
 bool bt_ad_has_manufacturer_data(struct bt_ad *ad,
@@ -147,6 +156,8 @@ void bt_ad_clear_service_data(struct bt_ad *ad);
 
 bool bt_ad_add_name(struct bt_ad *ad, const char *name);
 
+const char *bt_ad_get_name(struct bt_ad *ad);
+
 void bt_ad_clear_name(struct bt_ad *ad);
 
 bool bt_ad_add_appearance(struct bt_ad *ad, uint16_t appearance);
@@ -157,6 +168,8 @@ bool bt_ad_add_flags(struct bt_ad *ad, uint8_t *flags, size_t len);
 
 bool bt_ad_has_flags(struct bt_ad *ad);
 
+uint8_t bt_ad_get_flags(struct bt_ad *ad);
+
 void bt_ad_clear_flags(struct bt_ad *ad);
 
 bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len);
@@ -169,6 +182,8 @@ bool bt_ad_remove_data(struct bt_ad *ad, uint8_t type);
 
 void bt_ad_clear_data(struct bt_ad *ad);
 
+int8_t bt_ad_get_tx_power(struct bt_ad *ad);
+
 struct bt_ad_pattern *bt_ad_pattern_new(uint8_t type, size_t offset,
 					size_t len, const uint8_t *data);
 
diff --git a/src/shared/asha.c b/src/shared/asha.c
new file mode 100644
index 0000000..67f2631
--- /dev/null
+++ b/src/shared/asha.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Asymptotic Inc.
+ *
+ *  Author: Arun Raghavan <arun@asymptotic.io>
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/log.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+
+#include "asha.h"
+
+/* We use strings instead of uint128_t to maintain readability */
+#define ASHA_CHRC_READ_ONLY_PROPERTIES_UUID "6333651e-c481-4a3e-9169-7c902aad37bb"
+#define ASHA_CHRC_AUDIO_CONTROL_POINT_UUID "f0d4de7e-4a88-476c-9d9f-1937b0996cc0"
+#define ASHA_CHRC_AUDIO_STATUS_UUID "38663f1a-e711-4cac-b641-326b56404837"
+#define ASHA_CHRC_VOLUME_UUID "00e4ca9e-ab14-41e4-8823-f9e70c7e91df"
+#define ASHA_CHRC_LE_PSM_OUT_UUID "2d410339-82b6-42aa-b34e-e2e01df8cc1a"
+
+struct bt_asha *bt_asha_new(void)
+{
+	struct bt_asha *asha;
+
+	asha = new0(struct bt_asha, 1);
+
+	return asha;
+}
+
+void bt_asha_reset(struct bt_asha *asha)
+{
+	if (asha->status_notify_id) {
+		bt_gatt_client_unregister_notify(asha->client,
+						asha->status_notify_id);
+	}
+
+	gatt_db_unref(asha->db);
+	asha->db = NULL;
+
+	bt_gatt_client_unref(asha->client);
+	asha->client = NULL;
+
+	asha->psm = 0;
+}
+
+void bt_asha_state_reset(struct bt_asha *asha)
+{
+	asha->state = ASHA_STOPPED;
+
+	asha->cb = NULL;
+	asha->cb_user_data = NULL;
+}
+
+void bt_asha_free(struct bt_asha *asha)
+{
+	gatt_db_unref(asha->db);
+	bt_gatt_client_unref(asha->client);
+	free(asha);
+}
+
+static void asha_acp_sent(bool success, uint8_t err, void *user_data)
+{
+	struct bt_asha *asha = user_data;
+
+	if (success) {
+		DBG("AudioControlPoint command successfully sent");
+	} else {
+		error("Failed to send AudioControlPoint command: %d", err);
+
+		if (asha->cb)
+			asha->cb(-1, asha->cb_user_data);
+
+		bt_asha_state_reset(asha);
+	}
+}
+
+static int asha_send_acp(struct bt_asha *asha, uint8_t *cmd,
+		unsigned int len, bt_asha_cb_t cb, void *user_data)
+{
+	if (!bt_gatt_client_write_value(asha->client, asha->acp_handle, cmd,
+				len, asha_acp_sent, asha, NULL)) {
+		error("Error writing ACP command");
+		return -1;
+	}
+
+	asha->cb = cb;
+	asha->cb_user_data = user_data;
+
+	return 0;
+}
+
+unsigned int bt_asha_start(struct bt_asha *asha, bt_asha_cb_t cb,
+								void *user_data)
+{
+	uint8_t acp_start_cmd[] = {
+		0x01,		/* START */
+		0x01,		/* G.722, 16 kHz */
+		0,			/* Unknown media type */
+		asha->volume,	/* Volume */
+		0,			/* Other disconnected */
+	};
+	int ret;
+
+	if (asha->state != ASHA_STOPPED) {
+		error("ASHA device start failed. Bad state %d", asha->state);
+		return 0;
+	}
+
+	ret = asha_send_acp(asha, acp_start_cmd, sizeof(acp_start_cmd), cb,
+			user_data);
+	if (ret < 0)
+		return ret;
+
+	asha->state = ASHA_STARTING;
+
+	return 0;
+}
+
+unsigned int bt_asha_stop(struct bt_asha *asha, bt_asha_cb_t cb,
+								void *user_data)
+{
+	uint8_t acp_stop_cmd[] = {
+		0x02, /* STOP */
+	};
+
+	if (asha->state != ASHA_STARTED)
+		return 0;
+
+	asha->state = ASHA_STOPPING;
+
+	return asha_send_acp(asha, acp_stop_cmd, sizeof(acp_stop_cmd),
+								cb, user_data);
+}
+
+bool bt_asha_set_volume(struct bt_asha *asha, int8_t volume)
+{
+	if (!bt_gatt_client_write_without_response(asha->client,
+						asha->volume_handle, false,
+						(const uint8_t *)&volume, 1)) {
+		error("Error writing volume");
+		return false;
+	}
+
+	asha->volume = volume;
+	return true;
+}
+
+static bool uuid_cmp(const char *uuid1, const bt_uuid_t *uuid2)
+{
+	bt_uuid_t lhs;
+
+	bt_string_to_uuid(&lhs, uuid1);
+
+	return bt_uuid_cmp(&lhs, uuid2) == 0;
+}
+
+static void read_psm(bool success,
+			uint8_t att_ecode,
+			const uint8_t *value,
+			uint16_t length,
+			void *user_data)
+{
+	struct bt_asha *asha = user_data;
+
+	if (!success) {
+		DBG("Reading PSM failed with ATT error: %u", att_ecode);
+		return;
+	}
+
+	if (length != 2) {
+		DBG("Reading PSM failed: unexpected length %u", length);
+		return;
+	}
+
+	asha->psm = get_le16(value);
+
+	DBG("Got PSM: %u", asha->psm);
+}
+
+static void read_rops(bool success,
+			uint8_t att_ecode,
+			const uint8_t *value,
+			uint16_t length,
+			void *user_data)
+{
+	struct bt_asha *asha = user_data;
+
+	if (!success) {
+		DBG("Reading ROPs failed with ATT error: %u", att_ecode);
+		return;
+	}
+
+	if (length != 17) {
+		DBG("Reading ROPs failed: unexpected length %u", length);
+		return;
+	}
+
+	if (value[0] != 0x01) {
+		DBG("Unexpected ASHA version: %u", value[0]);
+		return;
+	}
+
+	/* Device Capabilities */
+	asha->right_side = (value[1] & 0x1) != 0;
+	asha->binaural = (value[1] & 0x2) != 0;
+	asha->csis_supported = (value[1] & 0x4) != 0;
+	/* HiSyncId: 2 byte company id, 6 byte ID shared by left and right */
+	memcpy(asha->hisyncid, &value[2], 8);
+	/* FeatureMap */
+	asha->coc_streaming_supported = (value[10] & 0x1) != 0;
+	/* RenderDelay */
+	asha->render_delay = get_le16(&value[11]);
+	/* byte 13 & 14 are reserved */
+	/* Codec IDs */
+	asha->codec_ids = get_le16(&value[15]);
+
+	DBG("Got ROPS: side %u, binaural %u, csis: %u, delay %u, codecs: %u",
+			asha->right_side, asha->binaural, asha->csis_supported,
+			asha->render_delay, asha->codec_ids);
+}
+
+static void audio_status_register(uint16_t att_ecode, void *user_data)
+{
+	if (att_ecode)
+		DBG("AudioStatusPoint register failed 0x%04x", att_ecode);
+	else
+		DBG("AudioStatusPoint register succeeded");
+}
+
+static void audio_status_notify(uint16_t value_handle, const uint8_t *value,
+					uint16_t length, void *user_data)
+{
+	struct bt_asha *asha = user_data;
+	uint8_t status = *value;
+	/* Back these up to survive the reset paths */
+	bt_asha_cb_t cb = asha->cb;
+	bt_asha_cb_t cb_user_data = asha->cb_user_data;
+
+	if (asha->state == ASHA_STARTING) {
+		if (status == 0) {
+			asha->state = ASHA_STARTED;
+			DBG("ASHA start complete");
+		} else {
+			bt_asha_state_reset(asha);
+			DBG("ASHA start failed");
+		}
+	} else if (asha->state == ASHA_STOPPING) {
+		/* We reset our state, regardless */
+		bt_asha_state_reset(asha);
+		DBG("ASHA stop %s", status == 0 ? "complete" : "failed");
+	}
+
+	if (cb) {
+		cb(status, cb_user_data);
+		asha->cb = NULL;
+		asha->cb_user_data = NULL;
+	}
+}
+
+static void handle_characteristic(struct gatt_db_attribute *attr,
+								void *user_data)
+{
+	struct bt_asha *asha = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid;
+	char uuid_str[MAX_LEN_UUID_STR];
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
+								NULL, &uuid)) {
+		error("Failed to obtain characteristic data");
+		return;
+	}
+
+	bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
+	if (uuid_cmp(ASHA_CHRC_LE_PSM_OUT_UUID, &uuid)) {
+		DBG("Got chrc %s/0x%x: LE_PSM_ID", uuid_str, value_handle);
+		if (!bt_gatt_client_read_value(asha->client, value_handle,
+					read_psm, asha, NULL))
+			DBG("Failed to send request to read battery level");
+	} else if (uuid_cmp(ASHA_CHRC_READ_ONLY_PROPERTIES_UUID, &uuid)) {
+		DBG("Got chrc %s/0x%x: READ_ONLY_PROPERTIES", uuid_str,
+								value_handle);
+		if (!bt_gatt_client_read_value(asha->client, value_handle,
+					read_rops, asha, NULL))
+			DBG("Failed to send request for readonly properties");
+	} else if (uuid_cmp(ASHA_CHRC_AUDIO_CONTROL_POINT_UUID, &uuid)) {
+		DBG("Got chrc %s/0x%x: AUDIO_CONTROL_POINT", uuid_str,
+								value_handle);
+		/* Store this for later writes */
+		asha->acp_handle = value_handle;
+	} else if (uuid_cmp(ASHA_CHRC_VOLUME_UUID, &uuid)) {
+		DBG("Got chrc %s/0x%x: VOLUME", uuid_str, value_handle);
+		/* Store this for later writes */
+		asha->volume_handle = value_handle;
+	} else if (uuid_cmp(ASHA_CHRC_AUDIO_STATUS_UUID, &uuid)) {
+		DBG("Got chrc %s/0x%x: AUDIO_STATUS", uuid_str, value_handle);
+		asha->status_notify_id =
+			bt_gatt_client_register_notify(asha->client,
+				value_handle, audio_status_register,
+				audio_status_notify, asha, NULL);
+		if (!asha->status_notify_id)
+			DBG("Failed to send request to notify AudioStatus");
+	} else {
+		DBG("Unsupported characteristic: %s", uuid_str);
+	}
+}
+
+static void foreach_asha_service(struct gatt_db_attribute *attr,
+							void *user_data)
+{
+	struct bt_asha *asha = user_data;
+
+	DBG("Found ASHA GATT service");
+
+	asha->attr = attr;
+	gatt_db_service_set_claimed(attr, true);
+	gatt_db_service_foreach_char(asha->attr, handle_characteristic, asha);
+}
+
+bool bt_asha_probe(struct bt_asha *asha, struct gatt_db *db,
+						struct bt_gatt_client *client)
+{
+	bt_uuid_t asha_uuid;
+
+	asha->db = gatt_db_ref(db);
+	asha->client = bt_gatt_client_clone(client);
+
+	bt_uuid16_create(&asha_uuid, ASHA_SERVICE);
+	gatt_db_foreach_service(db, &asha_uuid, foreach_asha_service, asha);
+
+	if (!asha->attr) {
+		error("ASHA attribute not found");
+		bt_asha_reset(asha);
+		return false;
+	}
+
+	return true;
+}
diff --git a/src/shared/asha.h b/src/shared/asha.h
new file mode 100644
index 0000000..c2c232f
--- /dev/null
+++ b/src/shared/asha.h
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Asymptotic Inc.
+ *
+ *  Author: Arun Raghavan <arun@asymptotic.io>
+ *
+ *
+ */
+
+#
+
+#include <stdbool.h>
+#include <stdint.h>
+
+enum bt_asha_state_t {
+	ASHA_STOPPED = 0,
+	ASHA_STARTING,
+	ASHA_STARTED,
+	ASHA_STOPPING,
+};
+
+typedef void (*bt_asha_cb_t)(int status, void *data);
+
+struct bt_asha {
+	struct bt_gatt_client *client;
+	struct gatt_db *db;
+	struct gatt_db_attribute *attr;
+	uint16_t acp_handle;
+	uint16_t volume_handle;
+	unsigned int status_notify_id;
+
+	uint16_t psm;
+	bool right_side;
+	bool binaural;
+	bool csis_supported;
+	bool coc_streaming_supported;
+	uint8_t hisyncid[8];
+	uint16_t render_delay;
+	uint16_t codec_ids;
+	int8_t volume;
+
+	enum bt_asha_state_t state;
+	bt_asha_cb_t cb;
+	void *cb_user_data;
+};
+
+struct bt_asha *bt_asha_new(void);
+void bt_asha_reset(struct bt_asha *asha);
+void bt_asha_state_reset(struct bt_asha *asha);
+void bt_asha_free(struct bt_asha *asha);
+
+unsigned int bt_asha_start(struct bt_asha *asha, bt_asha_cb_t cb,
+							void *user_data);
+unsigned int bt_asha_stop(struct bt_asha *asha, bt_asha_cb_t cb,
+							void *user_data);
+
+bool bt_asha_set_volume(struct bt_asha *asha, int8_t volume);
+
+bool bt_asha_probe(struct bt_asha *asha, struct gatt_db *db,
+						struct bt_gatt_client *client);
diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index a08b241..69f45b6 100644
--- a/src/shared/att-types.h
+++ b/src/shared/att-types.h
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2014  Google Inc.
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -101,9 +102,10 @@ struct bt_att_pdu_error_rsp {
 /*
  * 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
+ * 0xE0-0xFB are reserved for future use. The remaining 4 are defined as the
  * following:
  */
+#define BT_ERROR_WRITE_REQUEST_REJECTED         0xfc
 #define BT_ERROR_CCC_IMPROPERLY_CONFIGURED      0xfd
 #define BT_ERROR_ALREADY_IN_PROGRESS            0xfe
 #define BT_ERROR_OUT_OF_RANGE                   0xff
diff --git a/src/shared/att.c b/src/shared/att.c
index f7bef08..4a406f4 100644
--- a/src/shared/att.c
+++ b/src/shared/att.c
@@ -193,6 +193,7 @@ struct att_send_op {
 	uint8_t opcode;
 	void *pdu;
 	uint16_t len;
+	bool retry;
 	bt_att_response_func_t callback;
 	bt_att_destroy_func_t destroy;
 	void *user_data;
@@ -550,7 +551,7 @@ static bool can_write_data(struct io *io, void *user_data)
 	if (!op)
 		return false;
 
-	if (!bt_att_chan_write(chan, op->opcode, op->pdu, op->len)) {
+	if (bt_att_chan_write(chan, op->opcode, op->pdu, op->len) < 0) {
 		if (op->callback)
 			op->callback(BT_ATT_OP_ERROR_RSP, NULL, 0,
 							op->user_data);
@@ -785,6 +786,12 @@ static bool handle_error_rsp(struct bt_att_chan *chan, uint8_t *pdu,
 
 	*opcode = rsp->opcode;
 
+	/* If operation has already been marked as retry don't attempt to change
+	 * the security again.
+	 */
+	if (op->retry)
+		return false;
+
 	/* Attempt to change security */
 	if (!change_security(chan, rsp->ecode))
 		return false;
@@ -798,9 +805,10 @@ static bool handle_error_rsp(struct bt_att_chan *chan, uint8_t *pdu,
 	DBG(att, "(chan %p) Retrying operation %p", chan, op);
 
 	chan->pending_req = NULL;
+	op->retry = true;
 
-	/* Push operation back to request queue */
-	return queue_push_head(att->req_queue, op);
+	/* Push operation back to channel queue */
+	return queue_push_head(chan->queue, op);
 }
 
 static void handle_rsp(struct bt_att_chan *chan, uint8_t opcode, uint8_t *pdu,
@@ -1001,8 +1009,9 @@ static void handle_notify(struct bt_att_chan *chan, uint8_t *pdu,
 		found = true;
 
 		if (notify->callback)
-			notify->callback(chan, opcode, pdu + 1, pdu_len - 1,
-							notify->user_data);
+			notify->callback(chan, chan->mtu, opcode,
+						pdu + 1, pdu_len - 1,
+						notify->user_data);
 
 		/* callback could remove all entries from notify list */
 		if (queue_isempty(att->notify_list))
@@ -1588,6 +1597,14 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
 
 	op->id = att->next_send_id++;
 
+	/* Always use fixed channel for BT_ATT_OP_MTU_REQ */
+	if (opcode == BT_ATT_OP_MTU_REQ) {
+		struct bt_att_chan *chan = queue_peek_tail(att->chans);
+
+		result = queue_push_tail(chan->queue, op);
+		goto done;
+	}
+
 	/* Add the op to the correct queue based on its type */
 	switch (op->type) {
 	case ATT_OP_TYPE_REQ:
@@ -1606,6 +1623,7 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
 		break;
 	}
 
+done:
 	if (!result) {
 		free(op->pdu);
 		free(op);
@@ -2025,3 +2043,29 @@ bool bt_att_has_crypto(struct bt_att *att)
 
 	return att->crypto ? true : false;
 }
+
+bool bt_att_set_retry(struct bt_att *att, unsigned int id, bool retry)
+{
+	struct att_send_op *op;
+
+	if (!id)
+		return false;
+
+	op = queue_find(att->req_queue, match_op_id, UINT_TO_PTR(id));
+	if (op)
+		goto done;
+
+	op = queue_find(att->ind_queue, match_op_id, UINT_TO_PTR(id));
+	if (op)
+		goto done;
+
+	op = queue_find(att->write_queue, match_op_id, UINT_TO_PTR(id));
+
+done:
+	if (!op)
+		return false;
+
+	op->retry = !retry;
+
+	return true;
+}
diff --git a/src/shared/att.h b/src/shared/att.h
index 4aa3de8..53a3f7a 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -35,7 +35,7 @@ int bt_att_get_channels(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)(struct bt_att_chan *chan,
+typedef void (*bt_att_notify_func_t)(struct bt_att_chan *chan, uint16_t mtu,
 					uint8_t opcode, const void *pdu,
 					uint16_t length, void *user_data);
 typedef void (*bt_att_destroy_func_t)(void *user_data);
@@ -110,3 +110,4 @@ bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16],
 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);
+bool bt_att_set_retry(struct bt_att *att, unsigned int id, bool retry);
diff --git a/src/shared/bap-debug.c b/src/shared/bap-debug.c
new file mode 100644
index 0000000..495a22c
--- /dev/null
+++ b/src/shared/bap-debug.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  Intel Corporation.
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "src/shared/util.h"
+#include "src/shared/bap-debug.h"
+
+static const struct util_bit_debugger pac_freq_table[] = {
+	UTIL_BIT_DEBUG(0, "8 Khz (0x0001)"),
+	UTIL_BIT_DEBUG(1, "11.25 Khz (0x0002)"),
+	UTIL_BIT_DEBUG(2, "16 Khz (0x0004)"),
+	UTIL_BIT_DEBUG(3, "22.05 Khz (0x0008)"),
+	UTIL_BIT_DEBUG(4, "24 Khz (0x0010)"),
+	UTIL_BIT_DEBUG(5, "32 Khz (0x0020)"),
+	UTIL_BIT_DEBUG(6, "44.1 Khz (0x0040)"),
+	UTIL_BIT_DEBUG(7, "48 Khz (0x0080)"),
+	UTIL_BIT_DEBUG(8, "88.2 Khz (0x0100)"),
+	UTIL_BIT_DEBUG(9, "96 Khz (0x0200)"),
+	UTIL_BIT_DEBUG(10, "176.4 Khz (0x0400)"),
+	UTIL_BIT_DEBUG(11, "192 Khz (0x0800)"),
+	UTIL_BIT_DEBUG(12, "384 Khz (0x1000)"),
+	UTIL_BIT_DEBUG(13, "RFU (0x2000)"),
+	UTIL_BIT_DEBUG(14, "RFU (0x4000)"),
+	UTIL_BIT_DEBUG(15, "RFU (0x8000)"),
+	{ }
+};
+
+static void pac_debug_freq(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint16_t value;
+	uint16_t mask;
+
+	if (!util_iov_pull_le16(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Sampling Frequencies: 0x%4.4x", value);
+
+	mask = util_debug_bit("Sampling Frequency: ", value, pac_freq_table,
+				func, user_data);
+	if (mask)
+		util_debug(func, user_data, "Unknown fields (0x%4.4x)",
+						mask);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+					user_data);
+}
+
+static const struct util_bit_debugger pac_duration_table[] = {
+	UTIL_BIT_DEBUG(0, "7.5 ms (0x01)"),
+	UTIL_BIT_DEBUG(1, "10 ms (0x02)"),
+	UTIL_BIT_DEBUG(2, "RFU (0x04)"),
+	UTIL_BIT_DEBUG(3, "RFU (0x08)"),
+	UTIL_BIT_DEBUG(4, "7.5 ms preferred (0x10)"),
+	UTIL_BIT_DEBUG(5, "10 ms preferred (0x20)"),
+	UTIL_BIT_DEBUG(6, "RFU (0x40)"),
+	UTIL_BIT_DEBUG(7, "RFU (0x80)"),
+	{ }
+};
+
+static void pac_debug_duration(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+	uint8_t mask;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Frame Duration: 0x%2.2x", value);
+
+	mask = util_debug_bit("Frame Duration: ", value, pac_duration_table,
+				func, user_data);
+	if (mask)
+		util_debug(func, user_data, "Unknown fields (0x%2.2x)",
+					mask);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+					user_data);
+}
+
+static const struct util_bit_debugger pac_channel_table[] = {
+	UTIL_BIT_DEBUG(0, "1 channel (0x01)"),
+	UTIL_BIT_DEBUG(1, "2 channel (0x02)"),
+	UTIL_BIT_DEBUG(2, "3 channel (0x04)"),
+	UTIL_BIT_DEBUG(3, "4 channel (0x08)"),
+	UTIL_BIT_DEBUG(4, "5 channel (0x10)"),
+	UTIL_BIT_DEBUG(5, "6 channel (0x20)"),
+	UTIL_BIT_DEBUG(6, "7 channel (0x40)"),
+	UTIL_BIT_DEBUG(7, "8 channel (0x80)"),
+	{ }
+};
+
+static void pac_debug_channels(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+	uint8_t mask;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Audio Channel Count: 0x%2.2x", value);
+
+	mask = util_debug_bit("Audio Channel Count: ", value,
+				pac_channel_table, func, user_data);
+	if (mask)
+		util_debug(func, user_data, "Unknown fields (0x%2.2x)",
+					mask);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+					user_data);
+}
+
+static void pac_debug_frame_length(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint16_t min, max;
+
+	if (!util_iov_pull_le16(&frame, &min)) {
+		util_debug(func, user_data, "min: invalid size");
+		goto done;
+	}
+
+	if (!util_iov_pull_le16(&frame, &max)) {
+		util_debug(func, user_data, "max: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data,
+			"Frame Length: %u (0x%4.4x) - %u (0x%4.4x)",
+			min, min, max, max);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+					user_data);
+}
+
+static void pac_debug_sdu(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Max SDU: %u (0x%2.2x)", value, value);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+					user_data);
+}
+
+static const struct util_ltv_debugger pac_cap_table[] = {
+	UTIL_LTV_DEBUG(0x01, pac_debug_freq),
+	UTIL_LTV_DEBUG(0x02, pac_debug_duration),
+	UTIL_LTV_DEBUG(0x03, pac_debug_channels),
+	UTIL_LTV_DEBUG(0x04, pac_debug_frame_length),
+	UTIL_LTV_DEBUG(0x05, pac_debug_sdu)
+};
+
+bool bt_bap_debug_caps(void *data, size_t len, util_debug_func_t func,
+						void *user_data)
+{
+	return util_debug_ltv(data, len, pac_cap_table,
+				ARRAY_SIZE(pac_cap_table),
+				func, user_data);
+}
+
+static void ase_debug_freq(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	switch (value) {
+	case 0x01:
+		util_debug(func, user_data, "Sampling Frequency: 8 Khz (0x01)");
+		break;
+	case 0x02:
+		util_debug(func, user_data,
+				"Sampling Frequency: 11.25 Khz (0x02)");
+		break;
+	case 0x03:
+		util_debug(func, user_data,
+				"Sampling Frequency: 16 Khz (0x03)");
+		break;
+	case 0x04:
+		util_debug(func, user_data,
+				"Sampling Frequency: 22.05 Khz (0x04)");
+		break;
+	case 0x05:
+		util_debug(func, user_data,
+				"Sampling Frequency: 24 Khz (0x05)");
+		break;
+	case 0x06:
+		util_debug(func, user_data,
+				"Sampling Frequency: 32 Khz (0x06)");
+		break;
+	case 0x07:
+		util_debug(func, user_data,
+				"Sampling Frequency: 44.1 Khz (0x07)");
+		break;
+	case 0x08:
+		util_debug(func, user_data,
+				"Sampling Frequency: 48 Khz (0x08)");
+		break;
+	case 0x09:
+		util_debug(func, user_data,
+				"Sampling Frequency: 88.2 Khz (0x09)");
+		break;
+	case 0x0a:
+		util_debug(func, user_data,
+				"Sampling Frequency: 96 Khz (0x0a)");
+		break;
+	case 0x0b:
+		util_debug(func, user_data,
+				"Sampling Frequency: 176.4 Khz (0x0b)");
+		break;
+	case 0x0c:
+		util_debug(func, user_data,
+				"Sampling Frequency: 192 Khz (0x0c)");
+		break;
+	case 0x0d:
+		util_debug(func, user_data,
+				"Sampling Frequency: 384 Khz (0x0d)");
+		break;
+	default:
+		util_debug(func, user_data,
+				"Sampling Frequency: RFU (0x%2.2x)", value);
+		break;
+	}
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static void ase_debug_duration(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "\tvalue: invalid size\n");
+		goto done;
+	}
+
+	switch (value) {
+	case 0x00:
+		util_debug(func, user_data, "Frame Duration: 7.5 ms (0x00)");
+		break;
+	case 0x01:
+		util_debug(func, user_data, "Frame Duration: 10 ms (0x01)");
+		break;
+	default:
+		util_debug(func, user_data, "Frame Duration: RFU (0x%2.2x)",
+				value);
+		break;
+	}
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static const struct util_bit_debugger channel_location_table[] = {
+	UTIL_BIT_DEBUG(0, "Front Left (0x00000001)"),
+	UTIL_BIT_DEBUG(1, "Front Right (0x00000002)"),
+	UTIL_BIT_DEBUG(2, "Front Center (0x00000004)"),
+	UTIL_BIT_DEBUG(3, "Low Frequency Effects 1 (0x00000008)"),
+	UTIL_BIT_DEBUG(4, "Back Left (0x00000010)"),
+	UTIL_BIT_DEBUG(5, "Back Right (0x00000020)"),
+	UTIL_BIT_DEBUG(6, "Front Left of Center (0x00000040)"),
+	UTIL_BIT_DEBUG(7, "Front Right of Center (0x00000080)"),
+	UTIL_BIT_DEBUG(8, "Back Center (0x00000100)"),
+	UTIL_BIT_DEBUG(9, "Low Frequency Effects 2 (0x00000200)"),
+	UTIL_BIT_DEBUG(10, "Side Left (0x00000400)"),
+	UTIL_BIT_DEBUG(11, "Side Right (0x00000800)"),
+	UTIL_BIT_DEBUG(12, "Top Front Left (0x00001000)"),
+	UTIL_BIT_DEBUG(13, "Top Front Right (0x00002000)"),
+	UTIL_BIT_DEBUG(14, "Top Front Center (0x00004000)"),
+	UTIL_BIT_DEBUG(15, "Top Center (0x00008000)"),
+	UTIL_BIT_DEBUG(16, "Top Back Left (0x00010000)"),
+	UTIL_BIT_DEBUG(17, "Top Back Right (0x00020000)"),
+	UTIL_BIT_DEBUG(18, "Top Side Left (0x00040000)"),
+	UTIL_BIT_DEBUG(19, "Top Side Right (0x00080000)"),
+	UTIL_BIT_DEBUG(20, "Top Back Center (0x00100000)"),
+	UTIL_BIT_DEBUG(21, "Bottom Front Center (0x00200000)"),
+	UTIL_BIT_DEBUG(22, "Bottom Front Left (0x00400000)"),
+	UTIL_BIT_DEBUG(23, "Bottom Front Right (0x00800000)"),
+	UTIL_BIT_DEBUG(24, "Front Left Wide (0x01000000)"),
+	UTIL_BIT_DEBUG(25, "Front Right Wide (0x02000000)"),
+	UTIL_BIT_DEBUG(26, "Left Surround (0x04000000)"),
+	UTIL_BIT_DEBUG(27, "Right Surround (0x08000000)"),
+	UTIL_BIT_DEBUG(28, "RFU (0x10000000)"),
+	UTIL_BIT_DEBUG(29, "RFU (0x20000000)"),
+	UTIL_BIT_DEBUG(30, "RFU (0x40000000)"),
+	UTIL_BIT_DEBUG(31, "RFU (0x80000000)"),
+	{ }
+};
+
+static void debug_location(const struct iovec *frame, util_debug_func_t func,
+				void *user_data)
+{
+	uint32_t value;
+	uint32_t mask;
+
+	if (!util_iov_pull_le32((void *)frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Location: 0x%8.8x", value);
+
+	mask = util_debug_bit("Location: ", value, channel_location_table,
+				func, user_data);
+	if (mask)
+		util_debug(func, user_data, "Unknown fields (0x%8.8x)", mask);
+
+done:
+	if (frame->iov_len)
+		util_hexdump(' ', frame->iov_base, frame->iov_len, func,
+				user_data);
+}
+
+static void ase_debug_location(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+
+	debug_location(&frame, func, user_data);
+}
+
+static void ase_debug_frame_length(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint16_t value;
+
+	if (!util_iov_pull_le16(&frame, &value)) {
+		util_debug(func, user_data, "\tvalue: invalid size\n");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Frame Length: %u (0x%4.4x)",
+				value, value);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static void ase_debug_blocks(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint8_t value;
+
+	if (!util_iov_pull_u8(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Frame Blocks per SDU: %u (0x%2.2x)",
+				value, value);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static const struct util_ltv_debugger ase_cc_table[] = {
+	UTIL_LTV_DEBUG(0x01, ase_debug_freq),
+	UTIL_LTV_DEBUG(0x02, ase_debug_duration),
+	UTIL_LTV_DEBUG(0x03, ase_debug_location),
+	UTIL_LTV_DEBUG(0x04, ase_debug_frame_length),
+	UTIL_LTV_DEBUG(0x05, ase_debug_blocks)
+};
+
+bool bt_bap_debug_config(void *data, size_t len, util_debug_func_t func,
+						void *user_data)
+{
+	return util_debug_ltv(data, len, ase_cc_table,
+				ARRAY_SIZE(ase_cc_table),
+				func, user_data);
+}
+
+static const struct util_bit_debugger pac_context_table[] = {
+	UTIL_BIT_DEBUG(0, "\tUnspecified (0x0001)"),
+	UTIL_BIT_DEBUG(1, "\tConversational (0x0002)"),
+	UTIL_BIT_DEBUG(2, "\tMedia (0x0004)"),
+	UTIL_BIT_DEBUG(3, "\tGame (0x0008)"),
+	UTIL_BIT_DEBUG(4, "\tInstructional (0x0010)"),
+	UTIL_BIT_DEBUG(5, "\tVoice Assistants (0x0020)"),
+	UTIL_BIT_DEBUG(6, "\tLive (0x0040)"),
+	UTIL_BIT_DEBUG(7, "\tSound Effects (0x0080)"),
+	UTIL_BIT_DEBUG(8, "\tNotifications (0x0100)"),
+	UTIL_BIT_DEBUG(9, "\tRingtone (0x0200)"),
+	UTIL_BIT_DEBUG(10, "\tAlerts (0x0400)"),
+	UTIL_BIT_DEBUG(11, "\tEmergency alarm (0x0800)"),
+	UTIL_BIT_DEBUG(12, "\tRFU (0x1000)"),
+	UTIL_BIT_DEBUG(13, "\tRFU (0x2000)"),
+	UTIL_BIT_DEBUG(14, "\tRFU (0x4000)"),
+	UTIL_BIT_DEBUG(15, "\tRFU (0x8000)"),
+	{ }
+};
+
+static void debug_context(const struct iovec *frame, const char *label,
+				util_debug_func_t func, void *user_data)
+{
+	uint16_t value;
+	uint16_t mask;
+
+	if (!util_iov_pull_le16((void *)frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "%s: 0x%4.4x", label, value);
+
+	mask = util_debug_bit(label, value, pac_context_table, func, user_data);
+	if (mask)
+		util_debug(func, user_data, "Unknown fields (0x%4.4x)", mask);
+
+done:
+	if (frame->iov_len)
+		util_hexdump(' ', frame->iov_base, frame->iov_len, func,
+				user_data);
+}
+
+static void ase_debug_preferred_context(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+
+	debug_context(&frame, "Preferred Context", func, user_data);
+}
+
+static void ase_debug_context(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+
+	debug_context(&frame, "Context", func, user_data);
+}
+
+static void ase_debug_program_info(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	const char *str;
+
+	str = util_iov_pull_mem(&frame, len);
+	if (!str) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Program Info: %*s", len, str);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static void ase_debug_language(const uint8_t *data, uint8_t len,
+				util_debug_func_t func, void *user_data)
+{
+	struct iovec frame = { (void *)data, len };
+	uint32_t value;
+
+	if (!util_iov_pull_le24(&frame, &value)) {
+		util_debug(func, user_data, "value: invalid size");
+		goto done;
+	}
+
+	util_debug(func, user_data, "Language: 0x%6.6x\n", value);
+
+done:
+	if (frame.iov_len)
+		util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+				user_data);
+}
+
+static const struct util_ltv_debugger ase_metadata_table[] = {
+	UTIL_LTV_DEBUG(0x01, ase_debug_preferred_context),
+	UTIL_LTV_DEBUG(0x02, ase_debug_context),
+	UTIL_LTV_DEBUG(0x03, ase_debug_program_info),
+	UTIL_LTV_DEBUG(0x04, ase_debug_language)
+};
+
+bool bt_bap_debug_metadata(void *data, size_t len, util_debug_func_t func,
+						void *user_data)
+{
+	return util_debug_ltv(data, len, ase_metadata_table,
+				ARRAY_SIZE(ase_metadata_table),
+				func, user_data);
+}
diff --git a/src/shared/bap-debug.h b/src/shared/bap-debug.h
new file mode 100644
index 0000000..93f3b18
--- /dev/null
+++ b/src/shared/bap-debug.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  Intel Corporation.
+ */
+
+bool bt_bap_debug_caps(void *data, size_t len, util_debug_func_t func,
+						void *user_data);
+bool bt_bap_debug_config(void *data, size_t len, util_debug_func_t func,
+						void *user_data);
+bool bt_bap_debug_metadata(void *data, size_t len, util_debug_func_t func,
+						void *user_data);
diff --git a/src/shared/bap-defs.h b/src/shared/bap-defs.h
new file mode 100644
index 0000000..27fefa3
--- /dev/null
+++ b/src/shared/bap-defs.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
+ *
+ */
+
+#ifndef SRC_SHARED_BAP_DEFS_H_
+#define SRC_SHARED_BAP_DEFS_H_
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+#define BT_BAP_SINK			BIT(0)
+#define	BT_BAP_SOURCE			BIT(1)
+#define	BT_BAP_BCAST_SOURCE		BIT(2)
+#define	BT_BAP_BCAST_SINK		BIT(3)
+
+#define BT_BAP_STREAM_TYPE_UCAST	0x01
+#define	BT_BAP_STREAM_TYPE_BCAST	0x02
+
+#define BT_BAP_STREAM_STATE_IDLE	0x00
+#define BT_BAP_STREAM_STATE_CONFIG	0x01
+#define BT_BAP_STREAM_STATE_QOS		0x02
+#define BT_BAP_STREAM_STATE_ENABLING	0x03
+#define BT_BAP_STREAM_STATE_STREAMING	0x04
+#define BT_BAP_STREAM_STATE_DISABLING	0x05
+#define BT_BAP_STREAM_STATE_RELEASING	0x06
+
+#define BT_BAP_CONFIG_LATENCY_LOW	0x01
+#define BT_BAP_CONFIG_LATENCY_BALANCED	0x02
+#define BT_BAP_CONFIG_LATENCY_HIGH	0x03
+
+#define BT_BAP_CONFIG_PHY_1M		0x01
+#define BT_BAP_CONFIG_PHY_2M		0x02
+#define BT_BAP_CONFIG_PHY_CODEC		0x03
+
+struct bt_bap_codec {
+	uint8_t  id;
+	uint16_t cid;
+	uint16_t vid;
+} __packed;
+
+struct bt_ltv {
+	uint8_t  len;
+	uint8_t  type;
+	uint8_t  value[];
+} __packed;
+
+struct bt_bap_io_qos {
+	uint32_t interval;	/* Frame interval */
+	uint16_t latency;	/* Transport Latency */
+	uint16_t sdu;		/* Maximum SDU Size */
+	uint8_t  phy;		/* PHY */
+	uint8_t  rtn;		/* Retransmission Effort */
+};
+
+struct bt_bap_ucast_qos {
+	uint8_t  cig_id;
+	uint8_t  cis_id;
+	uint8_t  framing;		/* Frame framing */
+	uint32_t delay;			/* Presentation Delay */
+	uint8_t  target_latency;	/* Target Latency */
+	struct bt_bap_io_qos io_qos;
+};
+
+struct bt_bap_bcast_qos {
+	uint8_t  big;
+	uint8_t  bis;
+	uint8_t  sync_factor;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  encryption;
+	struct iovec *bcode;
+	uint8_t  options;
+	uint16_t skip;
+	uint16_t sync_timeout;
+	uint8_t  sync_cte_type;
+	uint8_t  mse;
+	uint16_t timeout;
+	uint8_t  pa_sync;
+	struct bt_bap_io_qos io_qos;
+	uint32_t delay;			/* Presentation Delay */
+};
+
+struct bt_bap_qos {
+	union {
+		struct bt_bap_ucast_qos ucast;
+		struct bt_bap_bcast_qos bcast;
+	};
+};
+
+#endif /* SRC_SHARED_BAP_DEFS_H_ */
diff --git a/src/shared/bap.c b/src/shared/bap.c
index c3c0d59..658ee13 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  */
 
@@ -28,6 +29,7 @@
 #include "src/shared/gatt-client.h"
 #include "src/shared/bap.h"
 #include "src/shared/ascs.h"
+#include "src/shared/bap-debug.h"
 
 /* Maximum number of ASE(s) */
 #define NUM_SINKS 2
@@ -46,7 +48,17 @@
 
 #define BAP_PROCESS_TIMEOUT 10
 
+#define BAP_FREQ_LTV_TYPE 1
+#define BAP_DURATION_LTV_TYPE 2
+#define BAP_CHANNEL_ALLOCATION_LTV_TYPE 3
+#define BAP_FRAME_LEN_LTV_TYPE 4
+#define CODEC_SPECIFIC_CONFIGURATION_MASK (\
+		(1<<BAP_FREQ_LTV_TYPE)|\
+		(1<<BAP_DURATION_LTV_TYPE)|\
+		(1<<BAP_FRAME_LEN_LTV_TYPE))
+
 struct bt_bap_pac_changed {
+	unsigned int id;
 	bt_bap_pac_func_t added;
 	bt_bap_pac_func_t removed;
 	bt_bap_destroy_func_t destroy;
@@ -90,6 +102,12 @@ struct bt_pacs {
 	struct gatt_db_attribute *context_ccc;
 	struct gatt_db_attribute *supported_context;
 	struct gatt_db_attribute *supported_context_ccc;
+	uint32_t source_loc_value;
+	uint32_t sink_loc_value;
+	uint16_t source_context_value;
+	uint16_t sink_context_value;
+	uint16_t supported_source_context_value;
+	uint16_t supported_sink_context_value;
 };
 
 struct bt_ase {
@@ -113,7 +131,8 @@ struct bt_bap_db {
 	struct bt_ascs *ascs;
 	struct queue *sinks;
 	struct queue *sources;
-	struct queue *endpoints;
+	struct queue *broadcast_sources;
+	struct queue *broadcast_sinks;
 };
 
 struct bt_bap_req {
@@ -127,17 +146,6 @@ struct bt_bap_req {
 	void *user_data;
 };
 
-typedef void (*bap_func_t)(struct bt_bap *bap, bool success, uint8_t att_ecode,
-					const uint8_t *value, uint16_t length,
-					void *user_data);
-
-struct bt_bap_pending {
-	unsigned int id;
-	struct bt_bap *bap;
-	bap_func_t func;
-	void *user_data;
-};
-
 typedef void (*bap_notify_t)(struct bt_bap *bap, uint16_t value_handle,
 				const uint8_t *value, uint16_t length,
 				void *user_data);
@@ -156,15 +164,20 @@ struct bt_bap {
 	struct bt_gatt_client *client;
 	struct bt_att *att;
 	struct bt_bap_req *req;
-	unsigned int cp_id;
 
+	unsigned int cp_id;
 	unsigned int process_id;
 	unsigned int disconn_id;
+	unsigned int idle_id;
+	bool in_cp_write;
+
 	struct queue *reqs;
-	struct queue *pending;
 	struct queue *notify;
 	struct queue *streams;
+	struct queue *local_eps;
+	struct queue *remote_eps;
 
+	struct queue *pac_cbs;
 	struct queue *ready_cbs;
 	struct queue *state_cbs;
 
@@ -174,21 +187,26 @@ struct bt_bap {
 	void *user_data;
 };
 
+struct bt_bap_chan {
+	uint8_t count;
+	uint32_t location;
+};
+
 struct bt_bap_pac {
 	struct bt_bap_db *bdb;
 	char *name;
 	uint8_t type;
-	uint32_t locations;
-	uint16_t contexts;
 	struct bt_bap_codec codec;
 	struct bt_bap_pac_qos qos;
 	struct iovec *data;
 	struct iovec *metadata;
+	struct queue *channels;
 	struct bt_bap_pac_ops *ops;
 	void *user_data;
 };
 
 struct bt_bap_endpoint {
+	struct bt_bap *bap;
 	struct bt_bap_db *bdb;
 	struct bt_bap_stream *stream;
 	struct gatt_db_attribute *attr;
@@ -206,10 +224,47 @@ struct bt_bap_stream_io {
 	bool connecting;
 };
 
+struct bt_bap_stream_ops {
+	uint8_t type;
+	void (*set_state)(struct bt_bap_stream *stream, uint8_t state);
+	unsigned int (*get_state)(struct bt_bap_stream *stream);
+	unsigned int (*config)(struct bt_bap_stream *stream,
+				struct bt_bap_qos *qos, struct iovec *data,
+				bt_bap_stream_func_t func, void *user_data);
+	unsigned int (*qos)(struct bt_bap_stream *stream,
+				struct bt_bap_qos *qos,
+				bt_bap_stream_func_t func, void *user_data);
+	unsigned int (*enable)(struct bt_bap_stream *stream, bool enable_links,
+				struct iovec *metadata,
+				bt_bap_stream_func_t func, void *user_data);
+	unsigned int (*start)(struct bt_bap_stream *stream,
+				bt_bap_stream_func_t func, void *user_data);
+	unsigned int (*disable)(struct bt_bap_stream *stream,
+				bool disable_links, bt_bap_stream_func_t func,
+				void *user_data);
+	unsigned int (*stop)(struct bt_bap_stream *stream,
+				bt_bap_stream_func_t func, void *user_data);
+	unsigned int (*metadata)(struct bt_bap_stream *stream,
+				struct iovec *data, bt_bap_stream_func_t func,
+				void *user_data);
+	unsigned int (*get_dir)(struct bt_bap_stream *stream);
+	unsigned int (*get_loc)(struct bt_bap_stream *stream);
+	unsigned int (*release)(struct bt_bap_stream *stream,
+				bt_bap_stream_func_t func, void *user_data);
+	void (*detach)(struct bt_bap_stream *stream);
+	bool (*set_io)(struct bt_bap_stream *stream, int fd);
+	struct bt_bap_stream_io* (*get_io)(struct bt_bap_stream *stream);
+	uint8_t (*io_dir)(struct bt_bap_stream *stream);
+	int (*io_link)(struct bt_bap_stream *stream,
+					struct bt_bap_stream *link);
+	int (*io_unlink)(struct bt_bap_stream *stream,
+					struct bt_bap_stream *link);
+};
+
 struct bt_bap_stream {
+	int ref_count;
 	struct bt_bap *bap;
 	struct bt_bap_endpoint *ep;
-	struct queue *pacs;
 	struct bt_bap_pac *lpac;
 	struct bt_bap_pac *rpac;
 	struct iovec *cc;
@@ -217,6 +272,10 @@ struct bt_bap_stream {
 	struct bt_bap_qos qos;
 	struct queue *links;
 	struct bt_bap_stream_io *io;
+	const struct bt_bap_stream_ops *ops;
+	uint8_t old_state;
+	uint8_t state;
+	unsigned int state_id;
 	bool client;
 	void *user_data;
 };
@@ -248,12 +307,38 @@ struct bt_pacs_context {
 	uint16_t  src;
 } __packed;
 
+struct bt_base {
+	uint8_t big_id;
+	uint32_t pres_delay;
+	uint8_t next_bis_index;
+	struct queue *subgroups;
+};
+
+struct bt_subgroup {
+	uint8_t index;
+	struct bt_bap_codec codec;
+	struct iovec *caps;
+	struct iovec *meta;
+	struct queue *bises;
+};
+
+struct bt_bis {
+	uint8_t index;
+	struct iovec *caps;
+};
+
 /* Contains local bt_bap_db */
 static struct queue *bap_db;
-static struct queue *pac_cbs;
 static struct queue *bap_cbs;
 static struct queue *sessions;
 
+static void bap_stream_set_io(void *data, void *user_data);
+static void stream_find_io(void *data, void *user_data);
+static void bap_stream_get_dir(void *data, void *user_data);
+static struct bt_bap_stream_io *stream_io_ref(struct bt_bap_stream_io *io);
+static int bap_bcast_io_unlink(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link);
+
 static bool bap_db_match(const void *data, const void *match_data)
 {
 	const struct bt_bap_db *bdb = data;
@@ -262,94 +347,26 @@ static bool bap_db_match(const void *data, const void *match_data)
 	return (bdb->db == db);
 }
 
-static void *iov_add(struct iovec *iov, size_t len)
-{
-	void *data;
-
-	data = iov->iov_base + iov->iov_len;
-	iov->iov_len += len;
-
-	return data;
-}
-
-static void *iov_add_mem(struct iovec *iov, size_t len, const void *d)
-{
-	void *data;
-
-	data = iov->iov_base + iov->iov_len;
-	iov->iov_len += len;
-
-	memcpy(data, d, len);
-
-	return data;
-}
-
-static void iov_free(void *data)
-{
-	struct iovec *iov = data;
-
-	if (!iov)
-		return;
-
-	free(iov->iov_base);
-	free(iov);
-}
-
-static void iov_memcpy(struct iovec *iov, void *src, size_t len)
-{
-	iov->iov_base = realloc(iov->iov_base, len);
-	iov->iov_len = len;
-	memcpy(iov->iov_base, src, len);
-}
-
-static int iov_memcmp(struct iovec *iov1, struct iovec *iov2)
-{
-	if (!iov1)
-		return 1;
-
-	if (!iov2)
-		return -1;
-
-	if (iov1->iov_len != iov2->iov_len)
-		return iov1->iov_len - iov2->iov_len;
-
-	return memcmp(iov1->iov_base, iov2->iov_base, iov1->iov_len);
-}
-
-static struct iovec *iov_dup(struct iovec *iov, size_t len)
-{
-	struct iovec *dup;
-	size_t i;
-
-	if (!iov)
-		return NULL;
-
-	dup = new0(struct iovec, len);
-
-	for (i = 0; i < len; i++)
-		iov_memcpy(&dup[i], iov[i].iov_base, iov[i].iov_len);
-
-	return dup;
-}
-
-unsigned int bt_bap_pac_register(bt_bap_pac_func_t added,
+unsigned int bt_bap_pac_register(struct bt_bap *bap, bt_bap_pac_func_t added,
 				bt_bap_pac_func_t removed, void *user_data,
 				bt_bap_destroy_func_t destroy)
 {
 	struct bt_bap_pac_changed *changed;
+	static unsigned int id;
+
+	if (!bap)
+		return 0;
 
 	changed = new0(struct bt_bap_pac_changed, 1);
+	changed->id = ++id ? id : ++id;
 	changed->added = added;
 	changed->removed = removed;
 	changed->destroy = destroy;
 	changed->data = user_data;
 
-	if (!pac_cbs)
-		pac_cbs = queue_new();
+	queue_push_tail(bap->pac_cbs, changed);
 
-	queue_push_tail(pac_cbs, changed);
-
-	return queue_length(pac_cbs);
+	return changed->id;
 }
 
 static void pac_changed_free(void *data)
@@ -362,39 +379,28 @@ static void pac_changed_free(void *data)
 	free(changed);
 }
 
-struct match_pac_id {
-	unsigned int id;
-	unsigned int index;
-};
-
-static bool match_index(const void *data, const void *match_data)
+static bool match_pac_changed_id(const void *data, const void *match_data)
 {
-	struct match_pac_id *match = (void *)match_data;
-
-	match->index++;
+	const struct bt_bap_pac_changed *changed = data;
+	unsigned int id = PTR_TO_UINT(match_data);
 
-	return match->id == match->index;
+	return (changed->id == id);
 }
 
-bool bt_bap_pac_unregister(unsigned int id)
+bool bt_bap_pac_unregister(struct bt_bap *bap, unsigned int id)
 {
 	struct bt_bap_pac_changed *changed;
-	struct match_pac_id match;
 
-	memset(&match, 0, sizeof(match));
-	match.id = id;
+	if (!bap)
+		return false;
 
-	changed = queue_remove_if(pac_cbs, match_index, &match);
+	changed = queue_remove_if(bap->pac_cbs, match_pac_changed_id,
+						UINT_TO_PTR(id));
 	if (!changed)
 		return false;
 
 	pac_changed_free(changed);
 
-	if (queue_isempty(pac_cbs)) {
-		queue_destroy(pac_cbs, NULL);
-		pac_cbs = NULL;
-	}
-
 	return true;
 }
 
@@ -407,27 +413,29 @@ static void pac_foreach(void *data, void *user_data)
 	struct bt_pac_metadata *meta;
 
 	if (!iov->iov_len) {
-		rsp = iov_add(iov, sizeof(*rsp));
+		rsp = util_iov_push(iov, sizeof(*rsp));
 		rsp->num_pac = 0;
 	} else
 		rsp = iov->iov_base;
 
 	rsp->num_pac++;
 
-	p = iov_add(iov, sizeof(*p));
+	p = util_iov_push(iov, sizeof(*p));
 	p->codec.id = pac->codec.id;
+	p->codec.cid = cpu_to_le16(pac->codec.cid);
+	p->codec.vid = cpu_to_le16(pac->codec.vid);
 
 	if (pac->data) {
 		p->cc_len = pac->data->iov_len;
-		iov_add_mem(iov, p->cc_len, pac->data->iov_base);
+		util_iov_push_mem(iov, p->cc_len, pac->data->iov_base);
 	} else
 		p->cc_len = 0;
 
-	meta = iov_add(iov, sizeof(*meta));
+	meta = util_iov_push(iov, sizeof(*meta));
 
 	if (pac->metadata) {
 		meta->len = pac->metadata->iov_len;
-		iov_add_mem(iov, meta->len, pac->metadata->iov_base);
+		util_iov_push_mem(iov, meta->len, pac->metadata->iov_base);
 	} else
 		meta->len = 0;
 }
@@ -448,6 +456,7 @@ static void pacs_sink_read(struct gatt_db_attribute *attrib,
 	iov.iov_len = 0;
 
 	queue_foreach(bdb->sinks, pac_foreach, &iov);
+	queue_foreach(bdb->broadcast_sinks, pac_foreach, &iov);
 
 	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
 							iov.iov_len);
@@ -458,7 +467,8 @@ static void pacs_sink_loc_read(struct gatt_db_attribute *attrib,
 				uint8_t opcode, struct bt_att *att,
 				void *user_data)
 {
-	uint32_t value = 0x00000003;
+	struct bt_pacs *pacs = user_data;
+	uint32_t value = cpu_to_le32(pacs->sink_loc_value);
 
 	gatt_db_attribute_read_result(attrib, id, 0, (void *) &value,
 							sizeof(value));
@@ -490,7 +500,8 @@ static void pacs_source_loc_read(struct gatt_db_attribute *attrib,
 				uint8_t opcode, struct bt_att *att,
 				void *user_data)
 {
-	uint32_t value = 0x00000001;
+	struct bt_pacs *pacs = user_data;
+	uint32_t value = cpu_to_le32(pacs->source_loc_value);
 
 	gatt_db_attribute_read_result(attrib, id, 0, (void *) &value,
 							sizeof(value));
@@ -501,9 +512,10 @@ static void pacs_context_read(struct gatt_db_attribute *attrib,
 				uint8_t opcode, struct bt_att *att,
 				void *user_data)
 {
+	struct bt_pacs *pacs = user_data;
 	struct bt_pacs_context ctx = {
-		.snk = 0x0fff,
-		.src = 0x000e
+		.snk = cpu_to_le16(pacs->sink_context_value),
+		.src = cpu_to_le16(pacs->source_context_value)
 	};
 
 	gatt_db_attribute_read_result(attrib, id, 0, (void *) &ctx,
@@ -515,9 +527,10 @@ static void pacs_supported_context_read(struct gatt_db_attribute *attrib,
 					uint8_t opcode, struct bt_att *att,
 					void *user_data)
 {
+	struct bt_pacs *pacs = user_data;
 	struct bt_pacs_context ctx = {
-		.snk = 0x0fff,
-		.src = 0x000e
+		.snk = cpu_to_le16(pacs->supported_sink_context_value),
+		.src = cpu_to_le16(pacs->supported_source_context_value)
 	};
 
 	gatt_db_attribute_read_result(attrib, id, 0, (void *) &ctx,
@@ -561,14 +574,14 @@ static struct bt_pacs *pacs_new(struct gatt_db *db)
 					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
 
 	bt_uuid16_create(&uuid, PAC_SOURCE_CHRC_UUID);
-	pacs->sink = gatt_db_service_add_characteristic(pacs->service, &uuid,
+	pacs->source = gatt_db_service_add_characteristic(pacs->service, &uuid,
 					BT_ATT_PERM_READ,
 					BT_GATT_CHRC_PROP_READ |
 					BT_GATT_CHRC_PROP_NOTIFY,
 					pacs_source_read, NULL,
 					pacs);
 
-	pacs->sink_ccc = gatt_db_service_add_ccc(pacs->service,
+	pacs->source_ccc = gatt_db_service_add_ccc(pacs->service,
 					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
 
 	bt_uuid16_create(&uuid, PAC_SOURCE_LOC_CHRC_UUID);
@@ -685,7 +698,24 @@ static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb,
 	return ep;
 }
 
-static struct bt_bap_endpoint *bap_get_endpoint(struct bt_bap_db *db,
+static struct bt_bap_endpoint *bap_endpoint_new_broadcast(struct bt_bap_db *bdb,
+								uint8_t type)
+{
+	struct bt_bap_endpoint *ep;
+
+	ep = new0(struct bt_bap_endpoint, 1);
+	ep->bdb = bdb;
+	ep->attr = NULL;
+	if (type == BT_BAP_BCAST_SINK)
+		ep->dir = BT_BAP_BCAST_SOURCE;
+	else
+		ep->dir = BT_BAP_BCAST_SINK;
+
+	return ep;
+}
+
+static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
+						struct bt_bap_db *db,
 						struct gatt_db_attribute *attr)
 {
 	struct bt_bap_endpoint *ep;
@@ -693,7 +723,7 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct bt_bap_db *db,
 	if (!db || !attr)
 		return NULL;
 
-	ep = queue_find(db->endpoints, bap_endpoint_match, attr);
+	ep = queue_find(endpoints, bap_endpoint_match, attr);
 	if (ep)
 		return ep;
 
@@ -701,7 +731,36 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct bt_bap_db *db,
 	if (!ep)
 		return NULL;
 
-	queue_push_tail(db->endpoints, ep);
+	queue_push_tail(endpoints, ep);
+
+	return ep;
+}
+
+static bool match_ep_type(const void *data, const void *match_data)
+{
+	const struct bt_bap_endpoint *ep = data;
+	const uint8_t type = PTR_TO_INT(match_data);
+
+	return (ep->dir == type);
+}
+
+static struct bt_bap_endpoint *bap_get_endpoint_bcast(struct queue *endpoints,
+					struct bt_bap_db *db, uint8_t type)
+{
+	struct bt_bap_endpoint *ep;
+
+	if (!db)
+		return NULL;
+
+	ep = queue_find(endpoints, match_ep_type, INT_TO_PTR(type));
+	if (ep)
+		return ep;
+
+	ep = bap_endpoint_new_broadcast(db, type);
+	if (!ep)
+		return NULL;
+
+	queue_push_tail(endpoints, ep);
 
 	return ep;
 }
@@ -714,23 +773,22 @@ static bool bap_endpoint_match_id(const void *data, const void *match_data)
 	return (ep->id == id);
 }
 
-static struct bt_bap_endpoint *bap_get_endpoint_id(struct bt_bap *bap,
-						struct bt_bap_db *db,
-						uint8_t id)
+static struct bt_bap_endpoint *bap_get_local_endpoint_id(struct bt_bap *bap,
+								uint8_t id)
 {
 	struct bt_bap_endpoint *ep;
 	struct gatt_db_attribute *attr = NULL;
 	size_t i;
 
-	if (!bap || !db)
+	if (!bap)
 		return NULL;
 
-	ep = queue_find(db->endpoints, bap_endpoint_match_id, UINT_TO_PTR(id));
+	ep = queue_find(bap->local_eps, bap_endpoint_match_id, UINT_TO_PTR(id));
 	if (ep)
 		return ep;
 
-	for (i = 0; i < ARRAY_SIZE(db->ascs->ase); i++) {
-		struct bt_ase *ase = db->ascs->ase[i];
+	for (i = 0; i < ARRAY_SIZE(bap->ldb->ascs->ase); i++) {
+		struct bt_ase *ase = bap->ldb->ascs->ase[i];
 
 		if (id) {
 			if (ase->id != id)
@@ -739,7 +797,7 @@ static struct bt_bap_endpoint *bap_get_endpoint_id(struct bt_bap *bap,
 			break;
 		}
 
-		ep = queue_find(db->endpoints, bap_endpoint_match, ase->attr);
+		ep = queue_find(bap->local_eps, bap_endpoint_match, ase->attr);
 		if (!ep) {
 			attr = ase->attr;
 			break;
@@ -749,12 +807,12 @@ static struct bt_bap_endpoint *bap_get_endpoint_id(struct bt_bap *bap,
 	if (!attr)
 		return NULL;
 
-	ep = bap_endpoint_new(db, attr);
+	ep = bap_endpoint_new(bap->ldb, attr);
 	if (!ep)
 		return NULL;
 
 	ep->id = id;
-	queue_push_tail(db->endpoints, ep);
+	queue_push_tail(bap->local_eps, ep);
 
 	return ep;
 }
@@ -765,11 +823,17 @@ static void ascs_ase_read(struct gatt_db_attribute *attrib,
 				void *user_data)
 {
 	struct bt_ase *ase = user_data;
-	struct bt_bap *bap = bap_get_session(att, ase->ascs->bdb->db);
-	struct bt_bap_endpoint *ep = bap_get_endpoint(bap->ldb, attrib);
+	struct bt_bap *bap = NULL;
+	struct bt_bap_endpoint *ep = NULL;
 	struct bt_ascs_ase_status rsp;
 
-	if (!ase || !bap || !ep) {
+	if (ase)
+		bap = bap_get_session(att, ase->ascs->bdb->db);
+
+	if (bap)
+		ep = bap_get_endpoint(bap->local_eps, bap->ldb, attrib);
+
+	if (!ep) {
 		gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
 								NULL, 0);
 		return;
@@ -814,19 +878,6 @@ static void ase_new(struct bt_ascs *ascs, int i)
 	ascs->ase[i] = ase;
 }
 
-static void *iov_pull_mem(struct iovec *iov, size_t len)
-{
-	void *data = iov->iov_base;
-
-	if (iov->iov_len < len)
-		return NULL;
-
-	iov->iov_base += len;
-	iov->iov_len -= len;
-
-	return data;
-}
-
 static bool bap_codec_equal(const struct bt_bap_codec *c1,
 				const struct bt_bap_codec *c2)
 {
@@ -837,27 +888,46 @@ static bool bap_codec_equal(const struct bt_bap_codec *c1,
 	return c1->id == c2->id;
 }
 
-static struct bt_bap_stream *bap_stream_new(struct bt_bap *bap,
-						struct bt_bap_endpoint *ep,
-						struct bt_bap_pac *lpac,
-						struct bt_bap_pac *rpac,
-						struct iovec *data,
-						bool client)
+static void ascs_ase_rsp_add(struct iovec *iov, uint8_t id,
+					uint8_t code, uint8_t reason)
 {
-	struct bt_bap_stream *stream;
+	struct bt_ascs_cp_rsp *cp;
+	struct bt_ascs_ase_rsp *rsp;
 
-	stream = new0(struct bt_bap_stream, 1);
-	stream->bap = bap;
-	stream->ep = ep;
-	ep->stream = stream;
-	stream->lpac = lpac;
-	stream->rpac = rpac;
-	stream->cc = iov_dup(data, 1);
-	stream->client = client;
+	if (!iov)
+		return;
 
-	queue_push_tail(bap->streams, stream);
+	cp = iov->iov_base;
 
-	return stream;
+	if (cp->num_ase == 0xff)
+		return;
+
+	switch (code) {
+	/* If the Response_Code value is 0x01 or 0x02, Number_of_ASEs shall be
+	 * set to 0xFF.
+	 */
+	case BT_ASCS_RSP_NOT_SUPPORTED:
+	case BT_ASCS_RSP_TRUNCATED:
+		cp->num_ase = 0xff;
+		break;
+	default:
+		cp->num_ase++;
+		break;
+	}
+
+	iov->iov_len += sizeof(*rsp);
+	iov->iov_base = realloc(iov->iov_base, iov->iov_len);
+
+	rsp = iov->iov_base + (iov->iov_len - sizeof(*rsp));
+	rsp->ase = id;
+	rsp->code = code;
+	rsp->reason = reason;
+}
+
+static void ascs_ase_rsp_success(struct iovec *iov, uint8_t id)
+{
+	return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_SUCCESS,
+					BT_ASCS_REASON_NONE);
 }
 
 static void stream_notify_config(struct bt_bap_stream *stream)
@@ -910,6 +980,12 @@ static void stream_notify_config(struct bt_bap_stream *stream)
 	put_le24(lpac->qos.ppd_min, config->ppd_min);
 	put_le24(lpac->qos.ppd_max, config->ppd_max);
 	config->codec = lpac->codec;
+
+	if (config->codec.id == 0x0ff) {
+		config->codec.vid = cpu_to_le16(config->codec.vid);
+		config->codec.cid = cpu_to_le16(config->codec.cid);
+	}
+
 	config->cc_len = stream->cc->iov_len;
 	memcpy(config->cc, stream->cc->iov_base, stream->cc->iov_len);
 
@@ -936,15 +1012,15 @@ static void stream_notify_qos(struct bt_bap_stream *stream)
 	status->state = ep->state;
 
 	qos = (void *)status->params;
-	qos->cis_id = stream->qos.cis_id;
-	qos->cig_id = stream->qos.cig_id;
-	put_le24(stream->qos.interval, qos->interval);
-	qos->framing = stream->qos.framing;
-	qos->phy = stream->qos.phy;
-	qos->sdu = cpu_to_le16(stream->qos.sdu);
-	qos->rtn = stream->qos.rtn;
-	qos->latency = cpu_to_le16(stream->qos.latency);
-	put_le24(stream->qos.delay, qos->pd);
+	qos->cis_id = stream->qos.ucast.cis_id;
+	qos->cig_id = stream->qos.ucast.cig_id;
+	put_le24(stream->qos.ucast.io_qos.interval, qos->interval);
+	qos->framing = stream->qos.ucast.framing;
+	qos->phy = stream->qos.ucast.io_qos.phy;
+	qos->sdu = cpu_to_le16(stream->qos.ucast.io_qos.sdu);
+	qos->rtn = stream->qos.ucast.io_qos.rtn;
+	qos->latency = cpu_to_le16(stream->qos.ucast.io_qos.latency);
+	put_le24(stream->qos.ucast.delay, qos->pd);
 
 	gatt_db_attribute_notify(ep->attr, (void *) status, len,
 					bt_bap_get_att(stream->bap));
@@ -973,8 +1049,8 @@ static void stream_notify_metadata(struct bt_bap_stream *stream)
 	status->state = ep->state;
 
 	meta = (void *)status->params;
-	meta->cis_id = stream->qos.cis_id;
-	meta->cig_id = stream->qos.cig_id;
+	meta->cis_id = stream->qos.ucast.cis_id;
+	meta->cig_id = stream->qos.ucast.cig_id;
 
 	if (stream->meta) {
 		meta->len = stream->meta->iov_len;
@@ -987,6 +1063,14 @@ static void stream_notify_metadata(struct bt_bap_stream *stream)
 	free(status);
 }
 
+static struct bt_bap *bt_bap_ref_safe(struct bt_bap *bap)
+{
+	if (!bap || !bap->ref_count || !queue_find(sessions, NULL, bap))
+		return NULL;
+
+	return bt_bap_ref(bap);
+}
+
 static void bap_stream_clear_cfm(struct bt_bap_stream *stream)
 {
 	if (!stream->lpac->ops || !stream->lpac->ops->clear)
@@ -1034,149 +1118,166 @@ static void stream_io_unref(struct bt_bap_stream_io *io)
 
 static void bap_stream_unlink(void *data, void *user_data)
 {
-	struct bt_bap_stream *link = data;
-	struct bt_bap_stream *stream = user_data;
+	struct bt_bap_stream *stream = data;
+	struct bt_bap_stream *link = user_data;
 
-	queue_remove(link->links, stream);
+	queue_remove(stream->links, link);
 }
 
 static void bap_stream_free(void *data)
 {
 	struct bt_bap_stream *stream = data;
 
+	timeout_remove(stream->state_id);
+
 	if (stream->ep)
 		stream->ep->stream = NULL;
 
 	queue_foreach(stream->links, bap_stream_unlink, stream);
 	queue_destroy(stream->links, NULL);
+
 	stream_io_unref(stream->io);
-	iov_free(stream->cc);
-	iov_free(stream->meta);
+	util_iov_free(stream->cc, 1);
+	util_iov_free(stream->meta, 1);
 	free(stream);
 }
 
-static void bap_stream_detach(struct bt_bap_stream *stream)
+static void bap_req_free(void *data)
 {
-	struct bt_bap_endpoint *ep = stream->ep;
-
-	if (!ep)
-		return;
+	struct bt_bap_req *req = data;
+	size_t i;
 
-	DBG(stream->bap, "stream %p ep %p", stream, ep);
+	queue_destroy(req->group, bap_req_free);
 
-	queue_remove(stream->bap->streams, stream);
-	bap_stream_clear_cfm(stream);
+	for (i = 0; i < req->len; i++)
+		free(req->iov[i].iov_base);
 
-	stream->ep = NULL;
-	ep->stream = NULL;
-	bap_stream_free(stream);
+	free(req->iov);
+	free(req);
 }
 
-static void bap_stream_io_link(void *data, void *user_data)
+static void bap_req_complete(struct bt_bap_req *req,
+				const struct bt_ascs_ase_rsp *rsp)
 {
-	struct bt_bap_stream *stream = data;
-	struct bt_bap_stream *link = user_data;
+	struct queue *group;
 
-	bt_bap_stream_io_link(stream, link);
-}
+	if (!req->func)
+		goto done;
 
-static void bap_stream_update_io_links(struct bt_bap_stream *stream)
-{
-	struct bt_bap *bap = stream->bap;
+	if (rsp)
+		req->func(req->stream, rsp->code, rsp->reason, req->user_data);
+	else
+		req->func(req->stream, BT_ASCS_RSP_UNSPECIFIED, 0x00,
+						req->user_data);
 
-	DBG(bap, "stream %p", stream);
+done:
+	/* Detach from request so it can be freed separately */
+	group = req->group;
+	req->group = NULL;
+
+	queue_foreach(group, (queue_foreach_func_t)bap_req_complete,
+							(void *)rsp);
 
-	queue_foreach(bap->streams, bap_stream_io_link, stream);
+	queue_destroy(group, NULL);
+
+	bap_req_free(req);
 }
 
-static struct bt_bap_stream_io *stream_io_ref(struct bt_bap_stream_io *io)
+static bool match_req_stream(const void *data, const void *match_data)
 {
-	if (!io)
-		return NULL;
-
-	__sync_fetch_and_add(&io->ref_count, 1);
+	const struct bt_bap_req *req = data;
 
-	return io;
+	return req->stream == match_data;
 }
 
-static struct bt_bap_stream_io *stream_io_new(struct bt_bap *bap, int fd)
+static void bap_req_abort(void *data)
 {
-	struct io *io;
-	struct bt_bap_stream_io *sio;
+	struct bt_bap_req *req = data;
+	struct bt_bap *bap = req->stream->bap;
 
-	io = io_new(fd);
-	if (!io)
-		return NULL;
+	DBG(bap, "req %p", req);
+	bap_req_complete(req, NULL);
+}
 
-	DBG(bap, "fd %d", fd);
+static void bap_abort_stream_req(struct bt_bap *bap,
+						struct bt_bap_stream *stream)
+{
+	queue_remove_all(bap->reqs, match_req_stream, stream, bap_req_abort);
+}
 
-	sio = new0(struct bt_bap_stream_io, 1);
-	sio->bap = bap;
-	sio->io = io;
+static void bt_bap_stream_unref(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return;
 
-	return stream_io_ref(sio);
+	if (__sync_sub_and_fetch(&stream->ref_count, 1))
+		return;
+
+	bap_stream_free(stream);
 }
 
-static void stream_find_io(void *data, void *user_data)
+static void bap_ucast_detach(struct bt_bap_stream *stream)
 {
-	struct bt_bap_stream *stream = data;
-	struct bt_bap_stream_io **io = user_data;
+	struct bt_bap_endpoint *ep = stream->ep;
 
-	if (*io)
+	if (!ep)
 		return;
 
-	*io = stream->io;
+	DBG(stream->bap, "stream %p ep %p", stream, ep);
+
+	bap_abort_stream_req(stream->bap, stream);
+
+	queue_remove(stream->bap->streams, stream);
+	bap_stream_clear_cfm(stream);
+
+	stream->ep = NULL;
+	ep->stream = NULL;
+	bt_bap_stream_unref(stream);
 }
 
-static struct bt_bap_stream_io *stream_get_io(struct bt_bap_stream *stream)
+static void bap_bcast_src_detach(struct bt_bap_stream *stream)
 {
-	struct bt_bap_stream_io *io;
+	struct bt_bap_endpoint *ep = stream->ep;
 
-	if (!stream)
-		return NULL;
+	if (!ep)
+		return;
 
-	if (stream->io)
-		return stream->io;
+	DBG(stream->bap, "stream %p ep %p", stream, ep);
 
-	io = NULL;
-	queue_foreach(stream->links, stream_find_io, &io);
+	queue_remove(stream->bap->streams, stream);
+	bap_stream_clear_cfm(stream);
 
-	return io;
-}
+	stream->ep = NULL;
+	ep->stream = NULL;
 
-static bool stream_io_disconnected(struct io *io, void *user_data);
+	bt_bap_stream_unref(stream);
+}
 
-static bool bap_stream_io_attach(struct bt_bap_stream *stream, int fd,
-							bool connecting)
+static void bap_bcast_sink_detach(struct bt_bap_stream *stream)
 {
-	struct bt_bap_stream_io *io;
+	DBG(stream->bap, "stream %p", stream);
 
-	io = stream_get_io(stream);
-	if (io) {
-		if (fd == stream_io_get_fd(io)) {
-			if (!stream->io)
-				stream->io = stream_io_ref(io);
+	queue_remove(stream->bap->streams, stream);
+	bap_stream_clear_cfm(stream);
 
-			io->connecting = connecting;
-			return true;
-		}
+	bt_bap_stream_unref(stream);
+}
 
-		DBG(stream->bap, "stream %p io already set", stream);
-		return false;
-	}
+static bool bap_stream_io_link(const void *data, const void *user_data)
+{
+	struct bt_bap_stream *stream = (void *)data;
+	struct bt_bap_stream *link = (void *)user_data;
 
-	DBG(stream->bap, "stream %p connecting %s", stream,
-				connecting ? "true" : "false");
+	return !bt_bap_stream_io_link(stream, link);
+}
 
-	io = stream_io_new(stream->bap, fd);
-	if (!io)
-		return false;
+static void bap_stream_update_io_links(struct bt_bap_stream *stream)
+{
+	struct bt_bap *bap = stream->bap;
 
-	io->connecting = connecting;
-	stream->io = io;
-	io_set_disconnect_handler(io->io, stream_io_disconnected, stream, NULL);
+	DBG(bap, "stream %p", stream);
 
-	return true;
+	queue_find(bap->streams, bap_stream_io_link, stream);
 }
 
 static bool match_stream_io(const void *data, const void *user_data)
@@ -1215,32 +1316,13 @@ static bool bap_stream_io_detach(struct bt_bap_stream *stream)
 	return true;
 }
 
-static void bap_stream_set_io(void *data, void *user_data)
+static void stream_stop_complete(struct bt_bap_stream *stream, uint8_t code,
+					uint8_t reason,	void *user_data)
 {
-	struct bt_bap_stream *stream = data;
-	int fd = PTR_TO_INT(user_data);
-	bool ret;
-
-	if (fd >= 0)
-		ret = bap_stream_io_attach(stream, fd, false);
-	else
-		ret = bap_stream_io_detach(stream);
-
-	if (!ret)
-		return;
+	DBG(stream->bap, "stream %p stop 0x%02x 0x%02x", stream, code, reason);
 
-	switch (stream->ep->state) {
-	case BT_BAP_STREAM_STATE_ENABLING:
-		if (fd < 0)
-			bt_bap_stream_disable(stream, false, NULL, NULL);
-		else
-			bt_bap_stream_start(stream, NULL, NULL);
-		break;
-	case BT_BAP_STREAM_STATE_DISABLING:
-		if (fd < 0)
-			bt_bap_stream_stop(stream, NULL, NULL);
-		break;
-	}
+	if (stream->ep->state == BT_ASCS_ASE_STATE_DISABLING)
+		bap_stream_io_detach(stream);
 }
 
 static void bap_stream_state_changed(struct bt_bap_stream *stream)
@@ -1248,13 +1330,6 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
 	struct bt_bap *bap = stream->bap;
 	const struct queue_entry *entry;
 
-	DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
-			bt_bap_stream_get_dir(stream),
-			bt_bap_stream_statestr(stream->ep->old_state),
-			bt_bap_stream_statestr(stream->ep->state));
-
-	bt_bap_ref(bap);
-
 	/* Pre notification updates */
 	switch (stream->ep->state) {
 	case BT_ASCS_ASE_STATE_IDLE:
@@ -1263,7 +1338,9 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
 		bap_stream_update_io_links(stream);
 		break;
 	case BT_ASCS_ASE_STATE_DISABLING:
-		bap_stream_io_detach(stream);
+		/* As client, we detach after Receiver Stop Ready */
+		if (!stream->client)
+			bap_stream_io_detach(stream);
 		break;
 	case BT_ASCS_ASE_STATE_QOS:
 		if (stream->io && !stream->io->connecting)
@@ -1288,7 +1365,14 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
 	/* Post notification updates */
 	switch (stream->ep->state) {
 	case BT_ASCS_ASE_STATE_IDLE:
-		bap_stream_detach(stream);
+		if (bap->req && bap->req->stream == stream) {
+			bap_req_complete(bap->req, NULL);
+			bap->req = NULL;
+		}
+
+		if (stream->ops && stream->ops->detach)
+			stream->ops->detach(stream);
+
 		break;
 	case BT_ASCS_ASE_STATE_QOS:
 		break;
@@ -1297,476 +1381,502 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
 			bt_bap_stream_start(stream, NULL, NULL);
 		break;
 	case BT_ASCS_ASE_STATE_DISABLING:
-		if (!bt_bap_stream_get_io(stream))
-			bt_bap_stream_stop(stream, NULL, NULL);
+		/* Send Stop Ready, and detach IO after remote replies */
+		if (stream->client)
+			bt_bap_stream_stop(stream, stream_stop_complete, NULL);
 		break;
 	}
+}
+
+/* Return false if the stream is being detached */
+static bool stream_set_state(struct bt_bap_stream *stream, uint8_t state)
+{
+	struct bt_bap *bap = stream->bap;
+
+	/* Check if ref_count is already 0 which means detaching is in
+	 * progress.
+	 */
+	bap = bt_bap_ref_safe(bap);
+	if (!bap) {
+		if (stream->ops && stream->ops->detach)
+			stream->ops->detach(stream);
+
+		return false;
+	}
+
+	if (stream->ops && stream->ops->set_state)
+		stream->ops->set_state(stream, state);
 
 	bt_bap_unref(bap);
+	return true;
 }
 
-static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
+static void ep_config_cb(struct bt_bap_stream *stream, int err)
 {
-	struct bt_bap_endpoint *ep = stream->ep;
+	if (err)
+		return;
 
-	ep->old_state = ep->state;
-	ep->state = state;
+	stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
+}
 
-	if (stream->client)
-		goto done;
+static uint8_t stream_config(struct bt_bap_stream *stream, struct iovec *cc,
+							struct iovec *rsp)
+{
+	struct bt_bap_pac *pac = stream->lpac;
 
-	switch (ep->state) {
-	case BT_ASCS_ASE_STATE_IDLE:
-		break;
-	case BT_ASCS_ASE_STATE_CONFIG:
-		stream_notify_config(stream);
-		break;
-	case BT_ASCS_ASE_STATE_QOS:
-		stream_notify_qos(stream);
-		break;
-	case BT_ASCS_ASE_STATE_ENABLING:
-	case BT_ASCS_ASE_STATE_STREAMING:
-	case BT_ASCS_ASE_STATE_DISABLING:
-		stream_notify_metadata(stream);
-		break;
+	DBG(stream->bap, "stream %p", stream);
+
+	/* TODO: Wait for pac->ops response */
+	ascs_ase_rsp_success(rsp, stream->ep->id);
+
+	if (!util_iov_memcmp(stream->cc, cc)) {
+		stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
+		return 0;
 	}
 
-done:
-	bap_stream_state_changed(stream);
+	util_iov_free(stream->cc, 1);
+	stream->cc = util_iov_dup(cc, 1);
+
+	if (pac->ops && pac->ops->config)
+		pac->ops->config(stream, cc, NULL, ep_config_cb,
+						pac->user_data);
+
+	return 0;
 }
 
-static void ascs_ase_rsp_add(struct iovec *iov, uint8_t id,
-					uint8_t code, uint8_t reason)
+static struct bt_bap_req *bap_req_new(struct bt_bap_stream *stream,
+					uint8_t op, struct iovec *iov,
+					size_t len,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_ascs_cp_rsp *cp;
-	struct bt_ascs_ase_rsp *rsp;
+	struct bt_bap_req *req;
+	static unsigned int id;
 
-	if (!iov)
-		return;
+	req = new0(struct bt_bap_req, 1);
+	req->id = ++id ? id : ++id;
+	req->stream = stream;
+	req->op = op;
+	req->iov = util_iov_dup(iov, len);
+	req->len = len;
+	req->func = func;
+	req->user_data = user_data;
 
-	cp = iov->iov_base;
+	return req;
+}
 
-	if (cp->num_ase == 0xff)
-		return;
+static uint16_t bap_req_len(struct bt_bap_req *req)
+{
+	uint16_t len = 0;
+	size_t i;
+	const struct queue_entry *e;
 
-	switch (code) {
-	/* If the Response_Code value is 0x01 or 0x02, Number_of_ASEs shall be
-	 * set to 0xFF.
-	 */
-	case BT_ASCS_RSP_NOT_SUPPORTED:
-	case BT_ASCS_RSP_TRUNCATED:
-		cp->num_ase = 0xff;
-		break;
-	default:
-		cp->num_ase++;
-		break;
-	}
+	for (i = 0; i < req->len; i++)
+		len += req->iov[i].iov_len;
 
-	iov->iov_len += sizeof(*rsp);
-	iov->iov_base = realloc(iov->iov_base, iov->iov_len);
+	e = queue_get_entries(req->group);
+	for (; e; e = e->next)
+		len += bap_req_len(e->data);
 
-	rsp = iov->iov_base + (iov->iov_len - sizeof(*rsp));
-	rsp->ase = id;
-	rsp->code = code;
-	rsp->reason = reason;
+	return len;
 }
 
-static void ascs_ase_rsp_add_errno(struct iovec *iov, uint8_t id, int err)
+static bool match_req(const void *data, const void *match_data)
 {
-	struct bt_ascs_cp_rsp *rsp = iov->iov_base;
+	const struct bt_bap_req *pend = data;
+	const struct bt_bap_req *req = match_data;
 
-	switch (err) {
-	case -ENOBUFS:
-	case -ENOMEM:
-		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_NO_MEM,
-						BT_ASCS_REASON_NONE);
-	case -EINVAL:
-		switch (rsp->op) {
-		case BT_ASCS_CONFIG:
-		/* Fallthrough */
-		case BT_ASCS_QOS:
-			return ascs_ase_rsp_add(iov, id,
-						BT_ASCS_RSP_CONF_INVALID,
-						BT_ASCS_REASON_NONE);
-		case BT_ASCS_ENABLE:
-		/* Fallthrough */
-		case BT_ASCS_METADATA:
-			return ascs_ase_rsp_add(iov, id,
-						BT_ASCS_RSP_METADATA_INVALID,
-						BT_ASCS_REASON_NONE);
-		default:
-			return ascs_ase_rsp_add(iov, id,
-						BT_ASCS_RSP_UNSPECIFIED,
-						BT_ASCS_REASON_NONE);
-		}
-	case -ENOTSUP:
-		switch (rsp->op) {
-		case BT_ASCS_CONFIG:
-		/* Fallthrough */
-		case BT_ASCS_QOS:
-			return ascs_ase_rsp_add(iov, id,
-						BT_ASCS_RSP_CONF_UNSUPPORTED,
-						BT_ASCS_REASON_NONE);
-		case BT_ASCS_ENABLE:
-		/* Fallthrough */
-		case BT_ASCS_METADATA:
-			return ascs_ase_rsp_add(iov, id,
-					BT_ASCS_RSP_METADATA_UNSUPPORTED,
-					BT_ASCS_REASON_NONE);
-		default:
-			return ascs_ase_rsp_add(iov, id,
-						BT_ASCS_RSP_NOT_SUPPORTED,
-						BT_ASCS_REASON_NONE);
-		}
-	case -EBADMSG:
-		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_INVALID_ASE_STATE,
-						BT_ASCS_REASON_NONE);
-	case -ENOMSG:
-		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_TRUNCATED,
-						BT_ASCS_REASON_NONE);
-	default:
-		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_UNSPECIFIED,
-						BT_ASCS_REASON_NONE);
-	}
+	return pend->op == req->op;
 }
 
-static void ascs_ase_rsp_success(struct iovec *iov, uint8_t id)
+static struct bt_ascs *bap_get_ascs(struct bt_bap *bap)
 {
-	return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_SUCCESS,
-					BT_ASCS_REASON_NONE);
+	if (!bap || !bap->rdb)
+		return NULL;
+
+	if (bap->rdb->ascs)
+		return bap->rdb->ascs;
+
+	bap->rdb->ascs = new0(struct bt_ascs, 1);
+	bap->rdb->ascs->bdb = bap->rdb;
+
+	return bap->rdb->ascs;
 }
 
-static void ep_config_cb(struct bt_bap_stream *stream, int err)
+static void append_group(void *data, void *user_data)
 {
-	if (err)
-		return;
+	struct bt_bap_req *req = data;
+	struct iovec *iov = user_data;
+	size_t i;
 
-	stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
+	for (i = 0; i < req->len; i++)
+		util_iov_push_mem(iov, req->iov[i].iov_len,
+					req->iov[i].iov_base);
 }
 
-static uint8_t stream_config(struct bt_bap_stream *stream, struct iovec *cc,
-							struct iovec *rsp)
+static bool bap_send(struct bt_bap *bap, struct bt_bap_req *req)
 {
-	struct bt_bap_pac *pac = stream->lpac;
+	struct bt_ascs *ascs = bap_get_ascs(bap);
+	int ret;
+	uint16_t handle;
+	struct bt_ascs_ase_hdr hdr;
+	struct iovec iov;
+	size_t i;
 
-	DBG(stream->bap, "stream %p", stream);
+	iov.iov_len = sizeof(hdr) + bap_req_len(req);
 
-	/* TODO: Wait for pac->ops response */
-	ascs_ase_rsp_success(rsp, stream->ep->id);
+	DBG(bap, "req %p len %u", req, iov.iov_len);
 
-	if (!iov_memcmp(stream->cc, cc)) {
-		stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
-		return 0;
+	if (req->stream && !queue_find(bap->streams, NULL, req->stream)) {
+		DBG(bap, "stream %p detached, aborting op 0x%02x", req->op);
+		return false;
 	}
 
-	iov_free(stream->cc);
-	stream->cc = iov_dup(cc, 1);
-
-	if (pac->ops && pac->ops->config)
-		pac->ops->config(stream, cc, NULL, ep_config_cb,
-						pac->user_data);
-
-	return 0;
-}
+	if (!gatt_db_attribute_get_char_data(ascs->ase_cp, NULL, &handle,
+						NULL, NULL, NULL)) {
+		DBG(bap, "Unable to find Control Point");
+		return false;
+	}
 
-static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
-				 struct bt_ascs_config *req,
-				 struct iovec *iov, struct iovec *rsp)
-{
-	struct iovec cc;
-	const struct queue_entry *e;
+	iov.iov_base = alloca(iov.iov_len);
+	iov.iov_len = 0;
 
-	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+	hdr.op = req->op;
+	hdr.num = 1 + queue_length(req->group);
 
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x00 (Idle) */
-	case BT_ASCS_ASE_STATE_IDLE:
-	 /* or 0x01 (Codec Configured) */
-	case BT_ASCS_ASE_STATE_CONFIG:
-	 /* or 0x02 (QoS Configured) */
-	case BT_ASCS_ASE_STATE_QOS:
-		break;
-	default:
-		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	util_iov_push_mem(&iov, sizeof(hdr), &hdr);
 
-	if (iov->iov_len < req->cc_len)
-		return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+	for (i = 0; i < req->len; i++)
+		util_iov_push_mem(&iov, req->iov[i].iov_len,
+					req->iov[i].iov_base);
 
-	cc.iov_base = iov_pull_mem(iov, req->cc_len);
-	cc.iov_len = req->cc_len;
+	/* Append the request group with the same opcode */
+	queue_foreach(req->group, append_group, &iov);
 
-	if (!bap_print_cc(cc.iov_base, cc.iov_len, bap->debug_func,
-						bap->debug_data)) {
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_CONF_INVALID,
-				BT_ASCS_REASON_CODEC_DATA);
-		return 0;
+	ret = bt_gatt_client_write_without_response(bap->client, handle,
+							false, iov.iov_base,
+							iov.iov_len);
+	if (!ret) {
+		DBG(bap, "Unable to Write to Control Point");
+		return false;
 	}
 
-	switch (ep->dir) {
-	case BT_BAP_SINK:
-		e = queue_get_entries(bap->ldb->sinks);
-		break;
-	case BT_BAP_SOURCE:
-		e = queue_get_entries(bap->ldb->sources);
-		break;
-	default:
-		e = NULL;
-	}
+	bap->req = req;
 
-	for (; e; e = e->next) {
-		struct bt_bap_pac *pac = e->data;
+	return true;
+}
 
-		if (!bap_codec_equal(&req->codec, &pac->codec))
-			continue;
+static bool bap_process_queue(void *data)
+{
+	struct bt_bap *bap = data;
+	struct bt_bap_req *req;
 
-		if (!ep->stream)
-			ep->stream = bap_stream_new(bap, ep, pac, NULL, NULL,
-									false);
+	DBG(bap, "");
 
-		break;
+	if (bap->process_id) {
+		timeout_remove(bap->process_id);
+		bap->process_id = 0;
 	}
 
-	if (!e) {
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_CONF_INVALID,
-				BT_ASCS_REASON_CODEC);
-		return 0;
+	while ((req = queue_pop_head(bap->reqs))) {
+		if (bap_send(bap, req))
+			break;
+		bap_req_complete(req, NULL);
 	}
 
-	return stream_config(ep->stream, &cc, rsp);
+	return false;
 }
 
-static uint8_t ascs_config(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
+static bool bap_queue_req(struct bt_bap *bap, struct bt_bap_req *req)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_config *req;
-
-	req = iov_pull_mem(iov, sizeof(*req));
-
-	DBG(bap, "codec 0x%02x phy 0x%02x latency %u", req->codec.id, req->phy,
-							req->latency);
+	struct bt_bap_req *pend;
+	struct queue *queue;
+	struct bt_att *att = bt_bap_get_att(bap);
+	uint16_t mtu = bt_att_get_mtu(att);
+	uint16_t len = 2 + bap_req_len(req);
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
-		return 0;
+	if (len > mtu) {
+		DBG(bap, "Unable to queue request: req len %u > %u mtu", len,
+									mtu);
+		return false;
 	}
 
-	return ep_config(ep, bap, req, iov, rsp);
-}
-
-static uint8_t stream_qos(struct bt_bap_stream *stream, struct bt_bap_qos *qos,
-							struct iovec *rsp)
-{
-	DBG(stream->bap, "stream %p", stream);
+	pend = queue_find(bap->reqs, match_req, req);
+	/* Check if req can be grouped together and it fits in the MTU */
+	if (pend && (bap_req_len(pend) + len < mtu)) {
+		if (!pend->group)
+			pend->group = queue_new();
+		/* Group requests with the same opcode */
+		queue = pend->group;
+	} else {
+		queue = bap->reqs;
+	}
 
-	ascs_ase_rsp_success(rsp, stream->ep->id);
+	DBG(bap, "req %p (op 0x%2.2x) queue %p", req, req->op, queue);
 
-	if (memcmp(&stream->qos, qos, sizeof(*qos)))
-		stream->qos = *qos;
+	if (!queue_push_tail(queue, req)) {
+		DBG(bap, "Unable to queue request");
+		return false;
+	}
 
-	stream_set_state(stream, BT_BAP_STREAM_STATE_QOS);
+	/* Only attempot to process queue if there is no outstanding request
+	 * and it has not been scheduled.
+	 */
+	if (!bap->req && !bap->process_id)
+		bap->process_id = timeout_add(BAP_PROCESS_TIMEOUT,
+						bap_process_queue, bap, NULL);
 
-	return 0;
+	return true;
 }
 
-static uint8_t ep_qos(struct bt_bap_endpoint *ep, struct bt_bap *bap,
-			 struct bt_bap_qos *qos, struct iovec *rsp)
+static bool stream_notify_state(void *data)
 {
-	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+	struct bt_bap_stream *stream = data;
+	struct bt_bap_endpoint *ep = stream->ep;
+
+	DBG(stream->bap, "stream %p", stream);
+
+	if (stream->state_id) {
+		timeout_remove(stream->state_id);
+		stream->state_id = 0;
+	}
 
 	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
+	case BT_ASCS_ASE_STATE_IDLE:
+		break;
 	case BT_ASCS_ASE_STATE_CONFIG:
-	 /* or 0x02 (QoS Configured) */
+		stream_notify_config(stream);
+		break;
 	case BT_ASCS_ASE_STATE_QOS:
+		stream_notify_qos(stream);
+		break;
+	case BT_ASCS_ASE_STATE_ENABLING:
+	case BT_ASCS_ASE_STATE_STREAMING:
+	case BT_ASCS_ASE_STATE_DISABLING:
+		stream_notify_metadata(stream);
 		break;
-	default:
-		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
-	}
-
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
 	}
 
-	return stream_qos(ep->stream, qos, rsp);
+	return false;
 }
 
-static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
-					struct iovec *iov, struct iovec *rsp)
+static void bap_ucast_set_state(struct bt_bap_stream *stream, uint8_t state)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_qos *req;
-	struct bt_bap_qos qos;
-
-	req = iov_pull_mem(iov, sizeof(*req));
-
-	memset(&qos, 0, sizeof(qos));
+	struct bt_bap_endpoint *ep = stream->ep;
 
-	qos.cig_id = req->cig;
-	qos.cis_id = req->cis;
-	qos.interval = get_le24(req->interval);
-	qos.framing = req->framing;
-	qos.phy = req->phy;
-	qos.sdu = le16_to_cpu(req->sdu);
-	qos.rtn = req->rtn;
-	qos.latency = le16_to_cpu(req->latency);
-	qos.delay = get_le24(req->pd);
+	ep->old_state = ep->state;
+	ep->state = state;
 
-	DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
-			"phy 0x%02x SDU %u rtn %u latency %u pd %u",
-			req->cig, req->cis, qos.interval, qos.framing, qos.phy,
-			qos.sdu, qos.rtn, qos.latency, qos.delay);
+	DBG(stream->bap, "stream %p dir 0x%02x: %s -> %s", stream,
+			bt_bap_stream_get_dir(stream),
+			bt_bap_stream_statestr(stream->ep->old_state),
+			bt_bap_stream_statestr(stream->ep->state));
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "%s: Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	if (stream->client)
+		goto done;
 
-	return ep_qos(ep, bap, &qos, rsp);
+	if (!stream->bap->in_cp_write)
+		stream_notify_state(stream);
+	else if (!stream->state_id)
+		stream->state_id = timeout_add(BAP_PROCESS_TIMEOUT,
+						stream_notify_state,
+						stream, NULL);
+
+done:
+	bap_stream_state_changed(stream);
 }
 
-static uint8_t stream_enable(struct bt_bap_stream *stream, struct iovec *meta,
-							struct iovec *rsp)
+static unsigned int bap_ucast_get_state(struct bt_bap_stream *stream)
 {
-	DBG(stream->bap, "stream %p", stream);
+	return stream->ep->state;
+}
 
-	ascs_ase_rsp_success(rsp, stream->ep->id);
+static unsigned int bap_ucast_config(struct bt_bap_stream *stream,
+					struct bt_bap_qos *qos,
+					struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	struct iovec iov[2];
+	struct bt_ascs_config config;
+	uint8_t iovlen = 1;
+	struct bt_bap_req *req;
 
-	iov_free(stream->meta);
-	stream->meta = iov_dup(meta, 1);
+	if (!stream->client) {
+		stream_config(stream, data, NULL);
+		return -EINVAL;
+	}
 
-	stream_set_state(stream, BT_BAP_STREAM_STATE_ENABLING);
+	memset(&config, 0, sizeof(config));
 
-	/* Sink can autonomously for to Streaming state if io already exits */
-	if (stream->io && stream->ep->dir == BT_BAP_SINK)
-		stream_set_state(stream, BT_BAP_STREAM_STATE_STREAMING);
+	config.ase = stream->ep->id;
+	config.latency = qos->ucast.target_latency;
+	config.phy = qos->ucast.io_qos.phy;
+	config.codec = stream->rpac->codec;
 
-	return 0;
+	if (config.codec.id == 0xff) {
+		config.codec.cid = cpu_to_le16(config.codec.cid);
+		config.codec.vid = cpu_to_le16(config.codec.vid);
+	}
+
+	iov[0].iov_base = &config;
+		iov[0].iov_len = sizeof(config);
+
+	if (data) {
+		if (!bt_bap_debug_config(data->iov_base, data->iov_len,
+					stream->bap->debug_func,
+					stream->bap->debug_data))
+			return 0;
+
+		config.cc_len = data->iov_len;
+		iov[1] = *data;
+		iovlen++;
+	}
+
+	req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
+		return 0;
+	}
+
+	stream->qos = *qos;
+
+	return req->id;
 }
 
-static bool bap_print_ltv(const char *label, void *data, size_t len,
-				util_debug_func_t func, void *user_data)
+static unsigned int bap_ucast_qos(struct bt_bap_stream *stream,
+					struct bt_bap_qos *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct iovec iov = {
-		.iov_base = data,
-		.iov_len = len,
-	};
-	int i;
+	struct iovec iov;
+	struct bt_ascs_qos qos;
+	struct bt_bap_req *req;
 
-	util_debug(func, user_data, "Length %zu", iov.iov_len);
+	/* Table 3.2: ASE state machine transition
+	 * Initiating device - client Only
+	 */
+	if (!stream->client)
+		return 0;
 
-	for (i = 0; iov.iov_len > 1; i++) {
-		struct bt_ltv *ltv = iov_pull_mem(&iov, sizeof(*ltv));
-		uint8_t *data;
+	memset(&qos, 0, sizeof(qos));
 
-		if (!ltv) {
-			util_debug(func, user_data, "Unable to parse %s",
-								label);
-			return false;
-		}
+	/* TODO: Figure out how to pass these values around */
+	qos.ase = stream->ep->id;
+	qos.cig = data->ucast.cig_id;
+	qos.cis = data->ucast.cis_id;
+	put_le24(data->ucast.io_qos.interval, qos.interval);
+	qos.framing = data->ucast.framing;
+	qos.phy = data->ucast.io_qos.phy;
+	qos.sdu = cpu_to_le16(data->ucast.io_qos.sdu);
+	qos.rtn = data->ucast.io_qos.rtn;
+	qos.latency = cpu_to_le16(data->ucast.io_qos.latency);
+	put_le24(data->ucast.delay, qos.pd);
 
-		util_debug(func, user_data, "%s #%u: len %u type %u",
-					label, i, ltv->len, ltv->type);
+	iov.iov_base = &qos;
+	iov.iov_len = sizeof(qos);
 
-		data = iov_pull_mem(&iov, ltv->len - 1);
-		if (!data) {
-			util_debug(func, user_data, "Unable to parse %s",
-								label);
-			return false;
-		}
+	req = bap_req_new(stream, BT_ASCS_QOS, &iov, 1, func, user_data);
 
-		util_hexdump(' ', ltv->value, ltv->len - 1, func, user_data);
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
+		return 0;
 	}
 
-	return true;
-}
+	stream->qos = *data;
 
-static bool bap_print_metadata(void *data, size_t len, util_debug_func_t func,
-						void *user_data)
-{
-	return bap_print_ltv("Metadata", data, len, func, user_data);
+	return req->id;
 }
 
-static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
-			struct bt_ascs_enable *req, struct iovec *iov,
-			struct iovec *rsp)
+static unsigned int bap_stream_metadata(struct bt_bap_stream *stream,
+					uint8_t op, struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct iovec meta;
+	struct iovec iov[2];
+	struct bt_ascs_metadata meta;
+	struct bt_bap_req *req;
+	struct metadata {
+		uint8_t len;
+		uint8_t type;
+		uint8_t data[2];
+	} ctx = LTV(0x02, 0x01, 0x00); /* Context = Unspecified */
 
-	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+	memset(&meta, 0, sizeof(meta));
 
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x02 (QoS Configured) */
-	case BT_ASCS_ASE_STATE_QOS:
-		break;
-	default:
-		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	meta.ase = stream->ep->id;
 
-	meta.iov_base = iov_pull_mem(iov, req->meta.len);
-	meta.iov_len = req->meta.len;
+	iov[0].iov_base = &meta;
+	iov[0].iov_len = sizeof(meta);
 
-	if (!bap_print_metadata(meta.iov_base, meta.iov_len, bap->debug_func,
-							bap->debug_data)) {
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_METADATA_INVALID,
-				BT_ASCS_REASON_NONE);
-		return 0;
+	if (data)
+		iov[1] = *data;
+	else {
+		iov[1].iov_base = &ctx;
+		iov[1].iov_len = sizeof(ctx);
 	}
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	meta.len = iov[1].iov_len;
+
+	req = bap_req_new(stream, op, iov, 2, func, user_data);
+
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
 		return 0;
 	}
 
-	return stream_enable(ep->stream, &meta, rsp);
+	return req->id;
 }
 
-static uint8_t ascs_enable(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
+static unsigned int bap_bcast_qos(struct bt_bap_stream *stream,
+					struct bt_bap_qos *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_enable *req;
+	stream->qos = *data;
+	return 1;
+}
+
+static unsigned int bap_bcast_config(struct bt_bap_stream *stream,
+				     struct bt_bap_qos *qos, struct iovec *data,
+				     bt_bap_stream_func_t func, void *user_data)
+{
+	stream->qos = *qos;
+	stream->lpac->ops->config(stream, stream->cc, &stream->qos,
+			ep_config_cb, stream->lpac->user_data);
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	return 1;
+}
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->meta.ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->meta.ase);
-		ascs_ase_rsp_add(rsp, req->meta.ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+static void bap_stream_enable_link(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	struct iovec *metadata = user_data;
+
+	bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, NULL, NULL);
+}
+
+static unsigned int bap_ucast_enable(struct bt_bap_stream *stream,
+					bool enable_links, struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	int ret;
+
+	/* Table 3.2: ASE state machine transition
+	 * Initiating device - client Only
+	 */
+	if (!stream->client)
 		return 0;
-	}
 
-	return ep_enable(ep, bap, req, iov, rsp);
+	ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, data, func,
+					user_data);
+	if (!ret || !enable_links)
+		return ret;
+
+	queue_foreach(stream->links, bap_stream_enable_link, data);
+
+	return ret;
 }
 
 static uint8_t stream_start(struct bt_bap_stream *stream, struct iovec *rsp)
@@ -1780,75 +1890,47 @@ static uint8_t stream_start(struct bt_bap_stream *stream, struct iovec *rsp)
 	return 0;
 }
 
-static uint8_t ep_start(struct bt_bap_endpoint *ep, struct iovec *rsp)
+static unsigned int bap_ucast_start(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap_stream *stream = ep->stream;
-
-	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+	struct iovec iov;
+	struct bt_ascs_start start;
+	struct bt_bap_req *req;
 
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x03 (Enabling) */
-	case BT_ASCS_ASE_STATE_ENABLING:
-		break;
-	default:
-		DBG(ep->stream->bap, "Invalid state %s",
-				bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	if (!stream->client) {
+		if (stream->ep->dir == BT_BAP_SINK)
+			stream_start(stream, NULL);
 		return 0;
 	}
 
-	/* If the ASE_ID  written by the client represents a Sink ASE, the
-	 * server shall not accept the Receiver Start Ready operation for that
-	 * ASE. The server shall send a notification of the ASE Control Point
-	 * characteristic to the client, and the server shall set the
-	 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
-	 */
-	if (ep->dir == BT_BAP_SINK) {
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_DIR, BT_ASCS_REASON_NONE);
+	if (stream->ep->dir == BT_BAP_SINK)
 		return 0;
-	}
 
-	return stream_start(ep->stream, rsp);
-}
-
-static uint8_t ascs_start(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
-{
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_start *req;
+	memset(&start, 0, sizeof(start));
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	start.ase = stream->ep->id;
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	iov.iov_base = &start;
+	iov.iov_len = sizeof(start);
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found for %p", ep);
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	req = bap_req_new(stream, BT_ASCS_START, &iov, 1, func, user_data);
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
 		return 0;
 	}
 
-	return ep_start(ep, rsp);
+	return req->id;
 }
 
 static uint8_t stream_disable(struct bt_bap_stream *stream, struct iovec *rsp)
 {
-	DBG(stream->bap, "stream %p", stream);
-
 	if (!stream || stream->ep->state == BT_BAP_STREAM_STATE_QOS ||
 			stream->ep->state == BT_BAP_STREAM_STATE_IDLE)
 		return 0;
 
+	DBG(stream->bap, "stream %p", stream);
+
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
 	/* Sink can autonomously transit to QOS while source needs to go to
@@ -1862,64 +1944,51 @@ static uint8_t stream_disable(struct bt_bap_stream *stream, struct iovec *rsp)
 	return 0;
 }
 
-static uint8_t ep_disable(struct bt_bap_endpoint *ep, struct iovec *rsp)
+static void bap_stream_disable_link(void *data, void *user_data)
 {
-	struct bt_bap_stream *stream = ep->stream;
+	struct bt_bap_stream *stream = data;
 
-	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
-
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x03 (Enabling) */
-	case BT_ASCS_ASE_STATE_ENABLING:
-	 /* or 0x04 (Streaming) */
-	case BT_ASCS_ASE_STATE_STREAMING:
-		break;
-	default:
-		DBG(stream->bap, "Invalid state %s",
-				bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
-	}
-
-	return stream_disable(ep->stream, rsp);
+	bt_bap_stream_disable(stream, false, NULL, NULL);
 }
 
-static uint8_t ascs_disable(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
+static unsigned int bap_ucast_disable(struct bt_bap_stream *stream,
+					bool disable_links,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_disable *req;
+	struct iovec iov;
+	struct bt_ascs_disable disable;
+	struct bt_bap_req *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	if (!stream->client)
+		return stream_disable(stream, NULL);
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	memset(&disable, 0, sizeof(disable));
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	disable.ase = stream->ep->id;
+
+	iov.iov_base = &disable;
+	iov.iov_len = sizeof(disable);
+
+	req = bap_req_new(stream, BT_ASCS_DISABLE, &iov, 1, func, user_data);
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
 		return 0;
 	}
 
-	return ep_disable(ep, rsp);
+	if (disable_links)
+		queue_foreach(stream->links, bap_stream_disable_link, NULL);
+
+	return req->id;
 }
 
 static uint8_t stream_stop(struct bt_bap_stream *stream, struct iovec *rsp)
 {
-	DBG(stream->bap, "stream %p", stream);
-
 	if (!stream)
 		return 0;
 
+	DBG(stream->bap, "stream %p", stream);
+
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
 	stream_set_state(stream, BT_BAP_STREAM_STATE_QOS);
@@ -1927,65 +1996,38 @@ static uint8_t stream_stop(struct bt_bap_stream *stream, struct iovec *rsp)
 	return 0;
 }
 
-static uint8_t ep_stop(struct bt_bap_endpoint *ep, struct iovec *rsp)
+static unsigned int bap_ucast_stop(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap_stream *stream = ep->stream;
-
-	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+	struct iovec iov;
+	struct bt_ascs_stop stop;
+	struct bt_bap_req *req;
 
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x05 (Disabling) */
-	case BT_ASCS_ASE_STATE_DISABLING:
-		break;
-	default:
-		DBG(stream->bap, "Invalid state %s",
-				bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	if (!stream->client) {
+		if (stream->ep->dir == BT_BAP_SINK)
+			stream_stop(stream, NULL);
 		return 0;
 	}
 
-	/* If the ASE_ID  written by the client represents a Sink ASE, the
-	 * server shall not accept the Receiver Stop Ready operation for that
-	 * ASE. The server shall send a notification of the ASE Control Point
-	 * characteristic to the client, and the server shall set the
-	 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
-	 */
-	if (ep->dir == BT_BAP_SINK) {
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_DIR, BT_ASCS_REASON_NONE);
+	if (stream->ep->dir == BT_BAP_SINK)
 		return 0;
-	}
 
-	return stream_stop(ep->stream, rsp);
-}
+	memset(&stop, 0, sizeof(stop));
 
-static uint8_t ascs_stop(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
-{
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_stop *req;
+	stop.ase = stream->ep->id;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	iov.iov_base = &stop;
+	iov.iov_len = sizeof(stop);
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
-		return 0;
-	}
+	req = bap_req_new(stream, BT_ASCS_STOP, &iov, 1, func, user_data);
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	if (!bap_queue_req(stream->bap, req)) {
+		bap_req_free(req);
 		return 0;
 	}
 
-	return ep_stop(ep, rsp);
+	return req->id;
 }
 
 static uint8_t stream_metadata(struct bt_bap_stream *stream, struct iovec *meta,
@@ -1995,62 +2037,33 @@ static uint8_t stream_metadata(struct bt_bap_stream *stream, struct iovec *meta,
 
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
-	iov_free(stream->meta);
-	stream->meta = iov_dup(meta, 1);
+	util_iov_free(stream->meta, 1);
+	stream->meta = util_iov_dup(meta, 1);
 
 	return 0;
 }
 
-static uint8_t ep_metadata(struct bt_bap_endpoint *ep, struct iovec *meta,
-						struct iovec *rsp)
-{
-	struct bt_bap_stream *stream = ep->stream;
-
-	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
-
-	switch (ep->state) {
-	/* Valid only if ASE_State field = 0x03 (Enabling) */
-	case BT_ASCS_ASE_STATE_ENABLING:
-	 /* or 0x04 (Streaming) */
-	case BT_ASCS_ASE_STATE_STREAMING:
-		break;
-	default:
-		DBG(stream->bap, "Invalid state %s",
-				bt_bap_stream_statestr(ep->state));
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
-	}
-
-	return stream_metadata(ep->stream, meta, rsp);
-}
-
-static uint8_t ascs_metadata(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
+static unsigned int bap_ucast_metadata(struct bt_bap_stream *stream,
+					struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_metadata *req;
-
-	req = iov_pull_mem(iov, sizeof(*req));
-
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+	if (!stream->client) {
+		stream_metadata(stream, data, NULL);
 		return 0;
 	}
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
-		return 0;
+	switch (bt_bap_stream_get_state(stream)) {
+	/* Valid only if ASE_State field = 0x03 (Enabling) */
+	case BT_BAP_STREAM_STATE_ENABLING:
+	 /* or 0x04 (Streaming) */
+	case BT_BAP_STREAM_STATE_STREAMING:
+		return bap_stream_metadata(stream, BT_ASCS_METADATA, data, func,
+						user_data);
 	}
 
-	return ep_metadata(ep, iov, rsp);
+	stream_metadata(stream, data, NULL);
+	return 0;
 }
 
 static uint8_t stream_release(struct bt_bap_stream *stream, struct iovec *rsp)
@@ -2070,45 +2083,1268 @@ static uint8_t stream_release(struct bt_bap_stream *stream, struct iovec *rsp)
 	return 0;
 }
 
-static uint8_t ascs_release(struct bt_ascs *ascs, struct bt_bap *bap,
-				struct iovec *iov, struct iovec *rsp)
+static bool bap_stream_valid(struct bt_bap_stream *stream)
 {
-	struct bt_bap_endpoint *ep;
-	struct bt_ascs_release *req;
+	if (!stream || !stream->bap)
+		return false;
+
+	return queue_find(stream->bap->streams, NULL, stream);
+}
 
-	req = iov_pull_mem(iov, sizeof(*req));
+static unsigned int bap_ucast_get_dir(struct bt_bap_stream *stream)
+{
+	return stream->ep->dir;
+}
 
-	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
-	if (!ep) {
-		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
-		ascs_ase_rsp_add(rsp, req->ase,
-				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+static unsigned int bap_ucast_get_location(struct bt_bap_stream *stream)
+{
+	struct bt_pacs *pacs;
+
+	if (!stream)
+		return 0x00000000;
+
+	pacs = stream->client ? stream->bap->rdb->pacs : stream->bap->ldb->pacs;
+
+	if (stream->ep->dir == BT_BAP_SOURCE)
+		return pacs->source_loc_value;
+	else if (stream->ep->dir == BT_BAP_SINK)
+		return pacs->sink_loc_value;
+	return 0x00000000;
+}
+
+static unsigned int bap_ucast_release(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	struct iovec iov;
+	struct bt_ascs_release rel;
+	struct bt_bap_req *req;
+	struct bt_bap *bap;
+
+	if (!stream->client) {
+		stream_release(stream, NULL);
 		return 0;
 	}
 
-	if (!ep->stream) {
-		DBG(bap, "No stream found");
-		ascs_ase_rsp_add(rsp, ep->id,
-				BT_ASCS_RSP_INVALID_ASE_STATE,
-				BT_ASCS_REASON_NONE);
+	memset(&req, 0, sizeof(req));
+
+	rel.ase = stream->ep->id;
+
+	iov.iov_base = &rel;
+	iov.iov_len = sizeof(rel);
+
+	bap = stream->bap;
+
+	/* If stream does not belong to a client session, clean it up now */
+	if (!bap_stream_valid(stream)) {
+		stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
+		stream = NULL;
 		return 0;
 	}
 
-	return stream_release(ep->stream, rsp);
+	req = bap_req_new(stream, BT_ASCS_RELEASE, &iov, 1, func, user_data);
+	if (!bap_queue_req(bap, req)) {
+		bap_req_free(req);
+		return 0;
+	}
+
+	return req->id;
 }
 
-#define ASCS_OP(_str, _op, _size, _func) \
-	{ \
-		.str = _str, \
-		.op = _op, \
-		.size = _size, \
-		.func = _func, \
+static struct bt_bap_stream *bt_bap_stream_ref(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return NULL;
+
+	__sync_fetch_and_add(&stream->ref_count, 1);
+
+	return stream;
+}
+
+static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
+{
+	struct bt_bap *bap = stream->bap;
+	const struct queue_entry *entry;
+
+	stream->old_state = stream->state;
+	stream->state = state;
+
+	bt_bap_stream_ref(stream);
+
+	DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
+			bt_bap_stream_get_dir(stream),
+			bt_bap_stream_statestr(stream->old_state),
+			bt_bap_stream_statestr(stream->state));
+
+	for (entry = queue_get_entries(bap->state_cbs); entry;
+							entry = entry->next) {
+		struct bt_bap_state *state = entry->data;
+
+		if (state->func)
+			state->func(stream, stream->old_state,
+					stream->state, state->data);
 	}
 
-struct ascs_op_handler {
-	const char *str;
-	uint8_t  op;
-	size_t   size;
+	/* Post notification updates */
+	switch (stream->state) {
+	case BT_ASCS_ASE_STATE_IDLE:
+		if (stream->ops && stream->ops->detach)
+			stream->ops->detach(stream);
+		break;
+	case BT_ASCS_ASE_STATE_RELEASING:
+		bap_stream_io_detach(stream);
+		stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
+		break;
+	case BT_ASCS_ASE_STATE_ENABLING:
+		if (bt_bap_stream_get_io(stream))
+			/* Start stream if fd has already been set */
+			bt_bap_stream_start(stream, NULL, NULL);
+
+		break;
+	}
+
+	bt_bap_stream_unref(stream);
+}
+
+static unsigned int bap_bcast_get_state(struct bt_bap_stream *stream)
+{
+	return stream->state;
+}
+
+static bool bcast_sink_stream_enabled(const void *data, const void *match_data)
+{
+	struct bt_bap_stream *stream = (struct bt_bap_stream *)data;
+	struct bt_bap_stream *match = (struct bt_bap_stream *)match_data;
+	uint8_t state = bt_bap_stream_get_state(stream);
+
+	if (stream == match)
+		return false;
+
+	if (queue_find(stream->links, NULL, match))
+		return false;
+
+	/* Ignore streams that are not Broadcast Sink */
+	if (bt_bap_pac_get_type(stream->lpac) != BT_BAP_BCAST_SINK)
+		return false;
+
+	return ((state == BT_BAP_STREAM_STATE_ENABLING) ||
+			bt_bap_stream_get_io(stream));
+}
+
+static unsigned int bap_bcast_sink_enable(struct bt_bap_stream *stream,
+					bool enable_links, struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	struct bt_bap *bap = stream->bap;
+
+	/* The stream cannot be enabled if there is any other
+	 * unlinked stream for the same source that is in the
+	 * process of enabling or that has already been started.
+	 */
+	if (queue_find(bap->streams, bcast_sink_stream_enabled, stream))
+		return 0;
+
+	stream_set_state(stream, BT_BAP_STREAM_STATE_ENABLING);
+
+	return 1;
+}
+
+static unsigned int bap_bcast_src_enable(struct bt_bap_stream *stream,
+					bool enable_links, struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	stream_set_state(stream, BT_BAP_STREAM_STATE_ENABLING);
+
+	return 1;
+}
+
+static unsigned int bap_bcast_start(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	stream_set_state(stream, BT_BAP_STREAM_STATE_STREAMING);
+
+	return 1;
+}
+
+static unsigned int bap_bcast_disable(struct bt_bap_stream *stream,
+					bool disable_links,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	bap_stream_io_detach(stream);
+	stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
+
+	return 1;
+}
+
+static unsigned int bap_bcast_metadata(struct bt_bap_stream *stream,
+					struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	util_iov_free(stream->meta, 1);
+	stream->meta = util_iov_dup(data, 1);
+
+	return 1;
+}
+
+static unsigned int bap_bcast_src_get_dir(struct bt_bap_stream *stream)
+{
+	return BT_BAP_BCAST_SINK;
+}
+
+static unsigned int bap_bcast_sink_get_dir(struct bt_bap_stream *stream)
+{
+	return BT_BAP_BCAST_SOURCE;
+}
+
+static void bap_sink_get_allocation(size_t i, uint8_t l, uint8_t t,
+		uint8_t *v, void *user_data)
+{
+	uint32_t location32;
+
+	if (!v)
+		return;
+
+	memcpy(&location32, v, l);
+	*((uint32_t *)user_data) = le32_to_cpu(location32);
+}
+
+static unsigned int bap_bcast_get_location(struct bt_bap_stream *stream)
+{
+	uint8_t type = BAP_CHANNEL_ALLOCATION_LTV_TYPE;
+	uint32_t allocation = 0;
+	struct iovec *caps;
+
+	caps = bt_bap_stream_get_config(stream);
+
+	/* Get stream allocation from capabilities */
+	util_ltv_foreach(caps->iov_base, caps->iov_len, &type,
+			bap_sink_get_allocation, &allocation);
+
+	return allocation;
+}
+
+static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
+
+	return 1;
+}
+
+static bool bap_ucast_set_io(struct bt_bap_stream *stream, int fd)
+{
+	if (!stream || (fd >= 0 && stream->io && !stream->io->connecting))
+		return false;
+
+	bap_stream_set_io(stream, INT_TO_PTR(fd));
+
+	queue_foreach(stream->links, bap_stream_set_io, INT_TO_PTR(fd));
+
+	return true;
+}
+
+static bool bap_bcast_set_io(struct bt_bap_stream *stream, int fd)
+{
+	if (!stream || (fd >= 0 && stream->io && !stream->io->connecting))
+		return false;
+
+	bap_stream_set_io(stream, INT_TO_PTR(fd));
+
+	return true;
+}
+
+static struct bt_bap_stream_io *bap_ucast_get_io(struct bt_bap_stream *stream)
+{
+	struct bt_bap_stream_io *io = NULL;
+
+	if (!stream)
+		return NULL;
+
+	if (stream->io)
+		return stream->io;
+
+	queue_foreach(stream->links, stream_find_io, &io);
+
+	return io;
+}
+
+static struct bt_bap_stream_io *bap_bcast_get_io(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return NULL;
+
+	return stream->io;
+}
+
+static uint8_t bap_ucast_io_dir(struct bt_bap_stream *stream)
+{
+	uint8_t dir;
+
+	if (!stream)
+		return 0x00;
+
+	dir = stream->ep->dir;
+
+	queue_foreach(stream->links, bap_stream_get_dir, &dir);
+
+	return dir;
+}
+
+static uint8_t bap_bcast_io_dir(struct bt_bap_stream *stream)
+{
+	uint8_t dir;
+	uint8_t pac_type = bt_bap_pac_get_type(stream->lpac);
+
+	if (!stream)
+		return 0x00;
+
+	if (pac_type == BT_BAP_BCAST_SINK)
+		dir = BT_BAP_BCAST_SOURCE;
+	else
+		dir = BT_BAP_BCAST_SINK;
+
+	return dir;
+}
+
+static int bap_ucast_io_link(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link)
+{
+	struct bt_bap *bap;
+
+	if (!stream || !link || stream == link)
+		return -EINVAL;
+
+	bap = stream->bap;
+
+	if (!queue_isempty(stream->links) || !queue_isempty(link->links))
+		return -EALREADY;
+
+	if (stream->client != link->client ||
+			stream->qos.ucast.cig_id != link->qos.ucast.cig_id ||
+			stream->qos.ucast.cis_id != link->qos.ucast.cis_id ||
+			stream->ep->dir == link->ep->dir)
+		return -EINVAL;
+
+	if (!stream->links)
+		stream->links = queue_new();
+
+	if (!link->links)
+		link->links = queue_new();
+
+	queue_push_tail(stream->links, link);
+	queue_push_tail(link->links, stream);
+
+	/* Link IOs if already set on stream/link */
+	if (stream->io && !link->io)
+		link->io = stream_io_ref(stream->io);
+	else if (link->io && !stream->io)
+		stream->io = stream_io_ref(link->io);
+
+	DBG(bap, "stream %p link %p", stream, link);
+
+	return 0;
+}
+
+static void stream_link(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = (void *)data;
+	struct bt_bap_stream *link = (void *)user_data;
+
+	bt_bap_stream_io_link(stream, link);
+}
+
+static int bap_bcast_io_link(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link)
+{
+	struct bt_bap *bap;
+
+	if (!stream || !link || stream == link)
+		return -EINVAL;
+
+	bap = stream->bap;
+
+	if (queue_find(stream->links, NULL, link) ||
+		queue_find(link->links, NULL, stream))
+		return -EALREADY;
+
+	if (!stream->links)
+		stream->links = queue_new();
+
+	if (!link->links)
+		link->links = queue_new();
+
+	queue_push_tail(stream->links, link);
+	queue_push_tail(link->links, stream);
+
+	DBG(bap, "stream %p link %p", stream, link);
+
+	queue_foreach(stream->links, stream_link, link);
+
+	return 0;
+}
+
+static void stream_unlink(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = (void *)data;
+	struct bt_bap_stream *link = (void *)user_data;
+
+	bap_bcast_io_unlink(stream, link);
+}
+
+static int bap_bcast_io_unlink(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link)
+{
+	struct bt_bap *bap;
+
+	if (!stream || !link || stream == link)
+		return -EINVAL;
+
+	bap = stream->bap;
+
+	if (!queue_find(stream->links, NULL, link) ||
+		!queue_find(link->links, NULL, stream))
+		return -EALREADY;
+
+	queue_remove(stream->links, link);
+	queue_remove(link->links, stream);
+
+	DBG(bap, "stream %p unlink %p", stream, link);
+
+	queue_foreach(stream->links, stream_unlink, link);
+
+	return 0;
+}
+
+#define STREAM_OPS(_type, _set_state, _get_state, _config, _qos, _enable, \
+	_start, _disable, _stop, _metadata, _get_dir, _get_loc, _release, \
+	_detach, _set_io, _get_io, _io_dir, _io_link, _io_unlink) \
+{ \
+	.type = _type, \
+	.set_state = _set_state, \
+	.get_state = _get_state, \
+	.config = _config, \
+	.qos = _qos, \
+	.enable = _enable, \
+	.start = _start, \
+	.disable = _disable, \
+	.stop = _stop, \
+	.metadata = _metadata, \
+	.get_dir = _get_dir,\
+	.get_loc = _get_loc, \
+	.release = _release, \
+	.detach = _detach, \
+	.set_io = _set_io, \
+	.get_io = _get_io, \
+	.io_dir = _io_dir, \
+	.io_link = _io_link, \
+	.io_unlink = _io_unlink, \
+}
+
+static const struct bt_bap_stream_ops stream_ops[] = {
+	STREAM_OPS(BT_BAP_SINK, bap_ucast_set_state,
+			bap_ucast_get_state,
+			bap_ucast_config, bap_ucast_qos, bap_ucast_enable,
+			bap_ucast_start, bap_ucast_disable, bap_ucast_stop,
+			bap_ucast_metadata, bap_ucast_get_dir,
+			bap_ucast_get_location,
+			bap_ucast_release, bap_ucast_detach,
+			bap_ucast_set_io, bap_ucast_get_io,
+			bap_ucast_io_dir, bap_ucast_io_link,
+			NULL),
+	STREAM_OPS(BT_BAP_SOURCE, bap_ucast_set_state,
+			bap_ucast_get_state,
+			bap_ucast_config, bap_ucast_qos, bap_ucast_enable,
+			bap_ucast_start, bap_ucast_disable, bap_ucast_stop,
+			bap_ucast_metadata, bap_ucast_get_dir,
+			bap_ucast_get_location,
+			bap_ucast_release, bap_ucast_detach,
+			bap_ucast_set_io, bap_ucast_get_io,
+			bap_ucast_io_dir, bap_ucast_io_link,
+			NULL),
+	STREAM_OPS(BT_BAP_BCAST_SINK, bap_bcast_set_state,
+			bap_bcast_get_state,
+			bap_bcast_config, bap_bcast_qos, bap_bcast_sink_enable,
+			bap_bcast_start, bap_bcast_disable, NULL,
+			bap_bcast_metadata, bap_bcast_sink_get_dir,
+			bap_bcast_get_location,
+			bap_bcast_release, bap_bcast_sink_detach,
+			bap_bcast_set_io, bap_bcast_get_io,
+			bap_bcast_io_dir, bap_bcast_io_link,
+			bap_bcast_io_unlink),
+	STREAM_OPS(BT_BAP_BCAST_SOURCE, bap_bcast_set_state,
+			bap_bcast_get_state,
+			bap_bcast_config, bap_bcast_qos, bap_bcast_src_enable,
+			bap_bcast_start, bap_bcast_disable, NULL,
+			bap_bcast_metadata, bap_bcast_src_get_dir,
+			bap_bcast_get_location,
+			bap_bcast_release, bap_bcast_src_detach,
+			bap_bcast_set_io, bap_bcast_get_io,
+			bap_bcast_io_dir, bap_bcast_io_link,
+			bap_bcast_io_unlink),
+};
+
+static const struct bt_bap_stream_ops *
+bap_stream_new_ops(struct bt_bap_stream *stream)
+{
+	const struct bt_bap_stream_ops *ops;
+	uint8_t type = bt_bap_pac_get_type(stream->lpac);
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(stream_ops); i++) {
+		ops = &stream_ops[i];
+
+		if (ops->type == type)
+			return ops;
+	}
+
+	return NULL;
+}
+
+static struct bt_bap_stream *bap_stream_new(struct bt_bap *bap,
+						struct bt_bap_endpoint *ep,
+						struct bt_bap_pac *lpac,
+						struct bt_bap_pac *rpac,
+						struct iovec *data,
+						bool client)
+{
+	struct bt_bap_stream *stream;
+
+	stream = new0(struct bt_bap_stream, 1);
+	stream->bap = bap;
+	stream->ep = ep;
+	if (ep != NULL)
+		ep->stream = stream;
+	stream->lpac = lpac;
+	stream->rpac = rpac;
+	stream->cc = util_iov_dup(data, 1);
+	stream->client = client;
+	stream->ops = bap_stream_new_ops(stream);
+
+	queue_push_tail(bap->streams, stream);
+
+	return bt_bap_stream_ref(stream);
+}
+
+static struct bt_bap_stream_io *stream_io_ref(struct bt_bap_stream_io *io)
+{
+	if (!io)
+		return NULL;
+
+	__sync_fetch_and_add(&io->ref_count, 1);
+
+	return io;
+}
+
+static struct bt_bap_stream_io *stream_io_new(struct bt_bap *bap, int fd)
+{
+	struct io *io;
+	struct bt_bap_stream_io *sio;
+
+	io = io_new(fd);
+	if (!io)
+		return NULL;
+
+	DBG(bap, "fd %d", fd);
+
+	sio = new0(struct bt_bap_stream_io, 1);
+	sio->bap = bap;
+	sio->io = io;
+
+	return stream_io_ref(sio);
+}
+
+static void stream_find_io(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	struct bt_bap_stream_io **io = user_data;
+
+	if (*io)
+		return;
+
+	*io = stream->io;
+}
+
+static struct bt_bap_stream_io *stream_get_io(struct bt_bap_stream *stream)
+{
+	struct bt_bap_stream_io *io;
+	struct bt_bap *bap;
+
+	if (!bap_stream_valid(stream))
+		return NULL;
+
+	if (!stream->ops || !stream->ops->get_io)
+		return NULL;
+
+	if (!bt_bap_ref_safe(stream->bap))
+		return NULL;
+
+	bap = stream->bap;
+
+	io = stream->ops->get_io(stream);
+
+	bt_bap_unref(bap);
+
+	return io;
+}
+
+static bool stream_io_disconnected(struct io *io, void *user_data);
+
+static bool bap_stream_io_attach(struct bt_bap_stream *stream, int fd,
+							bool connecting)
+{
+	struct bt_bap_stream_io *io;
+
+	io = stream_get_io(stream);
+	if (io) {
+		if (fd == stream_io_get_fd(io)) {
+			if (!stream->io)
+				stream->io = stream_io_ref(io);
+
+			io->connecting = connecting;
+			return true;
+		}
+
+		DBG(stream->bap, "stream %p io already set", stream);
+		return false;
+	}
+
+	DBG(stream->bap, "stream %p connecting %s", stream,
+				connecting ? "true" : "false");
+
+	io = stream_io_new(stream->bap, fd);
+	if (!io)
+		return false;
+
+	io->connecting = connecting;
+	stream->io = io;
+	io_set_disconnect_handler(io->io, stream_io_disconnected, stream, NULL);
+
+	return true;
+}
+
+static void bap_stream_set_io(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	int fd = PTR_TO_INT(user_data);
+	bool ret;
+	uint8_t state;
+
+	if (fd >= 0)
+		ret = bap_stream_io_attach(stream, fd, false);
+	else
+		ret = bap_stream_io_detach(stream);
+
+	if (!ret)
+		return;
+
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BCAST)
+		state = stream->state;
+	else
+		state = stream->ep->state;
+
+	switch (state) {
+	case BT_BAP_STREAM_STATE_ENABLING:
+		if (fd < 0)
+			bt_bap_stream_disable(stream, false, NULL, NULL);
+		else
+			bt_bap_stream_start(stream, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_DISABLING:
+		if (fd < 0)
+			bt_bap_stream_stop(stream, NULL, NULL);
+		break;
+	}
+}
+
+static void ascs_ase_rsp_add_errno(struct iovec *iov, uint8_t id, int err)
+{
+	struct bt_ascs_cp_rsp *rsp = iov->iov_base;
+
+	switch (err) {
+	case -ENOBUFS:
+	case -ENOMEM:
+		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_NO_MEM,
+						BT_ASCS_REASON_NONE);
+	case -EINVAL:
+		switch (rsp->op) {
+		case BT_ASCS_CONFIG:
+		/* Fallthrough */
+		case BT_ASCS_QOS:
+			return ascs_ase_rsp_add(iov, id,
+						BT_ASCS_RSP_CONF_INVALID,
+						BT_ASCS_REASON_NONE);
+		case BT_ASCS_ENABLE:
+		/* Fallthrough */
+		case BT_ASCS_METADATA:
+			return ascs_ase_rsp_add(iov, id,
+						BT_ASCS_RSP_METADATA_INVALID,
+						BT_ASCS_REASON_NONE);
+		default:
+			return ascs_ase_rsp_add(iov, id,
+						BT_ASCS_RSP_UNSPECIFIED,
+						BT_ASCS_REASON_NONE);
+		}
+	case -ENOTSUP:
+		switch (rsp->op) {
+		case BT_ASCS_CONFIG:
+		/* Fallthrough */
+		case BT_ASCS_QOS:
+			return ascs_ase_rsp_add(iov, id,
+						BT_ASCS_RSP_CONF_UNSUPPORTED,
+						BT_ASCS_REASON_NONE);
+		case BT_ASCS_ENABLE:
+		/* Fallthrough */
+		case BT_ASCS_METADATA:
+			return ascs_ase_rsp_add(iov, id,
+					BT_ASCS_RSP_METADATA_UNSUPPORTED,
+					BT_ASCS_REASON_NONE);
+		default:
+			return ascs_ase_rsp_add(iov, id,
+						BT_ASCS_RSP_NOT_SUPPORTED,
+						BT_ASCS_REASON_NONE);
+		}
+	case -EBADMSG:
+		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_INVALID_ASE_STATE,
+						BT_ASCS_REASON_NONE);
+	case -ENOMSG:
+		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_TRUNCATED,
+						BT_ASCS_REASON_NONE);
+	default:
+		return ascs_ase_rsp_add(iov, id, BT_ASCS_RSP_UNSPECIFIED,
+						BT_ASCS_REASON_NONE);
+	}
+}
+
+static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+				 struct bt_ascs_config *req,
+				 struct iovec *iov, struct iovec *rsp)
+{
+	struct iovec cc;
+	const struct queue_entry *e;
+
+	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x00 (Idle) */
+	case BT_ASCS_ASE_STATE_IDLE:
+	 /* or 0x01 (Codec Configured) */
+	case BT_ASCS_ASE_STATE_CONFIG:
+	 /* or 0x02 (QoS Configured) */
+	case BT_ASCS_ASE_STATE_QOS:
+		break;
+	default:
+		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (iov->iov_len < req->cc_len)
+		return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+
+	cc.iov_base = util_iov_pull_mem(iov, req->cc_len);
+	cc.iov_len = req->cc_len;
+
+	if (!bt_bap_debug_caps(cc.iov_base, cc.iov_len, bap->debug_func,
+						bap->debug_data)) {
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_CONF_INVALID,
+				BT_ASCS_REASON_CODEC_DATA);
+		return 0;
+	}
+
+	switch (ep->dir) {
+	case BT_BAP_SINK:
+		e = queue_get_entries(bap->ldb->sinks);
+		break;
+	case BT_BAP_SOURCE:
+		e = queue_get_entries(bap->ldb->sources);
+		break;
+	default:
+		e = NULL;
+	}
+
+	for (; e; e = e->next) {
+		struct bt_bap_pac *pac = e->data;
+
+		if (!bap_codec_equal(&req->codec, &pac->codec))
+			continue;
+
+		if (!ep->stream)
+			ep->stream = bap_stream_new(bap, ep, pac, NULL, NULL,
+									false);
+
+		break;
+	}
+
+	if (!e) {
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_CONF_INVALID,
+				BT_ASCS_REASON_CODEC);
+		return 0;
+	}
+
+	return stream_config(ep->stream, &cc, rsp);
+}
+
+static uint8_t ascs_config(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_config *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	DBG(bap, "codec 0x%02x phy 0x%02x latency %u", req->codec.id, req->phy,
+							req->latency);
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_config(ep, bap, req, iov, rsp);
+}
+
+static uint8_t stream_qos(struct bt_bap_stream *stream, struct bt_bap_qos *qos,
+							struct iovec *rsp)
+{
+	DBG(stream->bap, "stream %p", stream);
+
+	ascs_ase_rsp_success(rsp, stream->ep->id);
+
+	if (memcmp(&stream->qos, qos, sizeof(*qos)))
+		stream->qos = *qos;
+
+	stream_set_state(stream, BT_BAP_STREAM_STATE_QOS);
+
+	return 0;
+}
+
+static uint8_t ep_qos(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+			 struct bt_bap_qos *qos, struct iovec *rsp)
+{
+	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
+	case BT_ASCS_ASE_STATE_CONFIG:
+	 /* or 0x02 (QoS Configured) */
+	case BT_ASCS_ASE_STATE_QOS:
+		break;
+	default:
+		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_qos(ep->stream, qos, rsp);
+}
+
+static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
+					struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_qos *req;
+	struct bt_bap_qos qos;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	memset(&qos, 0, sizeof(qos));
+
+	qos.ucast.cig_id = req->cig;
+	qos.ucast.cis_id = req->cis;
+	qos.ucast.io_qos.interval = get_le24(req->interval);
+	qos.ucast.framing = req->framing;
+	qos.ucast.io_qos.phy = req->phy;
+	qos.ucast.io_qos.sdu = le16_to_cpu(req->sdu);
+	qos.ucast.io_qos.rtn = req->rtn;
+	qos.ucast.io_qos.latency = le16_to_cpu(req->latency);
+	qos.ucast.delay = get_le24(req->pd);
+
+	DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
+			"phy 0x%02x SDU %u rtn %u latency %u pd %u",
+			req->cig, req->cis, qos.ucast.io_qos.interval,
+			qos.ucast.framing, qos.ucast.io_qos.phy,
+			qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn,
+			qos.ucast.io_qos.latency, qos.ucast.delay);
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "%s: Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_qos(ep, bap, &qos, rsp);
+}
+
+static uint8_t stream_enable(struct bt_bap_stream *stream, struct iovec *meta,
+							struct iovec *rsp)
+{
+	DBG(stream->bap, "stream %p", stream);
+
+	ascs_ase_rsp_success(rsp, stream->ep->id);
+
+	util_iov_free(stream->meta, 1);
+	stream->meta = util_iov_dup(meta, 1);
+
+	if (!stream_set_state(stream, BT_BAP_STREAM_STATE_ENABLING))
+		return 1;
+
+	/* Sink can autonomously for to Streaming state if io already exits */
+	if (stream->io && stream->ep->dir == BT_BAP_SINK)
+		stream_set_state(stream, BT_BAP_STREAM_STATE_STREAMING);
+
+	return 0;
+}
+
+static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+			struct bt_ascs_enable *req, struct iovec *iov,
+			struct iovec *rsp)
+{
+	struct iovec meta;
+
+	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x02 (QoS Configured) */
+	case BT_ASCS_ASE_STATE_QOS:
+		break;
+	default:
+		DBG(bap, "Invalid state %s", bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	meta.iov_base = util_iov_pull_mem(iov, req->meta.len);
+	meta.iov_len = req->meta.len;
+
+	if (!bt_bap_debug_metadata(meta.iov_base, meta.iov_len,
+					bap->debug_func, bap->debug_data)) {
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_METADATA_INVALID,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_enable(ep->stream, &meta, rsp);
+}
+
+static uint8_t ascs_enable(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_enable *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->meta.ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->meta.ase);
+		ascs_ase_rsp_add(rsp, req->meta.ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_enable(ep, bap, req, iov, rsp);
+}
+
+static uint8_t ep_start(struct bt_bap_endpoint *ep, struct iovec *rsp)
+{
+	struct bt_bap_stream *stream = ep->stream;
+
+	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x03 (Enabling) */
+	case BT_ASCS_ASE_STATE_ENABLING:
+		break;
+	default:
+		DBG(ep->stream->bap, "Invalid state %s",
+				bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	/* If the ASE_ID  written by the client represents a Sink ASE, the
+	 * server shall not accept the Receiver Start Ready operation for that
+	 * ASE. The server shall send a notification of the ASE Control Point
+	 * characteristic to the client, and the server shall set the
+	 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
+	 */
+	if (ep->dir == BT_BAP_SINK) {
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_DIR, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_start(ep->stream, rsp);
+}
+
+static uint8_t ascs_start(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_start *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found for %p", ep);
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_start(ep, rsp);
+}
+
+static uint8_t ep_disable(struct bt_bap_endpoint *ep, struct iovec *rsp)
+{
+	struct bt_bap_stream *stream = ep->stream;
+
+	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x03 (Enabling) */
+	case BT_ASCS_ASE_STATE_ENABLING:
+	 /* or 0x04 (Streaming) */
+	case BT_ASCS_ASE_STATE_STREAMING:
+		break;
+	default:
+		DBG(stream->bap, "Invalid state %s",
+				bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_disable(ep->stream, rsp);
+}
+
+static uint8_t ascs_disable(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_disable *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_disable(ep, rsp);
+}
+
+static uint8_t ep_stop(struct bt_bap_endpoint *ep, struct iovec *rsp)
+{
+	struct bt_bap_stream *stream = ep->stream;
+
+	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x05 (Disabling) */
+	case BT_ASCS_ASE_STATE_DISABLING:
+		break;
+	default:
+		DBG(stream->bap, "Invalid state %s",
+				bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	/* If the ASE_ID  written by the client represents a Sink ASE, the
+	 * server shall not accept the Receiver Stop Ready operation for that
+	 * ASE. The server shall send a notification of the ASE Control Point
+	 * characteristic to the client, and the server shall set the
+	 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
+	 */
+	if (ep->dir == BT_BAP_SINK) {
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_DIR, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_stop(ep->stream, rsp);
+}
+
+static uint8_t ascs_stop(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_stop *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_stop(ep, rsp);
+}
+
+static uint8_t ep_metadata(struct bt_bap_endpoint *ep, struct iovec *meta,
+						struct iovec *rsp)
+{
+	struct bt_bap_stream *stream = ep->stream;
+
+	DBG(stream->bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+
+	switch (ep->state) {
+	/* Valid only if ASE_State field = 0x03 (Enabling) */
+	case BT_ASCS_ASE_STATE_ENABLING:
+	 /* or 0x04 (Streaming) */
+	case BT_ASCS_ASE_STATE_STREAMING:
+		break;
+	default:
+		DBG(stream->bap, "Invalid state %s",
+				bt_bap_stream_statestr(ep->state));
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_metadata(ep->stream, meta, rsp);
+}
+
+static uint8_t ascs_metadata(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_metadata *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return ep_metadata(ep, iov, rsp);
+}
+
+static uint8_t ascs_release(struct bt_ascs *ascs, struct bt_bap *bap,
+				struct iovec *iov, struct iovec *rsp)
+{
+	struct bt_bap_endpoint *ep;
+	struct bt_ascs_release *req;
+
+	req = util_iov_pull_mem(iov, sizeof(*req));
+
+	ep = bap_get_local_endpoint_id(bap, req->ase);
+	if (!ep) {
+		DBG(bap, "Invalid ASE ID 0x%02x", req->ase);
+		ascs_ase_rsp_add(rsp, req->ase,
+				BT_ASCS_RSP_INVALID_ASE, BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	if (!ep->stream) {
+		DBG(bap, "No stream found");
+		ascs_ase_rsp_add(rsp, ep->id,
+				BT_ASCS_RSP_INVALID_ASE_STATE,
+				BT_ASCS_REASON_NONE);
+		return 0;
+	}
+
+	return stream_release(ep->stream, rsp);
+}
+
+#define ASCS_OP(_str, _op, _size, _func) \
+	{ \
+		.str = _str, \
+		.op = _op, \
+		.size = _size, \
+		.func = _func, \
+	}
+
+struct ascs_op_handler {
+	const char *str;
+	uint8_t  op;
+	size_t   size;
 	uint8_t  (*func)(struct bt_ascs *ascs, struct bt_bap *bap,
 			struct iovec *iov, struct iovec *rsp);
 } handlers[] = {
@@ -2131,2671 +3367,3703 @@ struct ascs_op_handler {
 	{}
 };
 
-static struct iovec *ascs_ase_cp_rsp_new(uint8_t op)
+static struct iovec *ascs_ase_cp_rsp_new(uint8_t op)
+{
+	struct bt_ascs_cp_rsp *rsp;
+	struct iovec *iov;
+
+	iov = new0(struct iovec, 1);
+	rsp = new0(struct bt_ascs_cp_rsp, 1);
+	rsp->op = op;
+	iov->iov_base = rsp;
+	iov->iov_len = sizeof(*rsp);
+
+	return iov;
+}
+
+static void ascs_ase_cp_write(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 bt_ascs *ascs = user_data;
+	struct bt_bap *bap = bap_get_session(att, ascs->bdb->db);
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = len,
+	};
+	struct bt_ascs_ase_hdr *hdr;
+	struct ascs_op_handler *handler;
+	uint8_t ret = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+	struct iovec *rsp;
+
+	if (offset) {
+		DBG(bap, "invalid offset %u", offset);
+		gatt_db_attribute_write_result(attrib, id,
+						BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len < sizeof(*hdr)) {
+		DBG(bap, "invalid len %u < %u sizeof(*hdr)", len,
+							sizeof(*hdr));
+		gatt_db_attribute_write_result(attrib, id,
+				BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	hdr = util_iov_pull_mem(&iov, sizeof(*hdr));
+	rsp = ascs_ase_cp_rsp_new(hdr->op);
+
+	for (handler = handlers; handler && handler->str; handler++) {
+		if (handler->op != hdr->op)
+			continue;
+
+		if (iov.iov_len < hdr->num * handler->size) {
+			DBG(bap, "invalid len %u < %u "
+				  "hdr->num * handler->size", len,
+				  hdr->num * handler->size);
+			ret = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+			goto respond;
+		}
+
+		break;
+	}
+
+	if (handler && handler->str) {
+		int i;
+
+		DBG(bap, "%s", handler->str);
+
+		/* Set in_cp_write so ASE notification are not sent ahead of
+		 * CP notifcation.
+		 */
+		bap->in_cp_write = true;
+
+		for (i = 0; i < hdr->num; i++)
+			ret = handler->func(ascs, bap, &iov, rsp);
+
+		bap->in_cp_write = false;
+	} else {
+		DBG(bap, "Unknown opcode 0x%02x", hdr->op);
+		ascs_ase_rsp_add_errno(rsp, 0x00, -ENOTSUP);
+	}
+
+respond:
+	if (ret == BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN)
+		ascs_ase_rsp_add_errno(rsp, 0x00, -ENOMSG);
+
+	gatt_db_attribute_notify(attrib, rsp->iov_base, rsp->iov_len, att);
+	gatt_db_attribute_write_result(attrib, id, ret);
+
+	util_iov_free(rsp, 1);
+}
+
+static struct bt_ascs *ascs_new(struct gatt_db *db)
+{
+	struct bt_ascs *ascs;
+	bt_uuid_t uuid;
+	int i;
+
+	if (!db)
+		return NULL;
+
+	ascs = new0(struct bt_ascs, 1);
+
+	/* Populate DB with ASCS attributes */
+	bt_uuid16_create(&uuid, ASCS_UUID);
+	ascs->service = gatt_db_add_service(db, &uuid, true,
+						4 + (NUM_ASES * 3));
+
+	for (i = 0; i < NUM_ASES; i++)
+		ase_new(ascs, i);
+
+	bt_uuid16_create(&uuid, ASE_CP_UUID);
+	ascs->ase_cp = gatt_db_service_add_characteristic(ascs->service,
+					&uuid,
+					BT_ATT_PERM_WRITE,
+					BT_GATT_CHRC_PROP_WRITE |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					NULL, ascs_ase_cp_write,
+					ascs);
+
+	ascs->ase_cp_ccc = gatt_db_service_add_ccc(ascs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	gatt_db_service_set_active(ascs->service, true);
+
+	return ascs;
+}
+
+static struct bt_bap_db *bap_db_new(struct gatt_db *db)
+{
+	struct bt_bap_db *bdb;
+
+	if (!db)
+		return NULL;
+
+	bdb = new0(struct bt_bap_db, 1);
+	bdb->db = gatt_db_ref(db);
+	bdb->sinks = queue_new();
+	bdb->sources = queue_new();
+	bdb->broadcast_sources = queue_new();
+	bdb->broadcast_sinks = queue_new();
+
+	if (!bap_db)
+		bap_db = queue_new();
+
+	bdb->pacs = pacs_new(db);
+	bdb->pacs->bdb = bdb;
+
+	bdb->ascs = ascs_new(db);
+	bdb->ascs->bdb = bdb;
+
+	queue_push_tail(bap_db, bdb);
+
+	return bdb;
+}
+
+static struct bt_bap_db *bap_get_db(struct gatt_db *db)
+{
+	struct bt_bap_db *bdb;
+
+	bdb = queue_find(bap_db, bap_db_match, db);
+	if (bdb)
+		return bdb;
+
+	return bap_db_new(db);
+}
+
+static struct bt_pacs *bap_get_pacs(struct bt_bap *bap)
+{
+	if (!bap)
+		return NULL;
+
+	if (bap->rdb->pacs)
+		return bap->rdb->pacs;
+
+	bap->rdb->pacs = new0(struct bt_pacs, 1);
+	bap->rdb->pacs->bdb = bap->rdb;
+
+	return bap->rdb->pacs;
+}
+
+static bool match_codec(const void *data, const void *user_data)
+{
+	const struct bt_bap_pac *pac = data;
+	const struct bt_bap_codec *codec = user_data;
+
+	return bap_codec_equal(&pac->codec, codec);
+}
+
+static struct bt_bap_pac *bap_pac_find(struct bt_bap_db *bdb, uint8_t type,
+					struct bt_bap_codec *codec)
+{
+	switch (type) {
+	case BT_BAP_SOURCE:
+		return queue_find(bdb->sources, match_codec, codec);
+	case BT_BAP_SINK:
+		return queue_find(bdb->sinks, match_codec, codec);
+	case BT_BAP_BCAST_SOURCE:
+		return queue_find(bdb->broadcast_sources, match_codec, codec);
+	case BT_BAP_BCAST_SINK:
+		return queue_find(bdb->broadcast_sinks, match_codec, codec);
+	}
+
+	return NULL;
+}
+
+static void *ltv_merge(struct iovec *data, struct iovec *cont)
+{
+	uint8_t delimiter = 0;
+
+	if (!data)
+		return NULL;
+
+	if (!cont || !cont->iov_len || !cont->iov_base)
+		return data->iov_base;
+
+	util_iov_append(data, &delimiter, sizeof(delimiter));
+
+	return util_iov_append(data, cont->iov_base, cont->iov_len);
+}
+
+static void bap_pac_chan_add(struct bt_bap_pac *pac, uint8_t count,
+				uint32_t location)
+{
+	struct bt_bap_chan *chan;
+
+	if (!pac->channels)
+		pac->channels = queue_new();
+
+	chan = new0(struct bt_bap_chan, 1);
+	chan->count = count;
+	chan->location = location;
+
+	queue_push_tail(pac->channels, chan);
+}
+
+static void bap_pac_foreach_channel(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
+{
+	struct bt_bap_pac *pac = user_data;
+
+	if (!v)
+		return;
+
+	bap_pac_chan_add(pac, *v, bt_bap_pac_get_locations(pac));
+}
+
+static void bap_pac_update_channels(struct bt_bap_pac *pac, struct iovec *data)
+{
+	uint8_t type = 0x03;
+
+	if (!data)
+		return;
+
+	util_ltv_foreach(data->iov_base, data->iov_len, &type,
+				bap_pac_foreach_channel, pac);
+
+	/* If record didn't set a channel count but set a location use that as
+	 * channel count.
+	 */
+	if (queue_isempty(pac->channels) && pac->qos.location)
+		bap_pac_chan_add(pac, pac->qos.location, pac->qos.location);
+
+}
+
+static void bap_pac_merge(struct bt_bap_pac *pac, struct iovec *data,
+					struct iovec *metadata)
+{
+	/* Merge data into existing record */
+	if (pac->data)
+		ltv_merge(pac->data, data);
+	else
+		pac->data = util_iov_dup(data, 1);
+
+	/* Update channels */
+	bap_pac_update_channels(pac, data);
+
+	/* Merge metadata into existing record */
+	if (pac->metadata)
+		ltv_merge(pac->metadata, metadata);
+	else
+		pac->metadata = util_iov_dup(metadata, 1);
+}
+
+static struct bt_bap_pac *bap_pac_new(struct bt_bap_db *bdb, const char *name,
+					uint8_t type,
+					struct bt_bap_codec *codec,
+					struct bt_bap_pac_qos *qos,
+					struct iovec *data,
+					struct iovec *metadata)
+{
+	struct bt_bap_pac *pac;
+
+	pac = new0(struct bt_bap_pac, 1);
+	pac->bdb = bdb;
+	pac->name = name ? strdup(name) : NULL;
+	pac->type = type;
+
+	if (codec)
+		pac->codec = *codec;
+
+	if (qos)
+		pac->qos = *qos;
+
+	bap_pac_merge(pac, data, metadata);
+
+	return pac;
+}
+
+static void bap_pac_free(void *data)
 {
-	struct bt_ascs_cp_rsp *rsp;
-	struct iovec *iov;
+	struct bt_bap_pac *pac = data;
 
-	iov = new0(struct iovec, 1);
-	rsp = new0(struct bt_ascs_cp_rsp, 1);
-	rsp->op = op;
-	iov->iov_base = rsp;
-	iov->iov_len = sizeof(*rsp);
+	free(pac->name);
+	util_iov_free(pac->metadata, 1);
+	util_iov_free(pac->data, 1);
+	queue_destroy(pac->channels, free);
+	free(pac);
+}
 
-	return iov;
+static void pacs_sink_location_changed(struct bt_pacs *pacs)
+{
+	uint32_t location = cpu_to_le32(pacs->sink_loc_value);
+
+	gatt_db_attribute_notify(pacs->sink_loc, (void *)&location,
+					sizeof(location), NULL);
 }
 
-static void ascs_ase_cp_write(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)
+static void pacs_add_sink_location(struct bt_pacs *pacs, uint32_t location)
 {
-	struct bt_ascs *ascs = user_data;
-	struct bt_bap *bap = bap_get_session(att, ascs->bdb->db);
-	struct iovec iov = {
-		.iov_base = (void *) value,
-		.iov_len = len,
-	};
-	struct bt_ascs_ase_hdr *hdr;
-	struct ascs_op_handler *handler;
-	uint8_t ret = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
-	struct iovec *rsp;
+	/* Check if location value needs updating */
+	if (location == pacs->sink_loc_value)
+		return;
 
-	if (offset) {
-		DBG(bap, "invalid offset %u", offset);
-		gatt_db_attribute_write_result(attrib, id,
-						BT_ATT_ERROR_INVALID_OFFSET);
+	pacs->sink_loc_value |= location;
+
+	pacs_sink_location_changed(pacs);
+}
+
+static void pacs_supported_context_changed(struct bt_pacs *pacs)
+{
+	struct bt_pacs_context ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+
+	ctx.snk = cpu_to_le16(pacs->supported_sink_context_value);
+	ctx.src = cpu_to_le16(pacs->supported_source_context_value);
+
+	gatt_db_attribute_notify(pacs->supported_context, (void *)&ctx,
+					sizeof(ctx), NULL);
+}
+
+static void pacs_add_sink_supported_context(struct bt_pacs *pacs,
+						uint16_t context)
+{
+	context |= pacs->supported_sink_context_value;
+
+	/* Check if context value needs updating */
+	if (context == pacs->supported_sink_context_value)
 		return;
-	}
 
-	if (len < sizeof(*hdr)) {
-		DBG(bap, "invalid len %u < %u sizeof(*hdr)", len,
-							sizeof(*hdr));
-		gatt_db_attribute_write_result(attrib, id,
-				BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+	pacs->supported_sink_context_value = context;
+
+	pacs_supported_context_changed(pacs);
+}
+
+static void pacs_context_changed(struct bt_pacs *pacs)
+{
+	struct bt_pacs_context ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+
+	ctx.snk = cpu_to_le16(pacs->sink_context_value);
+	ctx.src = cpu_to_le16(pacs->source_context_value);
+
+	gatt_db_attribute_notify(pacs->context, (void *)&ctx, sizeof(ctx),
+					NULL);
+}
+
+static void pacs_add_sink_context(struct bt_pacs *pacs, uint16_t context)
+{
+	context |= pacs->supported_sink_context_value;
+
+	/* Check if context value needs updating */
+	if (context == pacs->sink_context_value)
+		return;
+
+	pacs->sink_context_value = context;
+
+	pacs_context_changed(pacs);
+}
+
+static void bap_add_sink(struct bt_bap_pac *pac)
+{
+	struct iovec iov;
+	uint8_t value[512];
+
+	queue_push_tail(pac->bdb->sinks, pac);
+
+	memset(value, 0, sizeof(value));
+
+	iov.iov_base = value;
+	iov.iov_len = 0;
+
+	queue_foreach(pac->bdb->sinks, pac_foreach, &iov);
+
+	pacs_add_sink_location(pac->bdb->pacs, pac->qos.location);
+	pacs_add_sink_supported_context(pac->bdb->pacs,
+					pac->qos.supported_context);
+	pacs_add_sink_context(pac->bdb->pacs, pac->qos.context);
+	gatt_db_attribute_notify(pac->bdb->pacs->sink, iov.iov_base,
+				iov.iov_len, NULL);
+}
+
+static void pacs_source_location_changed(struct bt_pacs *pacs)
+{
+	uint32_t location = cpu_to_le32(pacs->source_loc_value);
+
+	gatt_db_attribute_notify(pacs->source_loc, (void *)&location,
+					sizeof(location), NULL);
+}
+
+static void pacs_add_source_location(struct bt_pacs *pacs, uint32_t location)
+{
+	location |= pacs->source_loc_value;
+
+	/* Check if location value needs updating */
+	if (location == pacs->source_loc_value)
+		return;
+
+	pacs->source_loc_value = location;
+
+	pacs_source_location_changed(pacs);
+}
+
+static void pacs_add_source_supported_context(struct bt_pacs *pacs,
+						uint16_t context)
+{
+	context |= pacs->supported_source_context_value;
+
+	/* Check if context value needs updating */
+	if (context == pacs->supported_source_context_value)
+		return;
+
+	pacs->supported_source_context_value = context;
+
+	pacs_supported_context_changed(pacs);
+}
+
+static void pacs_add_source_context(struct bt_pacs *pacs, uint16_t context)
+{
+	context |= pacs->source_context_value;
+
+	/* Check if context value needs updating */
+	if (context == pacs->source_context_value)
 		return;
+
+	pacs->source_context_value = context;
+
+	pacs_context_changed(pacs);
+}
+
+static void bap_add_source(struct bt_bap_pac *pac)
+{
+	struct iovec iov;
+	uint8_t value[512];
+
+	queue_push_tail(pac->bdb->sources, pac);
+
+	memset(value, 0, sizeof(value));
+
+	iov.iov_base = value;
+	iov.iov_len = 0;
+
+	queue_foreach(pac->bdb->sources, pac_foreach, &iov);
+
+	pacs_add_source_location(pac->bdb->pacs, pac->qos.location);
+	pacs_add_source_supported_context(pac->bdb->pacs,
+					pac->qos.supported_context);
+	pacs_add_source_context(pac->bdb->pacs, pac->qos.context);
+
+	gatt_db_attribute_notify(pac->bdb->pacs->source, iov.iov_base,
+				iov.iov_len, NULL);
+}
+
+static void bap_add_broadcast_source(struct bt_bap_pac *pac)
+{
+	queue_push_tail(pac->bdb->broadcast_sources, pac);
+}
+
+static void bap_add_broadcast_sink(struct bt_bap_pac *pac)
+{
+	queue_push_tail(pac->bdb->broadcast_sinks, pac);
+
+	/* Update local PACS for broadcast sink also, when registering an
+	 * endpoint
+	 */
+	pacs_add_sink_location(pac->bdb->pacs, pac->qos.location);
+	pacs_add_sink_supported_context(pac->bdb->pacs,
+			pac->qos.supported_context);
+}
+
+static void notify_pac_added(void *data, void *user_data)
+{
+	struct bt_bap_pac_changed *changed = data;
+	struct bt_bap_pac *pac = user_data;
+
+	if (changed->added)
+		changed->added(pac, changed->data);
+}
+
+static void notify_session_pac_added(void *data, void *user_data)
+{
+	struct bt_bap *bap = data;
+
+	queue_foreach(bap->pac_cbs, notify_pac_added, user_data);
+}
+
+struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
+					const char *name, uint8_t type,
+					uint8_t id, uint16_t cid, uint16_t vid,
+					struct bt_bap_pac_qos *qos,
+					struct iovec *data,
+					struct iovec *metadata)
+{
+	struct bt_bap_db *bdb;
+	struct bt_bap_pac *pac;
+	struct bt_bap_codec codec;
+
+	if (!db)
+		return NULL;
+
+	bdb = bap_get_db(db);
+	if (!bdb)
+		return NULL;
+
+	if ((id != 0xff) && ((cid != 0U)  || (vid != 0U)))
+		return NULL;
+
+	codec.id = id;
+	codec.cid = cid;
+	codec.vid = vid;
+
+	pac = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);
+
+	switch (type) {
+	case BT_BAP_SINK:
+		bap_add_sink(pac);
+		break;
+	case BT_BAP_SOURCE:
+		bap_add_source(pac);
+		break;
+	case BT_BAP_BCAST_SOURCE:
+		bap_add_broadcast_source(pac);
+		break;
+	case BT_BAP_BCAST_SINK:
+		bap_add_broadcast_sink(pac);
+		break;
+	default:
+		bap_pac_free(pac);
+		return NULL;
+	}
+
+	queue_foreach(sessions, notify_session_pac_added, pac);
+
+	return pac;
+}
+
+struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
+					uint8_t type, uint8_t id,
+					struct bt_bap_pac_qos *qos,
+					struct iovec *data,
+					struct iovec *metadata)
+{
+	return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
+							data, metadata);
+}
+
+uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac)
+{
+	if (!pac)
+		return 0x00;
+
+	return pac->type;
+}
+
+uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
+{
+	struct bt_pacs *pacs;
+
+	if (!pac)
+		return 0;
+
+	if (pac->qos.location)
+		return pac->qos.location;
+
+	pacs = pac->bdb->pacs;
+
+	switch (pac->type) {
+	case BT_BAP_SOURCE:
+		return pacs->source_loc_value;
+	case BT_BAP_SINK:
+		return pacs->sink_loc_value;
+	default:
+		return 0;
+	}
+}
+
+uint16_t bt_bap_pac_get_supported_context(struct bt_bap_pac *pac)
+{
+	struct bt_pacs *pacs;
+
+	if (!pac)
+		return 0;
+
+	pacs = pac->bdb->pacs;
+
+	switch (pac->type) {
+	case BT_BAP_SOURCE:
+		return pacs->supported_source_context_value;
+	case BT_BAP_SINK:
+		return pacs->supported_sink_context_value;
+	default:
+		return 0;
 	}
+}
 
-	hdr = iov_pull_mem(&iov, sizeof(*hdr));
-	rsp = ascs_ase_cp_rsp_new(hdr->op);
+uint16_t bt_bap_pac_get_context(struct bt_bap_pac *pac)
+{
+	struct bt_pacs *pacs;
 
-	for (handler = handlers; handler && handler->str; handler++) {
-		if (handler->op != hdr->op)
-			continue;
+	if (!pac)
+		return 0;
 
-		if (iov.iov_len < hdr->num * handler->size) {
-			DBG(bap, "invalid len %u < %u "
-				  "hdr->num * handler->size", len,
-				  hdr->num * handler->size);
-			ret = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
-			goto respond;
-		}
+	pacs = pac->bdb->pacs;
 
-		break;
+	switch (pac->type) {
+	case BT_BAP_SOURCE:
+		return pacs->source_context_value;
+	case BT_BAP_SINK:
+		return pacs->sink_context_value;
+	default:
+		return 0;
 	}
+}
 
-	if (handler && handler->str) {
-		int i;
+struct bt_bap_pac_qos *bt_bap_pac_get_qos(struct bt_bap_pac *pac)
+{
+	if (!pac || !pac->qos.phy)
+		return NULL;
 
-		DBG(bap, "%s", handler->str);
+	return &pac->qos;
+}
 
-		for (i = 0; i < hdr->num; i++)
-			ret = handler->func(ascs, bap, &iov, rsp);
-	} else {
-		DBG(bap, "Unknown opcode 0x%02x", hdr->op);
-		ascs_ase_rsp_add_errno(rsp, 0x00, -ENOTSUP);
+struct iovec *bt_bap_pac_get_data(struct bt_bap_pac *pac)
+{
+	return pac->data;
+}
+
+struct iovec *bt_bap_pac_get_metadata(struct bt_bap_pac *pac)
+{
+	return pac->metadata;
+}
+
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return 0x00;
+
+	switch (bt_bap_pac_get_type(stream->lpac)) {
+	case BT_BAP_SINK:
+	case BT_BAP_SOURCE:
+		return BT_BAP_STREAM_TYPE_UCAST;
+	case BT_BAP_BCAST_SOURCE:
+	case BT_BAP_BCAST_SINK:
+		return BT_BAP_STREAM_TYPE_BCAST;
 	}
 
-respond:
-	if (ret == BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN)
-		ascs_ase_rsp_add_errno(rsp, 0x00, -ENOMSG);
+	return 0x00;
+}
 
-	gatt_db_attribute_notify(attrib, rsp->iov_base, rsp->iov_len, att);
-	gatt_db_attribute_write_result(attrib, id, ret);
+static void notify_pac_removed(void *data, void *user_data)
+{
+	struct bt_bap_pac_changed *changed = data;
+	struct bt_bap_pac *pac = user_data;
 
-	iov_free(rsp);
+	if (changed->removed)
+		changed->removed(pac, changed->data);
 }
 
-static struct bt_ascs *ascs_new(struct gatt_db *db)
+static void notify_session_pac_removed(void *data, void *user_data)
 {
-	struct bt_ascs *ascs;
-	bt_uuid_t uuid;
-	int i;
+	struct bt_bap *bap = data;
 
-	if (!db)
-		return NULL;
+	queue_foreach(bap->pac_cbs, notify_pac_removed, user_data);
+}
 
-	ascs = new0(struct bt_ascs, 1);
+bool bt_bap_pac_set_ops(struct bt_bap_pac *pac, struct bt_bap_pac_ops *ops,
+					void *user_data)
+{
+	if (!pac)
+		return false;
 
-	/* Populate DB with ASCS attributes */
-	bt_uuid16_create(&uuid, ASCS_UUID);
-	ascs->service = gatt_db_add_service(db, &uuid, true,
-						4 + (NUM_ASES * 3));
+	pac->ops = ops;
+	pac->user_data = user_data;
 
-	for (i = 0; i < NUM_ASES; i++)
-		ase_new(ascs, i);
+	return true;
+}
 
-	bt_uuid16_create(&uuid, ASE_CP_UUID);
-	ascs->ase_cp = gatt_db_service_add_characteristic(ascs->service,
-					&uuid,
-					BT_ATT_PERM_WRITE,
-					BT_GATT_CHRC_PROP_WRITE |
-					BT_GATT_CHRC_PROP_NOTIFY,
-					NULL, ascs_ase_cp_write,
-					ascs);
+static bool match_stream_lpac(const void *data, const void *user_data)
+{
+	const struct bt_bap_stream *stream = data;
+	const struct bt_bap_pac *pac = user_data;
 
-	ascs->ase_cp_ccc = gatt_db_service_add_ccc(ascs->service,
-					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	return stream->lpac == pac;
+}
 
-	gatt_db_service_set_active(ascs->service, true);
+static void remove_streams(void *data, void *user_data)
+{
+	struct bt_bap *bap = data;
+	struct bt_bap_pac *pac = user_data;
+	struct bt_bap_stream *stream;
 
-	return ascs;
+	stream = queue_remove_if(bap->streams, match_stream_lpac, pac);
+	if (stream)
+		bt_bap_stream_release(stream, NULL, NULL);
 }
 
-static struct bt_bap_db *bap_db_new(struct gatt_db *db)
+static void bap_pac_sink_removed(void *data, void *user_data)
 {
-	struct bt_bap_db *bdb;
+	struct bt_bap_pac *pac = data;
+	struct bt_bap_pac_qos *qos = user_data;
 
-	if (!db)
-		return NULL;
+	qos->location |= pac->qos.location;
+	qos->supported_context |= pac->qos.supported_context;
+	qos->context |= pac->qos.context;
+}
 
-	bdb = new0(struct bt_bap_db, 1);
-	bdb->db = gatt_db_ref(db);
-	bdb->sinks = queue_new();
-	bdb->sources = queue_new();
-	bdb->endpoints = queue_new();
+bool bt_bap_remove_pac(struct bt_bap_pac *pac)
+{
+	if (!pac)
+		return false;
 
-	if (!bap_db)
-		bap_db = queue_new();
+	if (queue_remove_if(pac->bdb->sinks, NULL, pac)) {
+		struct bt_pacs *pacs = pac->bdb->pacs;
+		struct bt_bap_pac_qos qos;
 
-	bdb->pacs = pacs_new(db);
-	bdb->pacs->bdb = bdb;
+		memset(&qos, 0, sizeof(qos));
+		queue_foreach(pac->bdb->sinks, bap_pac_sink_removed, &qos);
 
-	bdb->ascs = ascs_new(db);
-	bdb->ascs->bdb = bdb;
+		if (pacs->sink_loc_value != qos.location) {
+			pacs->sink_loc_value = qos.location;
+			pacs_sink_location_changed(pacs);
+		}
 
-	queue_push_tail(bap_db, bdb);
+		if (pacs->supported_sink_context_value !=
+				qos.supported_context) {
+			pacs->supported_sink_context_value =
+							qos.supported_context;
+			pacs_supported_context_changed(pacs);
+		}
 
-	return bdb;
+		if (pacs->sink_context_value != qos.context) {
+			pacs->sink_context_value = qos.context;
+			pacs_context_changed(pacs);
+		}
+
+
+		goto found;
+	}
+
+	if (queue_remove_if(pac->bdb->sources, NULL, pac))
+		goto found;
+
+	if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac))
+		goto found;
+
+	return false;
+
+found:
+	queue_foreach(sessions, remove_streams, pac);
+	queue_foreach(sessions, notify_session_pac_removed, pac);
+	bap_pac_free(pac);
+	return true;
 }
 
-static struct bt_bap_db *bap_get_db(struct gatt_db *db)
+static void bap_db_free(void *data)
 {
-	struct bt_bap_db *bdb;
+	struct bt_bap_db *bdb = data;
 
-	bdb = queue_find(bap_db, bap_db_match, db);
-	if (bdb)
-		return bdb;
+	if (!bdb)
+		return;
 
-	return bap_db_new(db);
+	queue_destroy(bdb->sinks, bap_pac_free);
+	queue_destroy(bdb->sources, bap_pac_free);
+	gatt_db_unref(bdb->db);
+
+	free(bdb->pacs);
+	free(bdb->ascs);
+	free(bdb);
 }
 
-static struct bt_pacs *bap_get_pacs(struct bt_bap *bap)
+static void bap_ready_free(void *data)
 {
-	if (!bap)
-		return NULL;
-
-	if (bap->rdb->pacs)
-		return bap->rdb->pacs;
+	struct bt_bap_ready *ready = data;
 
-	bap->rdb->pacs = new0(struct bt_pacs, 1);
-	bap->rdb->pacs->bdb = bap->rdb;
+	if (ready->destroy)
+		ready->destroy(ready->data);
 
-	return bap->rdb->pacs;
+	free(ready);
 }
 
-static struct bt_ascs *bap_get_ascs(struct bt_bap *bap)
+static void bap_state_free(void *data)
 {
-	if (!bap)
-		return NULL;
+	struct bt_bap_state *state = data;
 
-	if (bap->rdb->ascs)
-		return bap->rdb->ascs;
+	if (state->destroy)
+		state->destroy(state->data);
 
-	bap->rdb->ascs = new0(struct bt_ascs, 1);
-	bap->rdb->ascs->bdb = bap->rdb;
+	free(state);
+}
 
-	return bap->rdb->ascs;
+static void bap_ep_free(void *data)
+{
+	struct bt_bap_endpoint *ep = data;
+
+	if (ep && ep->stream)
+		ep->stream->ep = NULL;
+
+	free(ep);
 }
 
-static struct bt_bap_pac *bap_pac_new(struct bt_bap_db *bdb, const char *name,
-					uint8_t type,
-					struct bt_bap_codec *codec,
-					struct bt_bap_pac_qos *qos,
-					struct iovec *data,
-					struct iovec *metadata)
+static void bap_detached(void *data, void *user_data)
 {
-	struct bt_bap_pac *pac;
+	struct bt_bap_cb *cb = data;
+	struct bt_bap *bap = user_data;
 
-	pac = new0(struct bt_bap_pac, 1);
-	pac->bdb = bdb;
-	pac->name = name ? strdup(name) : NULL;
-	pac->type = type;
-	pac->codec = *codec;
-	pac->data = iov_dup(data, 1);
-	pac->metadata = iov_dup(metadata, 1);
+	cb->detached(bap, cb->user_data);
+}
 
-	if (qos)
-		pac->qos = *qos;
+static void bap_stream_unref(void *data)
+{
+	struct bt_bap_stream *stream = data;
 
-	return pac;
+	bt_bap_stream_unref(stream);
 }
 
-static void bap_pac_free(void *data)
+static void bap_free(void *data)
 {
-	struct bt_bap_pac *pac = data;
+	struct bt_bap *bap = data;
 
-	free(pac->name);
-	iov_free(pac->metadata);
-	iov_free(pac->data);
-	free(pac);
+	timeout_remove(bap->process_id);
+
+	bt_bap_detach(bap);
+
+	bap_db_free(bap->rdb);
+
+	queue_destroy(bap->pac_cbs, pac_changed_free);
+	queue_destroy(bap->ready_cbs, bap_ready_free);
+	queue_destroy(bap->state_cbs, bap_state_free);
+	queue_destroy(bap->local_eps, free);
+	queue_destroy(bap->remote_eps, bap_ep_free);
+
+	queue_destroy(bap->reqs, bap_req_free);
+	queue_destroy(bap->notify, NULL);
+	queue_destroy(bap->streams, bap_stream_unref);
+
+	free(bap);
 }
 
-static void bap_add_sink(struct bt_bap_pac *pac)
+unsigned int bt_bap_register(bt_bap_func_t attached, bt_bap_func_t detached,
+							void *user_data)
 {
-	struct iovec iov;
-	uint8_t value[512];
+	struct bt_bap_cb *cb;
+	static unsigned int id;
 
-	queue_push_tail(pac->bdb->sinks, pac);
+	if (!attached && !detached)
+		return 0;
 
-	memset(value, 0, sizeof(value));
+	if (!bap_cbs)
+		bap_cbs = queue_new();
 
-	iov.iov_base = value;
-	iov.iov_len = 0;
+	cb = new0(struct bt_bap_cb, 1);
+	cb->id = ++id ? id : ++id;
+	cb->attached = attached;
+	cb->detached = detached;
+	cb->user_data = user_data;
 
-	queue_foreach(pac->bdb->sinks, pac_foreach, &iov);
+	queue_push_tail(bap_cbs, cb);
 
-	gatt_db_attribute_notify(pac->bdb->pacs->sink, iov.iov_base,
-				iov.iov_len, NULL);
+	return cb->id;
 }
 
-static void bap_add_source(struct bt_bap_pac *pac)
+static bool match_id(const void *data, const void *match_data)
 {
-	struct iovec iov;
-	uint8_t value[512];
+	const struct bt_bap_cb *cb = data;
+	unsigned int id = PTR_TO_UINT(match_data);
 
-	queue_push_tail(pac->bdb->sources, pac);
+	return (cb->id == id);
+}
 
-	memset(value, 0, sizeof(value));
+bool bt_bap_unregister(unsigned int id)
+{
+	struct bt_bap_cb *cb;
 
-	iov.iov_base = value;
-	iov.iov_len = 0;
+	cb = queue_remove_if(bap_cbs, match_id, UINT_TO_PTR(id));
+	if (!cb)
+		return false;
 
-	queue_foreach(pac->bdb->sinks, pac_foreach, &iov);
+	free(cb);
 
-	gatt_db_attribute_notify(pac->bdb->pacs->source, iov.iov_base,
-				iov.iov_len, NULL);
+	return true;
 }
 
-static void notify_pac_added(void *data, void *user_data)
+static void bap_attached(void *data, void *user_data)
 {
-	struct bt_bap_pac_changed *changed = data;
-	struct bt_bap_pac *pac = user_data;
+	struct bt_bap_cb *cb = data;
+	struct bt_bap *bap = user_data;
 
-	if (changed->added)
-		changed->added(pac, changed->data);
+	cb->attached(bap, cb->user_data);
 }
 
-struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
-					const char *name, uint8_t type,
-					uint8_t id, uint16_t cid, uint16_t vid,
-					struct bt_bap_pac_qos *qos,
-					struct iovec *data,
-					struct iovec *metadata)
+struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb)
 {
+	struct bt_bap *bap;
 	struct bt_bap_db *bdb;
-	struct bt_bap_pac *pac;
-	struct bt_bap_codec codec;
 
-	if (!db)
+	if (!ldb)
 		return NULL;
 
-	bdb = bap_get_db(db);
+	bdb = bap_get_db(ldb);
 	if (!bdb)
 		return NULL;
 
-	codec.id = id;
-	codec.cid = cid;
-	codec.vid = vid;
+	bap = new0(struct bt_bap, 1);
+	bap->ldb = bdb;
+	bap->reqs = queue_new();
+	bap->notify = queue_new();
+	bap->pac_cbs = queue_new();
+	bap->ready_cbs = queue_new();
+	bap->streams = queue_new();
+	bap->state_cbs = queue_new();
+	bap->local_eps = queue_new();
 
-	pac = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);
+	if (!rdb)
+		goto done;
 
-	switch (type) {
-	case BT_BAP_SINK:
-		bap_add_sink(pac);
-		break;
-	case BT_BAP_SOURCE:
-		bap_add_source(pac);
-		break;
-	default:
-		bap_pac_free(pac);
-		return NULL;
-	}
+	bdb = new0(struct bt_bap_db, 1);
+	bdb->db = gatt_db_ref(rdb);
+	bdb->sinks = queue_new();
+	bdb->sources = queue_new();
 
-	queue_foreach(pac_cbs, notify_pac_added, pac);
+	bap->rdb = bdb;
+	bap->remote_eps = queue_new();
 
-	return pac;
+done:
+	return bt_bap_ref(bap);
 }
 
-struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
-					uint8_t type, uint8_t id,
-					struct bt_bap_pac_qos *qos,
-					struct iovec *data,
-					struct iovec *metadata)
+bool bt_bap_set_user_data(struct bt_bap *bap, void *user_data)
 {
-	return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
-							data, metadata);
-}
+	if (!bap)
+		return false;
 
-uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac)
-{
-	if (!pac)
-		return 0x00;
+	bap->user_data = user_data;
 
-	return pac->type;
+	return true;
 }
 
-static void notify_pac_removed(void *data, void *user_data)
+void *bt_bap_get_user_data(struct bt_bap *bap)
 {
-	struct bt_bap_pac_changed *changed = data;
-	struct bt_bap_pac *pac = user_data;
+	if (!bap)
+		return NULL;
 
-	if (changed->removed)
-		changed->removed(pac, changed->data);
+	return bap->user_data;
 }
 
-bool bt_bap_pac_set_ops(struct bt_bap_pac *pac, struct bt_bap_pac_ops *ops,
-					void *user_data)
+struct bt_att *bt_bap_get_att(struct bt_bap *bap)
 {
-	if (!pac)
-		return false;
+	if (!bap)
+		return NULL;
 
-	pac->ops = ops;
-	pac->user_data = user_data;
+	if (bap->att)
+		return bap->att;
 
-	return true;
+	return bt_gatt_client_get_att(bap->client);
 }
 
-static bool match_stream_lpac(const void *data, const void *user_data)
+struct bt_bap *bt_bap_ref(struct bt_bap *bap)
 {
-	const struct bt_bap_stream *stream = data;
-	const struct bt_bap_pac *pac = user_data;
+	if (!bap)
+		return NULL;
 
-	return stream->lpac == pac;
+	__sync_fetch_and_add(&bap->ref_count, 1);
+
+	return bap;
 }
 
-static void remove_streams(void *data, void *user_data)
+void bt_bap_unref(struct bt_bap *bap)
 {
-	struct bt_bap *bap = data;
-	struct bt_bap_pac *pac = user_data;
-	struct bt_bap_stream *stream;
+	if (!bap)
+		return;
 
-	stream = queue_remove_if(bap->streams, match_stream_lpac, pac);
-	if (stream)
-		bt_bap_stream_release(stream, NULL, NULL);
+	if (__sync_sub_and_fetch(&bap->ref_count, 1))
+		return;
+
+	bap_free(bap);
 }
 
-bool bt_bap_remove_pac(struct bt_bap_pac *pac)
+static void bap_notify_ready(struct bt_bap *bap)
 {
-	if (!pac)
-		return false;
+	const struct queue_entry *entry;
 
-	if (queue_remove_if(pac->bdb->sinks, NULL, pac))
-		goto found;
+	if (!bt_bap_ref_safe(bap))
+		return;
 
-	if (queue_remove_if(pac->bdb->sources, NULL, pac))
-		goto found;
+	for (entry = queue_get_entries(bap->ready_cbs); entry;
+							entry = entry->next) {
+		struct bt_bap_ready *ready = entry->data;
 
-	return false;
+		ready->func(bap, ready->data);
+	}
 
-found:
-	queue_foreach(sessions, remove_streams, pac);
-	queue_foreach(pac_cbs, notify_pac_removed, pac);
-	bap_pac_free(pac);
-	return true;
+	bt_bap_unref(bap);
 }
 
-static void bap_db_free(void *data)
+static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
+				struct queue *queue,
+				const uint8_t *value,
+				uint16_t len)
 {
-	struct bt_bap_db *bdb = data;
+	struct bt_pacs_read_rsp *rsp;
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = len,
+	};
+	int i;
 
-	if (!bdb)
+	rsp = util_iov_pull_mem(&iov, sizeof(*rsp));
+	if (!rsp) {
+		DBG(bap, "Unable to parse PAC");
 		return;
+	}
 
-	queue_destroy(bdb->sinks, bap_pac_free);
-	queue_destroy(bdb->sources, bap_pac_free);
-	queue_destroy(bdb->endpoints, free);
-	gatt_db_unref(bdb->db);
+	DBG(bap, "PAC(s) %u", rsp->num_pac);
 
-	free(bdb->pacs);
-	free(bdb->ascs);
-	free(bdb);
-}
+	for (i = 0; i < rsp->num_pac; i++) {
+		struct bt_bap_pac *pac;
+		struct bt_pac *p;
+		struct bt_ltv *cc;
+		struct bt_pac_metadata *meta;
+		struct iovec data, metadata;
 
-static void bap_ready_free(void *data)
-{
-	struct bt_bap_ready *ready = data;
+		p = util_iov_pull_mem(&iov, sizeof(*p));
+		if (!p) {
+			DBG(bap, "Unable to parse PAC");
+			return;
+		}
 
-	if (ready->destroy)
-		ready->destroy(ready->data);
+		if (p->codec.id == 0xff) {
+			p->codec.cid = le16_to_cpu(p->codec.cid);
+			p->codec.vid = le16_to_cpu(p->codec.vid);
+		}
 
-	free(ready);
-}
+		pac = NULL;
 
-static void bap_state_free(void *data)
-{
-	struct bt_bap_state *state = data;
+		if (!bt_bap_debug_caps(iov.iov_base, p->cc_len, bap->debug_func,
+					bap->debug_data))
+			return;
 
-	if (state->destroy)
-		state->destroy(state->data);
+		cc = util_iov_pull_mem(&iov, p->cc_len);
+		if (!cc) {
+			DBG(bap, "Unable to parse PAC codec capabilities");
+			return;
+		}
 
-	free(state);
-}
+		meta = util_iov_pull_mem(&iov, sizeof(*meta));
+		if (!meta) {
+			DBG(bap, "Unable to parse PAC metadata");
+			return;
+		}
 
-static void bap_req_free(void *data)
-{
-	struct bt_bap_req *req = data;
-	size_t i;
+		data.iov_len = p->cc_len;
+		data.iov_base = cc;
+
+		metadata.iov_len = meta->len;
+		metadata.iov_base = meta->data;
+
+		util_iov_pull_mem(&iov, meta->len);
+
+		DBG(bap, "PAC #%u: type %u codec 0x%02x cc_len %u meta_len %u",
+			i, type, p->codec.id, p->cc_len, meta->len);
+
+		/* Check if there is already a PAC record for the codec */
+		pac = bap_pac_find(bap->rdb, type, &p->codec);
+		if (pac) {
+			bap_pac_merge(pac, &data, &metadata);
+			continue;
+		}
+
+		pac = bap_pac_new(bap->rdb, NULL, type, &p->codec, NULL, &data,
+								&metadata);
+		if (!pac)
+			continue;
+
+		queue_push_tail(queue, pac);
+	}
+}
 
-	queue_destroy(req->group, bap_req_free);
+static void read_source_pac(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct bt_bap *bap = user_data;
 
-	for (i = 0; i < req->len; i++)
-		free(req->iov[i].iov_base);
+	if (!success) {
+		DBG(bap, "Unable to read Source PAC: error 0x%02x", att_ecode);
+		return;
+	}
 
-	free(req->iov);
-	free(req);
+	bap_parse_pacs(bap, BT_BAP_SOURCE, bap->rdb->sources, value, length);
 }
 
-static void bap_detached(void *data, void *user_data)
+static void read_sink_pac(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
 {
-	struct bt_bap_cb *cb = data;
 	struct bt_bap *bap = user_data;
 
-	cb->detached(bap, cb->user_data);
+	if (!success) {
+		DBG(bap, "Unable to read Sink PAC: error 0x%02x", att_ecode);
+		return;
+	}
+
+	bap_parse_pacs(bap, BT_BAP_SINK, bap->rdb->sinks, value, length);
 }
 
-static void bap_free(void *data)
+static void read_source_pac_loc(bool success, uint8_t att_ecode,
+					const uint8_t *value, uint16_t length,
+					void *user_data)
 {
-	struct bt_bap *bap = data;
+	struct bt_bap *bap = user_data;
+	struct bt_pacs *pacs = bap_get_pacs(bap);
 
-	bt_bap_detach(bap);
+	if (!success) {
+		DBG(bap, "Unable to read Source PAC Location: error 0x%02x",
+								att_ecode);
+		return;
+	}
 
-	bap_db_free(bap->rdb);
+	if (length != sizeof(uint32_t)) {
+		DBG(bap, "Invalid Source PAC Location size: %d", length);
+		return;
+	}
 
-	queue_destroy(bap->ready_cbs, bap_ready_free);
-	queue_destroy(bap->state_cbs, bap_state_free);
+	pacs->source_loc_value = get_le32(value);
 
-	queue_destroy(bap->reqs, bap_req_free);
-	queue_destroy(bap->pending, NULL);
-	queue_destroy(bap->notify, NULL);
-	queue_destroy(bap->streams, bap_stream_free);
+	/* Resume reading sinks if supported but for some reason is empty */
+	if (pacs->source && queue_isempty(bap->rdb->sources)) {
+		uint16_t value_handle;
 
-	free(bap);
+		if (gatt_db_attribute_get_char_data(pacs->source,
+						NULL, &value_handle,
+						NULL, NULL, NULL))
+			bt_gatt_client_read_value(bap->client, value_handle,
+							read_source_pac, bap,
+							NULL);
+	}
 }
 
-unsigned int bt_bap_register(bt_bap_func_t attached, bt_bap_func_t detached,
-							void *user_data)
+static void read_sink_pac_loc(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
 {
-	struct bt_bap_cb *cb;
-	static unsigned int id;
+	struct bt_bap *bap = user_data;
+	struct bt_pacs *pacs = bap_get_pacs(bap);
 
-	if (!attached && !detached)
-		return 0;
+	if (!success) {
+		DBG(bap, "Unable to read Sink PAC Location: error 0x%02x",
+								att_ecode);
+		return;
+	}
 
-	if (!bap_cbs)
-		bap_cbs = queue_new();
+	if (length != sizeof(uint32_t)) {
+		DBG(bap, "Invalid Sink PAC Location size: %d", length);
+		return;
+	}
 
-	cb = new0(struct bt_bap_cb, 1);
-	cb->id = ++id ? id : ++id;
-	cb->attached = attached;
-	cb->detached = detached;
-	cb->user_data = user_data;
+	pacs->sink_loc_value = get_le32(value);
 
-	queue_push_tail(bap_cbs, cb);
+	/* Resume reading sinks if supported but for some reason is empty */
+	if (pacs->sink && queue_isempty(bap->rdb->sinks)) {
+		uint16_t value_handle;
 
-	return cb->id;
+		if (gatt_db_attribute_get_char_data(pacs->sink,
+						NULL, &value_handle,
+						NULL, NULL, NULL))
+			bt_gatt_client_read_value(bap->client, value_handle,
+							read_sink_pac, bap,
+							NULL);
+	}
 }
 
-static bool match_id(const void *data, const void *match_data)
+static void read_pac_context(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
 {
-	const struct bt_bap_cb *cb = data;
-	unsigned int id = PTR_TO_UINT(match_data);
+	struct bt_bap *bap = user_data;
+	struct bt_pacs *pacs = bap_get_pacs(bap);
+	const struct bt_pacs_context *ctx = (void *)value;
 
-	return (cb->id == id);
+	if (!success) {
+		DBG(bap, "Unable to read PAC Context: error 0x%02x", att_ecode);
+		return;
+	}
+
+	if (length != sizeof(*ctx)) {
+		DBG(bap, "Invalid PAC Context size: %d", length);
+		return;
+	}
+
+	pacs->sink_context_value = le16_to_cpu(ctx->snk);
+	pacs->source_context_value = le16_to_cpu(ctx->src);
 }
 
-bool bt_bap_unregister(unsigned int id)
+static void read_pac_supported_context(bool success, uint8_t att_ecode,
+					const uint8_t *value, uint16_t length,
+					void *user_data)
 {
-	struct bt_bap_cb *cb;
+	struct bt_bap *bap = user_data;
+	struct bt_pacs *pacs = bap_get_pacs(bap);
+	const struct bt_pacs_context *ctx = (void *)value;
 
-	cb = queue_remove_if(bap_cbs, match_id, UINT_TO_PTR(id));
-	if (!cb)
-		return false;
+	if (!success) {
+		DBG(bap, "Unable to read PAC Supproted Context: error 0x%02x",
+								att_ecode);
+		return;
+	}
 
-	free(cb);
+	if (length != sizeof(*ctx)) {
+		DBG(bap, "Invalid PAC Supported Context size: %d", length);
+		return;
+	}
 
-	return true;
+	pacs->supported_sink_context_value = le16_to_cpu(ctx->snk);
+	pacs->supported_source_context_value = le16_to_cpu(ctx->src);
 }
 
-static void bap_attached(void *data, void *user_data)
+static void foreach_pacs_char(struct gatt_db_attribute *attr, void *user_data)
 {
-	struct bt_bap_cb *cb = data;
 	struct bt_bap *bap = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_sink, uuid_source, uuid_sink_loc, uuid_source_loc;
+	bt_uuid_t uuid_context, uuid_supported_context;
+	struct bt_pacs *pacs;
 
-	cb->attached(bap, cb->user_data);
-}
-
-struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb)
-{
-	struct bt_bap *bap;
-	struct bt_bap_db *bdb;
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
+		return;
 
-	if (!ldb)
-		return NULL;
+	bt_uuid16_create(&uuid_sink, PAC_SINK_CHRC_UUID);
+	bt_uuid16_create(&uuid_source, PAC_SOURCE_CHRC_UUID);
+	bt_uuid16_create(&uuid_sink_loc, PAC_SINK_LOC_CHRC_UUID);
+	bt_uuid16_create(&uuid_source_loc, PAC_SOURCE_LOC_CHRC_UUID);
+	bt_uuid16_create(&uuid_context, PAC_CONTEXT);
+	bt_uuid16_create(&uuid_supported_context, PAC_SUPPORTED_CONTEXT);
 
-	bdb = bap_get_db(ldb);
-	if (!bdb)
-		return NULL;
+	if (!bt_uuid_cmp(&uuid, &uuid_sink)) {
+		DBG(bap, "Sink PAC found: handle 0x%04x", value_handle);
 
-	bap = new0(struct bt_bap, 1);
-	bap->ldb = bdb;
-	bap->reqs = queue_new();
-	bap->pending = queue_new();
-	bap->notify = queue_new();
-	bap->ready_cbs = queue_new();
-	bap->streams = queue_new();
-	bap->state_cbs = queue_new();
+		pacs = bap_get_pacs(bap);
+		if (!pacs)
+			return;
 
-	if (!rdb)
-		goto done;
+		if (!pacs->sink)
+			pacs->sink = attr;
 
-	bdb = new0(struct bt_bap_db, 1);
-	bdb->db = gatt_db_ref(rdb);
-	bdb->sinks = queue_new();
-	bdb->sources = queue_new();
-	bdb->endpoints = queue_new();
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_sink_pac, bap, NULL);
+	}
 
-	bap->rdb = bdb;
+	if (!bt_uuid_cmp(&uuid, &uuid_source)) {
+		DBG(bap, "Source PAC found: handle 0x%04x", value_handle);
 
-done:
-	return bt_bap_ref(bap);
-}
+		pacs = bap_get_pacs(bap);
+		if (!pacs)
+			return;
 
-bool bt_bap_set_user_data(struct bt_bap *bap, void *user_data)
-{
-	if (!bap)
-		return false;
+		if (!pacs->source)
+			pacs->source = attr;
 
-	bap->user_data = user_data;
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_source_pac, bap, NULL);
+	}
 
-	return true;
-}
+	if (!bt_uuid_cmp(&uuid, &uuid_sink_loc)) {
+		DBG(bap, "Sink PAC Location found: handle 0x%04x",
+						value_handle);
 
-void *bt_bap_get_user_data(struct bt_bap *bap)
-{
-	if (!bap)
-		return NULL;
+		pacs = bap_get_pacs(bap);
+		if (!pacs || pacs->sink_loc)
+			return;
 
-	return bap->user_data;
-}
+		pacs->sink_loc = attr;
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_sink_pac_loc, bap, NULL);
+	}
 
-struct bt_att *bt_bap_get_att(struct bt_bap *bap)
-{
-	if (!bap)
-		return NULL;
+	if (!bt_uuid_cmp(&uuid, &uuid_source_loc)) {
+		DBG(bap, "Source PAC Location found: handle 0x%04x",
+						value_handle);
 
-	if (bap->att)
-		return bap->att;
+		pacs = bap_get_pacs(bap);
+		if (!pacs || pacs->source_loc)
+			return;
 
-	return bt_gatt_client_get_att(bap->client);
-}
+		pacs->source_loc = attr;
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_source_pac_loc, bap, NULL);
+	}
 
-struct bt_bap *bt_bap_ref(struct bt_bap *bap)
-{
-	if (!bap)
-		return NULL;
+	if (!bt_uuid_cmp(&uuid, &uuid_context)) {
+		DBG(bap, "PAC Context found: handle 0x%04x", value_handle);
 
-	__sync_fetch_and_add(&bap->ref_count, 1);
+		pacs = bap_get_pacs(bap);
+		if (!pacs || pacs->context)
+			return;
 
-	return bap;
-}
+		pacs->context = attr;
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_pac_context, bap, NULL);
+	}
 
-void bt_bap_unref(struct bt_bap *bap)
-{
-	if (!bap)
-		return;
+	if (!bt_uuid_cmp(&uuid, &uuid_supported_context)) {
+		DBG(bap, "PAC Supported Context found: handle 0x%04x",
+							value_handle);
 
-	if (__sync_sub_and_fetch(&bap->ref_count, 1))
-		return;
+		pacs = bap_get_pacs(bap);
+		if (!pacs || pacs->supported_context)
+			return;
 
-	bap_free(bap);
+		pacs->supported_context = attr;
+		bt_gatt_client_read_value(bap->client, value_handle,
+						read_pac_supported_context,
+						bap, NULL);
+	}
 }
 
-static void bap_notify_ready(struct bt_bap *bap)
+static void foreach_pacs_service(struct gatt_db_attribute *attr,
+						void *user_data)
 {
-	const struct queue_entry *entry;
+	struct bt_bap *bap = user_data;
+	struct bt_pacs *pacs = bap_get_pacs(bap);
 
-	if (!queue_isempty(bap->pending))
-		return;
+	pacs->service = attr;
 
-	bt_bap_ref(bap);
+	gatt_db_service_foreach_char(attr, foreach_pacs_char, bap);
+}
 
-	for (entry = queue_get_entries(bap->ready_cbs); entry;
-							entry = entry->next) {
-		struct bt_bap_ready *ready = entry->data;
+struct match_pac {
+	struct bt_bap_codec codec;
+	struct bt_bap_pac *lpac;
+	struct bt_bap_pac *rpac;
+	struct bt_bap_endpoint *ep;
+};
+
+static bool match_stream_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
+{
+	struct match_pac *match = user_data;
 
-		ready->func(bap, ready->data);
-	}
+	if (!bap_codec_equal(&match->codec, &lpac->codec))
+		return true;
 
-	bt_bap_unref(bap);
-}
+	match->lpac = lpac;
+	match->rpac = rpac;
 
-bool bap_print_cc(void *data, size_t len, util_debug_func_t func,
-						void *user_data)
-{
-	return bap_print_ltv("CC", data, len, func, user_data);
+	return false;
 }
 
-static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
-				struct queue *queue,
-				const uint8_t *value,
-				uint16_t len)
+static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep,
+							struct iovec *iov)
 {
-	struct bt_pacs_read_rsp *rsp;
-	struct iovec iov = {
-		.iov_base = (void *) value,
-		.iov_len = len,
-	};
+	struct bt_ascs_ase_status_config *cfg;
+	struct bt_ltv *cc;
+	uint32_t pd_min, pd_max, ppd_min, ppd_max;
 	int i;
 
-	rsp = iov_pull_mem(&iov, sizeof(*rsp));
-	if (!rsp) {
-		DBG(bap, "Unable to parse PAC");
+	cfg = util_iov_pull_mem(iov, sizeof(*cfg));
+	if (!cfg) {
+		DBG(bap, "Unable to parse Config Status");
 		return;
 	}
 
-	DBG(bap, "PAC(s) %u", rsp->num_pac);
-
-	for (i = 0; i < rsp->num_pac; i++) {
-		struct bt_bap_pac *pac;
-		struct bt_pac *p;
-		struct bt_ltv *cc;
-		struct bt_pac_metadata *meta;
-		struct iovec data, metadata;
+	pd_min = get_le24(cfg->pd_min);
+	pd_max = get_le24(cfg->pd_max);
+	ppd_min = get_le24(cfg->ppd_min);
+	ppd_max = get_le24(cfg->ppd_max);
 
-		p = iov_pull_mem(&iov, sizeof(*p));
-		if (!p) {
-			DBG(bap, "Unable to parse PAC");
-			return;
-		}
+	DBG(bap, "codec 0x%02x framing 0x%02x phy 0x%02x rtn %u "
+			"latency %u pd %u - %u ppd %u - %u", cfg->codec.id,
+			cfg->framing, cfg->phy, cfg->rtn,
+			le16_to_cpu(cfg->latency),
+			pd_min, pd_max, ppd_min, ppd_max);
 
-		pac = NULL;
+	if (iov->iov_len < cfg->cc_len) {
+		DBG(bap, "Unable to parse Config Status: len %zu < %u cc_len",
+						iov->iov_len, cfg->cc_len);
+		return;
+	}
 
-		if (!bap_print_cc(iov.iov_base, p->cc_len, bap->debug_func,
-					bap->debug_data))
-			return;
+	for (i = 0; iov->iov_len >= sizeof(*cc); i++) {
+		cc = util_iov_pull_mem(iov, sizeof(*cc));
+		if (!cc)
+			break;
 
-		cc = iov_pull_mem(&iov, p->cc_len);
-		if (!cc) {
-			DBG(bap, "Unable to parse PAC codec capabilities");
-			return;
-		}
+		DBG(bap, "Codec Config #%u: type 0x%02x len %u", i,
+						cc->type, cc->len);
 
-		meta = iov_pull_mem(&iov, sizeof(*meta));
-		if (!meta) {
-			DBG(bap, "Unable to parse PAC metadata");
-			return;
-		}
+		util_iov_pull_mem(iov, cc->len - 1);
+	}
 
-		data.iov_len = p->cc_len;
-		data.iov_base = cc;
+	/* Any previously applied codec configuration may be cached by the
+	 * server.
+	 */
+	if (!ep->stream) {
+		struct match_pac match;
 
-		metadata.iov_len = meta->len;
-		metadata.iov_base = meta->data;
+		match.lpac = NULL;
+		match.rpac = NULL;
+		match.codec.id = cfg->codec.id;
+		match.codec.cid = le16_to_cpu(cfg->codec.cid);
+		match.codec.vid = le16_to_cpu(cfg->codec.vid);
 
-		iov_pull_mem(&iov, meta->len);
+		bt_bap_foreach_pac(bap, ep->dir, match_stream_pac, &match);
+		if (!match.lpac || !match.rpac)
+			return;
 
-		pac = bap_pac_new(bap->rdb, NULL, type, &p->codec, NULL, &data,
-								&metadata);
-		if (!pac)
-			continue;
+		bap_stream_new(bap, ep, match.lpac, match.rpac, NULL, true);
+	}
 
-		DBG(bap, "PAC #%u: type %u codec 0x%02x cc_len %u meta_len %u",
-			i, type, p->codec.id, p->cc_len, meta->len);
+	if (!ep->stream)
+		return;
 
-		queue_push_tail(queue, pac);
+	/* Set preferred settings */
+	if (ep->stream->rpac) {
+		ep->stream->rpac->qos.framing = cfg->framing;
+		ep->stream->rpac->qos.phy = cfg->phy;
+		ep->stream->rpac->qos.rtn = cfg->rtn;
+		ep->stream->rpac->qos.latency = le16_to_cpu(cfg->latency);
+		ep->stream->rpac->qos.pd_min = pd_min;
+		ep->stream->rpac->qos.pd_max = pd_max;
+		ep->stream->rpac->qos.ppd_min = ppd_min;
+		ep->stream->rpac->qos.ppd_max = ppd_max;
 	}
+
+	if (!ep->stream->cc)
+		ep->stream->cc = new0(struct iovec, 1);
+
+	util_iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len);
 }
 
-static void read_source_pac(struct bt_bap *bap, bool success, uint8_t att_ecode,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
+static void bap_stream_config_cfm_cb(struct bt_bap_stream *stream, int err)
 {
-	if (!success) {
-		DBG(bap, "Unable to read Source PAC: error 0x%02x", att_ecode);
+	struct bt_bap *bap = stream->bap;
+
+	if (err) {
+		DBG(bap, "Config Confirmation failed: %d", err);
+		bt_bap_stream_release(stream, NULL, NULL);
 		return;
 	}
-
-	bap_parse_pacs(bap, BT_BAP_SOURCE, bap->rdb->sources, value, length);
 }
 
-static void read_sink_pac(struct bt_bap *bap, bool success, uint8_t att_ecode,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
+static void bap_stream_config_cfm(struct bt_bap_stream *stream)
 {
-	if (!success) {
-		DBG(bap, "Unable to read Sink PAC: error 0x%02x", att_ecode);
+	int err;
+
+	if (!stream->lpac->ops || !stream->lpac->ops->config)
 		return;
-	}
 
-	bap_parse_pacs(bap, BT_BAP_SINK, bap->rdb->sinks, value, length);
+	err = stream->lpac->ops->config(stream, stream->cc, &stream->qos,
+					bap_stream_config_cfm_cb,
+					stream->lpac->user_data);
+	if (err < 0) {
+		DBG(stream->bap, "Unable to send Config Confirmation: %d",
+									err);
+		bt_bap_stream_release(stream, NULL, NULL);
+	}
 }
 
-static void read_source_pac_loc(struct bt_bap *bap, bool success,
-				uint8_t att_ecode, const uint8_t *value,
-				uint16_t length, void *user_data)
+static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
+							struct iovec *iov)
 {
-	struct bt_pacs *pacs = bap_get_pacs(bap);
+	struct bt_ascs_ase_status_qos *qos;
+	uint32_t interval;
+	uint32_t pd;
+	uint16_t sdu;
+	uint16_t latency;
 
-	if (!success) {
-		DBG(bap, "Unable to read Source PAC Location: error 0x%02x",
-								att_ecode);
+	qos = util_iov_pull_mem(iov, sizeof(*qos));
+	if (!qos) {
+		DBG(bap, "Unable to parse QoS Status");
 		return;
 	}
 
-	gatt_db_attribute_write(pacs->source_loc, 0, value, length, 0, NULL,
-							NULL, NULL);
+	interval = get_le24(qos->interval);
+	pd = get_le24(qos->pd);
+	sdu = le16_to_cpu(qos->sdu);
+	latency = le16_to_cpu(qos->latency);
+
+	DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
+			"phy 0x%02x rtn %u latency %u pd %u", qos->cig_id,
+			qos->cis_id, interval, qos->framing, qos->phy,
+			qos->rtn, latency, pd);
+
+	if (!ep->stream)
+		return;
+
+	ep->stream->qos.ucast.io_qos.interval = interval;
+	ep->stream->qos.ucast.framing = qos->framing;
+	ep->stream->qos.ucast.io_qos.phy = qos->phy;
+	ep->stream->qos.ucast.io_qos.sdu = sdu;
+	ep->stream->qos.ucast.io_qos.rtn = qos->rtn;
+	ep->stream->qos.ucast.io_qos.latency = latency;
+	ep->stream->qos.ucast.delay = pd;
+
+	if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG)
+		bap_stream_config_cfm(ep->stream);
 }
 
-static void read_sink_pac_loc(struct bt_bap *bap, bool success,
-				uint8_t att_ecode, const uint8_t *value,
-				uint16_t length, void *user_data)
+static void ep_status_metadata(struct bt_bap *bap, struct bt_bap_endpoint *ep,
+							struct iovec *iov)
 {
-	struct bt_pacs *pacs = bap_get_pacs(bap);
+	struct bt_ascs_ase_status_metadata *meta;
 
-	if (!success) {
-		DBG(bap, "Unable to read Sink PAC Location: error 0x%02x",
-								att_ecode);
+	meta = util_iov_pull_mem(iov, sizeof(*meta));
+	if (!meta) {
+		DBG(bap, "Unable to parse Metadata Status");
 		return;
 	}
 
-	gatt_db_attribute_write(pacs->sink_loc, 0, value, length, 0, NULL,
-							NULL, NULL);
+	DBG(bap, "CIS 0x%02x CIG 0x%02x metadata len %u",
+			meta->cis_id, meta->cig_id, meta->len);
 }
 
-static void read_pac_context(struct bt_bap *bap, bool success,
-				uint8_t att_ecode, const uint8_t *value,
-				uint16_t length, void *user_data)
+static void bap_ep_set_status(struct bt_bap *bap, struct bt_bap_endpoint *ep,
+					const uint8_t *value, uint16_t length)
 {
-	struct bt_pacs *pacs = bap_get_pacs(bap);
+	struct bt_ascs_ase_status *rsp;
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = length,
+	};
 
-	if (!success) {
-		DBG(bap, "Unable to read PAC Context: error 0x%02x", att_ecode);
+	rsp = util_iov_pull_mem(&iov, sizeof(*rsp));
+	if (!rsp)
 		return;
+
+	ep->id = rsp->id;
+	ep->old_state = ep->state;
+	ep->state = rsp->state;
+
+	DBG(bap, "ASE status: ep %p id 0x%02x handle 0x%04x state %s "
+			"len %zu", ep, ep->id,
+			gatt_db_attribute_get_handle(ep->attr),
+			bt_bap_stream_statestr(ep->state), iov.iov_len);
+
+	switch (ep->state) {
+	case BT_ASCS_ASE_STATE_IDLE:
+		break;
+	case BT_ASCS_ASE_STATE_CONFIG:
+		ep_status_config(bap, ep, &iov);
+		break;
+	case BT_ASCS_ASE_STATE_QOS:
+		ep_status_qos(bap, ep, &iov);
+		break;
+	case BT_ASCS_ASE_STATE_ENABLING:
+	case BT_ASCS_ASE_STATE_STREAMING:
+	case BT_ASCS_ASE_STATE_DISABLING:
+		ep_status_metadata(bap, ep, &iov);
+		break;
+	case BT_ASCS_ASE_STATE_RELEASING:
+		break;
 	}
 
-	gatt_db_attribute_write(pacs->context, 0, value, length, 0, NULL,
-							NULL, NULL);
+	/* Only notifify if there is a stream */
+	if (!ep->stream)
+		return;
+
+	bap_stream_state_changed(ep->stream);
 }
 
-static void read_pac_supported_context(struct bt_bap *bap, bool success,
-					uint8_t att_ecode, const uint8_t *value,
-					uint16_t length, void *user_data)
+static void read_ase_status(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
 {
-	struct bt_pacs *pacs = bap_get_pacs(bap);
+	struct bt_bap_endpoint *ep = user_data;
+	struct bt_bap *bap = ep->bap;
 
 	if (!success) {
-		DBG(bap, "Unable to read PAC Supproted Context: error 0x%02x",
-								att_ecode);
+		DBG(bap, "ASE read status failed: 0x%04x", att_ecode);
 		return;
 	}
 
-	gatt_db_attribute_write(pacs->supported_context, 0, value, length, 0,
-							NULL, NULL, NULL);
+	bap_ep_set_status(bap, ep, value, length);
+}
+
+static void bap_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_bap_notify *notify = user_data;
+
+	if (att_ecode)
+		DBG(notify->bap, "ASE register failed: 0x%04x", att_ecode);
 }
 
-static void bap_pending_destroy(void *data)
+static void bap_endpoint_notify(struct bt_bap *bap, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
 {
-	struct bt_bap_pending *pending = data;
-	struct bt_bap *bap = pending->bap;
+	struct bt_bap_endpoint *ep = user_data;
+
+	bap_ep_set_status(bap, ep, value, length);
+}
 
-	if (queue_remove_if(bap->pending, NULL, pending))
-		free(pending);
+static void bap_notify(uint16_t value_handle, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_bap_notify *notify = user_data;
 
-	bap_notify_ready(bap);
+	if (notify->func)
+		notify->func(notify->bap, value_handle, value, length,
+						notify->user_data);
 }
 
-static void bap_pending_complete(bool success, uint8_t att_ecode,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
+static void bap_notify_destroy(void *data)
 {
-	struct bt_bap_pending *pending = user_data;
+	struct bt_bap_notify *notify = data;
+	struct bt_bap *bap = notify->bap;
 
-	if (pending->func)
-		pending->func(pending->bap, success, att_ecode, value, length,
-						pending->user_data);
+	if (queue_remove_if(bap->notify, NULL, notify))
+		free(notify);
 }
 
-static void bap_read_value(struct bt_bap *bap, uint16_t value_handle,
-				bap_func_t func, void *user_data)
+static unsigned int bap_register_notify(struct bt_bap *bap,
+					uint16_t value_handle,
+					bap_notify_t func,
+					void *user_data)
 {
-	struct bt_bap_pending *pending;
+	struct bt_bap_notify *notify;
 
-	pending = new0(struct bt_bap_pending, 1);
-	pending->bap = bap;
-	pending->func = func;
-	pending->user_data = user_data;
+	notify = new0(struct bt_bap_notify, 1);
+	notify->bap = bap;
+	notify->func = func;
+	notify->user_data = user_data;
 
-	pending->id = bt_gatt_client_read_value(bap->client, value_handle,
-						bap_pending_complete, pending,
-						bap_pending_destroy);
-	if (!pending->id) {
-		DBG(bap, "Unable to send Read request");
-		free(pending);
-		return;
+	notify->id = bt_gatt_client_register_notify(bap->client,
+						value_handle, bap_register,
+						bap_notify, notify,
+						bap_notify_destroy);
+	if (!notify->id) {
+		DBG(bap, "Unable to register for notifications");
+		free(notify);
+		return 0;
 	}
 
-	queue_push_tail(bap->pending, pending);
+	queue_push_tail(bap->notify, notify);
+
+	return notify->id;
 }
 
-static void foreach_pacs_char(struct gatt_db_attribute *attr, void *user_data)
+static void bap_endpoint_attach(struct bt_bap *bap, struct bt_bap_endpoint *ep)
 {
-	struct bt_bap *bap = user_data;
 	uint16_t value_handle;
-	bt_uuid_t uuid, uuid_sink, uuid_source, uuid_sink_loc, uuid_source_loc;
-	bt_uuid_t uuid_context, uuid_supported_context;
-	struct bt_pacs *pacs;
 
-	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
-						NULL, NULL, &uuid))
+	if (!gatt_db_attribute_get_char_data(ep->attr, NULL, &value_handle,
+						NULL, NULL, NULL))
 		return;
 
-	bt_uuid16_create(&uuid_sink, PAC_SINK_CHRC_UUID);
-	bt_uuid16_create(&uuid_source, PAC_SOURCE_CHRC_UUID);
-	bt_uuid16_create(&uuid_sink_loc, PAC_SINK_LOC_CHRC_UUID);
-	bt_uuid16_create(&uuid_source_loc, PAC_SOURCE_LOC_CHRC_UUID);
-	bt_uuid16_create(&uuid_context, PAC_CONTEXT);
-	bt_uuid16_create(&uuid_supported_context, PAC_SUPPORTED_CONTEXT);
-
-	if (!bt_uuid_cmp(&uuid, &uuid_sink)) {
-		DBG(bap, "Sink PAC found: handle 0x%04x", value_handle);
-
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->sink)
-			return;
+	DBG(bap, "ASE handle 0x%04x", value_handle);
 
-		pacs->sink = attr;
-		bap_read_value(bap, value_handle, read_sink_pac, bap);
-	}
+	ep->bap = bap;
 
-	if (!bt_uuid_cmp(&uuid, &uuid_source)) {
-		DBG(bap, "Source PAC found: handle 0x%04x", value_handle);
+	bt_gatt_client_read_value(bap->client, value_handle, read_ase_status,
+					ep, NULL);
 
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->source)
-			return;
+	ep->state_id = bap_register_notify(bap, value_handle,
+						bap_endpoint_notify, ep);
+}
 
-		pacs->source = attr;
-		bap_read_value(bap, value_handle, read_source_pac, NULL);
-	}
+static void bap_cp_notify(struct bt_bap *bap, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	const struct bt_ascs_cp_rsp *rsp = (void *)value;
+	const struct bt_ascs_ase_rsp *ase_rsp = NULL;
+	struct bt_bap_req *req;
+	int i;
 
-	if (!bt_uuid_cmp(&uuid, &uuid_sink_loc)) {
-		DBG(bap, "Sink PAC Location found: handle 0x%04x",
-						value_handle);
+	if (!bap->req)
+		return;
 
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->sink_loc)
-			return;
+	req = bap->req;
+	bap->req = NULL;
 
-		pacs->sink_loc = attr;
-		bap_read_value(bap, value_handle, read_sink_pac_loc, NULL);
+	if (length < sizeof(*rsp)) {
+		DBG(bap, "Invalid ASE CP notification: length %u < %zu",
+						length, sizeof(*rsp));
+		goto done;
 	}
 
-	if (!bt_uuid_cmp(&uuid, &uuid_source_loc)) {
-		DBG(bap, "Source PAC Location found: handle 0x%04x",
-						value_handle);
-
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->source_loc)
-			return;
-
-		pacs->source_loc = attr;
-		bap_read_value(bap, value_handle, read_source_pac_loc, NULL);
+	if (rsp->op != req->op) {
+		DBG(bap, "Invalid ASE CP notification: op 0x%02x != 0x%02x",
+						rsp->op, req->op);
+		goto done;
 	}
 
-	if (!bt_uuid_cmp(&uuid, &uuid_context)) {
-		DBG(bap, "PAC Context found: handle 0x%04x", value_handle);
-
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->context)
-			return;
+	length -= sizeof(*rsp);
 
-		pacs->context = attr;
-		bap_read_value(bap, value_handle, read_pac_context, NULL);
+	if (rsp->num_ase == 0xff) {
+		ase_rsp = rsp->rsp;
+		goto done;
 	}
 
-	if (!bt_uuid_cmp(&uuid, &uuid_supported_context)) {
-		DBG(bap, "PAC Supported Context found: handle 0x%04x",
-							value_handle);
-
-		pacs = bap_get_pacs(bap);
-		if (!pacs || pacs->supported_context)
-			return;
+	for (i = 0; i < rsp->num_ase; i++) {
+		if (length < sizeof(*ase_rsp)) {
+			DBG(bap, "Invalid ASE CP notification: length %u < %zu",
+					length, sizeof(*ase_rsp));
+			goto done;
+		}
 
-		pacs->supported_context = attr;
-		bap_read_value(bap, value_handle, read_pac_supported_context,
-									NULL);
+		ase_rsp = &rsp->rsp[i];
 	}
-}
-
-static void foreach_pacs_service(struct gatt_db_attribute *attr,
-						void *user_data)
-{
-	struct bt_bap *bap = user_data;
-	struct bt_pacs *pacs = bap_get_pacs(bap);
-
-	pacs->service = attr;
 
-	gatt_db_service_foreach_char(attr, foreach_pacs_char, bap);
+done:
+	bap_req_complete(req, ase_rsp);
+	bap_process_queue(bap);
 }
 
-struct match_pac {
-	struct bt_bap_codec codec;
-	struct bt_bap_pac *lpac;
-	struct bt_bap_pac *rpac;
-	struct bt_bap_endpoint *ep;
-};
-
-static bool match_stream_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-							void *user_data)
+static void bap_cp_attach(struct bt_bap *bap)
 {
-	struct match_pac *match = user_data;
+	uint16_t value_handle;
+	struct bt_ascs *ascs = bap_get_ascs(bap);
 
-	if (!bap_codec_equal(&match->codec, &lpac->codec))
-		return true;
+	if (!gatt_db_attribute_get_char_data(ascs->ase_cp, NULL,
+						&value_handle,
+						NULL, NULL, NULL))
+		return;
 
-	match->lpac = lpac;
-	match->rpac = rpac;
+	DBG(bap, "ASE CP handle 0x%04x", value_handle);
 
-	return false;
+	bap->cp_id = bap_register_notify(bap, value_handle, bap_cp_notify,
+								NULL);
 }
 
-static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep,
-							struct iovec *iov)
+static void foreach_ascs_char(struct gatt_db_attribute *attr, void *user_data)
 {
-	struct bt_ascs_ase_status_config *cfg;
-	struct bt_ltv *cc;
-	uint32_t pd_min, pd_max, ppd_min, ppd_max;
-	int i;
+	struct bt_bap *bap = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_sink, uuid_source, uuid_cp;
+	struct bt_ascs *ascs;
 
-	cfg = iov_pull_mem(iov, sizeof(*cfg));
-	if (!cfg) {
-		DBG(bap, "Unable to parse Config Status");
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
 		return;
-	}
 
-	pd_min = get_le24(cfg->pd_min);
-	pd_max = get_le24(cfg->pd_max);
-	ppd_min = get_le24(cfg->ppd_min);
-	ppd_max = get_le24(cfg->ppd_max);
+	bt_uuid16_create(&uuid_sink, ASE_SINK_UUID);
+	bt_uuid16_create(&uuid_source, ASE_SOURCE_UUID);
+	bt_uuid16_create(&uuid_cp, ASE_CP_UUID);
 
-	DBG(bap, "codec 0x%02x framing 0x%02x phy 0x%02x rtn %u "
-			"latency %u pd %u - %u ppd %u - %u", cfg->codec.id,
-			cfg->framing, cfg->phy, cfg->rtn,
-			le16_to_cpu(cfg->latency),
-			pd_min, pd_max, ppd_min, ppd_max);
+	if (!bt_uuid_cmp(&uuid, &uuid_sink) ||
+			!bt_uuid_cmp(&uuid, &uuid_source)) {
+		struct bt_bap_endpoint *ep;
 
-	if (iov->iov_len < cfg->cc_len) {
-		DBG(bap, "Unable to parse Config Status: len %zu < %u cc_len",
-						iov->iov_len, cfg->cc_len);
-		return;
-	}
+		ep = bap_get_endpoint(bap->remote_eps, bap->rdb, attr);
+		if (!ep)
+			return;
 
-	for (i = 0; iov->iov_len >= sizeof(*cc); i++) {
-		cc = iov_pull_mem(iov, sizeof(*cc));
-		if (!cc)
-			break;
+		if (!bt_uuid_cmp(&uuid, &uuid_sink))
+			DBG(bap, "ASE Sink found: handle 0x%04x", value_handle);
+		else
+			DBG(bap, "ASE Source found: handle 0x%04x",
+							value_handle);
 
-		DBG(bap, "Codec Config #%u: type 0x%02x len %u", i,
-						cc->type, cc->len);
+		bap_endpoint_attach(bap, ep);
 
-		iov_pull_mem(iov, cc->len - 1);
+		return;
 	}
 
-	/* Any previously applied codec configuration may be cached by the
-	 * server.
-	 */
-	if (!ep->stream) {
-		struct match_pac match;
+	if (!bt_uuid_cmp(&uuid, &uuid_cp)) {
+		ascs = bap_get_ascs(bap);
+		if (!ascs || ascs->ase_cp)
+			return;
 
-		match.lpac = NULL;
-		match.rpac = NULL;
-		match.codec.id = cfg->codec.id;
-		match.codec.cid = le16_to_cpu(cfg->codec.cid);
-		match.codec.vid = le16_to_cpu(cfg->codec.vid);
+		ascs->ase_cp = attr;
 
-		bt_bap_foreach_pac(bap, ep->dir, match_stream_pac, &match);
-		if (!match.lpac || !match.rpac)
-			return;
+		DBG(bap, "ASE Control Point found: handle 0x%04x",
+							value_handle);
 
-		bap_stream_new(bap, ep, match.lpac, match.rpac, NULL, true);
+		bap_cp_attach(bap);
 	}
+}
 
-	if (!ep->stream)
-		return;
+static void foreach_ascs_service(struct gatt_db_attribute *attr,
+						void *user_data)
+{
+	struct bt_bap *bap = user_data;
+	struct bt_ascs *ascs = bap_get_ascs(bap);
 
-	/* Set preferred settings */
-	if (ep->stream->rpac) {
-		ep->stream->rpac->qos.framing = cfg->framing;
-		ep->stream->rpac->qos.phy = cfg->phy;
-		ep->stream->rpac->qos.rtn = cfg->rtn;
-		ep->stream->rpac->qos.latency = le16_to_cpu(cfg->latency);
-		ep->stream->rpac->qos.pd_min = pd_min;
-		ep->stream->rpac->qos.pd_max = pd_max;
-		ep->stream->rpac->qos.ppd_min = ppd_min;
-		ep->stream->rpac->qos.ppd_max = ppd_max;
-	}
+	ascs->service = attr;
 
-	if (!ep->stream->cc)
-		ep->stream->cc = new0(struct iovec, 1);
+	gatt_db_service_set_claimed(attr, true);
 
-	iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len);
+	gatt_db_service_foreach_char(attr, foreach_ascs_char, bap);
 }
 
-static void bap_stream_config_cfm_cb(struct bt_bap_stream *stream, int err)
+static void bap_endpoint_foreach(void *data, void *user_data)
 {
-	struct bt_bap *bap = stream->bap;
+	struct bt_bap_endpoint *ep = data;
+	struct bt_bap *bap = user_data;
 
-	if (err) {
-		DBG(bap, "Config Confirmation failed: %d", err);
-		bt_bap_stream_release(stream, NULL, NULL);
-		return;
+	bap_endpoint_attach(bap, ep);
+}
+
+static void bap_attach_att(struct bt_bap *bap, struct bt_att *att)
+{
+	if (bap->disconn_id) {
+		if (att == bt_bap_get_att(bap))
+			return;
+		bt_att_unregister_disconnect(bap->att, bap->disconn_id);
 	}
+
+	bap->disconn_id = bt_att_register_disconnect(bap->att,
+							bap_disconnected,
+							bap, NULL);
 }
 
-static void bap_stream_config_cfm(struct bt_bap_stream *stream)
+static void bap_idle(void *data)
 {
-	int err;
+	struct bt_bap *bap = data;
 
-	if (!stream->lpac->ops || !stream->lpac->ops->config)
-		return;
+	bap->idle_id = 0;
 
-	err = stream->lpac->ops->config(stream, stream->cc, &stream->qos,
-					bap_stream_config_cfm_cb,
-					stream->lpac->user_data);
-	if (err < 0) {
-		DBG(stream->bap, "Unable to send Config Confirmation: %d",
-									err);
-		bt_bap_stream_release(stream, NULL, NULL);
-	}
+	bap_notify_ready(bap);
 }
 
-static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
-							struct iovec *iov)
+bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
 {
-	struct bt_ascs_ase_status_qos *qos;
-	uint32_t interval;
-	uint32_t pd;
-	uint16_t sdu;
-	uint16_t latency;
+	bt_uuid_t uuid;
 
-	qos = iov_pull_mem(iov, sizeof(*qos));
-	if (!qos) {
-		DBG(bap, "Unable to parse QoS Status");
-		return;
+	if (queue_find(sessions, NULL, bap)) {
+		/* If instance already been set but there is no client proceed
+		 * to clone it otherwise considered it already attached.
+		 */
+		if (client && !bap->client)
+			goto clone;
+		return true;
 	}
 
-	interval = get_le24(qos->interval);
-	pd = get_le24(qos->pd);
-	sdu = le16_to_cpu(qos->sdu);
-	latency = le16_to_cpu(qos->latency);
+	if (!sessions)
+		sessions = queue_new();
 
-	DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
-			"phy 0x%02x rtn %u latency %u pd %u", qos->cig_id,
-			qos->cis_id, interval, qos->framing, qos->phy,
-			qos->rtn, latency, pd);
+	queue_push_tail(sessions, bap);
 
-	if (!ep->stream)
-		return;
+	queue_foreach(bap_cbs, bap_attached, bap);
 
-	ep->stream->qos.interval = interval;
-	ep->stream->qos.framing = qos->framing;
-	ep->stream->qos.phy = qos->phy;
-	ep->stream->qos.sdu = sdu;
-	ep->stream->qos.rtn = qos->rtn;
-	ep->stream->qos.latency = latency;
-	ep->stream->qos.delay = pd;
+	if (!client) {
+		if (bap->att)
+			bap_attach_att(bap, bap->att);
+		return true;
+	}
 
-	if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG)
-		bap_stream_config_cfm(ep->stream);
-}
+	if (bap->client)
+		return false;
 
-static void ep_status_metadata(struct bt_bap *bap, struct bt_bap_endpoint *ep,
-							struct iovec *iov)
-{
-	struct bt_ascs_ase_status_metadata *meta;
+clone:
+	bap->client = bt_gatt_client_clone(client);
+	if (!bap->client)
+		return false;
 
-	meta = iov_pull_mem(iov, sizeof(*meta));
-	if (!meta) {
-		DBG(bap, "Unable to parse Metadata Status");
-		return;
-	}
+	bap_attach_att(bap, bt_gatt_client_get_att(client));
 
-	DBG(bap, "CIS 0x%02x CIG 0x%02x metadata len %u",
-			meta->cis_id, meta->cig_id, meta->len);
-}
+	bap->idle_id = bt_gatt_client_idle_register(bap->client, bap_idle,
+								bap, NULL);
 
-static void bap_ep_set_status(struct bt_bap *bap, struct bt_bap_endpoint *ep,
-					const uint8_t *value, uint16_t length)
-{
-	struct bt_ascs_ase_status *rsp;
-	struct iovec iov = {
-		.iov_base = (void *) value,
-		.iov_len = length,
-	};
+	if (bap->rdb->pacs) {
+		uint16_t value_handle;
+		struct bt_pacs *pacs = bap->rdb->pacs;
 
-	rsp = iov_pull_mem(&iov, sizeof(*rsp));
-	if (!rsp)
-		return;
+		/* Resume reading sinks if supported */
+		if (pacs->sink && queue_isempty(bap->rdb->sinks)) {
+			if (gatt_db_attribute_get_char_data(pacs->sink,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+							value_handle,
+							read_sink_pac,
+							bap, NULL);
+			}
+		}
 
-	ep->id = rsp->id;
-	ep->old_state = ep->state;
-	ep->state = rsp->state;
+		/* Resume reading sink locations if supported */
+		if (pacs->sink && pacs->sink_loc && !pacs->sink_loc_value) {
+			if (gatt_db_attribute_get_char_data(pacs->sink_loc,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+							value_handle,
+							read_sink_pac_loc,
+							bap, NULL);
+			}
+		}
 
-	DBG(bap, "ASE status: ep %p id 0x%02x handle 0x%04x state %s "
-			"len %zu", ep, ep->id,
-			gatt_db_attribute_get_handle(ep->attr),
-			bt_bap_stream_statestr(ep->state), iov.iov_len);
+		/* Resume reading sources if supported */
+		if (pacs->source && queue_isempty(bap->rdb->sources)) {
+			if (gatt_db_attribute_get_char_data(pacs->source,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+							value_handle,
+							read_source_pac,
+							bap, NULL);
+			}
+		}
 
-	switch (ep->state) {
-	case BT_ASCS_ASE_STATE_IDLE:
-		break;
-	case BT_ASCS_ASE_STATE_CONFIG:
-		ep_status_config(bap, ep, &iov);
-		break;
-	case BT_ASCS_ASE_STATE_QOS:
-		ep_status_qos(bap, ep, &iov);
-		break;
-	case BT_ASCS_ASE_STATE_ENABLING:
-	case BT_ASCS_ASE_STATE_STREAMING:
-	case BT_ASCS_ASE_STATE_DISABLING:
-		ep_status_metadata(bap, ep, &iov);
-		break;
-	case BT_ASCS_ASE_STATE_RELEASING:
-		break;
-	}
+		/* Resume reading source locations if supported */
+		if (pacs->source && pacs->source_loc &&
+				!pacs->source_loc_value) {
+			if (gatt_db_attribute_get_char_data(pacs->source_loc,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+							value_handle,
+							read_source_pac_loc,
+							bap, NULL);
+			}
+		}
 
-	/* Only notifify if there is a stream */
-	if (!ep->stream)
-		return;
+		/* Resume reading supported contexts if supported */
+		if (pacs->sink && pacs->supported_context &&
+				!pacs->supported_sink_context_value &&
+				!pacs->supported_source_context_value) {
+			if (gatt_db_attribute_get_char_data(
+							pacs->supported_context,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+						value_handle,
+						read_pac_supported_context,
+						bap, NULL);
+			}
+		}
 
-	bap_stream_state_changed(ep->stream);
-}
+		/* Resume reading contexts if supported */
+		if (pacs->sink && pacs->context &&
+				!pacs->sink_context_value &&
+				!pacs->source_context_value) {
+			if (gatt_db_attribute_get_char_data(pacs->context,
+							NULL, &value_handle,
+							NULL, NULL, NULL)) {
+				bt_gatt_client_read_value(bap->client,
+							value_handle,
+							read_pac_context,
+							bap, NULL);
+			}
+		}
 
-static void read_ase_status(struct bt_bap *bap, bool success, uint8_t att_ecode,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
-{
-	struct bt_bap_endpoint *ep = user_data;
+		queue_foreach(bap->remote_eps, bap_endpoint_foreach, bap);
 
-	if (!success)
-		return;
+		bap_cp_attach(bap);
 
-	bap_ep_set_status(bap, ep, value, length);
-}
+		return true;
+	}
 
-static void bap_register(uint16_t att_ecode, void *user_data)
-{
-	struct bt_bap_notify *notify = user_data;
+	bt_uuid16_create(&uuid, PACS_UUID);
+	gatt_db_foreach_service(bap->rdb->db, &uuid, foreach_pacs_service, bap);
 
-	if (att_ecode)
-		DBG(notify->bap, "ASE register failed: 0x%04x", att_ecode);
+	bt_uuid16_create(&uuid, ASCS_UUID);
+	gatt_db_foreach_service(bap->rdb->db, &uuid, foreach_ascs_service, bap);
+
+	return true;
 }
 
-static void bap_endpoint_notify(struct bt_bap *bap, uint16_t value_handle,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
+bool bt_bap_attach_broadcast(struct bt_bap *bap)
 {
-	struct bt_bap_endpoint *ep = user_data;
+	struct bt_bap_endpoint *ep;
 
-	bap_ep_set_status(bap, ep, value, length);
+	if (queue_find(sessions, NULL, bap))
+		return true;
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, bap);
+
+	ep = bap_get_endpoint_bcast(bap->remote_eps, bap->ldb,
+				BT_BAP_BCAST_SOURCE);
+	if (ep)
+		ep->bap = bap;
+
+	return true;
 }
 
-static void bap_notify(uint16_t value_handle, const uint8_t *value,
-				uint16_t length, void *user_data)
+static void stream_foreach_detach(void *data, void *user_data)
 {
-	struct bt_bap_notify *notify = user_data;
+	struct bt_bap_stream *stream = data;
 
-	if (notify->func)
-		notify->func(notify->bap, value_handle, value, length,
-						notify->user_data);
+	stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
 }
 
-static void bap_notify_destroy(void *data)
+static void bap_req_detach(void *data)
 {
-	struct bt_bap_notify *notify = data;
-	struct bt_bap *bap = notify->bap;
+	struct bt_bap_req *req = data;
 
-	if (queue_remove_if(bap->notify, NULL, notify))
-		free(notify);
+	bap_req_complete(req, NULL);
 }
 
-static unsigned int bap_register_notify(struct bt_bap *bap,
-					uint16_t value_handle,
-					bap_notify_t func,
-					void *user_data)
+void bt_bap_detach(struct bt_bap *bap)
 {
-	struct bt_bap_notify *notify;
+	DBG(bap, "%p", bap);
 
-	notify = new0(struct bt_bap_notify, 1);
-	notify->bap = bap;
-	notify->func = func;
-	notify->user_data = user_data;
+	if (!queue_remove(sessions, bap))
+		return;
 
-	notify->id = bt_gatt_client_register_notify(bap->client,
-						value_handle, bap_register,
-						bap_notify, notify,
-						bap_notify_destroy);
-	if (!notify->id) {
-		DBG(bap, "Unable to register for notifications");
-		free(notify);
-		return 0;
+	/* Cancel ongoing request */
+	if (bap->req) {
+		bap_req_detach(bap->req);
+		bap->req = NULL;
 	}
 
-	queue_push_tail(bap->notify, notify);
+	bt_gatt_client_idle_unregister(bap->client, bap->idle_id);
 
-	return notify->id;
+	/* Cancel queued requests */
+	queue_remove_all(bap->reqs, NULL, NULL, bap_req_detach);
+
+	bt_gatt_client_unref(bap->client);
+	bap->client = NULL;
+
+	bt_att_unregister_disconnect(bap->att, bap->disconn_id);
+	bap->att = NULL;
+
+	queue_foreach(bap->streams, stream_foreach_detach, bap);
+	queue_foreach(bap_cbs, bap_detached, bap);
 }
 
-static void bap_endpoint_attach(struct bt_bap *bap, struct bt_bap_endpoint *ep)
+bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t func,
+			void *user_data, bt_bap_destroy_func_t destroy)
 {
-	uint16_t value_handle;
-
-	if (!gatt_db_attribute_get_char_data(ep->attr, NULL, &value_handle,
-						NULL, NULL, NULL))
-		return;
+	if (!bap)
+		return false;
 
-	DBG(bap, "ASE handle 0x%04x", value_handle);
+	if (bap->debug_destroy)
+		bap->debug_destroy(bap->debug_data);
 
-	bap_read_value(bap, value_handle, read_ase_status, ep);
+	bap->debug_func = func;
+	bap->debug_destroy = destroy;
+	bap->debug_data = user_data;
 
-	ep->state_id = bap_register_notify(bap, value_handle,
-						bap_endpoint_notify, ep);
+	return true;
 }
 
-static void append_group(void *data, void *user_data)
+unsigned int bt_bap_ready_register(struct bt_bap *bap,
+				bt_bap_ready_func_t func, void *user_data,
+				bt_bap_destroy_func_t destroy)
 {
-	struct bt_bap_req *req = data;
-	struct iovec *iov = user_data;
-	size_t i;
+	struct bt_bap_ready *ready;
+	static unsigned int id;
 
-	for (i = 0; i < req->len; i++)
-		iov_add_mem(iov, req->iov[i].iov_len, req->iov[i].iov_base);
-}
+	if (!bap)
+		return 0;
 
-static bool bap_send(struct bt_bap *bap, struct bt_bap_req *req)
-{
-	struct bt_ascs *ascs = bap_get_ascs(bap);
-	int ret;
-	uint16_t handle;
-	uint8_t buf[64];
-	struct bt_ascs_ase_hdr hdr;
-	struct iovec iov  = {
-		.iov_base = buf,
-		.iov_len = 0,
-	};
-	size_t i;
+	ready = new0(struct bt_bap_ready, 1);
+	ready->id = ++id ? id : ++id;
+	ready->func = func;
+	ready->destroy = destroy;
+	ready->data = user_data;
 
-	if (!gatt_db_attribute_get_char_data(ascs->ase_cp, NULL, &handle,
-						NULL, NULL, NULL))
-		return false;
+	queue_push_tail(bap->ready_cbs, ready);
 
-	hdr.op = req->op;
-	hdr.num = 1 + queue_length(req->group);
+	return ready->id;
+}
 
-	iov_add_mem(&iov, sizeof(hdr), &hdr);
+static bool match_ready_id(const void *data, const void *match_data)
+{
+	const struct bt_bap_ready *ready = data;
+	unsigned int id = PTR_TO_UINT(match_data);
 
-	for (i = 0; i < req->len; i++)
-		iov_add_mem(&iov, req->iov[i].iov_len, req->iov[i].iov_base);
+	return (ready->id == id);
+}
 
-	/* Append the request group with the same opcode */
-	queue_foreach(req->group, append_group, &iov);
+bool bt_bap_ready_unregister(struct bt_bap *bap, unsigned int id)
+{
+	struct bt_bap_ready *ready;
 
-	ret = bt_gatt_client_write_without_response(bap->client, handle,
-							false, iov.iov_base,
-							iov.iov_len);
-	if (!ret)
+	ready = queue_remove_if(bap->ready_cbs, match_ready_id,
+						UINT_TO_PTR(id));
+	if (!ready)
 		return false;
 
-	bap->req = req;
+	bap_ready_free(ready);
 
-	return false;
+	return true;
 }
 
-static bool bap_process_queue(void *data)
+unsigned int bt_bap_state_register(struct bt_bap *bap,
+				bt_bap_state_func_t func,
+				bt_bap_connecting_func_t connecting,
+				void *user_data, bt_bap_destroy_func_t destroy)
 {
-	struct bt_bap *bap = data;
-	struct bt_bap_req *req;
+	struct bt_bap_state *state;
+	static unsigned int id;
 
-	if (bap->process_id) {
-		timeout_remove(bap->process_id);
-		bap->process_id = 0;
-	}
+	if (!bap)
+		return 0;
 
-	while ((req = queue_pop_head(bap->reqs))) {
-		if (!bap_send(bap, req))
-			break;
-	}
+	state = new0(struct bt_bap_state, 1);
+	state->id = ++id ? id : ++id;
+	state->func = func;
+	state->connecting = connecting;
+	state->destroy = destroy;
+	state->data = user_data;
 
-	return false;
+	queue_push_tail(bap->state_cbs, state);
+
+	return state->id;
 }
 
-static bool match_req(const void *data, const void *match_data)
+static bool match_state_id(const void *data, const void *match_data)
 {
-	const struct bt_bap_req *pend = data;
-	const struct bt_bap_req *req = match_data;
+	const struct bt_bap_state *state = data;
+	unsigned int id = PTR_TO_UINT(match_data);
 
-	return pend->op == req->op;
+	return (state->id == id);
 }
 
-static bool bap_queue_req(struct bt_bap *bap, struct bt_bap_req *req)
+bool bt_bap_state_unregister(struct bt_bap *bap, unsigned int id)
 {
-	struct bt_bap_req *pend;
-	struct queue *queue;
-
-	pend = queue_find(bap->reqs, match_req, req);
-	if (pend) {
-		if (!pend->group)
-			pend->group = queue_new();
-		/* Group requests with the same opcode */
-		queue = pend->group;
-	} else {
-		queue = bap->reqs;
-	}
+	struct bt_bap_state *state;
 
-	DBG(bap, "req %p (op 0x%2.2x) queue %p", req, req->op, queue);
+	if (!bap)
+		return false;
 
-	if (!queue_push_tail(queue, req)) {
-		DBG(bap, "Unable to queue request");
+	state = queue_remove_if(bap->state_cbs, match_state_id,
+						UINT_TO_PTR(id));
+	if (!state)
 		return false;
-	}
 
-	/* Only attempot to process queue if there is no outstanding request
-	 * and it has not been scheduled.
-	 */
-	if (!bap->req && !bap->process_id)
-		bap->process_id = timeout_add(BAP_PROCESS_TIMEOUT,
-						bap_process_queue, bap, NULL);
+	bap_state_free(state);
 
-	return true;
+	return false;
 }
 
-static void bap_req_complete(struct bt_bap_req *req,
-				const struct bt_ascs_ase_rsp *rsp)
+const char *bt_bap_stream_statestr(uint8_t state)
 {
-	struct queue *group;
+	switch (state) {
+	case BT_BAP_STREAM_STATE_IDLE:
+		return "idle";
+	case BT_BAP_STREAM_STATE_CONFIG:
+		return "config";
+	case BT_BAP_STREAM_STATE_QOS:
+		return "qos";
+	case BT_BAP_STREAM_STATE_ENABLING:
+		return "enabling";
+	case BT_BAP_STREAM_STATE_STREAMING:
+		return "streaming";
+	case BT_BAP_STREAM_STATE_DISABLING:
+		return "disabling";
+	case BT_BAP_STREAM_STATE_RELEASING:
+		return "releasing";
+	}
 
-	if (!req->func)
-		goto done;
+	return "unknown";
+}
 
-	if (rsp)
-		req->func(req->stream, rsp->code, rsp->reason, req->user_data);
-	else
-		req->func(req->stream, BT_ASCS_RSP_UNSPECIFIED, 0x00,
-						req->user_data);
+static void bap_foreach_pac(struct queue *l, struct queue *r,
+				bt_bap_pac_foreach_t func, void *user_data)
+{
+	const struct queue_entry *el;
 
-done:
-	/* Detach from request so it can be freed separately */
-	group = req->group;
-	req->group = NULL;
+	for (el = queue_get_entries(l); el; el = el->next) {
+		struct bt_bap_pac *lpac = el->data;
+		const struct queue_entry *er;
 
-	queue_foreach(group, (queue_foreach_func_t)bap_req_complete,
-							(void *)rsp);
+		for (er = queue_get_entries(r); er; er = er->next) {
+			struct bt_bap_pac *rpac = er->data;
 
-	queue_destroy(group, NULL);
+			/* Skip checking codec for bcast source,
+			 * it will be checked when BASE info are received
+			 */
+			if ((rpac->type != BT_BAP_BCAST_SOURCE) &&
+				(!bap_codec_equal(&lpac->codec, &rpac->codec)))
+				continue;
 
-	bap_req_free(req);
+			if (!func(lpac, rpac, user_data))
+				return;
+		}
+	}
 }
 
-static void bap_cp_notify(struct bt_bap *bap, uint16_t value_handle,
-				const uint8_t *value, uint16_t length,
-				void *user_data)
+void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
+			bt_bap_pac_foreach_t func, void *user_data)
 {
-	const struct bt_ascs_cp_rsp *rsp = (void *)value;
-	const struct bt_ascs_ase_rsp *ase_rsp = NULL;
-	struct bt_bap_req *req;
-	int i;
-
-	if (!bap->req)
+	if (!bap || !func || !bap->rdb || queue_isempty(bap_db))
 		return;
 
-	req = bap->req;
-	bap->req = NULL;
-
-	if (length < sizeof(*rsp)) {
-		DBG(bap, "Invalid ASE CP notification: length %u < %zu",
-						length, sizeof(*rsp));
-		goto done;
+	switch (type) {
+	case BT_BAP_SINK:
+		return bap_foreach_pac(bap->ldb->sources, bap->rdb->sinks,
+							func, user_data);
+	case BT_BAP_SOURCE:
+		return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
+							func, user_data);
+	case BT_BAP_BCAST_SOURCE:
+	case BT_BAP_BCAST_SINK:
+		return bap_foreach_pac(bap->ldb->broadcast_sinks,
+						bap->rdb->broadcast_sources,
+						func, user_data);
 	}
+}
 
-	if (rsp->op != req->op) {
-		DBG(bap, "Invalid ASE CP notification: op 0x%02x != 0x%02x",
-						rsp->op, req->op);
-		goto done;
-	}
+int bt_bap_pac_get_vendor_codec(struct bt_bap_pac *pac, uint8_t *id,
+				uint16_t *cid, uint16_t *vid,
+				struct iovec **data, struct iovec **metadata)
+{
+	if (!pac)
+		return -EINVAL;
 
-	length -= sizeof(*rsp);
+	if (id)
+		*id = pac->codec.id;
 
-	if (rsp->num_ase == 0xff) {
-		ase_rsp = rsp->rsp;
-		goto done;
-	}
+	if (cid)
+		*cid = pac->codec.cid;
 
-	for (i = 0; i < rsp->num_ase; i++) {
-		if (length < sizeof(*ase_rsp)) {
-			DBG(bap, "Invalid ASE CP notification: length %u < %zu",
-					length, sizeof(*ase_rsp));
-			goto done;
-		}
+	if (vid)
+		*vid = pac->codec.cid;
+
+	if (data && pac->data)
+		*data = pac->data;
+
+	if (metadata && pac->metadata)
+		*metadata = pac->metadata;
 
-		ase_rsp = &rsp->rsp[i];
-	}
+	return 0;
+}
 
-done:
-	bap_req_complete(req, ase_rsp);
-	bap_process_queue(bap);
+int bt_bap_pac_get_codec(struct bt_bap_pac *pac, uint8_t *id,
+				struct iovec **data, struct iovec **metadata)
+{
+	return bt_bap_pac_get_vendor_codec(pac, id, NULL, NULL, data, metadata);
 }
 
-static void bap_cp_attach(struct bt_bap *bap)
+void bt_bap_pac_set_user_data(struct bt_bap_pac *pac, void *user_data)
 {
-	uint16_t value_handle;
-	struct bt_ascs *ascs = bap_get_ascs(bap);
+	pac->user_data = user_data;
+}
 
-	if (!gatt_db_attribute_get_char_data(ascs->ase_cp, NULL,
-						&value_handle,
-						NULL, NULL, NULL))
-		return;
+void *bt_bap_pac_get_user_data(struct bt_bap_pac *pac)
+{
+	return pac->user_data;
+}
 
-	DBG(bap, "ASE CP handle 0x%04x", value_handle);
+bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac)
+{
+	if (!bap->ldb)
+		return false;
 
-	bap->cp_id = bap_register_notify(bap, value_handle, bap_cp_notify,
-								NULL);
+	if (queue_find(bap->ldb->broadcast_sinks, NULL, pac))
+		return true;
+
+	if (queue_find(bap->ldb->broadcast_sources, NULL, pac))
+		return true;
+
+	return false;
 }
 
-static void foreach_ascs_char(struct gatt_db_attribute *attr, void *user_data)
+static bool find_ep_unused(const void *data, const void *user_data)
 {
-	struct bt_bap *bap = user_data;
-	uint16_t value_handle;
-	bt_uuid_t uuid, uuid_sink, uuid_source, uuid_cp;
-	struct bt_ascs *ascs;
+	const struct bt_bap_endpoint *ep = data;
+	const struct match_pac *match = user_data;
 
-	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
-						NULL, NULL, &uuid))
-		return;
+	if (ep->stream)
+		return false;
 
-	bt_uuid16_create(&uuid_sink, ASE_SINK_UUID);
-	bt_uuid16_create(&uuid_source, ASE_SOURCE_UUID);
-	bt_uuid16_create(&uuid_cp, ASE_CP_UUID);
+	if (match->rpac)
+		return ep->dir == match->rpac->type;
+	else
+		return true;
+}
 
-	if (!bt_uuid_cmp(&uuid, &uuid_sink) ||
-			!bt_uuid_cmp(&uuid, &uuid_source)) {
-		struct bt_bap_endpoint *ep;
+static bool find_ep_pacs(const void *data, const void *user_data)
+{
+	const struct bt_bap_endpoint *ep = data;
+	const struct match_pac *match = user_data;
 
-		ep = bap_get_endpoint(bap->rdb, attr);
-		if (!ep)
-			return;
+	if (!ep->stream)
+		return false;
 
-		if (!bt_uuid_cmp(&uuid, &uuid_sink))
-			DBG(bap, "ASE Sink found: handle 0x%04x", value_handle);
-		else
-			DBG(bap, "ASE Source found: handle 0x%04x",
-							value_handle);
+	if (ep->stream->lpac != match->lpac)
+		return false;
 
-		bap_endpoint_attach(bap, ep);
+	if (ep->stream->rpac != match->rpac)
+		return false;
 
-		return;
+	switch (ep->state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+	case BT_BAP_STREAM_STATE_QOS:
+		return true;
 	}
 
-	if (!bt_uuid_cmp(&uuid, &uuid_cp)) {
-		ascs = bap_get_ascs(bap);
-		if (!ascs || ascs->ase_cp)
-			return;
-
-		ascs->ase_cp = attr;
+	return false;
+}
 
-		DBG(bap, "ASE Control Point found: handle 0x%04x",
-							value_handle);
+static bool find_ep_source(const void *data, const void *user_data)
+{
+	const struct bt_bap_endpoint *ep = data;
 
-		bap_cp_attach(bap);
-	}
+	if (ep->dir == BT_BAP_BCAST_SINK)
+		return true;
+	else
+		return false;
 }
 
-static void foreach_ascs_service(struct gatt_db_attribute *attr,
-						void *user_data)
+unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
+					struct bt_bap_qos *qos,
+					struct iovec *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	struct bt_bap *bap = user_data;
-	struct bt_ascs *ascs = bap_get_ascs(bap);
+	unsigned int id;
+	struct bt_bap *bap;
 
-	ascs->service = attr;
+	if (!bap_stream_valid(stream))
+		return 0;
 
-	gatt_db_service_set_claimed(attr, true);
+	if (!stream->ops || !stream->ops->config)
+		return 0;
 
-	gatt_db_service_foreach_char(attr, foreach_ascs_char, bap);
-}
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-static void bap_endpoint_foreach(void *data, void *user_data)
-{
-	struct bt_bap_endpoint *ep = data;
-	struct bt_bap *bap = user_data;
+	bap = stream->bap;
 
-	bap_endpoint_attach(bap, ep);
-}
+	id = stream->ops->config(stream, qos, data, func, user_data);
 
-static void bap_attach_att(struct bt_bap *bap, struct bt_att *att)
-{
-	if (bap->disconn_id) {
-		if (att == bt_bap_get_att(bap))
-			return;
-		bt_att_unregister_disconnect(bap->att, bap->disconn_id);
-	}
+	bt_bap_unref(bap);
 
-	bap->disconn_id = bt_att_register_disconnect(bap->att,
-							bap_disconnected,
-							bap, NULL);
+	return id;
 }
 
-bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
+static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
 {
-	bt_uuid_t uuid;
+	struct match_pac *match = user_data;
 
-	if (queue_find(sessions, NULL, bap)) {
-		/* If instance already been set but there is no client proceed
-		 * to clone it otherwise considered it already attached.
-		 */
-		if (client && !bap->client)
-			goto clone;
+	if (match->lpac && match->lpac != lpac)
 		return true;
-	}
 
-	if (!sessions)
-		sessions = queue_new();
+	if (match->rpac && match->rpac != rpac)
+		return true;
 
-	queue_push_tail(sessions, bap);
+	match->lpac = lpac;
+	match->rpac = rpac;
 
-	queue_foreach(bap_cbs, bap_attached, bap);
+	return false;
+}
 
-	if (!client) {
-		bap_attach_att(bap, bap->att);
-		return true;
-	}
+int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+			int *count, bt_bap_pac_select_t func,
+			void *user_data)
+{
+	const struct queue_entry *lchan, *rchan;
+	int selected = 0;
 
-	if (bap->client)
-		return false;
+	if (!lpac || !rpac || !func)
+		return -EINVAL;
 
-clone:
-	bap->client = bt_gatt_client_clone(client);
-	if (!bap->client)
-		return false;
+	if (!lpac->ops || !lpac->ops->select)
+		return -EOPNOTSUPP;
 
-	bap_attach_att(bap, bt_gatt_client_get_att(client));
+	for (lchan = queue_get_entries(lpac->channels); lchan;
+					lchan = lchan->next) {
+		struct bt_bap_chan *lc = lchan->data;
+		struct bt_bap_chan map = *lc;
+		int i;
 
-	if (bap->rdb->pacs) {
-		uint16_t value_handle;
-		struct bt_pacs *pacs = bap->rdb->pacs;
+		for (i = 0, rchan = queue_get_entries(rpac->channels); rchan;
+					rchan = rchan->next, i++) {
+			struct bt_bap_chan *rc = rchan->data;
 
-		/* Resume reading sinks if supported */
-		if (pacs->sink && queue_isempty(bap->rdb->sinks)) {
-			if (gatt_db_attribute_get_char_data(pacs->sink,
-							NULL, &value_handle,
-							NULL, NULL, NULL)) {
-				bap_read_value(bap, value_handle,
-							read_sink_pac, bap);
-			}
-		}
+			/* Try matching the channel count */
+			if (!(map.count & rc->count))
+				break;
 
-		/* Resume reading sources if supported */
-		if (pacs->source && queue_isempty(bap->rdb->sources)) {
-			if (gatt_db_attribute_get_char_data(pacs->source,
-							NULL, &value_handle,
-							NULL, NULL, NULL)) {
-				bap_read_value(bap, value_handle,
-							read_source_pac, bap);
+			/* Check if location was set otherwise attempt to
+			 * assign one based on the number of channels it
+			 * supports.
+			 */
+			if (!rc->location) {
+				rc->location = bt_bap_pac_get_locations(rpac);
+				/* If channel count is 1 use a single
+				 * location
+				 */
+				if (rc->count == 0x01)
+					rc->location &= BIT(i);
 			}
-		}
 
-		queue_foreach(bap->rdb->endpoints, bap_endpoint_foreach, bap);
+			/* Try matching the channel location */
+			if (!(map.location & rc->location))
+				continue;
 
-		bap_cp_attach(bap);
+			lpac->ops->select(lpac, rpac, map.location &
+						rc->location, &rpac->qos,
+						func, user_data,
+						lpac->user_data);
+			selected++;
 
-		bap_notify_ready(bap);
+			/* Check if there are any channels left to select */
+			map.count &= ~(map.count & rc->count);
+			/* Check if there are any locations left to select */
+			map.location &= ~(map.location & rc->location);
 
-		return true;
+			if (!map.count || !map.location)
+				break;
+
+			/* Check if device require AC*(i) settings */
+			if (rc->count == 0x01)
+				map.count = map.count >> 1;
+		}
 	}
 
-	bt_uuid16_create(&uuid, PACS_UUID);
-	gatt_db_foreach_service(bap->rdb->db, &uuid, foreach_pacs_service, bap);
+	/* Fallback to no channel allocation since none could be matched. */
+	if (!selected) {
+		lpac->ops->select(lpac, rpac, 0, &rpac->qos, func, user_data,
+					lpac->user_data);
+		selected++;
+	}
 
-	bt_uuid16_create(&uuid, ASCS_UUID);
-	gatt_db_foreach_service(bap->rdb->db, &uuid, foreach_ascs_service, bap);
+	if (count)
+		*count += selected;
 
-	return true;
+	return 0;
 }
 
-static void stream_foreach_detach(void *data, void *user_data)
+void bt_bap_cancel_select(struct bt_bap_pac *lpac, bt_bap_pac_select_t func,
+								void *user_data)
 {
-	struct bt_bap_stream *stream = data;
+	if (!lpac || !func)
+		return;
 
-	stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
+	if (!lpac->ops || !lpac->ops->cancel_select)
+		return;
+
+	lpac->ops->cancel_select(lpac, func, user_data, lpac->user_data);
 }
 
-void bt_bap_detach(struct bt_bap *bap)
+static struct bt_bap_stream *bap_bcast_stream_new(struct bt_bap *bap,
+					struct bt_bap_pac *lpac,
+					struct bt_bap_qos *pqos,
+					struct iovec *data)
 {
-	DBG(bap, "%p", bap);
+	struct bt_bap_stream *stream = NULL;
+	struct bt_bap_endpoint *ep = NULL;
+	struct match_pac match;
 
-	if (!queue_remove(sessions, bap))
-		return;
+	if (!bap)
+		return NULL;
 
-	bt_gatt_client_unref(bap->client);
-	bap->client = NULL;
+	if (lpac->type == BT_BAP_BCAST_SOURCE) {
+		match.lpac = lpac;
+		match.rpac = NULL;
+		memset(&match.codec, 0, sizeof(match.codec));
+
+		bt_bap_foreach_pac(bap, BT_BAP_BCAST_SINK, match_pac, &match);
+		if ((!match.lpac) || (!lpac))
+			return NULL;
+
+		lpac = match.lpac;
+
+		ep = queue_find(bap->remote_eps, find_ep_source, NULL);
+		if (!ep)
+			return NULL;
+	}
+
+	if (!stream)
+		stream = bap_stream_new(bap, ep, lpac, NULL, data, true);
+
+	return stream;
+}
+
+static struct bt_bap_stream *bap_ucast_stream_new(struct bt_bap *bap,
+					struct bt_bap_pac *lpac,
+					struct bt_bap_pac *rpac,
+					struct bt_bap_qos *pqos,
+					struct iovec *data)
+{
+	struct bt_bap_stream *stream = NULL;
+	struct bt_bap_endpoint *ep = NULL;
+	struct match_pac match;
+
+	if (!lpac || !rpac || !bap_codec_equal(&lpac->codec, &rpac->codec))
+		return NULL;
+
+	memset(&match, 0, sizeof(match));
+	match.lpac = lpac;
+	match.rpac = rpac;
+
+	/* Check for existing stream */
+	ep = queue_find(bap->remote_eps, find_ep_pacs, &match);
+	if (!ep) {
+		/* Check for unused ASE */
+		ep = queue_find(bap->remote_eps, find_ep_unused, &match);
+		if (!ep) {
+			DBG(bap, "Unable to find unused ASE");
+			return NULL;
+		}
+	}
 
-	bt_att_unregister_disconnect(bap->att, bap->disconn_id);
-	bap->att = NULL;
+	stream = ep->stream;
+	if (!stream)
+		stream = bap_stream_new(bap, ep, lpac, rpac, data, true);
 
-	queue_foreach(bap->streams, stream_foreach_detach, bap);
-	queue_foreach(bap_cbs, bap_detached, bap);
+	return stream;
 }
 
-bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t func,
-			void *user_data, bt_bap_destroy_func_t destroy)
+struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
+					struct bt_bap_pac *lpac,
+					struct bt_bap_pac *rpac,
+					struct bt_bap_qos *pqos,
+					struct iovec *data)
 {
 	if (!bap)
-		return false;
-
-	if (bap->debug_destroy)
-		bap->debug_destroy(bap->debug_data);
+		return NULL;
 
-	bap->debug_func = func;
-	bap->debug_destroy = destroy;
-	bap->debug_data = user_data;
+	/* Check if ATT is attached then it must be a unicast stream */
+	if (bt_bap_get_att(bap))
+		return bap_ucast_stream_new(bap, lpac, rpac, pqos, data);
 
-	return true;
+	return bap_bcast_stream_new(bap, lpac, pqos, data);
 }
 
-unsigned int bt_bap_ready_register(struct bt_bap *bap,
-				bt_bap_ready_func_t func, void *user_data,
-				bt_bap_destroy_func_t destroy)
+struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream)
 {
-	struct bt_bap_ready *ready;
-	static unsigned int id;
-
-	if (!bap)
-		return 0;
-
-	ready = new0(struct bt_bap_ready, 1);
-	ready->id = ++id ? id : ++id;
-	ready->func = func;
-	ready->destroy = destroy;
-	ready->data = user_data;
-
-	queue_push_tail(bap->ready_cbs, ready);
+	if (!stream)
+		return NULL;
 
-	return ready->id;
+	return stream->bap;
 }
 
-static bool match_ready_id(const void *data, const void *match_data)
+uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream)
 {
-	const struct bt_bap_ready *ready = data;
-	unsigned int id = PTR_TO_UINT(match_data);
+	if (!stream)
+		return BT_BAP_STREAM_STATE_IDLE;
 
-	return (ready->id == id);
+	return stream->ops->get_state(stream);
 }
 
-bool bt_bap_ready_unregister(struct bt_bap *bap, unsigned int id)
+bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
 {
-	struct bt_bap_ready *ready;
-
-	ready = queue_remove_if(bap->ready_cbs, match_ready_id,
-						UINT_TO_PTR(id));
-	if (!ready)
+	if (!stream)
 		return false;
 
-	bap_ready_free(ready);
+	stream->user_data = user_data;
 
 	return true;
 }
 
-unsigned int bt_bap_state_register(struct bt_bap *bap,
-				bt_bap_state_func_t func,
-				bt_bap_connecting_func_t connecting,
-				void *user_data, bt_bap_destroy_func_t destroy)
+void *bt_bap_stream_get_user_data(struct bt_bap_stream *stream)
 {
-	struct bt_bap_state *state;
-	static unsigned int id;
-
-	if (!bap)
-		return 0;
-
-	state = new0(struct bt_bap_state, 1);
-	state->id = ++id ? id : ++id;
-	state->func = func;
-	state->connecting = connecting;
-	state->destroy = destroy;
-	state->data = user_data;
-
-	queue_push_tail(bap->state_cbs, state);
+	if (!stream)
+		return NULL;
 
-	return state->id;
+	return stream->user_data;
 }
 
-static bool match_state_id(const void *data, const void *match_data)
+unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream,
+					struct bt_bap_qos *data,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	const struct bt_bap_state *state = data;
-	unsigned int id = PTR_TO_UINT(match_data);
+	unsigned int id;
 
-	return (state->id == id);
-}
+	if (!bap_stream_valid(stream))
+		return 0;
 
-bool bt_bap_state_unregister(struct bt_bap *bap, unsigned int id)
-{
-	struct bt_bap_state *state;
+	if (!stream->ops || !stream->ops->qos)
+		return 0;
 
-	if (!bap)
-		return false;
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-	state = queue_remove_if(bap->state_cbs, match_state_id,
-						UINT_TO_PTR(id));
-	if (!state)
-		return false;
+	id = stream->ops->qos(stream, data, func, user_data);
 
-	bap_state_free(state);
+	bt_bap_unref(stream->bap);
 
-	return false;
+	return id;
 }
 
-const char *bt_bap_stream_statestr(uint8_t state)
+unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
+					bool enable_links,
+					struct iovec *metadata,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	switch (state) {
-	case BT_BAP_STREAM_STATE_IDLE:
-		return "idle";
-	case BT_BAP_STREAM_STATE_CONFIG:
-		return "config";
-	case BT_BAP_STREAM_STATE_QOS:
-		return "qos";
-	case BT_BAP_STREAM_STATE_ENABLING:
-		return "enabling";
-	case BT_BAP_STREAM_STATE_STREAMING:
-		return "streaming";
-	case BT_BAP_STREAM_STATE_DISABLING:
-		return "disabling";
-	case BT_BAP_STREAM_STATE_RELEASING:
-		return "releasing";
-	}
-
-	return "unknown";
-}
+	unsigned int id;
+	struct bt_bap *bap;
 
-static void bap_foreach_pac(struct queue *l, struct queue *r,
-				bt_bap_pac_foreach_t func, void *user_data)
-{
-	const struct queue_entry *el;
+	if (!bap_stream_valid(stream))
+		return 0;
 
-	for (el = queue_get_entries(l); el; el = el->next) {
-		struct bt_bap_pac *lpac = el->data;
-		const struct queue_entry *er;
+	if (!stream->ops || !stream->ops->enable)
+		return 0;
 
-		for (er = queue_get_entries(r); er; er = er->next) {
-			struct bt_bap_pac *rpac = er->data;
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-			if (!bap_codec_equal(&lpac->codec, &rpac->codec))
-				continue;
+	bap = stream->bap;
 
-			if (!func(lpac, rpac, user_data))
-				return;
-		}
-	}
-}
+	id = stream->ops->enable(stream, enable_links, metadata, func,
+					user_data);
 
-void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
-			bt_bap_pac_foreach_t func, void *user_data)
-{
-	if (!bap || !func || !bap->rdb || queue_isempty(bap_db))
-		return;
+	bt_bap_unref(bap);
 
-	switch (type) {
-	case BT_BAP_SINK:
-		return bap_foreach_pac(bap->ldb->sources, bap->rdb->sinks,
-							func, user_data);
-	case BT_BAP_SOURCE:
-		return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
-							func, user_data);
-	}
+	return id;
 }
 
-int bt_bap_pac_get_vendor_codec(struct bt_bap_pac *pac, uint8_t *id,
-				uint16_t *cid, uint16_t *vid,
-				struct iovec **data, struct iovec **metadata)
+unsigned int bt_bap_stream_start(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	if (!pac)
-		return -EINVAL;
-
-	if (id)
-		*id = pac->codec.id;
+	unsigned int id;
+	struct bt_bap *bap;
 
-	if (cid)
-		*cid = pac->codec.cid;
+	if (!bap_stream_valid(stream))
+		return 0;
 
-	if (vid)
-		*vid = pac->codec.cid;
+	if (!stream->ops || !stream->ops->start)
+		return 0;
 
-	if (data)
-		*data = pac->data;
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-	if (metadata)
-		*metadata = pac->metadata;
+	bap = stream->bap;
 
-	return 0;
-}
+	id = stream->ops->start(stream, func, user_data);
 
-int bt_bap_pac_get_codec(struct bt_bap_pac *pac, uint8_t *id,
-				struct iovec **data, struct iovec **metadata)
-{
-	return bt_bap_pac_get_vendor_codec(pac, id, NULL, NULL, data, metadata);
-}
+	bt_bap_unref(bap);
 
-void bt_bap_pac_set_user_data(struct bt_bap_pac *pac, void *user_data)
-{
-	pac->user_data = user_data;
+	return id;
 }
 
-void *bt_bap_pac_get_user_data(struct bt_bap_pac *pac)
+unsigned int bt_bap_stream_disable(struct bt_bap_stream *stream,
+					bool disable_links,
+					bt_bap_stream_func_t func,
+					void *user_data)
 {
-	return pac->user_data;
-}
+	unsigned int id;
+	struct bt_bap *bap;
 
-static bool find_ep_unused(const void *data, const void *user_data)
-{
-	const struct bt_bap_endpoint *ep = data;
-	const struct match_pac *match = user_data;
+	if (!bap_stream_valid(stream))
+		return 0;
 
-	if (ep->stream)
-		return false;
+	if (!stream->ops || !stream->ops->disable)
+		return 0;
 
-	return ep->dir == match->rpac->type;
-}
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-static bool find_ep_pacs(const void *data, const void *user_data)
-{
-	const struct bt_bap_endpoint *ep = data;
-	const struct match_pac *match = user_data;
+	bap = stream->bap;
 
-	if (!ep->stream)
-		return false;
+	id = stream->ops->disable(stream, disable_links, func, user_data);
 
-	if (ep->stream->lpac != match->lpac)
-		return false;
+	bt_bap_unref(bap);
 
-	return ep->stream->rpac == match->rpac;
+	return id;
 }
 
-static struct bt_bap_req *bap_req_new(struct bt_bap_stream *stream,
-					uint8_t op, struct iovec *iov,
-					size_t len,
+unsigned int bt_bap_stream_stop(struct bt_bap_stream *stream,
 					bt_bap_stream_func_t func,
 					void *user_data)
 {
-	struct bt_bap_req *req;
-	static unsigned int id;
+	unsigned int id;
 
-	req = new0(struct bt_bap_req, 1);
-	req->id = ++id;
-	req->stream = stream;
-	req->op = op;
-	req->iov = iov_dup(iov, len);
-	req->len = len;
-	req->func = func;
-	req->user_data = user_data;
+	if (!bap_stream_valid(stream))
+		return 0;
 
-	return req;
-}
+	if (!stream->ops || !stream->ops->stop)
+		return 0;
 
-static bool bap_stream_valid(struct bt_bap_stream *stream)
-{
-	if (!stream || !stream->bap)
-		return false;
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
+
+	id = stream->ops->stop(stream, func, user_data);
 
-	return queue_find(stream->bap->streams, NULL, stream);
+	bt_bap_unref(stream->bap);
+
+	return id;
 }
 
-unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
-					struct bt_bap_qos *qos,
-					struct iovec *data,
+unsigned int bt_bap_stream_metadata(struct bt_bap_stream *stream,
+					struct iovec *metadata,
 					bt_bap_stream_func_t func,
 					void *user_data)
 {
-	struct iovec iov[2];
-	struct bt_ascs_config config;
-	uint8_t iovlen = 1;
-	struct bt_bap_req *req;
+	unsigned int id;
 
 	if (!bap_stream_valid(stream))
 		return 0;
 
-	if (!stream->client) {
-		stream_config(stream, data, NULL);
+	if (!stream->ops || !stream->ops->metadata)
 		return 0;
-	}
 
-	memset(&config, 0, sizeof(config));
+	if (!bt_bap_ref_safe(stream->bap))
+		return 0;
 
-	config.ase = stream->ep->id;
-	config.latency = qos->target_latency;
-	config.phy = qos->phy;
-	config.codec = stream->rpac->codec;
+	id = stream->ops->metadata(stream, metadata, func, user_data);
 
-	iov[0].iov_base = &config;
-	iov[0].iov_len = sizeof(config);
+	bt_bap_unref(stream->bap);
 
-	if (data) {
-		if (!bap_print_cc(data->iov_base, data->iov_len,
-					stream->bap->debug_func,
-					stream->bap->debug_data))
-			return 0;
+	return id;
+}
 
-		config.cc_len = data->iov_len;
-		iov[1] = *data;
-		iovlen++;
-	}
+unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
+					bt_bap_stream_func_t func,
+					void *user_data)
+{
+	unsigned int id;
+	struct bt_bap *bap = stream->bap;
 
-	req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
+	if (!stream || !stream->ops || !stream->ops->release)
+		return 0;
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
+	if (!bt_bap_ref_safe(bap))
 		return 0;
-	}
 
-	stream->qos = *qos;
+	id = stream->ops->release(stream, func, user_data);
 
-	return req->id;
+	bt_bap_unref(bap);
+
+	return id;
 }
 
-static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-							void *user_data)
+uint8_t bt_bap_stream_get_dir(struct bt_bap_stream *stream)
 {
-	struct match_pac *match = user_data;
+	if (!stream)
+		return 0x00;
 
-	if (match->lpac && match->lpac != lpac)
-		return true;
+	return stream->ops->get_dir(stream);
+}
 
-	if (match->rpac && match->rpac != rpac)
-		return true;
+uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return 0x00000000;
 
-	match->lpac = lpac;
-	match->rpac = rpac;
+	return stream->ops->get_loc(stream);
+}
 
-	return false;
+struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return NULL;
+
+	return stream->cc;
 }
 
-int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-			bt_bap_pac_select_t func, void *user_data)
+struct bt_bap_qos *bt_bap_stream_get_qos(struct bt_bap_stream *stream)
 {
-	if (!lpac || !rpac || !func)
-		return -EINVAL;
+	if (!stream)
+		return NULL;
 
-	if (!lpac->ops || !lpac->ops->select)
-		return -EOPNOTSUPP;
+	return &stream->qos;
+}
 
-	lpac->ops->select(lpac, rpac, &rpac->qos,
-					func, user_data, lpac->user_data);
+struct iovec *bt_bap_stream_get_metadata(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return NULL;
 
-	return 0;
+	return stream->meta;
 }
 
-struct bt_bap_stream *bt_bap_config(struct bt_bap *bap,
-					struct bt_bap_pac *lpac,
-					struct bt_bap_pac *rpac,
-					struct bt_bap_qos *pqos,
-					struct iovec *data,
-					bt_bap_stream_func_t func,
-					void *user_data)
+struct io *bt_bap_stream_get_io(struct bt_bap_stream *stream)
 {
-	struct bt_bap_stream *stream;
-	struct bt_bap_endpoint *ep;
-	struct match_pac match;
-	int id;
+	struct bt_bap_stream_io *io;
 
-	if (!bap || !bap->rdb || queue_isempty(bap->rdb->endpoints))
+	io = stream_get_io(stream);
+	if (!io || io->connecting)
 		return NULL;
 
-	if (lpac && rpac) {
-		if (!bap_codec_equal(&lpac->codec, &rpac->codec))
-			return NULL;
-	} else {
-		uint8_t type;
+	return io->io;
+}
 
-		match.lpac = lpac;
-		match.rpac = rpac;
-		memset(&match.codec, 0, sizeof(match.codec));
+bool bt_bap_match_bcast_sink_stream(const void *data, const void *user_data)
+{
+	const struct bt_bap_stream *stream = data;
 
-		if (rpac)
-			type = rpac->type;
-		else if (lpac) {
-			switch(lpac->type) {
-			case BT_BAP_SINK:
-				type = BT_BAP_SOURCE;
-				break;
-			case BT_BAP_SOURCE:
-				type = BT_BAP_SINK;
-				break;
-			default:
-				return NULL;
-			}
-		} else
-			return NULL;
+	return stream->lpac->type == BT_BAP_BCAST_SINK;
+}
 
-		bt_bap_foreach_pac(bap, type, match_pac, &match);
-		if (!match.lpac || !match.rpac)
-			return NULL;
+static bool stream_io_disconnected(struct io *io, void *user_data)
+{
+	struct bt_bap_stream *stream = user_data;
 
-		lpac = match.lpac;
-		rpac = match.rpac;
-	}
+	DBG(stream->bap, "stream %p io disconnected", stream);
 
-	match.lpac = lpac;
-	match.rpac = rpac;
+	bt_bap_stream_set_io(stream, -1);
 
-	/* Check for existing stream */
-	ep = queue_find(bap->rdb->endpoints, find_ep_pacs, &match);
-	if (!ep) {
-		/* Check for unused ASE */
-		ep = queue_find(bap->rdb->endpoints, find_ep_unused, &match);
-		if (!ep) {
-			DBG(bap, "Unable to find unused ASE");
-			return NULL;
-		}
-	}
+	return false;
+}
 
-	stream = ep->stream;
-	if (!stream)
-		stream = bap_stream_new(bap, ep, lpac, rpac, data, true);
+bool bt_bap_stream_set_io(struct bt_bap_stream *stream, int fd)
+{
+	bool ret;
+	struct bt_bap *bap;
 
-	id = bt_bap_stream_config(stream, pqos, data, func, user_data);
-	if (!id) {
-		DBG(bap, "Unable to config stream");
-		queue_remove(bap->streams, stream);
-		ep->stream = NULL;
-		free(stream);
-		return NULL;
-	}
+	if (!bap_stream_valid(stream))
+		return false;
 
-	return stream;
+	if (!stream->ops || !stream->ops->set_io)
+		return false;
+
+	if (!bt_bap_ref_safe(stream->bap))
+		return false;
+
+	bap = stream->bap;
+
+	ret = stream->ops->set_io(stream, fd);
+
+	bt_bap_unref(bap);
+
+	return ret;
 }
 
-struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream)
+static bool match_req_id(const void *data, const void *match_data)
 {
-	if (!stream)
-		return NULL;
+	const struct bt_bap_req *req = data;
+	unsigned int id = PTR_TO_UINT(match_data);
 
-	return stream->bap;
+	return (req->id == id);
 }
 
-uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream)
+static bool match_name(const void *data, const void *match_data)
 {
-	if (!stream)
-		return BT_BAP_STREAM_STATE_IDLE;
+	const struct bt_bap_pac *pac = data;
+	const char *name = match_data;
 
-	return stream->ep->state;
+	return (!strcmp(pac->name, name));
 }
 
-bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
+int bt_bap_stream_cancel(struct bt_bap_stream *stream, unsigned int id)
 {
+	struct bt_bap_req *req;
+
 	if (!stream)
-		return false;
+		return -EINVAL;
 
-	stream->user_data = user_data;
+	if (stream->bap->req && stream->bap->req->id == id) {
+		req = stream->bap->req;
+		stream->bap->req = NULL;
+		bap_req_free(req);
+		return 0;
+	}
 
-	return true;
+	req = queue_remove_if(stream->bap->reqs, match_req_id,
+						UINT_TO_PTR(id));
+	if (!req)
+		return 0;
+
+	bap_req_free(req);
+
+	return 0;
 }
 
-void *bt_bap_stream_get_user_data(struct bt_bap_stream *stream)
+int bt_bap_stream_io_link(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link)
 {
-	if (!stream)
-		return NULL;
+	int ret;
+	struct bt_bap *bap;
 
-	return stream->user_data;
+	if (!bap_stream_valid(stream))
+		return -EINVAL;
+
+	if (!stream->ops || !stream->ops->io_link)
+		return -EINVAL;
+
+	if (!bt_bap_ref_safe(stream->bap))
+		return -EINVAL;
+
+	bap = stream->bap;
+
+	ret = stream->ops->io_link(stream, link);
+
+	bt_bap_unref(bap);
+
+	return ret;
 }
 
-unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream,
-					struct bt_bap_qos *data,
-					bt_bap_stream_func_t func,
-					void *user_data)
+int bt_bap_stream_io_unlink(struct bt_bap_stream *stream,
+				struct bt_bap_stream *link)
 {
-	struct iovec iov;
-	struct bt_ascs_qos qos;
-	struct bt_bap_req *req;
+	int ret;
+	struct bt_bap *bap;
 
 	if (!bap_stream_valid(stream))
-		return 0;
+		return -EINVAL;
 
-	if (!stream->client) {
-		stream_qos(stream, data, NULL);
-		return 0;
-	}
+	if (!stream->ops || !stream->ops->io_unlink)
+		return -EINVAL;
 
-	memset(&qos, 0, sizeof(qos));
+	if (!bt_bap_ref_safe(stream->bap))
+		return -EINVAL;
 
-	/* TODO: Figure out how to pass these values around */
-	qos.ase = stream->ep->id;
-	qos.cig = data->cig_id;
-	qos.cis = data->cis_id;
-	put_le24(data->interval, qos.interval);
-	qos.framing = data->framing;
-	qos.phy = data->phy;
-	qos.sdu = cpu_to_le16(data->sdu);
-	qos.rtn = data->rtn;
-	qos.latency = cpu_to_le16(data->latency);
-	put_le24(data->delay, qos.pd);
+	bap = stream->bap;
 
-	iov.iov_base = &qos;
-	iov.iov_len = sizeof(qos);
+	ret = stream->ops->io_unlink(stream, link);
 
-	req = bap_req_new(stream, BT_ASCS_QOS, &iov, 1, func, user_data);
+	bt_bap_unref(bap);
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+	return ret;
+}
 
-	stream->qos = *data;
+struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return NULL;
+
+	return stream->links;
+}
+
+static void bap_stream_get_in_qos(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	struct bt_bap_qos **qos = user_data;
+
+	if (!stream)
+		return;
+
+	if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
+				!stream->qos.ucast.io_qos.sdu)
+		return;
 
-	return req->id;
+	*qos = &stream->qos;
 }
 
-static int bap_stream_metadata(struct bt_bap_stream *stream, uint8_t op,
-					struct iovec *data,
-					bt_bap_stream_func_t func,
-					void *user_data)
+static void bap_stream_get_out_qos(void *data, void *user_data)
 {
-	struct iovec iov[2];
-	struct bt_ascs_metadata meta;
-	struct bt_bap_req *req;
-	struct metadata {
-		uint8_t len;
-		uint8_t type;
-		uint8_t data[2];
-	} ctx = LTV(0x02, 0x01, 0x00); /* Context = Unspecified */
-
-	memset(&meta, 0, sizeof(meta));
-
-	meta.ase = stream->ep->id;
+	struct bt_bap_stream *stream = data;
+	struct bt_bap_qos **qos = user_data;
 
-	iov[0].iov_base = &meta;
-	iov[0].iov_len = sizeof(meta);
+	if (!stream)
+		return;
 
-	if (data)
-		iov[1] = *data;
-	else {
-		iov[1].iov_base = &ctx;
-		iov[1].iov_len = sizeof(ctx);
-	}
+	if (!qos || *qos || stream->ep->dir != BT_BAP_SINK ||
+				!stream->qos.ucast.io_qos.sdu)
+		return;
 
-	meta.len = iov[1].iov_len;
+	*qos = &stream->qos;
+}
 
-	req = bap_req_new(stream, op, iov, 2, func, user_data);
+bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
+					struct bt_bap_qos **in,
+					struct bt_bap_qos **out)
+{
+	if (!stream || (!in && !out))
+		return false;
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
+	switch (stream->ep->dir) {
+	case BT_BAP_SOURCE:
+		bap_stream_get_in_qos(stream, in);
+		queue_foreach(stream->links, bap_stream_get_out_qos, out);
+		break;
+	case BT_BAP_SINK:
+		bap_stream_get_out_qos(stream, out);
+		queue_foreach(stream->links, bap_stream_get_in_qos, in);
+		break;
+	default:
+		return false;
 	}
 
-	return req->id;
+	DBG(stream->bap, "in %p out %p", in ? *in : NULL, out ? *out : NULL);
+
+	return in && out;
 }
 
-static void bap_stream_enable_link(void *data, void *user_data)
+static void bap_stream_get_dir(void *data, void *user_data)
 {
 	struct bt_bap_stream *stream = data;
-	struct iovec *metadata = user_data;
+	uint8_t *dir = user_data;
 
-	bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, NULL, NULL);
+	*dir |= stream->ep->dir;
 }
 
-unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
-					bool enable_links,
-					struct iovec *metadata,
-					bt_bap_stream_func_t func,
-					void *user_data)
+uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream)
 {
-	int ret;
+	uint8_t dir;
+	struct bt_bap *bap;
 
 	if (!bap_stream_valid(stream))
 		return 0;
 
-	if (!stream->client) {
-		stream_enable(stream, metadata, NULL);
+	if (!stream->ops || !stream->ops->set_io)
 		return 0;
-	}
 
-	ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
-								user_data);
-	if (!ret || !enable_links)
-		return ret;
+	if (!bt_bap_ref_safe(stream->bap))
+		return 00;
 
-	queue_foreach(stream->links, bap_stream_enable_link, metadata);
+	bap = stream->bap;
 
-	return ret;
+	dir = stream->ops->io_dir(stream);
+
+	bt_bap_unref(bap);
+
+	return dir;
 }
 
-unsigned int bt_bap_stream_start(struct bt_bap_stream *stream,
-					bt_bap_stream_func_t func,
-					void *user_data)
+static void bap_stream_io_connecting(void *data, void *user_data)
 {
-	struct iovec iov;
-	struct bt_ascs_start start;
-	struct bt_bap_req *req;
-
-	if (!bap_stream_valid(stream))
-		return 0;
+	struct bt_bap_stream *stream = data;
+	int fd = PTR_TO_INT(user_data);
+	const struct queue_entry *entry;
 
-	if (!stream->client) {
-		if (stream->ep->dir == BT_BAP_SINK)
-			stream_start(stream, NULL);
-		return 0;
-	}
+	if (!stream)
+		return;
 
-	if (stream->ep->dir == BT_BAP_SINK)
-		return 0;
+	if (fd >= 0)
+		bap_stream_io_attach(stream, fd, true);
+	else
+		bap_stream_io_detach(stream);
 
-	memset(&start, 0, sizeof(start));
+	for (entry = queue_get_entries(stream->bap->state_cbs); entry;
+							entry = entry->next) {
+		struct bt_bap_state *state = entry->data;
 
-	start.ase = stream->ep->id;
+		if (state->connecting)
+			state->connecting(stream, stream->io ? true : false,
+							fd, state->data);
+	}
+}
 
-	iov.iov_base = &start;
-	iov.iov_len = sizeof(start);
+int bt_bap_stream_io_connecting(struct bt_bap_stream *stream, int fd)
+{
+	if (!stream)
+		return -EINVAL;
 
-	req = bap_req_new(stream, BT_ASCS_START, &iov, 1, func, user_data);
+	bap_stream_io_connecting(stream, INT_TO_PTR(fd));
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+	queue_foreach(stream->links, bap_stream_io_connecting, INT_TO_PTR(fd));
 
-	return req->id;
+	return 0;
 }
 
-static void bap_stream_disable_link(void *data, void *user_data)
+bool bt_bap_stream_io_is_connecting(struct bt_bap_stream *stream, int *fd)
 {
-	struct bt_bap_stream *stream = data;
-	struct bt_bap_req *req;
-	struct iovec iov;
-	struct bt_ascs_disable disable;
-
-	memset(&disable, 0, sizeof(disable));
+	struct bt_bap_stream_io *io;
 
-	disable.ase = stream->ep->id;
+	if (!stream)
+		return false;
 
-	iov.iov_base = &disable;
-	iov.iov_len = sizeof(disable);
+	io = stream_get_io(stream);
+	if (!io)
+		return false;
 
-	req = bap_req_new(stream, BT_ASCS_DISABLE, &iov, 1, NULL, NULL);
+	if (fd)
+		*fd = stream_io_get_fd(io);
 
-	if (!bap_queue_req(stream->bap, req))
-		bap_req_free(req);
+	return io->connecting;
 }
 
-unsigned int bt_bap_stream_disable(struct bt_bap_stream *stream,
-					bool disable_links,
-					bt_bap_stream_func_t func,
-					void *user_data)
+bool bt_bap_new_bcast_source(struct bt_bap *bap, const char *name)
 {
-	struct iovec iov;
-	struct bt_ascs_disable disable;
-	struct bt_bap_req *req;
+	struct bt_bap_endpoint *ep;
+	struct bt_bap_pac *pac_broadcast_source;
 
-	if (!bap_stream_valid(stream))
-		return 0;
+	/* Add the remote source only if a local sink endpoint was registered */
+	if (queue_isempty(bap->ldb->broadcast_sinks))
+		return false;
 
-	if (!stream->client) {
-		stream_disable(stream, NULL);
-		return 0;
-	}
+	/* Add remote source endpoint */
+	if (!bap->rdb->broadcast_sources)
+		bap->rdb->broadcast_sources = queue_new();
 
-	memset(&disable, 0, sizeof(disable));
+	if (queue_find(bap->rdb->broadcast_sources, match_name, name))
+		return true;
 
-	disable.ase = stream->ep->id;
+	pac_broadcast_source = bap_pac_new(bap->rdb, name, BT_BAP_BCAST_SOURCE,
+			NULL, NULL, NULL, NULL);
+	queue_push_tail(bap->rdb->broadcast_sources, pac_broadcast_source);
 
-	iov.iov_base = &disable;
-	iov.iov_len = sizeof(disable);
+	if (!pac_broadcast_source)
+		return false;
 
-	req = bap_req_new(stream, BT_ASCS_DISABLE, &iov, 1, func, user_data);
+	queue_foreach(bap->pac_cbs, notify_pac_added, pac_broadcast_source);
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+	/* Push remote endpoint with direction sink */
+	ep = bap_endpoint_new_broadcast(bap->rdb, BT_BAP_BCAST_SINK);
 
-	if (disable_links)
-		queue_foreach(stream->links, bap_stream_disable_link, NULL);
+	if (ep)
+		queue_push_tail(bap->remote_eps, ep);
 
-	return req->id;
+	return true;
 }
 
-unsigned int bt_bap_stream_stop(struct bt_bap_stream *stream,
-					bt_bap_stream_func_t func,
-					void *user_data)
+void bt_bap_update_bcast_source(struct bt_bap_pac *pac,
+					struct bt_bap_codec *codec,
+					struct iovec *data,
+					struct iovec *metadata)
 {
-	struct iovec iov;
-	struct bt_ascs_stop stop;
-	struct bt_bap_req *req;
-
-	if (!bap_stream_valid(stream))
-		return 0;
-
-	if (!stream->client) {
-		if (stream->ep->dir == BT_BAP_SINK)
-			stream_stop(stream, NULL);
-		return 0;
-	}
-
-	if (stream->ep->dir == BT_BAP_SINK)
-		return 0;
-
-	memset(&stop, 0, sizeof(stop));
-
-	stop.ase = stream->ep->id;
+	bap_pac_merge(pac, data, metadata);
+	pac->codec = *codec;
+}
 
-	iov.iov_base = &stop;
-	iov.iov_len = sizeof(stop);
+static void destroy_base_bis(void *data)
+{
+	struct bt_bis *bis = data;
 
-	req = bap_req_new(stream, BT_ASCS_STOP, &iov, 1, func, user_data);
+	if (!bis)
+		return;
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+	if (bis->caps)
+		util_iov_free(bis->caps, 1);
 
-	return req->id;
+	free(bis);
 }
 
-unsigned int bt_bap_stream_metadata(struct bt_bap_stream *stream,
-					struct iovec *metadata,
-					bt_bap_stream_func_t func,
-					void *user_data)
+static void generate_bis_base(void *data, void *user_data)
 {
-	if (!stream)
-		return 0;
+	struct bt_bis *bis = data;
+	struct iovec *base_iov = user_data;
+	uint8_t cc_length = bis->caps->iov_len;
 
-	if (!stream->client) {
-		stream_metadata(stream, metadata, NULL);
-		return 0;
-	}
+	if (!util_iov_push_u8(base_iov, bis->index))
+		return;
+
+	if (!util_iov_push_u8(base_iov, cc_length))
+		return;
 
-	return bap_stream_metadata(stream, BT_ASCS_METADATA, metadata, func,
-								user_data);
+	if (cc_length)
+		util_iov_push_mem(base_iov, bis->caps->iov_len,
+			bis->caps->iov_base);
 }
 
-unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
-					bt_bap_stream_func_t func,
-					void *user_data)
+static void generate_subgroup_base(void *data, void *user_data)
 {
-	struct iovec iov;
-	struct bt_ascs_release rel;
-	struct bt_bap_req *req;
+	struct bt_subgroup *sgrp = data;
+	struct iovec *base_iov = user_data;
 
-	if (!stream)
-		return 0;
+	if (!util_iov_push_u8(base_iov, queue_length(sgrp->bises)))
+		return;
 
-	if (!stream->client) {
-		stream_release(stream, NULL);
-		return 0;
-	}
+	if (!util_iov_push_u8(base_iov, sgrp->codec.id))
+		return;
 
-	memset(&req, 0, sizeof(req));
+	if (!util_iov_push_le16(base_iov, sgrp->codec.cid))
+		return;
 
-	rel.ase = stream->ep->id;
+	if (!util_iov_push_le16(base_iov, sgrp->codec.vid))
+		return;
 
-	iov.iov_base = &rel;
-	iov.iov_len = sizeof(rel);
+	if (sgrp->caps) {
+		if (!util_iov_push_u8(base_iov, sgrp->caps->iov_len))
+			return;
 
-	req = bap_req_new(stream, BT_ASCS_RELEASE, &iov, 1, func, user_data);
+		if (sgrp->caps->iov_len)
+			util_iov_push_mem(base_iov, sgrp->caps->iov_len,
+				sgrp->caps->iov_base);
+	} else if (!util_iov_push_u8(base_iov, 0))
+		return;
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+	if (sgrp->meta) {
+		if (!util_iov_push_u8(base_iov, sgrp->meta->iov_len))
+			return;
 
-	return req->id;
+		if (sgrp->meta->iov_len)
+			util_iov_push_mem(base_iov, sgrp->meta->iov_len,
+				sgrp->meta->iov_base);
+	} else if (!util_iov_push_u8(base_iov, 0))
+		return;
+
+	queue_foreach(sgrp->bises, generate_bis_base, base_iov);
 }
 
-uint8_t bt_bap_stream_get_dir(struct bt_bap_stream *stream)
+static struct iovec *generate_base(struct bt_base *base)
 {
-	if (!stream)
-		return 0x00;
+	struct iovec *base_iov = new0(struct iovec, 0x1);
 
-	return stream->ep->dir;
-}
+	base_iov->iov_base = util_malloc(BASE_MAX_LENGTH);
 
-uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
-{
-	struct bt_bap_pac *pac;
+	if (!util_iov_push_le24(base_iov, base->pres_delay)) {
+		free(base_iov->iov_base);
+		free(base_iov);
+		return NULL;
+	}
 
-	if (!stream)
-		return 0x00000000;
+	if (!util_iov_push_u8(base_iov,
+			queue_length(base->subgroups))) {
+		free(base_iov->iov_base);
+		free(base_iov);
+		return NULL;
+	}
 
-	pac = stream->rpac ? stream->rpac : stream->lpac;
+	queue_foreach(base->subgroups, generate_subgroup_base,
+				base_iov);
 
-	return pac->locations;
+	return base_iov;
 }
 
-struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
+static void add_new_bis(struct bt_subgroup *subgroup,
+			uint8_t bis_index, struct iovec *caps)
 {
-	if (!stream)
-		return NULL;
+	struct bt_bis *bis = new0(struct bt_bis, 1);
 
-	return stream->cc;
-}
+	bis->index = bis_index;
 
-struct bt_bap_qos *bt_bap_stream_get_qos(struct bt_bap_stream *stream)
-{
-	if (!stream)
-		return NULL;
+	if (caps)
+		bis->caps = caps;
+	else
+		bis->caps = new0(struct iovec, 1);
 
-	return &stream->qos;
+	queue_push_tail(subgroup->bises, bis);
 }
 
-struct iovec *bt_bap_stream_get_metadata(struct bt_bap_stream *stream)
+static void add_new_subgroup(struct bt_base *base,
+			struct bt_bap_stream *stream)
 {
-	if (!stream)
-		return NULL;
+	struct bt_bap_pac *lpac = stream->lpac;
+	struct bt_subgroup *sgrp = new0(
+				struct bt_subgroup, 1);
+	uint16_t cid = 0;
+	uint16_t vid = 0;
+
+	bt_bap_pac_get_vendor_codec(lpac, &sgrp->codec.id, &cid,
+			&vid, NULL, NULL);
+	sgrp->codec.cid = cid;
+	sgrp->codec.vid = vid;
+	sgrp->caps = util_iov_dup(stream->cc, 1);
+	sgrp->meta = util_iov_dup(stream->meta, 1);
+	sgrp->bises = queue_new();
+
+	stream->qos.bcast.bis = base->next_bis_index++;
+	add_new_bis(sgrp, stream->qos.bcast.bis,
+					NULL);
+	queue_push_tail(base->subgroups, sgrp);
+}
+
+struct bt_ltv_match {
+	uint8_t l;
+	void *data;
+	bool found;
+	uint32_t data32;
+};
 
-	return stream->meta;
-}
+struct bt_ltv_search {
+	struct iovec *iov;
+	bool found;
+};
 
-struct io *bt_bap_stream_get_io(struct bt_bap_stream *stream)
+static void match_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
 {
-	struct bt_bap_stream_io *io;
+	struct bt_ltv_match *ltv_match = user_data;
 
-	io = stream_get_io(stream);
-	if (!io || io->connecting)
-		return NULL;
+	if (ltv_match->found == true)
+		return;
 
-	return io->io;
+	if (ltv_match->l != l)
+		return;
+
+	if (!memcmp(v, ltv_match->data, l))
+		ltv_match->found = true;
 }
 
-static bool stream_io_disconnected(struct io *io, void *user_data)
+static void search_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
 {
-	struct bt_bap_stream *stream = user_data;
+	struct bt_ltv_search *ltv_search = user_data;
+	struct bt_ltv_match ltv_match;
 
-	DBG(stream->bap, "stream %p io disconnected", stream);
+	ltv_match.found = false;
+	ltv_match.l = l;
+	ltv_match.data = v;
 
-	bt_bap_stream_set_io(stream, -1);
+	util_ltv_foreach(ltv_search->iov->iov_base,
+			ltv_search->iov->iov_len, &t,
+			match_ltv, &ltv_match);
 
-	return false;
+	/* Once "found" has been updated to "false",
+	 * do not overwrite it anymore.
+	 * It means that an ltv was not found in the search list,
+	 * and this should be detected back in the parent function.
+	 */
+	if (ltv_search->found)
+		ltv_search->found = ltv_match.found;
 }
 
-bool bt_bap_stream_set_io(struct bt_bap_stream *stream, int fd)
+static bool compare_ltv(struct iovec *iov1,
+		struct iovec *iov2)
 {
-	if (!stream || (fd >= 0 && stream->io && !stream->io->connecting))
-		return false;
+	struct bt_ltv_search ltv_search;
 
-	bap_stream_set_io(stream, INT_TO_PTR(fd));
+	if ((!iov1) && (!iov2))
+		return true;
 
-	queue_foreach(stream->links, bap_stream_set_io, INT_TO_PTR(fd));
+	if ((!iov1) || (!iov2))
+		return false;
 
-	return true;
-}
+	/* Compare metadata length */
+	if (iov1->iov_len != iov2->iov_len)
+		return false;
 
-static bool match_req_id(const void *data, const void *match_data)
-{
-	const struct bt_bap_req *req = data;
-	unsigned int id = PTR_TO_UINT(match_data);
+	ltv_search.found = true;
+	ltv_search.iov = iov2;
 
-	return (req->id == id);
+	util_ltv_foreach(iov1->iov_base,
+			iov1->iov_len, NULL,
+			search_ltv, &ltv_search);
+
+	return ltv_search.found;
 }
 
-int bt_bap_stream_cancel(struct bt_bap_stream *stream, unsigned int id)
+struct bt_ltv_extract {
+	struct iovec *src;
+	void *value;
+	uint8_t len;
+	struct iovec *result;
+};
+
+static void extract_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
 {
-	struct bt_bap_req *req;
+	struct bt_ltv_extract *ext_data = user_data;
+	struct bt_ltv_match ltv_match;
+	uint8_t ltv_len = 0;
 
-	if (!stream)
-		return -EINVAL;
+	ltv_match.found = false;
+	ltv_match.l = l;
+	ltv_match.data = v;
 
-	if (stream->bap->req && stream->bap->req->id == id) {
-		req = stream->bap->req;
-		stream->bap->req = NULL;
-		bap_req_free(req);
-		return 0;
+	/* Search each BIS caps ltv in subgroup caps
+	 * to extract the one that are BIS specific
+	 */
+	util_ltv_foreach(ext_data->src->iov_base,
+			ext_data->src->iov_len, &t,
+			match_ltv, &ltv_match);
+
+	if (!ltv_match.found) {
+		ltv_len = l + 1;
+		util_iov_append(ext_data->result, &ltv_len, 1);
+		util_iov_append(ext_data->result, &t, 1);
+		util_iov_append(ext_data->result, v, l);
 	}
+}
 
-	req = queue_remove_if(stream->bap->reqs, match_req_id,
-						UINT_TO_PTR(id));
-	if (!req)
-		return 0;
+static struct iovec *extract_diff_caps(
+		struct iovec *subgroup_caps, struct iovec *bis_caps)
+{
+	struct bt_ltv_extract ext_data;
 
-	bap_req_free(req);
+	ext_data.src = subgroup_caps;
+	ext_data.result = new0(struct iovec, 1);
 
-	return 0;
+	util_ltv_foreach(bis_caps->iov_base,
+			bis_caps->iov_len, NULL,
+			extract_ltv, &ext_data);
+
+	return ext_data.result;
 }
 
-int bt_bap_stream_io_link(struct bt_bap_stream *stream,
-				struct bt_bap_stream *link)
+static void set_base_subgroup(void *data, void *user_data)
 {
-	struct bt_bap *bap = stream->bap;
+	struct bt_bap_stream *stream = data;
+	struct bt_base *base = user_data;
+	/* BIS specific codec capabilities */
+	struct iovec *bis_caps;
 
-	if (!stream || !link || stream == link)
-		return -EINVAL;
+	if (bt_bap_pac_get_type(stream->lpac) != BT_BAP_BCAST_SOURCE)
+		return;
 
-	if (queue_find(stream->links, NULL, link))
-		return -EALREADY;
+	if (stream->qos.bcast.big != base->big_id)
+		return;
 
-	if (stream->client != link->client ||
-			stream->qos.cig_id != link->qos.cig_id ||
-			stream->qos.cis_id != link->qos.cis_id)
-		return -EINVAL;
+	if (base->pres_delay < stream->qos.bcast.delay)
+		base->pres_delay = stream->qos.bcast.delay;
 
-	if (!stream->links)
-		stream->links = queue_new();
+	if (queue_isempty(base->subgroups)) {
+		add_new_subgroup(base, stream);
+	} else {
+		/* Verify if a subgroup has the same metadata */
+		const struct queue_entry *entry;
+		struct bt_subgroup *subgroup = NULL;
+		bool same_meta = false;
+
+		for (entry = queue_get_entries(base->subgroups);
+						entry; entry = entry->next) {
+			subgroup = entry->data;
+			same_meta = compare_ltv(subgroup->meta,	stream->meta);
+			if (same_meta)
+				break;
+		}
 
-	if (!link->links)
-		link->links = queue_new();
+		if (!same_meta) {
+			/* No subgroup with the same metadata found.
+			 * Create a new one.
+			 */
+			add_new_subgroup(base, stream);
+		} else {
+			/* Subgroup found with the same metadata.
+			 * Extract different codec capabilities.
+			 */
+			bis_caps = extract_diff_caps(
+					subgroup->caps,
+					stream->cc);
+
+			stream->qos.bcast.bis = base->next_bis_index++;
+			add_new_bis(subgroup,
+					stream->qos.bcast.bis,
+					bis_caps);
+		}
+	}
+}
 
-	queue_push_tail(stream->links, link);
-	queue_push_tail(link->links, stream);
+static void destroy_base_subgroup(void *data)
+{
+	struct bt_subgroup *subgroup = data;
 
-	/* Link IOs if already set on stream/link */
-	if (stream->io && !link->io)
-		link->io = stream_io_ref(stream->io);
-	else if (link->io && !stream->io)
-		stream->io = stream_io_ref(link->io);
+	if (!subgroup)
+		return;
 
-	DBG(bap, "stream %p link %p", stream, link);
+	if (subgroup->caps)
+		util_iov_free(subgroup->caps, 1);
 
-	return 0;
-}
+	if (subgroup->meta)
+		util_iov_free(subgroup->meta, 1);
 
-struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream)
-{
-	if (!stream)
-		return NULL;
+	queue_destroy(subgroup->bises, destroy_base_bis);
 
-	return stream->links;
+	free(subgroup);
 }
 
-static void bap_stream_get_in_qos(void *data, void *user_data)
+/*
+ * Function to update the BASE using configuration data
+ * from each BIS belonging to the same BIG
+ */
+struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream)
 {
-	struct bt_bap_stream *stream = data;
-	struct bt_bap_qos **qos = user_data;
+	struct bt_base base;
+	struct iovec *base_iov;
 
-	if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
-						!stream->qos.sdu)
-		return;
+	base.subgroups = queue_new();
+	base.next_bis_index = 1;
+	base.big_id = stream->qos.bcast.big;
+	base.pres_delay = stream->qos.bcast.delay;
 
-	*qos = &stream->qos;
-}
+	/* If the BIG ID was explicitly set, create a BASE with information
+	 * from all streams belonging to this BIG. Otherwise, create a BASE
+	 * with only this BIS.
+	 */
+	if (stream->qos.bcast.big != 0xFF)
+		queue_foreach(stream->bap->streams, set_base_subgroup, &base);
+	else {
+		base.pres_delay = stream->qos.bcast.delay;
+		set_base_subgroup(stream, &base);
+	}
 
-static void bap_stream_get_out_qos(void *data, void *user_data)
-{
-	struct bt_bap_stream *stream = data;
-	struct bt_bap_qos **qos = user_data;
+	base_iov = generate_base(&base);
 
-	if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.sdu)
-		return;
+	queue_destroy(base.subgroups, destroy_base_subgroup);
 
-	*qos = &stream->qos;
+	return base_iov;
 }
 
-bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
-					struct bt_bap_qos **in,
-					struct bt_bap_qos **out)
+/*
+ * This function compares PAC Codec Specific Capabilities, with the Codec
+ * Specific Configuration LTVs received in the BASE of the BAP Source. The
+ * result is accumulated in data32 which is a bitmask of types.
+ */
+static void check_pac_caps_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
 {
-	if (!stream || (!in && !out))
-		return false;
+	struct bt_ltv_match *compare_data = user_data;
+	uint8_t *bis_v = compare_data->data;
+	uint16_t mask;
+	uint16_t min;
+	uint16_t max;
+	uint16_t frame_len;
 
-	switch (stream->ep->dir) {
-	case BT_BAP_SOURCE:
-		bap_stream_get_in_qos(stream, in);
-		queue_foreach(stream->links, bap_stream_get_out_qos, out);
+	switch (t) {
+	case BAP_FREQ_LTV_TYPE:
+		mask = get_le16(v);
+
+		if (mask & (1 << (bis_v[0] - 1)))
+			compare_data->data32 |= 1<<t;
 		break;
-	case BT_BAP_SINK:
-		bap_stream_get_out_qos(stream, out);
-		queue_foreach(stream->links, bap_stream_get_in_qos, in);
+	case BAP_DURATION_LTV_TYPE:
+		if ((v[0]) & (1 << bis_v[0]))
+			compare_data->data32 |= 1<<t;
+		break;
+	case BAP_FRAME_LEN_LTV_TYPE:
+		min = get_le16(v);
+		max = get_le16(v + 2);
+		frame_len = get_le16(bis_v);
+
+		if ((frame_len >= min) &&
+				(frame_len <= max))
+			compare_data->data32 |= 1<<t;
 		break;
-	default:
-		return false;
 	}
+}
 
-	DBG(stream->bap, "in %p out %p", in ? *in : NULL, out ? *out : NULL);
+static void check_source_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
+{
+	struct bt_ltv_match *local_data = user_data;
+	struct iovec *pac_caps = local_data->data;
+	struct bt_ltv_match compare_data;
 
-	return in && out;
+	compare_data.data = v;
+
+	/* Search inside local PAC's caps for LTV of type t */
+	util_ltv_foreach(pac_caps->iov_base, pac_caps->iov_len, &t,
+					check_pac_caps_ltv, &compare_data);
+
+	local_data->data32 |= compare_data.data32;
 }
 
-static void bap_stream_get_dir(void *data, void *user_data)
+static void bap_sink_check_level3_ltv(size_t i, uint8_t l, uint8_t t,
+		uint8_t *v, void *user_data)
 {
-	struct bt_bap_stream *stream = data;
-	uint8_t *dir = user_data;
+	struct bt_ltv_extract *merge_data = user_data;
 
-	*dir |= stream->ep->dir;
+	merge_data->value = v;
+	merge_data->len = l;
 }
 
-uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream)
+static void bap_sink_check_level2_ltv(size_t i, uint8_t l, uint8_t t,
+		uint8_t *v, void *user_data)
 {
-	uint8_t dir;
+	struct bt_ltv_extract *merge_data = user_data;
 
-	if (!stream)
-		return 0x00;
+	merge_data->value = NULL;
+	util_ltv_foreach(merge_data->src->iov_base,
+			merge_data->src->iov_len,
+			&t,
+			bap_sink_check_level3_ltv, merge_data);
 
-	dir = stream->ep->dir;
+	/* If the LTV at level 2 was found at level 3 add the one from level 3,
+	 * otherwise add the one at level 2
+	 */
+	if (merge_data->value)
+		util_ltv_push(merge_data->result, merge_data->len,
+				t, merge_data->value);
+	else
+		util_ltv_push(merge_data->result, l, t, v);
+}
 
-	queue_foreach(stream->links, bap_stream_get_dir, &dir);
+static void check_local_pac(void *data, void *user_data)
+{
+	struct bt_ltv_match *compare_data = user_data;
+	struct iovec *bis_data = (struct iovec *)compare_data->data;
+	const struct bt_bap_pac *pac = data;
 
-	return dir;
+	/* Keep searching for a matching PAC if one wasn't found
+	 * in previous PAC element
+	 */
+	if (compare_data->found == false) {
+		struct bt_ltv_match bis_compare_data = {
+				.data = pac->data,
+				.data32 = 0, /* LTVs bitmask result */
+				.found = false
+		};
+
+		/* loop each BIS LTV */
+		util_ltv_foreach(bis_data->iov_base, bis_data->iov_len, NULL,
+				check_source_ltv, &bis_compare_data);
+
+		/* We have a match if all selected LTVs have a match */
+		if ((bis_compare_data.data32 &
+				CODEC_SPECIFIC_CONFIGURATION_MASK) ==
+				CODEC_SPECIFIC_CONFIGURATION_MASK) {
+			compare_data->found = true;
+			compare_data->data = data;
+		}
+	}
 }
 
-static void bap_stream_io_connecting(void *data, void *user_data)
+static void bap_sink_match_allocation(size_t i, uint8_t l, uint8_t t,
+		uint8_t *v, void *user_data)
 {
-	struct bt_bap_stream *stream = data;
-	int fd = PTR_TO_INT(user_data);
-	const struct queue_entry *entry;
+	struct bt_ltv_match *data = user_data;
+	uint32_t location32;
 
-	if (fd >= 0)
-		bap_stream_io_attach(stream, fd, true);
+	if (!v)
+		return;
+
+	memcpy(&location32, v, l);
+	location32 = le32_to_cpu(location32);
+
+	/* If all the bits in the received bitmask are found in
+	 * the local bitmask then we have a match
+	 */
+	if ((location32 & data->data32) == location32)
+		data->found = true;
 	else
-		bap_stream_io_detach(stream);
+		data->found = false;
+}
 
-	for (entry = queue_get_entries(stream->bap->state_cbs); entry;
-							entry = entry->next) {
-		struct bt_bap_state *state = entry->data;
+static struct bt_ltv_match bap_check_bis(uint32_t sink_loc, struct queue *pacs,
+	struct iovec *bis_data)
+{
+	struct bt_ltv_match compare_data = {};
 
-		if (state->connecting)
-			state->connecting(stream, stream->io ? true : false,
-							fd, state->data);
+	/* Check channel allocation against the PACS location.
+	 * If we don't have a location set we can accept any BIS location.
+	 * If the BIS doesn't have a location set we also accept it
+	 */
+	compare_data.found = true;
+
+	if (sink_loc) {
+		uint8_t type = BAP_CHANNEL_ALLOCATION_LTV_TYPE;
+
+		compare_data.data32 = sink_loc;
+		util_ltv_foreach(bis_data->iov_base, bis_data->iov_len, &type,
+				bap_sink_match_allocation, &compare_data);
+	}
+
+	/* Check remaining LTVs against the PACs list */
+	if (compare_data.found) {
+		compare_data.data = bis_data;
+		compare_data.found = false;
+		queue_foreach(pacs, check_local_pac, &compare_data);
 	}
+
+	return compare_data;
 }
 
-int bt_bap_stream_io_connecting(struct bt_bap_stream *stream, int fd)
+struct iovec *bt_bap_merge_caps(struct iovec *l2_caps, struct iovec *l3_caps)
 {
-	if (!stream)
-		return -EINVAL;
+	struct bt_ltv_extract merge_data = {0};
 
-	bap_stream_io_connecting(stream, INT_TO_PTR(fd));
+	if (!l2_caps)
+		/* Codec_Specific_Configuration parameters shall
+		 * be present at Level 2.
+		 */
+		return NULL;
 
-	queue_foreach(stream->links, bap_stream_io_connecting, INT_TO_PTR(fd));
+	if (!l3_caps)
+		/* Codec_Specific_Configuration parameters may
+		 * be present at Level 3.
+		 */
+		return util_iov_dup(l2_caps, 1);
 
-	return 0;
+	merge_data.src = l3_caps;
+	merge_data.result = new0(struct iovec, 1);
+
+	/* Create a Codec Specific Configuration with LTVs at level 2 (subgroup)
+	 * overwritten by LTVs at level 3 (BIS)
+	 */
+	util_ltv_foreach(l2_caps->iov_base,
+			l2_caps->iov_len,
+			NULL,
+			bap_sink_check_level2_ltv, &merge_data);
+
+	return merge_data.result;
 }
 
-bool bt_bap_stream_io_is_connecting(struct bt_bap_stream *stream, int *fd)
+void bt_bap_verify_bis(struct bt_bap *bap, uint8_t bis_index,
+		struct iovec *caps,
+		struct bt_bap_pac **lpac)
 {
-	struct bt_bap_stream_io *io;
+	struct bt_ltv_match match_data;
+	uint32_t sink_loc;
+	struct queue *pacs;
 
-	if (!stream)
-		return false;
+	if (!caps)
+		return;
 
-	io = stream_get_io(stream);
-	if (!io)
-		return false;
+	/* If the bap session corresponds to a client connection with
+	 * a BAP Server, bis caps should be checked against peer caps.
+	 * If the bap session corresponds to a scanned broadcast source,
+	 * bis caps should be checked against local broadcast sink caps.
+	 */
+	if (bap->client) {
+		sink_loc = bap->rdb->pacs->sink_loc_value;
+		pacs = bap->rdb->sinks;
+	} else {
+		sink_loc = bap->ldb->pacs->sink_loc_value;
+		pacs = bap->ldb->broadcast_sinks;
+	}
 
-	if (fd)
-		*fd = stream_io_get_fd(io);
+	/* Check each BIS Codec Specific Configuration LTVs against our Codec
+	 * Specific Capabilities and if the BIS matches create a PAC with it
+	 */
+	match_data = bap_check_bis(sink_loc, pacs, caps);
+	if (match_data.found == true) {
+		*lpac = match_data.data;
+		DBG(bap, "Matching BIS %i", bis_index);
+	} else {
+		*lpac = NULL;
+	}
 
-	return io->connecting;
 }
diff --git a/src/shared/bap.h b/src/shared/bap.h
index 7b9f88c..126348e 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -4,64 +4,18 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  */
 
 #include <stdbool.h>
 #include <inttypes.h>
-
-#ifndef __packed
-#define __packed __attribute__((packed))
-#endif
-
-#define BT_BAP_SINK			0x01
-#define	BT_BAP_SOURCE			0x02
-
-#define BT_BAP_STREAM_STATE_IDLE	0x00
-#define BT_BAP_STREAM_STATE_CONFIG	0x01
-#define BT_BAP_STREAM_STATE_QOS		0x02
-#define BT_BAP_STREAM_STATE_ENABLING	0x03
-#define BT_BAP_STREAM_STATE_STREAMING	0x04
-#define BT_BAP_STREAM_STATE_DISABLING	0x05
-#define BT_BAP_STREAM_STATE_RELEASING	0x06
-
-#define BT_BAP_CONFIG_LATENCY_LOW	0x01
-#define BT_BAP_CONFIG_LATENCY_BALACED	0x02
-#define BT_BAP_CONFIG_LATENCY_HIGH	0x03
-
-#define BT_BAP_CONFIG_PHY_1M		0x01
-#define BT_BAP_CONFIG_PHY_2M		0x02
-#define BT_BAP_CONFIG_PHY_CODEC		0x03
+#include "src/shared/bap-defs.h"
 
 struct bt_bap;
 struct bt_bap_pac;
 struct bt_bap_stream;
 
-struct bt_bap_codec {
-	uint8_t  id;
-	uint16_t vid;
-	uint16_t cid;
-} __packed;
-
-struct bt_ltv {
-	uint8_t  len;
-	uint8_t  type;
-	uint8_t  value[0];
-} __packed;
-
-struct bt_bap_qos {
-	uint8_t  cig_id;
-	uint8_t  cis_id;
-	uint32_t interval;		/* Frame interval */
-	uint8_t  framing;		/* Frame framing */
-	uint8_t  phy;			/* PHY */
-	uint16_t sdu;			/* Maximum SDU Size */
-	uint8_t  rtn;			/* Retransmission Effort */
-	uint16_t latency;		/* Transport Latency */
-	uint32_t delay;			/* Presentation Delay */
-	uint8_t  target_latency;	/* Target Latency */
-};
-
 typedef void (*bt_bap_ready_func_t)(struct bt_bap *bap, void *user_data);
 typedef void (*bt_bap_destroy_func_t)(void *user_data);
 typedef void (*bt_bap_debug_func_t)(const char *str, void *user_data);
@@ -87,12 +41,6 @@ typedef void (*bt_bap_stream_func_t)(struct bt_bap_stream *stream,
 typedef void (*bt_bap_func_t)(struct bt_bap *bap, void *user_data);
 
 /* Local PAC related functions */
-
-unsigned int bt_bap_pac_register(bt_bap_pac_func_t added,
-				bt_bap_pac_func_t removed, void *user_data,
-				bt_bap_destroy_func_t destroy);
-bool bt_bap_pac_unregister(unsigned int id);
-
 struct bt_bap_pac_qos {
 	uint8_t  framing;
 	uint8_t  phy;
@@ -102,6 +50,9 @@ struct bt_bap_pac_qos {
 	uint32_t pd_max;
 	uint32_t ppd_min;
 	uint32_t ppd_max;
+	uint32_t location;
+	uint16_t supported_context;
+	uint16_t context;
 };
 
 struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
@@ -119,7 +70,9 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
 
 struct bt_bap_pac_ops {
 	int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-			struct bt_bap_pac_qos *qos,
+			uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
+			bt_bap_pac_select_t cb, void *cb_data, void *user_data);
+	void (*cancel_select)(struct bt_bap_pac *lpac,
 			bt_bap_pac_select_t cb, void *cb_data, void *user_data);
 	int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
 			struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
@@ -134,6 +87,20 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac);
 
 uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac);
 
+uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac);
+
+uint16_t bt_bap_pac_get_supported_context(struct bt_bap_pac *pac);
+
+uint16_t bt_bap_pac_get_context(struct bt_bap_pac *pac);
+
+struct bt_bap_pac_qos *bt_bap_pac_get_qos(struct bt_bap_pac *pac);
+
+struct iovec *bt_bap_pac_get_data(struct bt_bap_pac *pac);
+
+struct iovec *bt_bap_pac_get_metadata(struct bt_bap_pac *pac);
+
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream);
+
 struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac);
 
 /* Session related function */
@@ -153,13 +120,16 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap);
 void bt_bap_unref(struct bt_bap *bap);
 
 bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client);
+bool bt_bap_attach_broadcast(struct bt_bap *bap);
 void bt_bap_detach(struct bt_bap *bap);
 
 bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,
 			void *user_data, bt_bap_destroy_func_t destroy);
 
-bool bap_print_cc(void *data, size_t len, util_debug_func_t func,
-						void *user_data);
+unsigned int bt_bap_pac_register(struct bt_bap *bap, bt_bap_pac_func_t added,
+				bt_bap_pac_func_t removed, void *user_data,
+				bt_bap_destroy_func_t destroy);
+bool bt_bap_pac_unregister(struct bt_bap *bap, unsigned int id);
 
 unsigned int bt_bap_ready_register(struct bt_bap *bap,
 				bt_bap_ready_func_t func, void *user_data,
@@ -189,15 +159,17 @@ void *bt_bap_pac_get_user_data(struct bt_bap_pac *pac);
 
 /* Stream related functions */
 int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-			bt_bap_pac_select_t func, void *user_data);
+			int *count, bt_bap_pac_select_t func,
+			void *user_data);
+
+void bt_bap_cancel_select(struct bt_bap_pac *lpac, bt_bap_pac_select_t func,
+			void *user_data);
 
-struct bt_bap_stream *bt_bap_config(struct bt_bap *bap,
+struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
 					struct bt_bap_pac *lpac,
 					struct bt_bap_pac *rpac,
 					struct bt_bap_qos *pqos,
-					struct iovec *data,
-					bt_bap_stream_func_t func,
-					void *user_data);
+					struct iovec *data);
 
 struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream);
 uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream);
@@ -252,13 +224,15 @@ struct bt_bap_qos *bt_bap_stream_get_qos(struct bt_bap_stream *stream);
 struct iovec *bt_bap_stream_get_metadata(struct bt_bap_stream *stream);
 
 struct io *bt_bap_stream_get_io(struct bt_bap_stream *stream);
-
+bool bt_bap_match_bcast_sink_stream(const void *data, const void *user_data);
 bool bt_bap_stream_set_io(struct bt_bap_stream *stream, int fd);
 
 int bt_bap_stream_cancel(struct bt_bap_stream *stream, unsigned int id);
 
 int bt_bap_stream_io_link(struct bt_bap_stream *stream,
 					struct bt_bap_stream *link);
+int bt_bap_stream_io_unlink(struct bt_bap_stream *stream,
+					struct bt_bap_stream *link);
 struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream);
 bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
 					struct bt_bap_qos **in,
@@ -268,3 +242,20 @@ uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream);
 
 int bt_bap_stream_io_connecting(struct bt_bap_stream *stream, int fd);
 bool bt_bap_stream_io_is_connecting(struct bt_bap_stream *stream, int *fd);
+
+bool bt_bap_new_bcast_source(struct bt_bap *bap, const char *name);
+void bt_bap_update_bcast_source(struct bt_bap_pac *pac,
+					struct bt_bap_codec *codec,
+					struct iovec *data,
+					struct iovec *metadata);
+
+bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac);
+
+struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream);
+
+struct iovec *bt_bap_merge_caps(struct iovec *l2_caps, struct iovec *l3_caps);
+
+void bt_bap_verify_bis(struct bt_bap *bap, uint8_t bis_index,
+		struct iovec *caps,
+		struct bt_bap_pac **lpac);
+
diff --git a/src/shared/bass.c b/src/shared/bass.c
new file mode 100644
index 0000000..d99a140
--- /dev/null
+++ b/src/shared/bass.c
@@ -0,0 +1,1875 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2023-2024 NXP
+ *
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/bass.h"
+
+#define DBG(_bass, fmt, arg...) \
+	bass_debug(_bass, "%s:%s() " fmt, __FILE__, __func__, ## arg)
+
+struct bt_bass_db;
+
+struct bt_bass_cb {
+	unsigned int id;
+	bt_bass_func_t attached;
+	bt_bass_func_t detached;
+	void *user_data;
+};
+
+struct bt_bcast_recv_state {
+	struct bt_bass_db *bdb;
+	struct gatt_db_attribute *attr;
+	struct gatt_db_attribute *ccc;
+};
+
+struct bt_bass_db {
+	struct gatt_db *db;
+	bdaddr_t adapter_bdaddr;
+	struct queue *bcast_srcs;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *bcast_audio_scan_cp;
+	struct bt_bcast_recv_state *bcast_recv_states[NUM_BCAST_RECV_STATES];
+};
+
+struct bt_bass {
+	int ref_count;
+	struct bt_bass_db *ldb;
+	struct bt_bass_db *rdb;
+	struct bt_gatt_client *client;
+	struct bt_att *att;
+
+	struct queue *notify;
+
+	bt_bass_debug_func_t debug_func;
+	bt_bass_destroy_func_t debug_destroy;
+	void *debug_data;
+
+	struct queue *src_cbs;
+	struct queue *cp_handlers;
+
+	unsigned int disconn_id;
+
+	void *user_data;
+};
+
+struct bt_bass_cp_handler {
+	unsigned int id;
+	bt_bass_cp_handler_func_t handler;
+	bt_bass_destroy_func_t destroy;
+	void *data;
+};
+
+/* BASS subgroup field of the Broadcast
+ * Receive State characteristic
+ */
+struct bt_bass_subgroup_data {
+	uint32_t bis_sync;
+	uint32_t pending_bis_sync;
+	uint8_t meta_len;
+	uint8_t *meta;
+};
+
+/* BASS Broadcast Source structure */
+struct bt_bcast_src {
+	struct bt_bass *bass;
+	struct gatt_db_attribute *attr;
+	uint8_t id;
+	uint8_t addr_type;
+	bdaddr_t addr;
+	uint8_t sid;
+	uint32_t bid;
+	uint8_t sync_state;
+	uint8_t enc;
+	uint8_t bad_code[BT_BASS_BCAST_CODE_SIZE];
+	uint8_t num_subgroups;
+	struct bt_bass_subgroup_data *subgroup_data;
+};
+
+typedef void (*bass_notify_t)(struct bt_bass *bass, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data);
+
+struct bt_bass_notify {
+	unsigned int id;
+	struct bt_bass *bass;
+	bass_notify_t func;
+	void *user_data;
+};
+
+static struct queue *bass_db;
+static struct queue *bass_cbs;
+static struct queue *sessions;
+
+struct bt_bass_src_changed {
+	unsigned int id;
+	bt_bass_src_func_t cb;
+	bt_bass_destroy_func_t destroy;
+	void *data;
+};
+
+static void bass_bcast_src_free(void *data);
+
+static void bass_debug(struct bt_bass *bass, const char *format, ...)
+{
+	va_list ap;
+
+	if (!bass || !format || !bass->debug_func)
+		return;
+
+	va_start(ap, format);
+	util_debug_va(bass->debug_func, bass->debug_data, format, ap);
+	va_end(ap);
+}
+
+unsigned int bt_bass_cp_handler_register(struct bt_bass *bass,
+				bt_bass_cp_handler_func_t handler,
+				bt_bass_destroy_func_t destroy,
+				void *user_data)
+{
+	struct bt_bass_cp_handler *cb;
+	static unsigned int id;
+
+	if (!bass)
+		return 0;
+
+	cb = new0(struct bt_bass_cp_handler, 1);
+	cb->id = ++id ? id : ++id;
+	cb->handler = handler;
+	cb->destroy = destroy;
+	cb->data = user_data;
+
+	queue_push_tail(bass->cp_handlers, cb);
+
+	return cb->id;
+}
+
+static void bass_cp_handler_free(void *data)
+{
+	struct bt_bass_cp_handler *cb = data;
+
+	if (cb->destroy)
+		cb->destroy(cb->data);
+
+	free(cb);
+}
+
+static bool match_cb_id(const void *data, const void *match_data)
+{
+	const struct bt_bass_cp_handler *cb = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (cb->id == id);
+}
+
+bool bt_bass_cp_handler_unregister(struct bt_bass *bass,
+				unsigned int id)
+{
+	struct bt_bass_cp_handler *cb;
+
+	if (!bass)
+		return false;
+
+	cb = queue_remove_if(bass->cp_handlers, match_cb_id,
+						UINT_TO_PTR(id));
+	if (!cb)
+		return false;
+
+	bass_cp_handler_free(cb);
+
+	return true;
+}
+
+unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb,
+				void *user_data, bt_bass_destroy_func_t destroy)
+{
+	struct bt_bass_src_changed *changed;
+	static unsigned int id;
+
+	if (!bass)
+		return 0;
+
+	changed = new0(struct bt_bass_src_changed, 1);
+	if (!changed)
+		return 0;
+
+	changed->id = ++id ? id : ++id;
+	changed->cb = cb;
+	changed->destroy = destroy;
+	changed->data = user_data;
+
+	queue_push_tail(bass->src_cbs, changed);
+
+	return changed->id;
+}
+
+static void bass_src_changed_free(void *data)
+{
+	struct bt_bass_src_changed *changed = data;
+
+	if (changed->destroy)
+		changed->destroy(changed->data);
+
+	free(changed);
+}
+
+static bool match_src_changed_id(const void *data, const void *match_data)
+{
+	const struct bt_bass_src_changed *changed = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (changed->id == id);
+}
+
+bool bt_bass_src_unregister(struct bt_bass *bass, unsigned int id)
+{
+	struct bt_bass_src_changed *changed;
+
+	if (!bass)
+		return false;
+
+	changed = queue_remove_if(bass->src_cbs, match_src_changed_id,
+						UINT_TO_PTR(id));
+	if (!changed)
+		return false;
+
+	bass_src_changed_free(changed);
+
+	return true;
+}
+
+static int bass_build_bcast_src(struct bt_bcast_src *bcast_src,
+				const uint8_t *value, uint16_t length)
+{
+	struct bt_bass_subgroup_data *subgroup_data = NULL;
+	uint8_t id;
+	uint8_t addr_type;
+	uint8_t *addr;
+	uint8_t sid;
+	uint32_t bid;
+	uint8_t pa_sync_state;
+	uint8_t enc;
+	uint8_t *bad_code = NULL;
+	uint8_t num_subgroups;
+	uint32_t bis_sync_state;
+	uint8_t meta_len;
+	uint8_t *meta;
+
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = length,
+	};
+
+	/* Extract all fields from notification */
+	if (!util_iov_pull_u8(&iov, &id)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (!util_iov_pull_u8(&iov, &addr_type)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	addr = util_iov_pull_mem(&iov, sizeof(bdaddr_t));
+	if (!addr) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (!util_iov_pull_u8(&iov, &sid)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (!util_iov_pull_le24(&iov, &bid)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (!util_iov_pull_u8(&iov, &pa_sync_state)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (!util_iov_pull_u8(&iov, &enc)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (enc == BT_BASS_BIG_ENC_STATE_BAD_CODE) {
+		bad_code = util_iov_pull_mem(&iov, BT_BASS_BCAST_CODE_SIZE);
+		if (!bad_code) {
+			DBG(bcast_src->bass, "Unable to parse "
+				"Broadcast Receive State");
+			return -1;
+		}
+	}
+
+	if (!util_iov_pull_u8(&iov, &num_subgroups)) {
+		DBG(bcast_src->bass, "Unable to parse Broadcast Receive State");
+		return -1;
+	}
+
+	if (num_subgroups == 0)
+		goto done;
+
+	subgroup_data = new0(struct bt_bass_subgroup_data, 1);
+	if (!subgroup_data) {
+		DBG(bcast_src->bass, "Unable to allocate memory");
+		return -1;
+	}
+
+	for (int i = 0; i < num_subgroups; i++) {
+		if (!util_iov_pull_le32(&iov, &bis_sync_state)) {
+			DBG(bcast_src->bass, "Unable to parse "
+				"Broadcast Receive State");
+
+			for (int j = 0; j < i; j++)
+				free(subgroup_data[j].meta);
+
+			free(subgroup_data);
+			return -1;
+		}
+
+		subgroup_data[i].bis_sync = bis_sync_state;
+
+		if (!util_iov_pull_u8(&iov, &meta_len)) {
+			DBG(bcast_src->bass, "Unable to parse "
+				"Broadcast Receive State");
+
+			for (int j = 0; j < i; j++)
+				free(subgroup_data[j].meta);
+
+			free(subgroup_data);
+			return -1;
+		}
+
+		subgroup_data[i].meta_len = meta_len;
+
+		if (meta_len == 0)
+			continue;
+
+		subgroup_data[i].meta = malloc0(meta_len);
+		if (!subgroup_data[i].meta) {
+			DBG(bcast_src->bass, "Unable to allocate memory");
+
+			for (int j = 0; j < i; j++)
+				free(subgroup_data[j].meta);
+
+			free(subgroup_data);
+			return -1;
+		}
+
+		meta = util_iov_pull_mem(&iov, meta_len);
+		if (!meta) {
+			DBG(bcast_src->bass, "Unable to parse "
+				"Broadcast Receive State");
+
+			for (int j = 0; j < i; j++)
+				free(subgroup_data[j].meta);
+
+			free(subgroup_data);
+			return -1;
+		}
+
+		memcpy(subgroup_data[i].meta, meta, meta_len);
+	}
+
+done:
+	/*
+	 * If no errors occurred, copy extracted fields into
+	 * the broadcast source structure
+	 */
+	if (bcast_src->subgroup_data) {
+		for (int i = 0; i < bcast_src->num_subgroups; i++)
+			free(bcast_src->subgroup_data[i].meta);
+
+		free(bcast_src->subgroup_data);
+	}
+
+	bcast_src->id = id;
+	bcast_src->addr_type = addr_type;
+	memcpy(&bcast_src->addr, addr, sizeof(bdaddr_t));
+	bcast_src->sid = sid;
+	bcast_src->bid = bid;
+	bcast_src->sync_state = pa_sync_state;
+	bcast_src->enc = enc;
+
+	if (enc == BT_BASS_BIG_ENC_STATE_BAD_CODE)
+		memcpy(bcast_src->bad_code, bad_code, BT_BASS_BCAST_CODE_SIZE);
+	else
+		memset(bcast_src->bad_code, 0, BT_BASS_BCAST_CODE_SIZE);
+
+	bcast_src->num_subgroups = num_subgroups;
+
+	bcast_src->subgroup_data = subgroup_data;
+
+	return 0;
+}
+
+static struct iovec *bass_parse_bcast_src(struct bt_bcast_src *bcast_src)
+{
+	size_t len = 0;
+	uint8_t *notif = NULL;
+	struct iovec *iov;
+
+	if (!bcast_src)
+		return NULL;
+
+	len = BT_BASS_BCAST_SRC_LEN + bcast_src->num_subgroups *
+			BT_BASS_BCAST_SRC_SUBGROUP_LEN;
+
+	if (bcast_src->enc == BT_BASS_BIG_ENC_STATE_BAD_CODE)
+		len += BT_BASS_BCAST_CODE_SIZE;
+
+	for (size_t i = 0; i < bcast_src->num_subgroups; i++) {
+		/* Add length for subgroup metadata */
+		len += bcast_src->subgroup_data[i].meta_len;
+	}
+
+	notif = malloc0(len);
+	if (!notif)
+		return NULL;
+
+	iov = new0(struct iovec, 1);
+	if (!iov) {
+		free(notif);
+		return NULL;
+	}
+
+	iov->iov_base = notif;
+	iov->iov_len = 0;
+
+	util_iov_push_u8(iov, bcast_src->id);
+	util_iov_push_u8(iov, bcast_src->addr_type);
+	util_iov_push_mem(iov, sizeof(bcast_src->addr),
+			&bcast_src->addr);
+	util_iov_push_u8(iov, bcast_src->sid);
+	util_iov_push_le24(iov, bcast_src->bid);
+	util_iov_push_u8(iov, bcast_src->sync_state);
+	util_iov_push_u8(iov, bcast_src->enc);
+
+	if (bcast_src->enc == BT_BASS_BIG_ENC_STATE_BAD_CODE)
+		util_iov_push_mem(iov, sizeof(bcast_src->bad_code),
+					bcast_src->bad_code);
+
+	util_iov_push_u8(iov, bcast_src->num_subgroups);
+
+	for (size_t i = 0; i < bcast_src->num_subgroups; i++) {
+		/* Add subgroup bis_sync */
+		util_iov_push_le32(iov, bcast_src->subgroup_data[i].bis_sync);
+
+		/* Add subgroup meta_len */
+		util_iov_push_u8(iov, bcast_src->subgroup_data[i].meta_len);
+
+		/* Add subgroup metadata */
+		if (bcast_src->subgroup_data[i].meta_len > 0)
+			util_iov_push_mem(iov,
+				bcast_src->subgroup_data[i].meta_len,
+				bcast_src->subgroup_data[i].meta);
+	}
+
+	return iov;
+}
+
+static bool bass_check_cp_command_subgroup_data_len(uint8_t num_subgroups,
+							struct iovec *iov)
+{
+	uint32_t bis_sync_state;
+	uint8_t *meta_len;
+	uint8_t *meta;
+
+	for (int i = 0; i < num_subgroups; i++) {
+		if (!util_iov_pull_le32(iov, &bis_sync_state))
+			return false;
+
+		meta_len = util_iov_pull_mem(iov,
+					sizeof(*meta_len));
+		if (!meta_len)
+			return false;
+
+		meta = util_iov_pull_mem(iov, *meta_len);
+		if (!meta)
+			return false;
+	}
+
+	return true;
+}
+
+static bool bass_check_cp_command_len(const uint8_t *value, size_t len)
+{
+	struct bt_bass_bcast_audio_scan_cp_hdr *hdr;
+	union {
+		struct bt_bass_add_src_params *add_src_params;
+		struct bt_bass_mod_src_params *mod_src_params;
+		struct bt_bass_set_bcast_code_params *set_bcast_code_params;
+		struct bt_bass_remove_src_params *remove_src_params;
+	} params;
+
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = len,
+	};
+
+	/* Get command header */
+	hdr = util_iov_pull_mem(&iov, sizeof(*hdr));
+
+	if (!hdr)
+		return false;
+
+	/* Check command parameters */
+	switch (hdr->op) {
+	case BT_BASS_ADD_SRC:
+		params.add_src_params = util_iov_pull_mem(&iov,
+						sizeof(*params.add_src_params));
+		if (!params.add_src_params)
+			return false;
+
+		if (!bass_check_cp_command_subgroup_data_len(
+					params.add_src_params->num_subgroups,
+					&iov))
+			return false;
+
+		break;
+	case BT_BASS_MOD_SRC:
+		params.mod_src_params = util_iov_pull_mem(&iov,
+						sizeof(*params.mod_src_params));
+		if (!params.mod_src_params)
+			return false;
+
+		if (!bass_check_cp_command_subgroup_data_len(
+					params.mod_src_params->num_subgroups,
+					&iov))
+			return false;
+
+		break;
+	case BT_BASS_SET_BCAST_CODE:
+		params.set_bcast_code_params = util_iov_pull_mem(&iov,
+					sizeof(*params.set_bcast_code_params));
+		if (!params.set_bcast_code_params)
+			return false;
+
+		break;
+	case BT_BASS_REMOVE_SRC:
+		params.remove_src_params = util_iov_pull_mem(&iov,
+					sizeof(*params.remove_src_params));
+		if (!params.remove_src_params)
+			return false;
+
+		break;
+	case BT_BASS_REMOTE_SCAN_STOPPED:
+	case BT_BASS_REMOTE_SCAN_STARTED:
+		break;
+	default:
+		return true;
+	}
+
+	if (iov.iov_len > 0)
+		return false;
+
+	return true;
+}
+
+static void bass_handle_remote_scan_stopped_op(struct bt_bass *bass,
+					struct gatt_db_attribute *attrib,
+					uint8_t opcode,
+					unsigned int id,
+					struct iovec *iov,
+					struct bt_att *att)
+{
+	gatt_db_attribute_write_result(attrib, id, 0x00);
+}
+
+static void bass_handle_remote_scan_started_op(struct bt_bass *bass,
+					struct gatt_db_attribute *attrib,
+					uint8_t opcode,
+					unsigned int id,
+					struct iovec *iov,
+					struct bt_att *att)
+{
+	gatt_db_attribute_write_result(attrib, id, 0x00);
+}
+
+static bool bass_src_id_match(const void *data, const void *match_data)
+{
+	const struct bt_bcast_src *bcast_src = data;
+	const uint8_t *id = match_data;
+
+	return (bcast_src->id == *id);
+}
+
+static void bass_handle_remove_src_op(struct bt_bass *bass,
+					struct gatt_db_attribute *attrib,
+					uint8_t opcode,
+					unsigned int id,
+					struct iovec *iov,
+					struct bt_att *att)
+{
+	struct bt_bass_remove_src_params *params;
+	struct bt_bcast_src *bcast_src;
+	int att_err = 0;
+
+	/* Get Remove Source command parameters */
+	params = util_iov_pull_mem(iov, sizeof(*params));
+
+	bcast_src = queue_find(bass->ldb->bcast_srcs,
+						bass_src_id_match,
+						&params->id);
+
+	if (!bcast_src) {
+		/* No source matches the written source id */
+		att_err = BT_BASS_ERROR_INVALID_SOURCE_ID;
+		goto done;
+	}
+
+	/* Ignore if server is synchronized to the PA
+	 * of the source
+	 */
+	if (bcast_src->sync_state == BT_BASS_SYNCHRONIZED_TO_PA)
+		goto done;
+
+	/* Ignore if server is synchronized to any BIS
+	 * of the source
+	 */
+	for (int i = 0; i < bcast_src->num_subgroups; i++)
+		if (bcast_src->subgroup_data[i].bis_sync)
+			goto done;
+
+	/* Accept the operation and remove source */
+	queue_remove(bass->ldb->bcast_srcs, bcast_src);
+	gatt_db_attribute_notify(bcast_src->attr, NULL, 0, att);
+	bass_bcast_src_free(bcast_src);
+
+done:
+	gatt_db_attribute_write_result(attrib, id,
+			att_err);
+}
+
+static bool bass_src_attr_match(const void *data, const void *match_data)
+{
+	const struct bt_bcast_src *bcast_src = data;
+	const struct gatt_db_attribute *attr = match_data;
+
+	return (bcast_src->attr == attr);
+}
+
+static bool bass_trigger_big_sync(struct bt_bcast_src *bcast_src)
+{
+	for (int i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *data =
+				&bcast_src->subgroup_data[i];
+
+		if (data->pending_bis_sync &&
+			data->pending_bis_sync != BIS_SYNC_NO_PREF)
+			return true;
+	}
+
+	return false;
+}
+
+static struct bt_bass *bass_get_session(struct bt_att *att, struct gatt_db *db,
+		const bdaddr_t *adapter_bdaddr)
+{
+	const struct queue_entry *entry;
+	struct bt_bass *bass;
+
+	for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
+		struct bt_bass *bass = entry->data;
+
+		if (att == bt_bass_get_att(bass))
+			return bass;
+	}
+
+	bass = bt_bass_new(db, NULL, adapter_bdaddr);
+	bass->att = att;
+
+	bt_bass_attach(bass, NULL);
+
+	return bass;
+}
+
+static bool bass_validate_bis_sync(uint8_t num_subgroups,
+				struct iovec *iov)
+{
+	uint32_t bis_sync_state;
+	uint32_t bitmask = 0U;
+	uint8_t *meta_len;
+
+	for (int i = 0; i < num_subgroups; i++) {
+		util_iov_pull_le32(iov, &bis_sync_state);
+
+		if (bis_sync_state != BIS_SYNC_NO_PREF)
+			for (int bis_idx = 0; bis_idx < 31; bis_idx++) {
+				if (bis_sync_state & (1 << bis_idx)) {
+					if (bitmask & (1 << bis_idx))
+						return false;
+
+					bitmask |= (1 << bis_idx);
+				}
+			}
+
+		meta_len = util_iov_pull_mem(iov,
+					sizeof(*meta_len));
+		util_iov_pull_mem(iov, *meta_len);
+	}
+
+	return true;
+}
+
+static bool bass_validate_add_src_params(uint8_t *value, size_t len)
+{
+	struct bt_bass_add_src_params *params;
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = len,
+	};
+
+	params = util_iov_pull_mem(&iov, sizeof(*params));
+
+	if (params->pa_sync > PA_SYNC_NO_PAST)
+		return false;
+
+	if (params->addr_type > 0x01)
+		return false;
+
+	if (params->sid > 0x0F)
+		return false;
+
+	if (!bass_validate_bis_sync(params->num_subgroups,
+					&iov))
+		return false;
+
+	return true;
+}
+
+static void bass_handle_add_src_op(struct bt_bass *bass,
+					struct gatt_db_attribute *attrib,
+					uint8_t opcode,
+					unsigned int id,
+					struct iovec *iov,
+					struct bt_att *att)
+{
+	struct bt_bcast_src *bcast_src, *src;
+	uint8_t src_id = 0;
+	struct gatt_db_attribute *attr;
+	uint8_t pa_sync;
+	struct iovec *notif;
+	int ret;
+	const struct queue_entry *entry;
+	struct bt_bass_add_src_params *params;
+
+	gatt_db_attribute_write_result(attrib, id, 0x00);
+
+	/* Ignore operation if parameters are invalid */
+	if (!bass_validate_add_src_params(iov->iov_base, iov->iov_len))
+		return;
+
+	/* Allocate a new broadcast source */
+	bcast_src = new0(struct bt_bcast_src, 1);
+	if (!bcast_src) {
+		DBG(bass, "Unable to allocate broadcast source");
+		return;
+	}
+
+	queue_push_tail(bass->ldb->bcast_srcs, bcast_src);
+
+	bcast_src->bass = bass;
+
+	/* Map the source to a Broadcast Receive State characteristic */
+	for (int i = 0; i < NUM_BCAST_RECV_STATES; i++) {
+		src = queue_find(bass->ldb->bcast_srcs,
+				bass_src_attr_match,
+				bass->ldb->bcast_recv_states[i]->attr);
+		if (!src) {
+			/* Found and empty characteristic */
+			bcast_src->attr =
+				bass->ldb->bcast_recv_states[i]->attr;
+			break;
+		}
+	}
+
+	if (!bcast_src->attr) {
+		/* If no empty characteristic has been found,
+		 * overwrite an existing one
+		 */
+		attr = bass->ldb->bcast_recv_states[0]->attr;
+
+		src = queue_find(bass->ldb->bcast_srcs,
+					bass_src_attr_match,
+					attr);
+
+		queue_remove(bass->ldb->bcast_srcs, src);
+		bass_bcast_src_free(src);
+		bcast_src->attr = attr;
+	}
+
+	/* Allocate source id */
+	while (true) {
+		src = queue_find(bass->ldb->bcast_srcs,
+				bass_src_id_match,
+				&src_id);
+		if (!src)
+			break;
+
+		if (src_id == 0xFF) {
+			DBG(bass, "Unable to allocate broadcast source id");
+			return;
+		}
+
+		src_id++;
+	}
+
+	bcast_src->id = src_id;
+
+	params = util_iov_pull_mem(iov, sizeof(*params));
+
+	/* Populate broadcast source fields from command parameters */
+	bcast_src->addr_type = params->addr_type;
+
+	/* Convert to three-value type */
+	if (bcast_src->addr_type)
+		params->addr_type = BDADDR_LE_RANDOM;
+	else
+		params->addr_type = BDADDR_LE_PUBLIC;
+
+	bacpy(&bcast_src->addr, &params->addr);
+	bcast_src->sid = params->sid;
+	memcpy(&bcast_src->bid, params->bid, sizeof(params->bid));
+
+	pa_sync = params->pa_sync;
+	bcast_src->sync_state = BT_BASS_NOT_SYNCHRONIZED_TO_PA;
+
+	bcast_src->num_subgroups = params->num_subgroups;
+
+	if (!bcast_src->num_subgroups)
+		return;
+
+	bcast_src->subgroup_data = new0(struct bt_bass_subgroup_data,
+					bcast_src->num_subgroups);
+	if (!bcast_src->subgroup_data) {
+		DBG(bass, "Unable to allocate subgroup data");
+		goto err;
+	}
+
+	for (int i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *data =
+				&bcast_src->subgroup_data[i];
+
+		util_iov_pull_le32(iov, &data->pending_bis_sync);
+
+		data->meta_len = *(uint8_t *)util_iov_pull_mem(iov,
+						sizeof(data->meta_len));
+		if (!data->meta_len)
+			continue;
+
+		data->meta = malloc0(data->meta_len);
+		if (!data->meta)
+			goto err;
+
+		memcpy(data->meta, (uint8_t *)util_iov_pull_mem(iov,
+					data->meta_len), data->meta_len);
+	}
+
+	if (pa_sync != PA_SYNC_NO_SYNC) {
+		for (entry = queue_get_entries(bass->cp_handlers); entry;
+							entry = entry->next) {
+			struct bt_bass_cp_handler *cb = entry->data;
+
+			if (cb->handler) {
+				ret = cb->handler(bcast_src,
+						BT_BASS_ADD_SRC,
+						params, cb->data);
+				if (ret)
+					goto err;
+			}
+		}
+	} else {
+		for (int i = 0; i < bcast_src->num_subgroups; i++)
+			bcast_src->subgroup_data[i].bis_sync =
+				bcast_src->subgroup_data[i].pending_bis_sync;
+
+		notif = bass_parse_bcast_src(bcast_src);
+		if (!notif)
+			return;
+
+		gatt_db_attribute_notify(bcast_src->attr,
+				notif->iov_base, notif->iov_len,
+				bt_bass_get_att(bcast_src->bass));
+
+		free(notif->iov_base);
+		free(notif);
+	}
+
+	return;
+
+err:
+	if (bcast_src->subgroup_data) {
+		for (int i = 0; i < bcast_src->num_subgroups; i++)
+			free(bcast_src->subgroup_data[i].meta);
+
+		free(bcast_src->subgroup_data);
+	}
+
+	free(bcast_src);
+}
+
+static void bass_handle_set_bcast_code_op(struct bt_bass *bass,
+					struct gatt_db_attribute *attrib,
+					uint8_t opcode,
+					unsigned int id,
+					struct iovec *iov,
+					struct bt_att *att)
+{
+	struct bt_bass_set_bcast_code_params *params;
+	struct bt_bcast_src *bcast_src;
+	struct iovec *notif;
+	const struct queue_entry *entry;
+	int ret;
+
+	/* Get Set Broadcast Code command parameters */
+	params = util_iov_pull_mem(iov, sizeof(*params));
+
+	bcast_src = queue_find(bass->ldb->bcast_srcs,
+						bass_src_id_match,
+						&params->id);
+
+	if (!bcast_src) {
+		/* No source matches the written source id */
+		gatt_db_attribute_write_result(attrib, id,
+					BT_BASS_ERROR_INVALID_SOURCE_ID);
+
+		return;
+	}
+
+	gatt_db_attribute_write_result(attrib, id, 0x00);
+
+	if (!bass_trigger_big_sync(bcast_src)) {
+		bcast_src->enc = BT_BASS_BIG_ENC_STATE_DEC;
+
+		notif = bass_parse_bcast_src(bcast_src);
+		if (!notif)
+			return;
+
+		gatt_db_attribute_notify(bcast_src->attr,
+					notif->iov_base, notif->iov_len,
+					bt_bass_get_att(bcast_src->bass));
+
+		free(notif->iov_base);
+		free(notif);
+		return;
+	}
+
+	for (entry = queue_get_entries(bass->cp_handlers); entry;
+						entry = entry->next) {
+		struct bt_bass_cp_handler *cb = entry->data;
+
+		if (cb->handler) {
+			ret = cb->handler(bcast_src,
+					BT_BASS_SET_BCAST_CODE,
+					params, cb->data);
+			if (ret)
+				DBG(bass, "Unable to handle Set "
+						"Broadcast Code operation");
+		}
+	}
+}
+
+#define BASS_OP(_str, _op, _size, _func) \
+	{ \
+		.str = _str, \
+		.op = _op, \
+		.size = _size, \
+		.func = _func, \
+	}
+
+struct bass_op_handler {
+	const char	*str;
+	uint8_t		op;
+	size_t		size;
+	void		(*func)(struct bt_bass *bass,
+				struct gatt_db_attribute *attrib,
+				uint8_t opcode,
+				unsigned int id,
+				struct iovec *iov,
+				struct bt_att *att);
+} bass_handlers[] = {
+	BASS_OP("Remote Scan Stopped", BT_BASS_REMOTE_SCAN_STOPPED,
+		0, bass_handle_remote_scan_stopped_op),
+	BASS_OP("Remote Scan Started", BT_BASS_REMOTE_SCAN_STARTED,
+		0, bass_handle_remote_scan_started_op),
+	BASS_OP("Remove Source", BT_BASS_REMOVE_SRC,
+		0, bass_handle_remove_src_op),
+	BASS_OP("Add Source", BT_BASS_ADD_SRC,
+		0, bass_handle_add_src_op),
+	BASS_OP("Set Broadcast Code", BT_BASS_SET_BCAST_CODE,
+		0, bass_handle_set_bcast_code_op),
+	{}
+};
+
+static void bass_bcast_audio_scan_cp_write(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 bt_bass_db *bdb = user_data;
+	struct bt_bass_bcast_audio_scan_cp_hdr *hdr;
+	struct bass_op_handler *handler;
+	struct bt_bass *bass = bass_get_session(att, bdb->db,
+						&bdb->adapter_bdaddr);
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = len,
+	};
+
+	/* Validate written command length */
+	if (!bass_check_cp_command_len(value, len)) {
+		gatt_db_attribute_write_result(attrib, id,
+				BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	/* Get command header */
+	hdr = util_iov_pull_mem(&iov, sizeof(*hdr));
+
+	/* Call the appropriate opcode handler */
+	for (handler = bass_handlers; handler && handler->str; handler++) {
+		if (handler->op == hdr->op) {
+			handler->func(bass, attrib, opcode, id, &iov, att);
+			return;
+		}
+	}
+
+	/* Send error response if unsupported opcode was written */
+	gatt_db_attribute_write_result(attrib, id,
+			BT_BASS_ERROR_OPCODE_NOT_SUPPORTED);
+}
+
+static bool bass_src_match_attrib(const void *data, const void *match_data)
+{
+	const struct bt_bcast_src *bcast_src = data;
+	const struct gatt_db_attribute *attr = match_data;
+
+	return (bcast_src->attr == attr);
+}
+
+static void bass_bcast_recv_state_read(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct bt_bass_db *bdb = user_data;
+	struct iovec *rsp;
+	struct bt_bcast_src *bcast_src;
+	struct bt_bass *bass = bass_get_session(att, bdb->db,
+						&bdb->adapter_bdaddr);
+
+	bcast_src = queue_find(bass->ldb->bcast_srcs,
+					bass_src_match_attrib,
+					attrib);
+
+	if (!bcast_src) {
+		gatt_db_attribute_read_result(attrib, id, 0, NULL,
+							0);
+		return;
+	}
+
+	/* Build read response */
+	rsp = bass_parse_bcast_src(bcast_src);
+
+	if (!rsp) {
+		gatt_db_attribute_read_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY,
+					NULL, 0);
+		return;
+	}
+
+	gatt_db_attribute_read_result(attrib, id, 0, rsp->iov_base,
+						rsp->iov_len);
+
+	free(rsp->iov_base);
+	free(rsp);
+}
+
+static void bcast_recv_new(struct bt_bass_db *bdb, int i)
+{
+	struct bt_bcast_recv_state *bcast_recv_state;
+	bt_uuid_t uuid;
+
+	if (!bdb)
+		return;
+
+	bcast_recv_state = new0(struct bt_bcast_recv_state, 1);
+	bcast_recv_state->bdb = bdb;
+
+	bt_uuid16_create(&uuid, BCAST_RECV_STATE_UUID);
+	bcast_recv_state->attr =
+		gatt_db_service_add_characteristic(bdb->service, &uuid,
+				BT_ATT_PERM_READ,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_NOTIFY,
+				bass_bcast_recv_state_read, NULL,
+				bdb);
+
+	bcast_recv_state->ccc = gatt_db_service_add_ccc(bdb->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bdb->bcast_recv_states[i] = bcast_recv_state;
+}
+
+static void bass_new(struct bt_bass_db *bdb)
+{
+	bt_uuid_t uuid;
+	int i;
+
+	/* Populate DB with BASS attributes */
+	bt_uuid16_create(&uuid, BASS_UUID);
+	bdb->service = gatt_db_add_service(bdb->db, &uuid, true,
+					3 + (NUM_BCAST_RECV_STATES * 3));
+
+	for (i = 0; i < NUM_BCAST_RECV_STATES; i++)
+		bcast_recv_new(bdb, i);
+
+	bt_uuid16_create(&uuid, BCAST_AUDIO_SCAN_CP_UUID);
+	bdb->bcast_audio_scan_cp =
+		gatt_db_service_add_characteristic(bdb->service,
+				&uuid,
+				BT_ATT_PERM_WRITE,
+				BT_GATT_CHRC_PROP_WRITE |
+				BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+				NULL, bass_bcast_audio_scan_cp_write,
+				bdb);
+
+	gatt_db_service_set_active(bdb->service, true);
+}
+
+static void bass_bcast_src_free(void *data)
+{
+	struct bt_bcast_src *bcast_src = data;
+
+	if (!bcast_src)
+		return;
+
+	for (int i = 0; i < bcast_src->num_subgroups; i++)
+		free(bcast_src->subgroup_data[i].meta);
+
+	free(bcast_src->subgroup_data);
+
+	free(bcast_src);
+}
+
+static void read_bcast_recv_state(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct bt_bcast_src *bcast_src = user_data;
+
+	if (!success) {
+		DBG(bcast_src->bass, "Unable to read "
+			"Broadcast Receive State: error 0x%02x",
+			att_ecode);
+		return;
+	}
+
+	if (length == 0) {
+		queue_remove(bcast_src->bass->rdb->bcast_srcs, bcast_src);
+		bass_bcast_src_free(bcast_src);
+		return;
+	}
+
+	if (bass_build_bcast_src(bcast_src, value, length)) {
+		queue_remove(bcast_src->bass->rdb->bcast_srcs, bcast_src);
+		bass_bcast_src_free(bcast_src);
+		return;
+	}
+}
+
+static void notify_src_changed(void *data, void *user_data)
+{
+	struct bt_bass_src_changed *changed = data;
+	struct bt_bcast_src *bcast_src = user_data;
+	uint32_t bis_sync = 0;
+
+	for (uint8_t i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *sgrp =
+				&bcast_src->subgroup_data[i];
+
+		/* Create a bitmask of all BIS indices that the peer has
+		 * synchronized with.
+		 */
+		bis_sync |= sgrp->bis_sync;
+	}
+
+	if (changed->cb)
+		changed->cb(bcast_src->id, bcast_src->bid, bcast_src->enc,
+					bis_sync, changed->data);
+}
+
+static void bcast_recv_state_notify(struct bt_bass *bass, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct gatt_db_attribute *attr = user_data;
+	struct bt_bcast_src *bcast_src;
+	bool new_src = false;
+
+	bcast_src = queue_find(bass->rdb->bcast_srcs,
+					bass_src_match_attrib, attr);
+	if (!bcast_src) {
+		new_src = true;
+		bcast_src = new0(struct bt_bcast_src, 1);
+
+		if (!bcast_src) {
+			DBG(bass, "Failed to allocate "
+				"memory for broadcast source");
+			return;
+		}
+
+		bcast_src->bass = bass;
+		bcast_src->attr = attr;
+	}
+
+	if (bass_build_bcast_src(bcast_src, value, length)
+							&& new_src) {
+		bass_bcast_src_free(bcast_src);
+		return;
+	}
+
+	if (new_src)
+		queue_push_tail(bass->rdb->bcast_srcs, bcast_src);
+
+	/* Notify the update in the Broadcast Receive State characteristic
+	 * to all drivers that registered a callback.
+	 */
+	queue_foreach(bass->src_cbs, notify_src_changed, bcast_src);
+}
+
+static void bass_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_bass_notify *notify = user_data;
+
+	if (att_ecode)
+		DBG(notify->bass, "BASS register notify failed: 0x%04x",
+					att_ecode);
+}
+
+static void bass_notify(uint16_t value_handle, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_bass_notify *notify = user_data;
+
+	if (notify->func)
+		notify->func(notify->bass, value_handle, value, length,
+						notify->user_data);
+}
+
+static void bass_notify_destroy(void *data)
+{
+	struct bt_bass_notify *notify = data;
+	struct bt_bass *bass = notify->bass;
+
+	if (queue_remove_if(bass->notify, NULL, notify))
+		free(notify);
+}
+
+static unsigned int bass_register_notify(struct bt_bass *bass,
+					uint16_t value_handle,
+					bass_notify_t func,
+					void *user_data)
+{
+	struct bt_bass_notify *notify;
+
+	notify = new0(struct bt_bass_notify, 1);
+	notify->bass = bass;
+	notify->func = func;
+	notify->user_data = user_data;
+
+	notify->id = bt_gatt_client_register_notify(bass->client,
+						value_handle, bass_register,
+						bass_notify, notify,
+						bass_notify_destroy);
+	if (!notify->id) {
+		DBG(bass, "Unable to register for notifications");
+		free(notify);
+		return 0;
+	}
+
+	queue_push_tail(bass->notify, notify);
+
+	return notify->id;
+}
+
+static void foreach_bass_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_bass *bass = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_bcast_audio_scan_cp, uuid_bcast_recv_state;
+
+	/* Get attribute value handle and uuid */
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
+		return;
+
+	bt_uuid16_create(&uuid_bcast_audio_scan_cp, BCAST_AUDIO_SCAN_CP_UUID);
+	bt_uuid16_create(&uuid_bcast_recv_state, BCAST_RECV_STATE_UUID);
+
+	if (!bt_uuid_cmp(&uuid, &uuid_bcast_audio_scan_cp)) {
+		/* Found Broadcast Audio Scan Control Point characteristic */
+		bass->rdb->bcast_audio_scan_cp = attr;
+
+		DBG(bass, "Broadcast Audio Scan Control Point "
+			"found: handle 0x%04x", value_handle);
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_bcast_recv_state)) {
+		/* Found Broadcast Receive State characteristic */
+		struct bt_bcast_src *bcast_src =
+				queue_find(bass->rdb->bcast_srcs,
+						bass_src_match_attrib, attr);
+
+		if (!bcast_src) {
+			bcast_src = new0(struct bt_bcast_src, 1);
+
+			if (bcast_src == NULL) {
+				DBG(bass, "Failed to allocate "
+					"memory for broadcast source");
+				return;
+			}
+
+			bcast_src->bass = bass;
+			bcast_src->attr = attr;
+
+			queue_push_tail(bass->rdb->bcast_srcs, bcast_src);
+		}
+
+		bt_gatt_client_read_value(bass->client, value_handle,
+						read_bcast_recv_state,
+						bcast_src, NULL);
+
+		(void)bass_register_notify(bass, value_handle,
+						bcast_recv_state_notify,
+						attr);
+
+		DBG(bass, "Broadcast Receive State found: handle 0x%04x",
+							value_handle);
+	}
+}
+
+static void foreach_bass_service(struct gatt_db_attribute *attr,
+						void *user_data)
+{
+	struct bt_bass *bass = user_data;
+
+	/* Store BASS service reference */
+	bass->rdb->service = attr;
+
+	/* Handle BASS characteristics */
+	gatt_db_service_foreach_char(attr, foreach_bass_char, bass);
+}
+
+static void bass_attached(void *data, void *user_data)
+{
+	struct bt_bass_cb *cb = data;
+	struct bt_bass *bass = user_data;
+
+	cb->attached(bass, cb->user_data);
+}
+
+static void bass_disconnected(int err, void *user_data)
+{
+	struct bt_bass *bass = user_data;
+
+	bass->disconn_id = 0;
+
+	DBG(bass, "bass %p disconnected err %d", bass, err);
+
+	bt_bass_detach(bass);
+}
+
+static void bass_attach_att(struct bt_bass *bass, struct bt_att *att)
+{
+	if (bass->disconn_id) {
+		if (att == bt_bass_get_att(bass))
+			return;
+
+		bt_att_unregister_disconnect(bt_bass_get_att(bass),
+							bass->disconn_id);
+	}
+
+	bass->disconn_id = bt_att_register_disconnect(att,
+							bass_disconnected,
+							bass, NULL);
+}
+
+bool bt_bass_attach(struct bt_bass *bass, struct bt_gatt_client *client)
+{
+	bt_uuid_t uuid;
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, bass);
+
+	queue_foreach(bass_cbs, bass_attached, bass);
+
+	if (!client) {
+		if (bass->att)
+			bass_attach_att(bass, bass->att);
+		return true;
+	}
+
+	if (bass->client)
+		return false;
+
+	bass->client = bt_gatt_client_clone(client);
+	if (!bass->client)
+		return false;
+
+	bass_attach_att(bass, bt_gatt_client_get_att(client));
+
+	bt_uuid16_create(&uuid, BASS_UUID);
+	gatt_db_foreach_service(bass->rdb->db, &uuid, foreach_bass_service,
+				bass);
+
+	return true;
+}
+
+bool bt_bass_set_att(struct bt_bass *bass, struct bt_att *att)
+{
+	if (!bass)
+		return false;
+
+	bass->att = att;
+	return true;
+}
+
+static void bass_detached(void *data, void *user_data)
+{
+	struct bt_bass_cb *cb = data;
+	struct bt_bass *bass = user_data;
+
+	cb->detached(bass, cb->user_data);
+}
+
+void bt_bass_detach(struct bt_bass *bass)
+{
+	struct  bt_att *att;
+
+	if (!queue_remove(sessions, bass))
+		return;
+
+	if (bass->client)
+		att = bt_gatt_client_get_att(bass->client);
+	else
+		att = bass->att;
+
+	bt_att_unregister_disconnect(att, bass->disconn_id);
+
+	bt_gatt_client_unref(bass->client);
+	bass->client = NULL;
+
+	bass->att = NULL;
+
+	queue_foreach(bass_cbs, bass_detached, bass);
+}
+
+static void bass_db_free(void *data)
+{
+	struct bt_bass_db *bdb = data;
+
+	if (!bdb)
+		return;
+
+	gatt_db_unref(bdb->db);
+	queue_destroy(bdb->bcast_srcs, bass_bcast_src_free);
+
+	free(bdb);
+}
+
+static void bass_free(void *data)
+{
+	struct bt_bass *bass = data;
+
+	bt_bass_detach(bass);
+	bass_db_free(bass->rdb);
+	queue_destroy(bass->notify, NULL);
+	queue_destroy(bass->src_cbs, bass_src_changed_free);
+	queue_destroy(bass->cp_handlers, bass_cp_handler_free);
+
+	free(bass);
+}
+
+void bt_bass_unref(struct bt_bass *bass)
+{
+	if (!bass)
+		return;
+
+	if (__sync_sub_and_fetch(&bass->ref_count, 1))
+		return;
+
+	bass_free(bass);
+}
+
+bool bt_bass_set_user_data(struct bt_bass *bass, void *user_data)
+{
+	if (!bass)
+		return false;
+
+	bass->user_data = user_data;
+
+	return true;
+}
+
+static struct bt_bass_db *bass_db_new(struct gatt_db *db,
+				const bdaddr_t *adapter_bdaddr)
+{
+	struct bt_bass_db *bdb;
+
+	if (!db)
+		return NULL;
+
+	bdb = new0(struct bt_bass_db, 1);
+	bdb->db = gatt_db_ref(db);
+	bacpy(&bdb->adapter_bdaddr, adapter_bdaddr);
+	bdb->bcast_srcs = queue_new();
+
+	if (!bass_db)
+		bass_db = queue_new();
+
+	bass_new(bdb);
+
+	queue_push_tail(bass_db, bdb);
+
+	return bdb;
+}
+
+static bool bass_db_match(const void *data, const void *match_data)
+{
+	const struct bt_bass_db *bdb = data;
+	const struct gatt_db *db = match_data;
+
+	return (bdb->db == db);
+}
+
+static struct bt_bass_db *bass_get_db(struct gatt_db *db,
+				const bdaddr_t *adapter_bdaddr)
+{
+	struct bt_bass_db *bdb;
+
+	bdb = queue_find(bass_db, bass_db_match, db);
+	if (bdb)
+		return bdb;
+
+	return bass_db_new(db, adapter_bdaddr);
+}
+
+static struct bt_bass *bt_bass_ref(struct bt_bass *bass)
+{
+	if (!bass)
+		return NULL;
+
+	__sync_fetch_and_add(&bass->ref_count, 1);
+
+	return bass;
+}
+
+struct bt_bass *bt_bass_new(struct gatt_db *ldb, struct gatt_db *rdb,
+				const bdaddr_t *adapter_bdaddr)
+{
+	struct bt_bass *bass;
+	struct bt_bass_db *db;
+
+	if (!ldb)
+		return NULL;
+
+	db = bass_get_db(ldb, adapter_bdaddr);
+	if (!db)
+		return NULL;
+
+	bass = new0(struct bt_bass, 1);
+	bass->ldb = db;
+	bass->notify = queue_new();
+	bass->src_cbs = queue_new();
+	bass->cp_handlers = queue_new();
+
+	if (!rdb)
+		goto done;
+
+	db = new0(struct bt_bass_db, 1);
+	db->db = gatt_db_ref(rdb);
+	db->bcast_srcs = queue_new();
+
+	bass->rdb = db;
+
+done:
+	bt_bass_ref(bass);
+
+	return bass;
+}
+
+struct bt_att *bt_bass_get_att(struct bt_bass *bass)
+{
+	if (!bass)
+		return NULL;
+
+	if (bass->att)
+		return bass->att;
+
+	return bt_gatt_client_get_att(bass->client);
+}
+
+struct bt_gatt_client *bt_bass_get_client(struct bt_bass *bass)
+{
+	if (!bass)
+		return NULL;
+
+	return bass->client;
+}
+
+bool bt_bass_set_debug(struct bt_bass *bass, bt_bass_debug_func_t func,
+			void *user_data, bt_bass_destroy_func_t destroy)
+{
+	if (!bass)
+		return false;
+
+	if (bass->debug_destroy)
+		bass->debug_destroy(bass->debug_data);
+
+	bass->debug_func = func;
+	bass->debug_destroy = destroy;
+	bass->debug_data = user_data;
+
+	return true;
+}
+
+unsigned int bt_bass_register(bt_bass_func_t attached, bt_bass_func_t detached,
+							void *user_data)
+{
+	struct bt_bass_cb *cb;
+	static unsigned int id;
+
+	if (!attached && !detached)
+		return 0;
+
+	if (!bass_cbs)
+		bass_cbs = queue_new();
+
+	cb = new0(struct bt_bass_cb, 1);
+	cb->id = ++id ? id : ++id;
+	cb->attached = attached;
+	cb->detached = detached;
+	cb->user_data = user_data;
+
+	queue_push_tail(bass_cbs, cb);
+
+	return cb->id;
+}
+static bool match_id(const void *data, const void *match_data)
+{
+	const struct bt_bass_cb *cb = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (cb->id == id);
+}
+
+bool bt_bass_unregister(unsigned int id)
+{
+	struct bt_bass_cb *cb;
+
+	cb = queue_remove_if(bass_cbs, match_id, UINT_TO_PTR(id));
+	if (!cb)
+		return false;
+
+	free(cb);
+
+	return true;
+}
+
+void bt_bass_add_db(struct gatt_db *db, const bdaddr_t *adapter_bdaddr)
+{
+	bass_db_new(db, adapter_bdaddr);
+}
+
+int bt_bass_send(struct bt_bass *bass,
+		struct bt_bass_bcast_audio_scan_cp_hdr *hdr,
+		struct iovec *params)
+{
+	struct iovec req = {0};
+	uint16_t handle;
+	int err = 0;
+
+	if (!bass || !bass->client || !bass->rdb)
+		return -EINVAL;
+
+	DBG(bass, "bass %p", bass);
+
+	req.iov_base = malloc0(sizeof(*hdr) + params->iov_len);
+	if (!req.iov_base)
+		return -EINVAL;
+
+	util_iov_push_mem(&req, sizeof(*hdr), hdr);
+	util_iov_push_mem(&req, params->iov_len, params->iov_base);
+
+	if (!gatt_db_attribute_get_char_data(bass->rdb->bcast_audio_scan_cp,
+			NULL, &handle, NULL, NULL, NULL)) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	if (!bt_gatt_client_write_without_response(bass->client, handle,
+					false, req.iov_base, req.iov_len))
+		err = -EINVAL;
+
+done:
+	free(req.iov_base);
+
+	return err;
+}
+
+static void bt_bass_notify_all(struct gatt_db_attribute *attr,
+						struct iovec *iov)
+{
+	const struct queue_entry *entry;
+
+	for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
+		struct bt_bass *bass = entry->data;
+
+		gatt_db_attribute_notify(attr, iov->iov_base,
+			iov->iov_len, bt_bass_get_att(bass));
+	}
+}
+
+int bt_bass_set_pa_sync(struct bt_bcast_src *bcast_src, uint8_t sync_state)
+{
+	struct iovec *iov;
+
+	if (!bcast_src)
+		return -EINVAL;
+
+	bcast_src->sync_state = sync_state;
+
+	iov = bass_parse_bcast_src(bcast_src);
+	if (!iov)
+		return -ENOMEM;
+
+	bt_bass_notify_all(bcast_src->attr, iov);
+
+	free(iov->iov_base);
+	free(iov);
+
+	return 0;
+}
+
+int bt_bass_set_bis_sync(struct bt_bcast_src *bcast_src, uint8_t bis)
+{
+	struct iovec *iov;
+
+	for (uint8_t i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *sgrp =
+				&bcast_src->subgroup_data[i];
+		uint32_t bitmask = 1 << (bis - 1);
+
+		if (sgrp->pending_bis_sync & bitmask) {
+			sgrp->bis_sync |= bitmask;
+
+			if (bcast_src->enc == BT_BASS_BIG_ENC_STATE_BCODE_REQ)
+				bcast_src->enc = BT_BASS_BIG_ENC_STATE_DEC;
+
+			iov = bass_parse_bcast_src(bcast_src);
+			if (!iov)
+				return -ENOMEM;
+
+			bt_bass_notify_all(bcast_src->attr, iov);
+
+			free(iov->iov_base);
+			free(iov);
+		}
+	}
+
+	return 0;
+}
+
+int bt_bass_clear_bis_sync(struct bt_bcast_src *bcast_src, uint8_t bis)
+{
+	struct iovec *iov;
+
+	for (uint8_t i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *sgrp =
+				&bcast_src->subgroup_data[i];
+		uint32_t bitmask = 1 << (bis - 1);
+
+		if (sgrp->pending_bis_sync & bitmask) {
+			sgrp->bis_sync &= ~bitmask;
+
+			iov = bass_parse_bcast_src(bcast_src);
+			if (!iov)
+				return -ENOMEM;
+
+			bt_bass_notify_all(bcast_src->attr, iov);
+
+			free(iov->iov_base);
+			free(iov);
+		}
+	}
+
+	return 0;
+}
+
+bool bt_bass_check_bis(struct bt_bcast_src *bcast_src, uint8_t bis)
+{
+	for (uint8_t i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *sgrp =
+				&bcast_src->subgroup_data[i];
+		uint32_t bitmask = 1 << (bis - 1);
+
+		if (sgrp->pending_bis_sync & bitmask)
+			return true;
+	}
+
+	return false;
+}
+
+int bt_bass_set_enc(struct bt_bcast_src *bcast_src, uint8_t enc)
+{
+	struct iovec *iov;
+
+	if (!bcast_src)
+		return -EINVAL;
+
+	if (bcast_src->enc == enc)
+		return 0;
+
+	bcast_src->enc = enc;
+
+	iov = bass_parse_bcast_src(bcast_src);
+	if (!iov)
+		return -ENOMEM;
+
+	bt_bass_notify_all(bcast_src->attr, iov);
+
+	free(iov->iov_base);
+	free(iov);
+
+	return 0;
+}
diff --git a/src/shared/bass.h b/src/shared/bass.h
new file mode 100644
index 0000000..d256b92
--- /dev/null
+++ b/src/shared/bass.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2023-2024 NXP
+ *
+ */
+
+struct bt_bass;
+struct bt_bcast_src;
+
+#define NUM_BCAST_RECV_STATES				2
+#define BT_BASS_BCAST_CODE_SIZE				16
+#define BT_BASS_BIG_SYNC_FAILED_BITMASK			0xFFFFFFFF
+#define BT_BASS_BCAST_SRC_LEN				15
+#define BT_BASS_BCAST_SRC_SUBGROUP_LEN			5
+
+/* Application error codes */
+#define BT_BASS_ERROR_OPCODE_NOT_SUPPORTED		0x80
+#define BT_BASS_ERROR_INVALID_SOURCE_ID			0x81
+
+/* PA_Sync_State values */
+#define BT_BASS_NOT_SYNCHRONIZED_TO_PA			0x00
+#define BT_BASS_SYNC_INFO_RE				0x01
+#define BT_BASS_SYNCHRONIZED_TO_PA			0x02
+#define BT_BASS_FAILED_TO_SYNCHRONIZE_TO_PA		0x03
+#define BT_BASS_NO_PAST					0x04
+
+/* BIG_Encryption values */
+#define BT_BASS_BIG_ENC_STATE_NO_ENC			0x00
+#define BT_BASS_BIG_ENC_STATE_BCODE_REQ			0x01
+#define BT_BASS_BIG_ENC_STATE_DEC			0x02
+#define BT_BASS_BIG_ENC_STATE_BAD_CODE			0x03
+
+/* Broadcast Audio Scan Control Point
+ * header structure
+ */
+struct bt_bass_bcast_audio_scan_cp_hdr {
+	uint8_t op;
+} __packed;
+
+#define BT_BASS_REMOTE_SCAN_STOPPED			0x00
+
+#define BT_BASS_REMOTE_SCAN_STARTED			0x01
+
+#define BT_BASS_ADD_SRC					0x02
+
+#define BT_BASS_ADDR_PUBLIC				0x00
+#define BT_BASS_ADDR_RANDOM				0x01
+
+/* PA_Sync values */
+#define PA_SYNC_NO_SYNC					0x00
+#define PA_SYNC_PAST					0x01
+#define PA_SYNC_NO_PAST					0x02
+
+/* BIS_Sync no preference bitmask */
+#define BIS_SYNC_NO_PREF				0xFFFFFFFF
+
+#define PA_INTERVAL_UNKNOWN				0xFFFF
+
+struct bt_bass_add_src_params {
+	uint8_t addr_type;
+	bdaddr_t addr;
+	uint8_t sid;
+	uint8_t bid[3];
+	uint8_t pa_sync;
+	uint16_t pa_interval;
+	uint8_t num_subgroups;
+	uint8_t subgroup_data[];
+} __packed;
+
+#define BT_BASS_MOD_SRC					0x03
+
+struct bt_bass_mod_src_params {
+	uint8_t id;
+	uint8_t pa_sync;
+	uint16_t pa_interval;
+	uint8_t num_subgroups;
+	uint8_t subgroup_data[];
+} __packed;
+
+#define BT_BASS_SET_BCAST_CODE				0x04
+
+struct bt_bass_set_bcast_code_params {
+	uint8_t id;
+	uint8_t bcast_code[BT_BASS_BCAST_CODE_SIZE];
+} __packed;
+
+#define BT_BASS_REMOVE_SRC				0x05
+
+struct bt_bass_remove_src_params {
+	uint8_t id;
+} __packed;
+
+typedef void (*bt_bass_func_t)(struct bt_bass *bass, void *user_data);
+typedef void (*bt_bass_destroy_func_t)(void *user_data);
+typedef void (*bt_bass_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_bass_src_func_t)(uint8_t id, uint32_t bid, uint8_t enc,
+					uint32_t bis_sync, void *user_data);
+
+typedef int (*bt_bass_cp_handler_func_t)(struct bt_bcast_src *bcast_src,
+		uint8_t op, void *params, void *user_data);
+
+struct bt_att *bt_bass_get_att(struct bt_bass *bass);
+struct bt_gatt_client *bt_bass_get_client(struct bt_bass *bass);
+unsigned int bt_bass_register(bt_bass_func_t attached, bt_bass_func_t detached,
+							void *user_data);
+bool bt_bass_unregister(unsigned int id);
+bool bt_bass_set_debug(struct bt_bass *bass, bt_bass_debug_func_t func,
+			void *user_data, bt_bass_destroy_func_t destroy);
+struct bt_bass *bt_bass_new(struct gatt_db *ldb, struct gatt_db *rdb,
+			const bdaddr_t *adapter_bdaddr);
+bool bt_bass_set_user_data(struct bt_bass *bass, void *user_data);
+void bt_bass_unref(struct bt_bass *bass);
+bool bt_bass_attach(struct bt_bass *bass, struct bt_gatt_client *client);
+bool bt_bass_set_att(struct bt_bass *bass, struct bt_att *att);
+void bt_bass_detach(struct bt_bass *bass);
+void bt_bass_add_db(struct gatt_db *db, const bdaddr_t *adapter_bdaddr);
+int bt_bass_send(struct bt_bass *bass,
+		struct bt_bass_bcast_audio_scan_cp_hdr *hdr,
+		struct iovec *params);
+unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb,
+			void *user_data, bt_bass_destroy_func_t destroy);
+bool bt_bass_src_unregister(struct bt_bass *bass, unsigned int id);
+unsigned int bt_bass_cp_handler_register(struct bt_bass *bass,
+				bt_bass_cp_handler_func_t handler,
+				bt_bass_destroy_func_t destroy,
+				void *user_data);
+bool bt_bass_cp_handler_unregister(struct bt_bass *bass,
+				unsigned int id);
+int bt_bass_set_pa_sync(struct bt_bcast_src *bcast_src, uint8_t sync_state);
+int bt_bass_set_bis_sync(struct bt_bcast_src *bcast_src, uint8_t bis);
+int bt_bass_clear_bis_sync(struct bt_bcast_src *bcast_src, uint8_t bis);
+bool bt_bass_check_bis(struct bt_bcast_src *bcast_src, uint8_t bis);
+int bt_bass_set_enc(struct bt_bcast_src *bcast_src, uint8_t enc);
diff --git a/src/shared/btsnoop.c b/src/shared/btsnoop.c
index 0a68282..bc5f7fc 100644
--- a/src/shared/btsnoop.c
+++ b/src/shared/btsnoop.c
@@ -305,6 +305,9 @@ static uint32_t get_flags_from_opcode(uint16_t opcode)
 	case BTSNOOP_OPCODE_SCO_TX_PKT:
 	case BTSNOOP_OPCODE_SCO_RX_PKT:
 		break;
+	case BTSNOOP_OPCODE_ISO_TX_PKT:
+	case BTSNOOP_OPCODE_ISO_RX_PKT:
+		break;
 	case BTSNOOP_OPCODE_OPEN_INDEX:
 	case BTSNOOP_OPCODE_CLOSE_INDEX:
 		break;
@@ -428,6 +431,14 @@ static bool pklg_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
 		*index = 0x0000;
 		*opcode = BTSNOOP_OPCODE_SCO_RX_PKT;
 		break;
+	case 0x12:
+		*index = 0x0000;
+		*opcode = BTSNOOP_OPCODE_ISO_TX_PKT;
+		break;
+	case 0x13:
+		*index = 0x0000;
+		*opcode = BTSNOOP_OPCODE_ISO_RX_PKT;
+		break;
 	case 0x0b:
 		*index = 0x0000;
 		*opcode = BTSNOOP_OPCODE_VENDOR_DIAG;
@@ -470,6 +481,11 @@ static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
 			return BTSNOOP_OPCODE_SCO_TX_PKT;
 	case 0x04:
 		return BTSNOOP_OPCODE_EVENT_PKT;
+	case 0x05:
+		if (flags & 0x01)
+			return BTSNOOP_OPCODE_ISO_RX_PKT;
+		else
+			return BTSNOOP_OPCODE_ISO_TX_PKT;
 	case 0xff:
 		if (flags & 0x02) {
 			if (flags & 0x01)
@@ -513,7 +529,7 @@ bool btsnoop_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
 		return false;
 	}
 
-	toread = be32toh(pkt.size);
+	toread = be32toh(pkt.len);
 	if (toread > BTSNOOP_MAX_PACKET_SIZE) {
 		btsnoop->aborted = true;
 		return false;
diff --git a/src/shared/ccp.c b/src/shared/ccp.c
new file mode 100644
index 0000000..8e1b0b5
--- /dev/null
+++ b/src/shared/ccp.c
@@ -0,0 +1,1226 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "lib/hci.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+#include "src/shared/timeout.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/ccp.h"
+
+#define DBG(_ccp, fmt, arg...) \
+	ccp_debug(_ccp, "%s:%s() " fmt, __FILE__, __func__, ## arg)
+
+struct bt_ccp_db {
+	struct gatt_db *db;
+	struct bt_ccs *ccs;
+};
+
+struct bt_ccp_pending {
+	unsigned int id;
+	struct bt_ccp *ccp;
+	bt_gatt_client_read_callback_t func;
+	void *user_data;
+};
+
+struct event_callback {
+	const struct bt_ccp_event_callback *cbs;
+	void *user_data;
+};
+
+struct bt_ccp {
+	int ref_count;
+	struct bt_gatt_client *client;
+	struct bt_ccp_db *ldb;
+	struct bt_ccp_db *rdb;
+
+	unsigned int bearer_name_id;
+	unsigned int bearer_uci_id;
+	unsigned int bearer_technology_id;
+	unsigned int bearer_uri_schemes_list_id;
+	unsigned int signal_strength_id;
+	unsigned int signal_reporting_intrvl_id;
+	unsigned int current_call_list_id;
+	unsigned int ccid_id;
+	unsigned int status_flag_id;
+	unsigned int target_bearer_uri_id;
+	unsigned int call_state_id;
+	unsigned int call_control_pt_id;
+	unsigned int call_control_opt_opcode_id;
+	unsigned int termination_reason_id;
+	unsigned int incoming_call_id;
+	unsigned int friendly_name_id;
+
+	struct event_callback *cb;
+	struct queue *pending;
+
+	bt_ccp_debug_func_t debug_func;
+	bt_ccp_destroy_func_t debug_destroy;
+	void *debug_data;
+	void *user_data;
+};
+
+struct bt_ccs {
+	struct bt_ccp_db *mdb;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *bearer_name;
+	struct gatt_db_attribute *bearer_name_ccc;
+	struct gatt_db_attribute *bearer_uci;
+	struct gatt_db_attribute *bearer_technology;
+	struct gatt_db_attribute *bearer_technology_ccc;
+	struct gatt_db_attribute *bearer_uri_schemes_list;
+	struct gatt_db_attribute *signal_strength;
+	struct gatt_db_attribute *signal_strength_ccc;
+	struct gatt_db_attribute *signal_reporting_intrvl;
+	struct gatt_db_attribute *current_call_list;
+	struct gatt_db_attribute *current_call_list_ccc;
+	struct gatt_db_attribute *ccid;
+	struct gatt_db_attribute *status_flag;
+	struct gatt_db_attribute *status_flag_ccc;
+	struct gatt_db_attribute *target_bearer_uri;
+	struct gatt_db_attribute *call_state;
+	struct gatt_db_attribute *call_state_ccc;
+	struct gatt_db_attribute *call_ctrl_point;
+	struct gatt_db_attribute *call_ctrl_point_ccc;
+	struct gatt_db_attribute *call_ctrl_opt_opcode;
+	struct gatt_db_attribute *termination_reason;
+	struct gatt_db_attribute *termination_reason_ccc;
+	struct gatt_db_attribute *incoming_call;
+	struct gatt_db_attribute *incoming_call_ccc;
+	struct gatt_db_attribute *friendly_name;
+	struct gatt_db_attribute *friendly_name_ccc;
+};
+
+static struct queue *ccp_db;
+
+static void ccp_debug(struct bt_ccp *ccp, const char *format, ...)
+{
+	va_list ap;
+
+	if (!ccp || !format || !ccp->debug_func)
+		return;
+
+	va_start(ap, format);
+	util_debug_va(ccp->debug_func, ccp->debug_data, format, ap);
+	va_end(ap);
+}
+
+static bool ccp_db_match(const void *data, const void *match_data)
+{
+	const struct bt_ccp_db *mdb = data;
+	const struct gatt_db *db = match_data;
+
+	return (mdb->db == db);
+}
+
+static void ccp_db_free(void *data)
+{
+	struct bt_ccp_db *bdb = data;
+
+	if (!bdb)
+		return;
+
+	gatt_db_unref(bdb->db);
+
+	free(bdb->ccs);
+	free(bdb);
+}
+
+static void ccp_free(void *data)
+{
+	struct bt_ccp *ccp = data;
+
+	DBG(ccp, "");
+
+	bt_ccp_detach(ccp);
+	ccp_db_free(ccp->rdb);
+	queue_destroy(ccp->pending, NULL);
+
+	free(ccp);
+}
+
+struct bt_ccp *bt_ccp_ref(struct bt_ccp *ccp)
+{
+	if (!ccp)
+		return NULL;
+
+	__sync_fetch_and_add(&ccp->ref_count, 1);
+
+	return ccp;
+}
+
+void bt_ccp_unref(struct bt_ccp *ccp)
+{
+	if (!ccp)
+		return;
+
+	if (__sync_sub_and_fetch(&ccp->ref_count, 1))
+		return;
+
+	ccp_free(ccp);
+}
+
+bool bt_ccp_set_user_data(struct bt_ccp *ccp, void *user_data)
+{
+	if (!ccp)
+		return false;
+
+	ccp->user_data = user_data;
+
+	return true;
+}
+
+void *bt_ccp_get_user_data(struct bt_ccp *ccp)
+{
+	if (!ccp)
+		return NULL;
+
+	return ccp->user_data;
+}
+
+bool bt_ccp_set_debug(struct bt_ccp *ccp, bt_ccp_debug_func_t func,
+		      void *user_data,
+		      bt_ccp_destroy_func_t destroy)
+{
+	if (!ccp)
+		return false;
+
+	if (ccp->debug_destroy)
+		ccp->debug_destroy(ccp->debug_data);
+
+	ccp->debug_func = func;
+	ccp->debug_destroy = destroy;
+	ccp->debug_data = user_data;
+
+	return true;
+}
+
+static void ccs_call_state_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	int call_state = 0;
+	struct iovec iov;
+
+	iov.iov_base = &call_state;
+	iov.iov_len = sizeof(int);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, iov.iov_len);
+}
+
+static void ccs_call_state_write(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)
+{
+	gatt_db_attribute_write_result(attrib, id,
+				       BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
+}
+
+static struct bt_ccs *ccs_new(struct gatt_db *db)
+{
+	struct bt_ccs *ccs;
+	bt_uuid_t uuid;
+
+	if (!db)
+		return NULL;
+
+	ccs = new0(struct bt_ccs, 1);
+
+	/* Populate DB with ccs attributes */
+	bt_uuid16_create(&uuid, GTBS_UUID);
+	ccs->service = gatt_db_add_service(db, &uuid, true, 42);
+
+	bt_uuid16_create(&uuid, BEARER_PROVIDER_NAME_CHRC_UUID);
+	ccs->bearer_name =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->bearer_name_ccc = gatt_db_service_add_ccc(ccs->service,
+						       BT_ATT_PERM_READ |
+						       BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, BEARER_UCI_CHRC_UUID);
+	ccs->bearer_uci =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ,
+						   ccs_call_state_read,
+						   NULL, ccs);
+
+	bt_uuid16_create(&uuid, BEARER_TECH_CHRC_UUID);
+	ccs->bearer_technology =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->bearer_technology_ccc = gatt_db_service_add_ccc(ccs->service,
+							     BT_ATT_PERM_READ |
+							     BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, BEARER_URI_SCHEME_CHRC_UUID);
+	ccs->bearer_uri_schemes_list =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	bt_uuid16_create(&uuid, BEARER_SIGNAL_STR_CHRC_UUID);
+	ccs->signal_strength =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->signal_strength_ccc = gatt_db_service_add_ccc(ccs->service,
+							   BT_ATT_PERM_READ |
+							   BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, BEARER_SIGNAL_INTRVL_CHRC_UUID);
+	ccs->signal_reporting_intrvl =
+	gatt_db_service_add_characteristic(ccs->service,
+					   &uuid, BT_ATT_PERM_READ |
+					   BT_ATT_PERM_WRITE,
+					   BT_GATT_CHRC_PROP_READ |
+					   BT_GATT_CHRC_PROP_WRITE |
+					   BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+					   ccs_call_state_read,
+					   ccs_call_state_write, ccs);
+
+	bt_uuid16_create(&uuid, CURR_CALL_LIST_CHRC_UUID);
+	ccs->current_call_list =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->current_call_list_ccc = gatt_db_service_add_ccc(ccs->service,
+							     BT_ATT_PERM_READ |
+							     BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, BEARER_CCID_CHRC_UUID);
+	ccs->ccid = gatt_db_service_add_characteristic(ccs->service,
+						       &uuid, BT_ATT_PERM_READ,
+						       BT_GATT_CHRC_PROP_READ,
+						       ccs_call_state_read,
+						       NULL, ccs);
+
+	bt_uuid16_create(&uuid, CALL_STATUS_FLAG_CHRC_UUID);
+	ccs->status_flag =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->status_flag_ccc = gatt_db_service_add_ccc(ccs->service,
+						       BT_ATT_PERM_READ |
+						       BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, INCOM_CALL_TARGET_URI_CHRC_UUID);
+	ccs->target_bearer_uri =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	bt_uuid16_create(&uuid, CALL_STATE_CHRC_UUID);
+	ccs->call_ctrl_point =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->call_ctrl_point_ccc = gatt_db_service_add_ccc(ccs->service,
+							   BT_ATT_PERM_READ |
+							   BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, CALL_CTRL_POINT_CHRC_UUID);
+	ccs->call_ctrl_opt_opcode =
+	gatt_db_service_add_characteristic(ccs->service,
+					   &uuid, BT_ATT_PERM_WRITE,
+					   BT_GATT_CHRC_PROP_WRITE |
+					   BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP
+					   | BT_GATT_CHRC_PROP_NOTIFY,
+					   NULL, ccs_call_state_write,
+					   ccs);
+
+	bt_uuid16_create(&uuid, CALL_CTRL_POINT_OPT_OPCODE_CHRC_UUID);
+	ccs->call_ctrl_opt_opcode =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	bt_uuid16_create(&uuid, TERMINATION_REASON_CHRC_UUID);
+	ccs->termination_reason =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	bt_uuid16_create(&uuid, INCOMING_CALL_CHRC_UUID);
+	ccs->incoming_call =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_NONE,
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   NULL, NULL, ccs);
+
+	ccs->incoming_call_ccc = gatt_db_service_add_ccc(ccs->service,
+							 BT_ATT_PERM_READ |
+							 BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, CALL_FRIENDLY_NAME_CHRC_UUID);
+	ccs->friendly_name =
+		gatt_db_service_add_characteristic(ccs->service,
+						   &uuid, BT_ATT_PERM_READ,
+						   BT_GATT_CHRC_PROP_READ |
+						   BT_GATT_CHRC_PROP_NOTIFY,
+						   ccs_call_state_read, NULL,
+						   ccs);
+
+	ccs->friendly_name_ccc = gatt_db_service_add_ccc(ccs->service,
+							 BT_ATT_PERM_READ |
+							 BT_ATT_PERM_WRITE);
+
+	gatt_db_service_set_active(ccs->service, false);
+
+	return ccs;
+}
+
+static struct bt_ccs *ccp_get_ccs(struct bt_ccp *ccp)
+{
+	if (!ccp)
+		return NULL;
+
+	if (ccp->rdb->ccs)
+		return ccp->rdb->ccs;
+
+	ccp->rdb->ccs = new0(struct bt_ccs, 1);
+	ccp->rdb->ccs->mdb = ccp->rdb;
+
+	return ccp->rdb->ccs;
+}
+
+static void ccp_pending_destroy(void *data)
+{
+	struct bt_ccp_pending *pending = data;
+	struct bt_ccp *ccp = pending->ccp;
+
+	queue_remove_if(ccp->pending, NULL, pending);
+}
+
+static void ccp_pending_complete(bool success, uint8_t att_ecode,
+				 const uint8_t *value, uint16_t length,
+				 void *user_data)
+{
+	struct bt_ccp_pending *pending = user_data;
+
+	if (pending->func)
+		pending->func(success, att_ecode, value, length,
+			      pending->user_data);
+}
+
+static void ccp_read_value(struct bt_ccp *ccp, uint16_t value_handle,
+			   bt_gatt_client_read_callback_t func,
+			   void *user_data)
+{
+	struct bt_ccp_pending *pending;
+
+	pending = new0(struct bt_ccp_pending, 1);
+	pending->ccp = ccp;
+	pending->func = func;
+	pending->user_data = user_data;
+
+	pending->id = bt_gatt_client_read_value(ccp->client, value_handle,
+						ccp_pending_complete, pending,
+						ccp_pending_destroy);
+	if (!pending->id) {
+		DBG(ccp, "Unable to send Read request");
+		free(pending);
+		return;
+	}
+
+	queue_push_tail(ccp->pending, pending);
+}
+
+static void read_call_back(bool success, uint8_t att_ecode,
+			   const uint8_t *value, uint16_t length,
+			   void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!success) {
+		DBG(ccp, "Unable to read call state: error 0x%02x", att_ecode);
+		return;
+	}
+}
+
+static void ccp_cb_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+
+	/* TODO: generic handler for non-mandatory CCP call backs */
+}
+
+static void ccp_cb_notify(uint16_t value_handle, const uint8_t *value,
+			  uint16_t length, void *user_data)
+{
+	 /* TODO: generic handler for non-mandatory CCP notifications */
+}
+
+static void ccp_cb_status_flag_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_status_flag_notify(uint16_t value_handle,
+				      const uint8_t *value,
+				      uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+}
+
+static void ccp_cb_terminate_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_terminate_notify(uint16_t value_handle, const uint8_t *value,
+				    uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+
+	/* TODO: update call state in Local context */
+}
+
+static void ccp_cb_bearer_name_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_bearer_name_notify(uint16_t value_handle,
+				      const uint8_t *value,
+				      uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+
+	/* TODO: update call details in Local context */
+}
+
+static void ccp_cb_call_list_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_call_list_notify(uint16_t value_handle, const uint8_t *value,
+				    uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+
+	 /* TODO: update call list in Local context */
+}
+
+static void ccp_cb_call_state_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_call_state_notify(uint16_t value_handle,
+				     const uint8_t *value,
+				     uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+
+	/* TODO: update call state in Local context */
+}
+
+static void ccp_cb_incom_call_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (att_ecode)
+		DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+}
+
+static void ccp_cb_incom_call_notify(uint16_t value_handle,
+				     const uint8_t *value,
+				     uint16_t length, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+
+	DBG(ccp, "");
+
+	if (!length)
+		return;
+
+	/* TODO: Handle incoming call notofiation, Answer/reject etc */
+}
+
+static void bt_ccp_incom_call_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->incoming_call, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->incoming_call_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_incom_call_register,
+					       ccp_cb_incom_call_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_call_state_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->call_state, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->call_state_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_call_state_register,
+					       ccp_cb_call_state_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_call_list_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->current_call_list, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->current_call_list_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_call_list_register,
+					       ccp_cb_call_list_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_name_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->bearer_name, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->bearer_name_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_bearer_name_register,
+					       ccp_cb_bearer_name_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_term_reason_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->termination_reason, NULL,
+					     &value_handle, NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->termination_reason_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_terminate_register,
+					       ccp_cb_terminate_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_status_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->status_flag, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->status_flag_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle,
+					       ccp_cb_status_flag_register,
+					       ccp_cb_status_flag_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_uci_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->bearer_uci, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->bearer_uci_id = bt_gatt_client_register_notify(ccp->client,
+							    value_handle,
+							    ccp_cb_register,
+							    ccp_cb_notify, ccp,
+							    NULL);
+}
+
+static void bt_ccp_technology_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->bearer_technology, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->bearer_technology_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_strength_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->signal_strength, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->signal_strength_id =
+		bt_gatt_client_register_notify(ccp->client, value_handle,
+					       ccp_cb_register, ccp_cb_notify,
+					       ccp, NULL);
+}
+
+static void bt_ccp_ccid_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->ccid, NULL, &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->ccid_id = bt_gatt_client_register_notify(ccp->client,
+						      value_handle,
+						      ccp_cb_register,
+						      ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_tar_uri_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->target_bearer_uri, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->target_bearer_uri_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp,
+					       NULL);
+}
+
+static void bt_ccp_ctrl_point_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->call_ctrl_point, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->call_control_pt_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_ctrl_opcode_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->call_ctrl_opt_opcode, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->call_control_opt_opcode_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_friendly_name_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->friendly_name, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->friendly_name_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_signal_intrvl_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->signal_reporting_intrvl, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->signal_reporting_intrvl_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void bt_ccp_uri_list_attach(struct bt_ccp *ccp)
+{
+	uint16_t value_handle;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	DBG(ccp, "");
+
+	if (!gatt_db_attribute_get_char_data(ccs->bearer_uri_schemes_list, NULL,
+					     &value_handle,
+					     NULL, NULL, NULL))
+		return;
+
+	ccp_read_value(ccp, value_handle, read_call_back, ccp);
+
+	ccp->bearer_uri_schemes_list_id =
+		bt_gatt_client_register_notify(ccp->client,
+					       value_handle, ccp_cb_register,
+					       ccp_cb_notify, ccp, NULL);
+}
+
+static void foreach_ccs_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+	struct bt_ccs *ccs;
+	uint16_t value_handle;
+	bt_uuid_t uuid;
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+					     NULL, NULL, &uuid))
+		return;
+
+	ccs = ccp_get_ccs(ccp);
+	if (!ccs || ccs->call_state)
+		return;
+
+	if (bt_uuid16_cmp(&uuid, BEARER_PROVIDER_NAME_CHRC_UUID)) {
+		DBG(ccp, "Found Bearer Name, handle 0x%04x", value_handle);
+
+		ccs->bearer_name = attr;
+		bt_ccp_name_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_UCI_CHRC_UUID)) {
+		DBG(ccp, "Found Bearer Uci, handle 0x%04x", value_handle);
+
+		ccs->bearer_uci = attr;
+		bt_ccp_uci_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_TECH_CHRC_UUID)) {
+		DBG(ccp, "Found Bearer Technology, handle %x", value_handle);
+
+		ccs->bearer_technology = attr;
+		bt_ccp_technology_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_SIGNAL_STR_CHRC_UUID)) {
+		DBG(ccp, "Found Signal Strength, handle 0x%04x", value_handle);
+
+		ccs->signal_strength = attr;
+		bt_ccp_strength_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_SIGNAL_INTRVL_CHRC_UUID)) {
+		DBG(ccp, "Found Signal Interval, handle 0x%04x", value_handle);
+
+		ccs->signal_reporting_intrvl = attr;
+		bt_ccp_signal_intrvl_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, CALL_STATUS_FLAG_CHRC_UUID)) {
+		DBG(ccp, "Found Status Flag, handle 0x%04x", value_handle);
+
+		ccs->status_flag = attr;
+		bt_ccp_status_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_URI_SCHEME_CHRC_UUID)) {
+		DBG(ccp, "Found URI Scheme, handle 0x%04x", value_handle);
+
+		ccs->bearer_uri_schemes_list = attr;
+		bt_ccp_uri_list_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, CURR_CALL_LIST_CHRC_UUID)) {
+		DBG(ccp, "Found Call List, handle 0x%04x", value_handle);
+
+		ccs->current_call_list = attr;
+		bt_ccp_call_list_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, BEARER_CCID_CHRC_UUID)) {
+		DBG(ccp, "Found CCID, handle 0x%04x", value_handle);
+
+		ccs->ccid = attr;
+		bt_ccp_ccid_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, INCOM_CALL_TARGET_URI_CHRC_UUID)) {
+		DBG(ccp, "Found Bearer Uri, handle 0x%04x", value_handle);
+
+		ccs->target_bearer_uri = attr;
+		bt_ccp_tar_uri_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, CALL_CTRL_POINT_CHRC_UUID)) {
+		DBG(ccp, "Found Control Point, handle 0x%04x", value_handle);
+
+		ccs->call_ctrl_point = attr;
+		bt_ccp_ctrl_point_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, CALL_CTRL_POINT_OPT_OPCODE_CHRC_UUID)) {
+		DBG(ccp, "Found Control opcode, handle 0x%04x", value_handle);
+
+		ccs->call_ctrl_opt_opcode = attr;
+		bt_ccp_ctrl_opcode_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, TERMINATION_REASON_CHRC_UUID)) {
+		DBG(ccp, "Found Termination Reason, handle %x", value_handle);
+
+		ccs->termination_reason = attr;
+		bt_ccp_term_reason_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, INCOMING_CALL_CHRC_UUID)) {
+		DBG(ccp, "Found Incoming call, handle 0x%04x", value_handle);
+
+		ccs->incoming_call = attr;
+		bt_ccp_incom_call_attach(ccp);
+	}
+
+	if (bt_uuid16_cmp(&uuid, CALL_FRIENDLY_NAME_CHRC_UUID)) {
+		DBG(ccp, "Found Friendly name, handle 0x%04x", value_handle);
+
+		ccs->friendly_name = attr;
+		bt_ccp_friendly_name_attach(ccp);
+	}
+}
+
+void bt_ccp_set_event_callbacks(struct bt_ccp *ccp,
+				const struct bt_ccp_event_callback *cbs,
+				void *user_data)
+{
+	struct event_callback *cb;
+
+	if (ccp->cb)
+		free(ccp->cb);
+
+	cb = new0(struct event_callback, 1);
+	cb->cbs = cbs;
+	cb->user_data = user_data;
+
+	ccp->cb = cb;
+}
+
+static void foreach_ccs_service(struct gatt_db_attribute *attr,
+				void *user_data)
+{
+	struct bt_ccp *ccp = user_data;
+	struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+	ccs->service = attr;
+
+	gatt_db_service_foreach_char(attr, foreach_ccs_char, ccp);
+}
+
+static struct bt_ccp_db *ccp_db_new(struct gatt_db *db)
+{
+	struct bt_ccp_db *mdb;
+
+	if (!db)
+		return NULL;
+
+	mdb = new0(struct bt_ccp_db, 1);
+	mdb->db = gatt_db_ref(db);
+
+	if (!ccp_db)
+		ccp_db = queue_new();
+
+	queue_push_tail(ccp_db, mdb);
+
+	mdb->ccs = ccs_new(db);
+	return mdb;
+}
+
+static struct bt_ccp_db *ccp_get_db(struct gatt_db *db)
+{
+	struct bt_ccp_db *mdb;
+
+	mdb = queue_find(ccp_db, ccp_db_match, db);
+	if (mdb)
+		return mdb;
+
+	return ccp_db_new(db);
+}
+
+struct bt_ccp *bt_ccp_new(struct gatt_db *ldb, struct gatt_db *rdb)
+{
+	struct bt_ccp *ccp;
+	struct bt_ccp_db *mdb;
+
+	if (!ldb)
+		return NULL;
+
+	mdb = ccp_get_db(ldb);
+	if (!mdb)
+		return NULL;
+
+	ccp = new0(struct bt_ccp, 1);
+	ccp->ldb = mdb;
+	ccp->pending = queue_new();
+
+	if (!rdb)
+		goto done;
+
+	mdb = new0(struct bt_ccp_db, 1);
+	mdb->db = gatt_db_ref(rdb);
+
+	ccp->rdb = mdb;
+
+done:
+	bt_ccp_ref(ccp);
+
+	return ccp;
+}
+
+void bt_ccp_register(struct gatt_db *db)
+{
+	ccp_db_new(db);
+}
+
+bool bt_ccp_attach(struct bt_ccp *ccp, struct bt_gatt_client *client)
+{
+	bt_uuid_t uuid;
+
+	DBG(ccp, "ccp %p", ccp);
+
+	ccp->client = bt_gatt_client_clone(client);
+	if (!ccp->client)
+		return false;
+
+	if (ccp->rdb->ccs) {
+		bt_ccp_call_state_attach(ccp);
+		return true;
+	}
+
+	bt_uuid16_create(&uuid, GTBS_UUID);
+	gatt_db_foreach_service(ccp->rdb->db, &uuid, foreach_ccs_service, ccp);
+
+	return true;
+}
+
+void bt_ccp_detach(struct bt_ccp *ccp)
+{
+	DBG(ccp, "%p", ccp);
+
+	bt_gatt_client_unref(ccp->client);
+	ccp->client = NULL;
+}
diff --git a/src/shared/ccp.h b/src/shared/ccp.h
new file mode 100644
index 0000000..28b8b03
--- /dev/null
+++ b/src/shared/ccp.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ */
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+struct bt_ccp;
+struct bt_ccp_db;
+struct bt_ccp_session_info;
+
+typedef void (*bt_ccp_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_ccp_destroy_func_t)(void *user_data);
+
+struct bt_ccp_event_callback {
+	void (*call_state)(struct bt_ccp *ccp,  const uint8_t *value,
+			   uint16_t length);
+};
+
+void bt_ccp_set_event_callbacks(struct bt_ccp *ccp,
+				const struct bt_ccp_event_callback *cbs,
+				void *user_data);
+
+bool bt_ccp_set_debug(struct bt_ccp *ccp, bt_ccp_debug_func_t cb,
+		      void *user_data, bt_ccp_destroy_func_t destroy);
+
+void bt_ccp_register(struct gatt_db *db);
+bool bt_ccp_attach(struct bt_ccp *ccp, struct bt_gatt_client *client);
+void bt_ccp_detach(struct bt_ccp *ccp);
+
+struct bt_ccp *bt_ccp_new(struct gatt_db *ldb, struct gatt_db *rdb);
+struct bt_ccp *bt_ccp_ref(struct bt_ccp *ccp);
+void bt_ccp_unref(struct bt_ccp *ccp);
+
+bool bt_ccp_set_user_data(struct bt_ccp *ccp, void *user_data);
+void *bt_ccp_get_user_data(struct bt_ccp *ccp);
diff --git a/src/shared/crypto.c b/src/shared/crypto.c
index d5efa41..5449621 100644
--- a/src/shared/crypto.c
+++ b/src/shared/crypto.c
@@ -586,41 +586,55 @@ bool bt_crypto_s1(struct bt_crypto *crypto, const uint8_t k[16],
 	return bt_crypto_e(crypto, k, res, res);
 }
 
-static bool aes_cmac(struct bt_crypto *crypto, const uint8_t key[16],
+static bool aes_cmac_be(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);
+	fd = alg_new(crypto->cmac_aes, key, 16);
 	if (fd < 0)
 		return false;
 
-	swap_buf(msg, msg_msb, msg_len);
-	len = send(fd, msg_msb, msg_len, 0);
+	len = send(fd, msg, msg_len, 0);
 	if (len < 0) {
 		close(fd);
 		return false;
 	}
 
-	len = read(fd, out, 16);
+	len = read(fd, res, 16);
 	if (len < 0) {
 		close(fd);
 		return false;
 	}
 
-	swap_buf(out, res, 16);
-
 	close(fd);
 
 	return true;
 }
 
+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];
+
+	if (msg_len > CMAC_MSG_MAX)
+		return false;
+
+	swap_buf(key, key_msb, 16);
+	swap_buf(msg, msg_msb, msg_len);
+
+	if (!aes_cmac_be(crypto, key_msb, msg_msb, msg_len, out))
+		return false;
+
+	swap_buf(out, res, 16);
+
+	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])
 {
@@ -737,3 +751,218 @@ bool bt_crypto_gatt_hash(struct bt_crypto *crypto, struct iovec *iov,
 
 	return true;
 }
+
+/*
+ * Resolvable Set Identifier hash function sih
+ *
+ * The RSI hash function sih is used to generate a hash value that is used in
+ * RSIs.
+ *
+ * The following variables are the inputs to the RSI hash function sih:
+ *
+ *   k is 128 bits
+ *   r is 24 bits
+ *   padding is 104 bits, all set to 0
+ *
+ * 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 LSO of r becomes the LSO of r', and the MSO of padding becomes the MSO
+ * of r'.
+ *
+ * For example, if the 24-bit value r is 0x3A98B5, then r' is
+ * 0x000000000000000000000000003A98B5.
+ *
+ * The output of the Resolvable Set Identifier function sih is:
+ *
+ *   sih(k, r)=e(k, r') mod 2^24
+ *
+ * The output of the security function e is truncated to 24 bits by taking the
+ * least significant 24 bits of the output of e as the result of sih.
+ */
+bool bt_crypto_sih(struct bt_crypto *crypto, const uint8_t k[16],
+					const uint8_t r[3], uint8_t hash[3])
+{
+	return bt_crypto_ah(crypto, k, r, hash);
+}
+
+static bool aes_cmac_zero(struct bt_crypto *crypto, const uint8_t *msg,
+					size_t msg_len, uint8_t res[16])
+{
+	const uint8_t zero[16] = {};
+
+	return aes_cmac_be(crypto, zero, msg, msg_len, res);
+}
+
+/* The inputs to function s1 are:
+ *
+ *   M is a non-zero length octet array or ASCII encoded string
+ *
+ * If M is an ASCII encoded string, M shall be converted into an integer number
+ * by replacing each string character with its ASCII code preserving the order.
+ * For example, if M is the string “CSIS”, M is converted into the integer
+ * number: 0x4353 4953.
+ *
+ * ZERO is the 128-bit value:
+ *
+ *   0x0000 0000 0000 0000 0000 0000 0000 0000
+ *
+ * The output of the salt generation function s1 shall be calculated as follows:
+ *
+ *   s1(M)=AES‐CMACZERO(M)
+ *
+ * Where AES-CMACZERO is the CMAC function defined in Section 4.2.
+ */
+static bool sef_s1(struct bt_crypto *crypto, const uint8_t *m,
+					size_t m_len, uint8_t res[16])
+{
+	/* s1(M)=AES‐CMACZERO(M) */
+	return aes_cmac_zero(crypto, m, m_len, res);
+}
+
+/* The key derivation function k1 is used to derive a key. The derived key is
+ * used to encrypt and decrypt the value of the Set Identity Resolving Key
+ * characteristic (see Section 5.1).
+ *
+ * The definition of this key generation function uses the MAC function
+ * AES-CMACT with a 128-bit key T.
+ *
+ * The inputs to function k1 are:
+ *
+ *   N is 0 or more octets
+ *
+ *   SALT is 128 bits
+ *
+ *   P is 0 or more octets
+ *
+ * The key (T) shall be computed as follows:
+ *
+ *   T=AES‐CMACSALT(N)
+ *
+ * Where AES-CMACSALT is the CMAC function defined in Section 4.2.
+ *
+ * The output of the key generation function k1 shall be calculated as follows:
+ *
+ *   k1(N, SALT, P)=AES‐CMACT(P)
+ *
+ * Where AES-CMACT is the CMAC function defined in Section 4.2.
+ */
+static bool sef_k1(struct bt_crypto *crypto, const uint8_t n[16],
+				uint8_t salt[16], const uint8_t *p,
+				size_t p_len, uint8_t res[16])
+{
+	uint8_t res1[16];
+
+	/* T=AES‐CMACSALT(N) */
+	if (!aes_cmac_be(crypto, salt, n, 16, res1))
+		return false;
+
+	/* k1(N, SALT, P)=AES‐CMACT(P) */
+	return aes_cmac_be(crypto, res1, p, p_len, res);
+}
+
+/*
+ * SIRK encryption function sef
+ *
+ * The SIRK encryption function sef shall be used by the server to encrypt the
+ * SIRK with a key K. The value of K depends on the transport on which the Set
+ * Identity Resolving Key characteristic is read or notified.
+ *
+ * If the Set Identity Resolving Key characteristic is read or notified on the
+ * Basic Rate/Enhanced Data Rate (BR/EDR) transport, K shall be equal to the
+ * Link Key shared by the server and the client.
+ *
+ *   K=LinkKey
+ *
+ * If the Set Identity Resolving Key characteristic is read or notified on the
+ * Bluetooth Low Energy (LE) transport, K shall be equal to the LTK shared by
+ * the server and client. That is,
+ *
+ *   K=LTK
+ *
+ * The inputs to the function sef are:
+ *
+ *   K is the key defined above in this section
+ *
+ *   SIRK is the value of the SIRK to be encrypted
+ *
+ * The output of the SIRK encryption function sef is as follows:
+ *
+ *   sef(K, SIRK)=k1(K, s1(“SIRKenc”), “csis”)^SIRK
+ *
+ * Where ^ is the bitwise exclusive or operation.
+ */
+bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16],
+			const uint8_t sirk[16], uint8_t out[16])
+{
+	const uint8_t m[] = {'S', 'I', 'R', 'K', 'e', 'n', 'c'};
+	const uint8_t p[] = {'c', 's', 'i', 's'};
+	uint8_t k_msb[16];
+	uint8_t salt[16];
+	uint8_t res_msb[16];
+	uint8_t res[16];
+
+	if (!crypto)
+		return false;
+
+	/* salt = s1(“SIRKenc”) */
+	if (!sef_s1(crypto, m, sizeof(m), salt))
+		return false;
+
+	/* Convert K to MSB/BE format */
+	swap_buf(k, k_msb, 16);
+
+	/* res_msb = k1(K, salt, “csis”) */
+	if (!sef_k1(crypto, k_msb, salt, p, sizeof(p), res_msb))
+		return false;
+
+	/* Convert back to LSB/LE format */
+	swap_buf(res_msb, res, 16);
+
+	/* res^SIRK */
+	u128_xor(res, sirk, out);
+
+	return true;
+}
+
+/* Generates a SIRK from a string using the following steps:
+ *  - Generate a hash (k) using the str as input
+ *  - Generate a hash (sirk) using vendor, product, version and source as input
+ *  - Encrypt sirk using k as LTK with sef function.
+ */
+bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor,
+			uint16_t product, uint16_t version, uint16_t source,
+			uint8_t sirk[16])
+{
+	struct iovec iov[4];
+	uint8_t k[16];
+	uint8_t sirk_plaintext[16];
+
+	if (!crypto)
+		return false;
+
+	iov[0].iov_base = (void *)str;
+	iov[0].iov_len = strlen(str);
+
+	/* Generate a k using the str as input */
+	if (!bt_crypto_gatt_hash(crypto, iov, 1, k))
+		return false;
+
+	iov[0].iov_base = &vendor;
+	iov[0].iov_len = sizeof(vendor);
+	iov[1].iov_base = &product;
+	iov[1].iov_len = sizeof(product);
+	iov[2].iov_base = &version;
+	iov[2].iov_len = sizeof(version);
+	iov[3].iov_base = &source;
+	iov[3].iov_len = sizeof(source);
+
+	/* Generate a sirk using vendor, product, version and source as input */
+	if (!bt_crypto_gatt_hash(crypto, iov, 4, sirk_plaintext))
+		return false;
+
+	/* Encrypt sirk using k as LTK with sef function */
+	return bt_crypto_sef(crypto, k, sirk_plaintext, sirk);
+}
diff --git a/src/shared/crypto.h b/src/shared/crypto.h
index 356326d..d45308a 100644
--- a/src/shared/crypto.h
+++ b/src/shared/crypto.h
@@ -53,3 +53,10 @@ bool bt_crypto_verify_att_sign(struct bt_crypto *crypto, const uint8_t key[16],
 				const uint8_t *pdu, uint16_t pdu_len);
 bool bt_crypto_gatt_hash(struct bt_crypto *crypto, struct iovec *iov,
 				size_t iov_len, uint8_t res[16]);
+bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16],
+			const uint8_t sirk[16], uint8_t out[16]);
+bool bt_crypto_sih(struct bt_crypto *crypto, const uint8_t k[16],
+					const uint8_t r[3], uint8_t hash[3]);
+bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor,
+			uint16_t product, uint16_t version, uint16_t source,
+			uint8_t sirk[16]);
diff --git a/src/shared/csip.c b/src/shared/csip.c
new file mode 100644
index 0000000..a9c57c9
--- /dev/null
+++ b/src/shared/csip.c
@@ -0,0 +1,845 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+#include "src/shared/timeout.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/crypto.h"
+#include "src/shared/csip.h"
+
+#define DBG(_csip, fmt, arg...) \
+	csip_debug(_csip, "%s:%s() " fmt, __FILE__, __func__, ## arg)
+
+/* SIRK is now hardcoded in the code. This can be moved
+ * to a configuration file. Since the code is to validate
+ * the CSIP use case of set member
+ */
+#define SIRK "761FAE703ED681F0C50B34155B6434FB"
+#define CSIS_SIZE	0x02
+#define CSIS_LOCK	0x01
+#define CSIS_RANK	0x01
+#define CSIS_PLAINTEXT	0x01
+#define CSIS_ENC	0x02
+
+struct bt_csip_db {
+	struct gatt_db *db;
+	struct bt_csis *csis;
+};
+
+struct csis_sirk {
+	uint8_t type;
+	uint8_t val[16];
+} __packed;
+
+struct bt_csis {
+	struct bt_csip_db *cdb;
+	struct csis_sirk *sirk_val;
+	uint8_t size_val;
+	uint8_t lock_val;
+	uint8_t rank_val;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *sirk;
+	struct gatt_db_attribute *size;
+	struct gatt_db_attribute *lock;
+	struct gatt_db_attribute *lock_ccc;
+	struct gatt_db_attribute *rank;
+	bt_csip_encrypt_func_t encrypt;
+};
+
+struct bt_csip_cb {
+	unsigned int id;
+	bt_csip_func_t attached;
+	bt_csip_func_t detached;
+	void *user_data;
+};
+
+struct bt_csip_ready {
+	unsigned int id;
+	bt_csip_ready_func_t func;
+	bt_csip_destroy_func_t destroy;
+	void *data;
+};
+
+struct bt_csip {
+	int ref_count;
+	struct bt_csip_db *ldb;
+	struct bt_csip_db *rdb;
+	struct bt_gatt_client *client;
+	struct bt_att *att;
+
+	unsigned int idle_id;
+	struct queue *ready_cbs;
+
+	bt_csip_debug_func_t debug_func;
+	bt_csip_destroy_func_t debug_destroy;
+	void *debug_data;
+
+	bt_csip_sirk_func_t sirk_func;
+	void *sirk_data;
+
+	void *user_data;
+};
+
+static struct queue *csip_db;
+static struct queue *csip_cbs;
+static struct queue *sessions;
+
+static void csip_detached(void *data, void *user_data)
+{
+	struct bt_csip_cb *cb = data;
+	struct bt_csip *csip = user_data;
+
+	cb->detached(csip, cb->user_data);
+}
+
+void bt_csip_detach(struct bt_csip *csip)
+{
+	if (!queue_remove(sessions, csip))
+		return;
+
+	bt_gatt_client_idle_unregister(csip->client, csip->idle_id);
+
+	bt_gatt_client_unref(csip->client);
+	csip->client = NULL;
+
+	queue_foreach(csip_cbs, csip_detached, csip);
+}
+
+static void csis_free(struct bt_csis *csis)
+{
+	if (!csis)
+		return;
+
+	free(csis->sirk_val);
+	free(csis);
+}
+
+static void csip_db_free(void *data)
+{
+	struct bt_csip_db *cdb = data;
+
+	if (!cdb)
+		return;
+
+	gatt_db_unref(cdb->db);
+
+	csis_free(cdb->csis);
+	free(cdb);
+}
+
+static void csip_ready_free(void *data)
+{
+	struct bt_csip_ready *ready = data;
+
+	if (ready->destroy)
+		ready->destroy(ready->data);
+
+	free(ready);
+}
+
+static void csip_free(void *data)
+{
+	struct bt_csip *csip = data;
+
+	bt_csip_detach(csip);
+
+	csip_db_free(csip->rdb);
+
+	queue_destroy(csip->ready_cbs, csip_ready_free);
+
+	free(csip);
+}
+
+struct bt_att *bt_csip_get_att(struct bt_csip *csip)
+{
+	if (!csip)
+		return NULL;
+
+	if (csip->att)
+		return csip->att;
+
+	return bt_gatt_client_get_att(csip->client);
+}
+
+struct bt_csip *bt_csip_ref(struct bt_csip *csip)
+{
+	if (!csip)
+		return NULL;
+
+	__sync_fetch_and_add(&csip->ref_count, 1);
+
+	return csip;
+}
+
+static struct bt_csip *bt_csip_ref_safe(struct bt_csip *csip)
+{
+	if (!csip || !csip->ref_count)
+		return NULL;
+
+	return bt_csip_ref(csip);
+}
+
+void bt_csip_unref(struct bt_csip *csip)
+{
+	if (!csip)
+		return;
+
+	if (__sync_sub_and_fetch(&csip->ref_count, 1))
+		return;
+
+	csip_free(csip);
+}
+
+static void csip_debug(struct bt_csip *csip, const char *format, ...)
+{
+	va_list ap;
+
+	if (!csip || !format || !csip->debug_func)
+		return;
+
+	va_start(ap, format);
+	util_debug_va(csip->debug_func, csip->debug_data, format, ap);
+	va_end(ap);
+}
+
+static void csis_sirk_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_csis *csis = user_data;
+	struct csis_sirk sirk;
+	struct iovec iov;
+
+	memcpy(&sirk, csis->sirk_val, sizeof(sirk));
+
+	if (sirk.type == BT_CSIP_SIRK_ENCRYPT &&
+				!csis->encrypt(att, sirk.val)) {
+		gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
+							NULL, 0);
+		return;
+	}
+
+	iov.iov_base = &sirk;
+	iov.iov_len = sizeof(sirk);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
+
+static void csis_size_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_csis *csis = user_data;
+	struct iovec iov;
+
+	iov.iov_base = &csis->size_val;
+	iov.iov_len = sizeof(csis->size_val);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
+
+static void csis_lock_read_cb(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	uint8_t value = CSIS_LOCK;
+
+	gatt_db_attribute_read_result(attrib, id, 0, &value, sizeof(value));
+}
+
+static void csis_lock_write_cb(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)
+{
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
+
+static void csis_rank_read_cb(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_csis *csis = user_data;
+	struct iovec iov;
+
+	iov.iov_base = &csis->rank_val;
+	iov.iov_len = sizeof(csis->rank_val);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, iov.iov_len);
+}
+
+static struct bt_csis *csis_new(struct gatt_db *db)
+{
+	struct bt_csis *csis;
+
+	if (!db)
+		return NULL;
+
+	csis = new0(struct bt_csis, 1);
+
+	return csis;
+}
+
+static struct bt_csip_db *csip_db_new(struct gatt_db *db)
+{
+	struct bt_csip_db *cdb;
+
+	if (!db)
+		return NULL;
+
+	cdb = new0(struct bt_csip_db, 1);
+	cdb->db = gatt_db_ref(db);
+
+	if (!csip_db)
+		csip_db = queue_new();
+
+	cdb->csis = csis_new(db);
+	cdb->csis->cdb = cdb;
+
+	queue_push_tail(csip_db, cdb);
+
+	return cdb;
+}
+
+bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data)
+{
+	if (!csip)
+		return false;
+
+	csip->user_data = user_data;
+
+	return true;
+}
+
+static bool csip_db_match(const void *data, const void *match_data)
+{
+	const struct bt_csip_db *cdb = data;
+	const struct gatt_db *db = match_data;
+
+	return (cdb->db == db);
+}
+
+static struct bt_csip_db *csip_get_db(struct gatt_db *db)
+{
+	struct bt_csip_db *cdb;
+
+	cdb = queue_find(csip_db, csip_db_match, db);
+	if (cdb)
+		return cdb;
+
+	return csip_db_new(db);
+}
+
+bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func,
+			void *user_data, bt_csip_destroy_func_t destroy)
+{
+	if (!csip)
+		return false;
+
+	if (csip->debug_destroy)
+		csip->debug_destroy(csip->debug_data);
+
+	csip->debug_func = func;
+	csip->debug_destroy = destroy;
+	csip->debug_data = user_data;
+
+	return true;
+}
+
+unsigned int bt_csip_register(bt_csip_func_t attached, bt_csip_func_t detached,
+							void *user_data)
+{
+	struct bt_csip_cb *cb;
+	static unsigned int id;
+
+	if (!attached && !detached)
+		return 0;
+
+	if (!csip_cbs)
+		csip_cbs = queue_new();
+
+	cb = new0(struct bt_csip_cb, 1);
+	cb->id = ++id ? id : ++id;
+	cb->attached = attached;
+	cb->detached = detached;
+	cb->user_data = user_data;
+
+	queue_push_tail(csip_cbs, cb);
+
+	return cb->id;
+}
+
+static bool match_id(const void *data, const void *match_data)
+{
+	const struct bt_csip_cb *cb = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (cb->id == id);
+}
+
+bool bt_csip_unregister(unsigned int id)
+{
+	struct bt_csip_cb *cb;
+
+	cb = queue_remove_if(csip_cbs, match_id, UINT_TO_PTR(id));
+	if (!cb)
+		return false;
+
+	free(cb);
+
+	return true;
+}
+
+struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb)
+{
+	struct bt_csip *csip;
+	struct bt_csip_db *db;
+
+	if (!ldb)
+		return NULL;
+
+	db = csip_get_db(ldb);
+	if (!db)
+		return NULL;
+
+	csip = new0(struct bt_csip, 1);
+	csip->ldb = db;
+	csip->ready_cbs = queue_new();
+
+	if (!rdb)
+		goto done;
+
+	db = new0(struct bt_csip_db, 1);
+	db->db = gatt_db_ref(rdb);
+
+	csip->rdb = db;
+
+done:
+	bt_csip_ref(csip);
+
+	return csip;
+}
+
+static struct bt_csis *csip_get_csis(struct bt_csip *csip)
+{
+	if (!csip)
+		return NULL;
+
+	if (csip->rdb->csis)
+		return csip->rdb->csis;
+
+	csip->rdb->csis = new0(struct bt_csis, 1);
+	csip->rdb->csis->cdb = csip->rdb;
+
+	return csip->rdb->csis;
+}
+
+static void read_sirk(bool success, uint8_t att_ecode, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_csip *csip = user_data;
+	struct bt_csis *csis;
+	struct csis_sirk *sirk;
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = length
+	};
+
+	if (!success) {
+		DBG(csip, "Unable to read SIRK: error 0x%02x", att_ecode);
+		return;
+	}
+
+	csis = csip_get_csis(csip);
+	if (!csis)
+		return;
+
+	sirk = util_iov_pull_mem(&iov, sizeof(*sirk));
+	if (!sirk) {
+		DBG(csip, "Invalid size for SIRK: len %u", length);
+		return;
+	}
+
+	if (!csis->sirk_val)
+		csis->sirk_val = new0(struct csis_sirk, 1);
+
+	memcpy(csis->sirk_val, sirk, sizeof(*sirk));
+}
+
+static void read_size(bool success, uint8_t att_ecode, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_csip *csip = user_data;
+	struct bt_csis *csis;
+
+	if (!success) {
+		DBG(csip, "Unable to read Size: error 0x%02x", att_ecode);
+		return;
+	}
+
+	csis = csip_get_csis(csip);
+	if (!csis)
+		return;
+
+	csis->size_val = *value;
+}
+
+static void read_rank(bool success, uint8_t att_ecode, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_csip *csip = user_data;
+	struct bt_csis *csis;
+
+	if (!success) {
+		DBG(csip, "Unable to read Rank: error 0x%02x", att_ecode);
+		return;
+	}
+
+	csis = csip_get_csis(csip);
+	if (!csis)
+		return;
+
+	csis->rank_val = *value;
+}
+
+static void csip_notify_ready(struct bt_csip *csip)
+{
+	const struct queue_entry *entry;
+
+	if (!bt_csip_ref_safe(csip))
+		return;
+
+	for (entry = queue_get_entries(csip->ready_cbs); entry;
+							entry = entry->next) {
+		struct bt_csip_ready *ready = entry->data;
+
+		ready->func(csip, ready->data);
+	}
+
+	bt_csip_unref(csip);
+}
+
+static void foreach_csis_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_csip *csip = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_sirk, uuid_size, uuid_rank;
+	struct bt_csis *csis;
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
+		return;
+
+	bt_uuid16_create(&uuid_sirk, CS_SIRK);
+	bt_uuid16_create(&uuid_size, CS_SIZE);
+	bt_uuid16_create(&uuid_rank, CS_RANK);
+
+	if (!bt_uuid_cmp(&uuid, &uuid_sirk)) {
+		DBG(csip, "SIRK found: handle 0x%04x", value_handle);
+
+		csis = csip_get_csis(csip);
+		if (!csis)
+			return;
+
+		csis->sirk = attr;
+
+		bt_gatt_client_read_value(csip->client, value_handle, read_sirk,
+							csip, NULL);
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_size)) {
+		DBG(csip, "Size found: handle 0x%04x", value_handle);
+
+		csis = csip_get_csis(csip);
+		if (!csis)
+			return;
+
+		csis->size = attr;
+
+		bt_gatt_client_read_value(csip->client, value_handle, read_size,
+							csip, NULL);
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_rank)) {
+		DBG(csip, "Rank found: handle 0x%04x", value_handle);
+
+		csis = csip_get_csis(csip);
+		if (!csis)
+			return;
+
+		csis->rank = attr;
+
+		bt_gatt_client_read_value(csip->client, value_handle, read_rank,
+							csip, NULL);
+	}
+}
+static void foreach_csis_service(struct gatt_db_attribute *attr,
+						void *user_data)
+{
+	struct bt_csip *csip = user_data;
+	struct bt_csis *csis = csip_get_csis(csip);
+
+	if (!csis)
+		return;
+
+	csis->service = attr;
+
+	gatt_db_service_set_claimed(attr, true);
+
+	gatt_db_service_foreach_char(attr, foreach_csis_char, csip);
+}
+
+static void csip_idle(void *data)
+{
+	struct bt_csip *csip = data;
+
+	csip->idle_id = 0;
+
+	csip_notify_ready(csip);
+}
+
+bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client)
+{
+	bt_uuid_t uuid;
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, csip);
+
+	if (!client)
+		return true;
+
+	if (csip->client)
+		return false;
+
+	csip->client = bt_gatt_client_clone(client);
+	if (!csip->client)
+		return false;
+
+	csip->idle_id = bt_gatt_client_idle_register(csip->client, csip_idle,
+								csip, NULL);
+
+	bt_uuid16_create(&uuid, CSIS_UUID);
+	gatt_db_foreach_service(csip->rdb->db, &uuid, foreach_csis_service,
+				csip);
+
+	return true;
+}
+
+static struct csis_sirk *sirk_new(struct bt_csis *csis, struct gatt_db *db,
+					uint8_t type, uint8_t k[16],
+					uint8_t size, uint8_t rank)
+{
+	struct csis_sirk *sirk;
+	bt_uuid_t uuid;
+	struct gatt_db_attribute *cas;
+
+	if (!csis)
+		return NULL;
+
+	if (csis->sirk)
+		sirk = csis->sirk_val;
+	else
+		sirk = new0(struct csis_sirk, 1);
+
+	sirk->type = type;
+	memcpy(sirk->val, k, sizeof(sirk->val));
+	csis->sirk_val = sirk;
+	csis->size_val = size;
+	csis->lock_val = 1;
+	csis->rank_val = rank;
+
+	/* Check if service already active as that means the attributes have
+	 * already been registered.
+	 */
+	if (gatt_db_service_get_active(csis->service))
+		return sirk;
+
+	/* Populate DB with CSIS attributes */
+	bt_uuid16_create(&uuid, CSIS_UUID);
+	csis->service = gatt_db_add_service(db, &uuid, true, 10);
+
+	bt_uuid16_create(&uuid, CS_SIRK);
+	csis->sirk = gatt_db_service_add_characteristic(csis->service,
+					&uuid,
+					BT_ATT_PERM_READ |
+					BT_ATT_PERM_READ_ENCRYPT,
+					BT_GATT_CHRC_PROP_READ,
+					csis_sirk_read, NULL,
+					csis);
+
+	bt_uuid16_create(&uuid, CS_SIZE);
+	csis->size = gatt_db_service_add_characteristic(csis->service,
+					&uuid,
+					BT_ATT_PERM_READ |
+					BT_ATT_PERM_READ_ENCRYPT,
+					BT_GATT_CHRC_PROP_READ,
+					csis_size_read, NULL,
+					csis);
+
+	/* Lock */
+	bt_uuid16_create(&uuid, CS_LOCK);
+	csis->lock = gatt_db_service_add_characteristic(csis->service, &uuid,
+					BT_ATT_PERM_READ |
+					BT_ATT_PERM_READ_ENCRYPT |
+					BT_ATT_PERM_WRITE |
+					BT_ATT_PERM_WRITE_ENCRYPT,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_WRITE |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					csis_lock_read_cb,
+					csis_lock_write_cb,
+					csis);
+
+	csis->lock_ccc = gatt_db_service_add_ccc(csis->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	/* Rank */
+	bt_uuid16_create(&uuid, CS_RANK);
+	csis->rank = gatt_db_service_add_characteristic(csis->service, &uuid,
+					BT_ATT_PERM_READ |
+					BT_ATT_PERM_READ_ENCRYPT,
+					BT_GATT_CHRC_PROP_READ,
+					csis_rank_read_cb,
+					NULL, csis);
+
+	/* Add the CAS service */
+	bt_uuid16_create(&uuid, 0x1853);
+	cas = gatt_db_add_service(db, &uuid, true, 2);
+	gatt_db_service_add_included(cas, csis->service);
+	gatt_db_service_set_active(cas, true);
+	gatt_db_service_add_included(cas, csis->service);
+
+	gatt_db_service_set_active(csis->service, true);
+
+	return sirk;
+}
+
+bool bt_csip_set_sirk(struct bt_csip *csip, bool encrypt,
+				uint8_t k[16], uint8_t size, uint8_t rank,
+				bt_csip_encrypt_func_t func)
+{
+	uint8_t zero[16] = {};
+	uint8_t type;
+
+	if (!csip || !csip->ldb || !memcmp(k, zero, sizeof(zero)))
+		return false;
+
+	type = encrypt ? BT_CSIP_SIRK_ENCRYPT : BT_CSIP_SIRK_CLEARTEXT;
+
+	/* In case of encrypted type requires sef key function */
+	if (type == BT_CSIP_SIRK_ENCRYPT && !func)
+		return false;
+
+	if (!sirk_new(csip->ldb->csis, csip->ldb->db, type, k, size, rank))
+		return false;
+
+	csip->ldb->csis->encrypt = func;
+
+	return true;
+}
+
+bool bt_csip_get_sirk(struct bt_csip *csip, uint8_t *type,
+				uint8_t k[16], uint8_t *size, uint8_t *rank)
+{
+	struct bt_csis *csis;
+
+	if (!csip)
+		return false;
+
+	csis = csip_get_csis(csip);
+	if (!csis)
+		return false;
+
+	if (!csis->sirk_val)
+		return false;
+
+	if (type)
+		*type = csis->sirk_val->type;
+
+	memcpy(k, csis->sirk_val->val, sizeof(csis->sirk_val->val));
+
+	if (size)
+		*size = csis->size_val;
+
+	if (rank)
+		*rank = csis->rank_val;
+
+	return true;
+}
+
+unsigned int bt_csip_ready_register(struct bt_csip *csip,
+				bt_csip_ready_func_t func, void *user_data,
+				bt_csip_destroy_func_t destroy)
+{
+	struct bt_csip_ready *ready;
+	static unsigned int id;
+
+	if (!csip)
+		return 0;
+
+	ready = new0(struct bt_csip_ready, 1);
+	ready->id = ++id ? id : ++id;
+	ready->func = func;
+	ready->destroy = destroy;
+	ready->data = user_data;
+
+	queue_push_tail(csip->ready_cbs, ready);
+
+	return ready->id;
+}
+
+static bool match_ready_id(const void *data, const void *match_data)
+{
+	const struct bt_csip_ready *ready = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (ready->id == id);
+}
+
+bool bt_csip_ready_unregister(struct bt_csip *csip, unsigned int id)
+{
+	struct bt_csip_ready *ready;
+
+	ready = queue_remove_if(csip->ready_cbs, match_ready_id,
+						UINT_TO_PTR(id));
+	if (!ready)
+		return false;
+
+	csip_ready_free(ready);
+
+	return true;
+}
diff --git a/src/shared/csip.h b/src/shared/csip.h
new file mode 100644
index 0000000..81c8954
--- /dev/null
+++ b/src/shared/csip.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *
+ */
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "src/shared/io.h"
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+struct bt_csip;
+
+enum {
+	BT_CSIP_SIRK_ENCRYPT = 0x00,
+	BT_CSIP_SIRK_CLEARTEXT = 0x01
+};
+
+typedef void (*bt_csip_ready_func_t)(struct bt_csip *csip, void *user_data);
+typedef void (*bt_csip_destroy_func_t)(void *user_data);
+typedef void (*bt_csip_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_csip_func_t)(struct bt_csip *csip, void *user_data);
+typedef bool (*bt_csip_encrypt_func_t)(struct bt_att *att, uint8_t k[16]);
+typedef bool (*bt_csip_sirk_func_t)(struct bt_csip *csip, uint8_t type,
+				    uint8_t k[16], uint8_t size, uint8_t rank,
+				    void *user_data);
+
+struct bt_csip *bt_csip_ref(struct bt_csip *csip);
+void bt_csip_unref(struct bt_csip *csip);
+
+bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client);
+void bt_csip_detach(struct bt_csip *csip);
+
+bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func,
+			void *user_data, bt_csip_destroy_func_t destroy);
+
+struct bt_att *bt_csip_get_att(struct bt_csip *csip);
+
+bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data);
+
+/* Session related function */
+unsigned int bt_csip_register(bt_csip_func_t added, bt_csip_func_t removed,
+							void *user_data);
+bool bt_csip_unregister(unsigned int id);
+struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb);
+
+bool bt_csip_set_sirk(struct bt_csip *csip, bool encrypt,
+				uint8_t k[16], uint8_t size, uint8_t rank,
+				bt_csip_encrypt_func_t func);
+
+bool bt_csip_get_sirk(struct bt_csip *csip, uint8_t *type,
+				uint8_t k[16], uint8_t *size, uint8_t *rank);
+
+unsigned int bt_csip_ready_register(struct bt_csip *csip,
+				bt_csip_ready_func_t func, void *user_data,
+				bt_csip_destroy_func_t destroy);
+bool bt_csip_ready_unregister(struct bt_csip *csip, unsigned int id);
diff --git a/src/shared/ecc.c b/src/shared/ecc.c
index adaae20..02bccbd 100644
--- a/src/shared/ecc.c
+++ b/src/shared/ecc.c
@@ -870,6 +870,8 @@ bool ecc_make_key(uint8_t public_key[64], uint8_t private_key[32])
 	uint64_t priv[NUM_ECC_DIGITS];
 	unsigned int tries = 0;
 
+	memset(&pk, 0, sizeof(pk));
+
 	do {
 		if (!get_random_number(priv) || (tries++ >= MAX_TRIES))
 			return false;
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 45b6ed9..9db3f52 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -38,7 +38,8 @@
 #define GATT_SVC_UUID	0x1801
 #define SVC_CHNGD_UUID	0x2a05
 #define DBG(_client, _format, arg...) \
-	gatt_log(_client, "%s:%s() " _format, __FILE__, __func__, ## arg)
+	gatt_log(_client, "[%p] %s:%s() " _format, _client, __FILE__, \
+		__func__, ## arg)
 
 struct ready_cb {
 	bt_gatt_client_callback_t callback;
@@ -46,6 +47,12 @@ struct ready_cb {
 	void *data;
 };
 
+struct idle_cb {
+	bt_gatt_client_idle_callback_t callback;
+	bt_gatt_client_destroy_func_t destroy;
+	void *data;
+};
+
 struct bt_gatt_client {
 	struct bt_att *att;
 	int ref_count;
@@ -55,6 +62,7 @@ struct bt_gatt_client {
 	struct queue *clones;
 
 	struct queue *ready_cbs;
+	struct queue *idle_cbs;
 
 	bt_gatt_client_service_changed_callback_t svc_chngd_callback;
 	bt_gatt_client_destroy_func_t svc_chngd_destroy;
@@ -146,9 +154,49 @@ static struct request *request_create(struct bt_gatt_client *client)
 	return request_ref(req);
 }
 
+static void idle_destroy(void *data)
+{
+	struct idle_cb *idle = data;
+
+	if (idle->destroy)
+		idle->destroy(idle->data);
+
+	free(idle);
+}
+
+static bool idle_notify(const void *data, const void *user_data)
+{
+	const struct idle_cb *idle = data;
+
+	idle->callback(idle->data);
+
+	return true;
+}
+
+static struct bt_gatt_client *
+bt_gatt_client_ref_safe(struct bt_gatt_client *client)
+{
+	if (!client || !client->ref_count)
+		return NULL;
+
+	return bt_gatt_client_ref(client);
+}
+
+static void notify_client_idle(struct bt_gatt_client *client)
+{
+	client = bt_gatt_client_ref_safe(client);
+	if (!client)
+		return;
+
+	queue_remove_all(client->idle_cbs, idle_notify, NULL, idle_destroy);
+
+	bt_gatt_client_unref(client);
+}
+
 static void request_unref(void *data)
 {
 	struct request *req = data;
+	struct bt_gatt_client *client = req->client;
 
 	if (__sync_sub_and_fetch(&req->ref_count, 1))
 		return;
@@ -156,8 +204,11 @@ static void request_unref(void *data)
 	if (req->destroy)
 		req->destroy(req->data);
 
-	if (!req->removed)
-		queue_remove(req->client->pending_requests, req);
+	if (!req->removed) {
+		queue_remove(client->pending_requests, req);
+		if (queue_isempty(client->pending_requests))
+			notify_client_idle(client);
+	}
 
 	free(req);
 }
@@ -357,15 +408,28 @@ static void discovery_op_free(struct discovery_op *op)
 
 static bool read_db_hash(struct discovery_op *op);
 
+static void gatt_log_va(struct bt_gatt_client *client, const char *format,
+						va_list va)
+{
+	if (!client || !format)
+		return;
+
+	if (client->debug_callback)
+		util_debug_va(client->debug_callback, client->debug_data,
+							format, va);
+	else
+		gatt_log_va(client->parent, format, va);
+}
+
 static void gatt_log(struct bt_gatt_client *client, const char *format, ...)
 {
 	va_list ap;
 
-	if (!client || !format || !client->debug_callback)
+	if (!client || !format)
 		return;
 
 	va_start(ap, format);
-	util_debug_va(client->debug_callback, client->debug_data, format, ap);
+	gatt_log_va(client, format, ap);
 	va_end(ap);
 }
 
@@ -500,6 +564,24 @@ static void discovery_req_clear(struct bt_gatt_client *client)
 	client->discovery_req = NULL;
 }
 
+static void discover_remove_pending(struct discovery_op *op,
+					struct gatt_db_attribute *attr)
+{
+	struct gatt_db_attribute *svc;
+
+	svc = gatt_db_attribute_get_service(attr);
+	if (!svc)
+		return;
+
+	if (!queue_remove(op->pending_svcs, svc))
+		return;
+
+	gatt_db_service_set_active(svc, true);
+
+	if (op->cur_svc == svc)
+		op->cur_svc = NULL;
+}
+
 static void discover_chrcs_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data);
@@ -576,12 +658,26 @@ static void discover_incl_cb(bool success, uint8_t att_ecode,
 				gatt_db_attribute_get_handle(attr), handle);
 			goto failed;
 		}
+
+		if (!gatt_db_attribute_get_service_data(attr, NULL, &end,
+							NULL, NULL)) {
+			DBG(client, "Unable to get service data at 0x%04x",
+								handle);
+			goto failed;
+		}
+
+		/* Skip if there are no attributes */
+		if (handle == end)
+			discover_remove_pending(op, attr);
 	}
 
 next:
 	range = queue_pop_head(op->discov_ranges);
-	if (!range)
+	if (!range) {
+		/* Skip if there are no attributes */
+		discover_remove_pending(op, op->cur_svc);
 		goto failed;
+	}
 
 	client->discovery_req = bt_gatt_discover_characteristics(client->att,
 							range->start,
@@ -639,6 +735,7 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
 		}
 
 		attr = gatt_db_insert_characteristic(client->db,
+							chrc_data->start_handle,
 							chrc_data->value_handle,
 							&chrc_data->uuid, 0,
 							chrc_data->properties,
@@ -725,11 +822,16 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
 		goto failed;
 	}
 
+	/* Done with the current service */
+	discover_remove_pending(op, op->cur_svc);
+
 done:
 	free(chrc_data);
 	return true;
 
 failed:
+	DBG(client, "Failed to discover descriptors");
+
 	free(chrc_data);
 	return false;
 }
@@ -798,9 +900,6 @@ static void ext_prop_read_cb(bool success, uint8_t att_ecode,
 	if (discovering)
 		return;
 
-	/* Done with the current service */
-	gatt_db_service_set_active(op->cur_svc, true);
-
 	goto done;
 
 failed:
@@ -888,9 +987,6 @@ next:
 	if (discovering)
 		return;
 
-	/* Done with the current service */
-	gatt_db_service_set_active(op->cur_svc, true);
-
 	goto done;
 
 failed:
@@ -997,9 +1093,6 @@ next:
 	if (discovering)
 		return;
 
-	/* Done with the current service */
-	gatt_db_service_set_active(op->cur_svc, true);
-
 	goto done;
 
 failed:
@@ -1018,6 +1111,20 @@ static bool match_handle_range(const void *data, const void *match_data)
 					(match_range->start <= range->end);
 }
 
+static struct handle_range *range_new(uint16_t start, uint16_t end)
+{
+	struct handle_range *range;
+
+	if (!start || !end || start > end)
+		return NULL;
+
+	range = new0(struct handle_range, 1);
+	range->start = start;
+	range->end = end;
+
+	return range;
+}
+
 static void remove_discov_range(struct discovery_op *op, uint16_t start,
 								uint16_t end)
 {
@@ -1034,16 +1141,18 @@ static void remove_discov_range(struct discovery_op *op, uint16_t start,
 	if ((range->start == start) && (range->end == end)) {
 		queue_remove(op->discov_ranges, range);
 		free(range);
-	} else if (range->start == start)
+	} else if (range->start == start) {
 		range->start = end + 1;
-	else if (range->end == end)
+		if (!range->start || range->start > range->end) {
+			queue_remove(op->discov_ranges, range);
+			free(range);
+		}
+	} else if (range->end == end)
 		range->end = start - 1;
 	else {
-		new_range = new0(struct handle_range, 1);
-		new_range->start = end + 1;
-		new_range->end = range->end;
-
-		queue_push_after(op->discov_ranges, range, new_range);
+		new_range = range_new(end + 1, range->end);
+		if (new_range)
+			queue_push_after(op->discov_ranges, range, new_range);
 
 		range->end = start - 1;
 	}
@@ -1167,7 +1276,9 @@ next:
 
 	range = queue_peek_head(op->discov_ranges);
 
-	client->discovery_req = bt_gatt_discover_included_services(client->att,
+	if (range)
+		client->discovery_req = bt_gatt_discover_included_services(
+							client->att,
 							range->start,
 							range->end,
 							discover_incl_cb,
@@ -1265,10 +1376,13 @@ static void notify_client_ready(struct bt_gatt_client *client, bool success,
 {
 	const struct queue_entry *entry;
 
-	if (client->ready)
+	client = bt_gatt_client_ref_safe(client);
+	if (!client)
 		return;
 
-	bt_gatt_client_ref(client);
+	if (client->ready)
+		goto done;
+
 	client->ready = success;
 
 	if (client->parent)
@@ -1291,6 +1405,7 @@ static void notify_client_ready(struct bt_gatt_client *client, bool success,
 		notify_client_ready(clone, success, att_ecode);
 	}
 
+done:
 	bt_gatt_client_unref(client);
 }
 
@@ -1550,31 +1665,30 @@ static void complete_notify_request(void *data)
 }
 
 static bool notify_data_write_ccc(struct notify_data *notify_data, bool enable,
-						bt_att_response_func_t callback)
+					bt_gatt_client_callback_t callback)
 {
-	uint8_t pdu[4];
 	unsigned int att_id;
+	uint16_t value = 0x0000;
 	uint16_t properties = notify_data->chrc->properties;
 
 	assert(notify_data->chrc->ccc_handle);
-	memset(pdu, 0, sizeof(pdu));
-	put_le16(notify_data->chrc->ccc_handle, pdu);
 
 	if (enable) {
 		/* Try to enable notifications or indications based on
 		 * whatever the characteristic supports.
 		 */
 		if (properties & BT_GATT_CHRC_PROP_NOTIFY)
-			pdu[2] = 0x01;
+			value = cpu_to_le16(0x0001);
 		else if (properties & BT_GATT_CHRC_PROP_INDICATE)
-			pdu[2] = 0x02;
-
-		if (!pdu[2])
+			value = cpu_to_le16(0x0002);
+		else
 			return false;
 	}
 
-	att_id = bt_att_send(notify_data->client->att, BT_ATT_OP_WRITE_REQ,
-						pdu, sizeof(pdu), callback,
+	att_id = bt_gatt_client_write_value(notify_data->client,
+						notify_data->chrc->ccc_handle,
+						(void *)&value, sizeof(value),
+						callback,
 						notify_data_ref(notify_data),
 						notify_data_unref);
 	notify_data->chrc->ccc_write_id = notify_data->att_id = att_id;
@@ -1604,8 +1718,8 @@ static bool notify_set_ecode(const void *data, const void *match_data)
 	return true;
 }
 
-static void enable_ccc_callback(uint8_t opcode, const void *pdu,
-					uint16_t length, void *user_data)
+static void enable_ccc_callback(bool success, uint8_t att_ecode,
+						void *user_data)
 {
 	struct notify_data *notify_data = user_data;
 
@@ -1613,10 +1727,9 @@ static void enable_ccc_callback(uint8_t opcode, const void *pdu,
 
 	notify_data->chrc->ccc_write_id = 0;
 
-	bt_gatt_client_ref(notify_data->client);
+	bt_gatt_client_ref_safe(notify_data->client);
 
-	if (opcode == BT_ATT_OP_ERROR_RSP)
-		notify_data->att_ecode = process_error(pdu, length);
+	notify_data->att_ecode = att_ecode;
 
 	/* Notify for all remaining requests. */
 	complete_notify_request(notify_data);
@@ -1655,8 +1768,11 @@ static unsigned int register_notify(struct bt_gatt_client *client,
 		 * descriptor.
 		 */
 		chrc = notify_chrc_create(client, handle);
-		if (!chrc)
+		if (!chrc) {
+			DBG(client, "Unable to locate characteristic at 0x%04x",
+							handle);
 			return 0;
+		}
 	}
 
 	/* Fail if we've hit the maximum allowed notify sessions */
@@ -1694,9 +1810,10 @@ static unsigned int register_notify(struct bt_gatt_client *client,
 	}
 
 	/*
-	 * If the ref count > 1, then notifications are already enabled.
+	 * If the ref count > 1, ccc handle cannot be found or registration
+	 * callback is not set consider notifications are already enabled.
 	 */
-	if (chrc->notify_count > 1 || !chrc->ccc_handle) {
+	if (chrc->notify_count > 1 || !chrc->ccc_handle || !callback) {
 		complete_notify_request(notify_data);
 		return notify_data->id;
 	}
@@ -2051,8 +2168,8 @@ struct value_data {
 	const void *data;
 };
 
-static void disable_ccc_callback(uint8_t opcode, const void *pdu,
-					uint16_t length, void *user_data)
+static void disable_ccc_callback(bool success, uint8_t att_ecode,
+						void *user_data)
 {
 	struct notify_data *notify_data = user_data;
 	struct notify_data *next_data;
@@ -2113,7 +2230,7 @@ static void notify_handler(void *data, void *user_data)
 				value_data->len, notify_data->user_data);
 }
 
-static void notify_cb(struct bt_att_chan *chan, uint8_t opcode,
+static void notify_cb(struct bt_att_chan *chan, uint16_t mtu, uint8_t opcode,
 					const void *pdu, uint16_t length,
 					void *user_data)
 {
@@ -2122,6 +2239,9 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode,
 
 	bt_gatt_client_ref(client);
 
+	if (queue_isempty(client->notify_list))
+		goto done;
+
 	memset(&data, 0, sizeof(data));
 
 	if (opcode == BT_ATT_OP_HANDLE_NFY_MULT) {
@@ -2156,6 +2276,7 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode,
 		queue_foreach(client->notify_list, notify_handler, &data);
 	}
 
+done:
 	if (opcode == BT_ATT_OP_HANDLE_IND && !client->parent)
 		bt_att_chan_send(chan, BT_ATT_OP_HANDLE_CONF, NULL, 0,
 							NULL, NULL, NULL);
@@ -2171,6 +2292,7 @@ static void bt_gatt_client_free(struct bt_gatt_client *client)
 	queue_destroy(client->notify_list, notify_data_cleanup);
 
 	queue_destroy(client->ready_cbs, ready_destroy);
+	queue_destroy(client->idle_cbs, idle_destroy);
 
 	if (client->debug_destroy)
 		client->debug_destroy(client->debug_data);
@@ -2229,6 +2351,7 @@ static struct bt_gatt_client *gatt_client_new(struct gatt_db *db,
 
 	client->clones = queue_new();
 	client->ready_cbs = queue_new();
+	client->idle_cbs = queue_new();
 	client->long_write_queue = queue_new();
 	client->svc_chngd_queue = queue_new();
 	client->notify_list = queue_new();
@@ -2698,7 +2821,7 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client,
 					void *user_data,
 					bt_gatt_client_destroy_func_t destroy)
 {
-	uint8_t pdu[num_handles * 2];
+	uint8_t *pdu = newa(uint8_t, num_handles * 2);
 	struct request *req;
 	struct read_op *op;
 	uint8_t opcode;
@@ -2735,7 +2858,7 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client,
 		BT_GATT_CHRC_CLI_FEAT_EATT ? BT_ATT_OP_READ_MULT_VL_REQ :
 		BT_ATT_OP_READ_MULT_REQ;
 
-	req->att_id = bt_att_send(client->att, opcode, pdu, sizeof(pdu),
+	req->att_id = bt_att_send(client->att, opcode, pdu, num_handles * 2,
 							read_multiple_cb, req,
 							request_unref);
 	if (!req->att_id) {
@@ -2928,7 +3051,7 @@ unsigned int bt_gatt_client_write_without_response(
 					uint16_t value_handle,
 					bool signed_write,
 					const uint8_t *value, uint16_t length) {
-	uint8_t pdu[2 + length];
+	uint8_t *pdu = newa(uint8_t, 2 + length);
 	struct request *req;
 	int security;
 	uint8_t op;
@@ -2951,7 +3074,7 @@ unsigned int bt_gatt_client_write_without_response(
 	put_le16(value_handle, pdu);
 	memcpy(pdu + 2, value, length);
 
-	req->att_id = bt_att_send(client->att, op, pdu, sizeof(pdu), NULL, req,
+	req->att_id = bt_att_send(client->att, op, pdu, 2 + length, NULL, req,
 								request_unref);
 	if (!req->att_id) {
 		request_unref(req);
@@ -3009,7 +3132,7 @@ unsigned int bt_gatt_client_write_value(struct bt_gatt_client *client,
 {
 	struct request *req;
 	struct write_op *op;
-	uint8_t pdu[2 + length];
+	uint8_t *pdu = newa(uint8_t, 2 + length);
 
 	if (!client)
 		return 0;
@@ -3033,7 +3156,7 @@ unsigned int bt_gatt_client_write_value(struct bt_gatt_client *client,
 	memcpy(pdu + 2, value, length);
 
 	req->att_id = bt_att_send(client->att, BT_ATT_OP_WRITE_REQ,
-							pdu, sizeof(pdu),
+							pdu, 2 + length,
 							write_cb, req,
 							request_unref);
 	if (!req->att_id) {
@@ -3448,7 +3571,7 @@ unsigned int bt_gatt_client_prepare_write(struct bt_gatt_client *client,
 {
 	struct request *req;
 	struct prep_write_op *op;
-	uint8_t pdu[4 + length];
+	uint8_t *pdu = newa(uint8_t, 4 + length);
 
 	if (!client)
 		return 0;
@@ -3507,7 +3630,7 @@ unsigned int bt_gatt_client_prepare_write(struct bt_gatt_client *client,
 	 * Note that request_unref will be done on write execute
 	 */
 	req->att_id = bt_att_send(client->att, BT_ATT_OP_PREP_WRITE_REQ, pdu,
-					sizeof(pdu), prep_write_cb, req,
+					length, prep_write_cb, req,
 					NULL);
 	if (!req->att_id) {
 		op->destroy = NULL;
@@ -3614,7 +3737,8 @@ unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client,
 				void *user_data,
 				bt_gatt_client_destroy_func_t destroy)
 {
-	if (!client || !client->db || !chrc_value_handle || !callback)
+	if (!client || !client->db || !chrc_value_handle ||
+				(!callback && !notify))
 		return 0;
 
 	if (client->in_svc_chngd)
@@ -3663,3 +3787,58 @@ int bt_gatt_client_get_security(struct bt_gatt_client *client)
 
 	return bt_att_get_security(client->att, NULL);
 }
+
+unsigned int bt_gatt_client_idle_register(struct bt_gatt_client *client,
+					bt_gatt_client_idle_callback_t callback,
+					void *user_data,
+					bt_gatt_client_destroy_func_t destroy)
+{
+	struct idle_cb *idle;
+
+	if (!client)
+		return 0;
+
+	idle = new0(struct idle_cb, 1);
+	idle->callback = callback;
+	idle->destroy = destroy;
+	idle->data = user_data;
+
+	queue_push_tail(client->idle_cbs, idle);
+
+	return PTR_TO_UINT(idle);
+}
+
+bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client,
+						unsigned int id)
+{
+	struct idle_cb *idle = UINT_TO_PTR(id);
+
+	if (!client || !id)
+		return false;
+
+	if (queue_remove(client->idle_cbs, idle)) {
+		idle_destroy(idle);
+		return true;
+	}
+
+	return false;
+}
+
+bool bt_gatt_client_set_retry(struct bt_gatt_client *client,
+					unsigned int id,
+					bool retry)
+{
+	struct request *req;
+
+	if (!client || !id)
+		return false;
+
+	req = queue_find(client->pending_requests, match_req_id,
+							UINT_TO_PTR(id));
+	if (!req)
+		return false;
+
+	bt_att_set_retry(client->att, req->att_id, retry);
+
+	return true;
+}
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index dc51023..63cf995 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -26,6 +26,7 @@ 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_idle_callback_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);
@@ -126,3 +127,13 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
 
 bool bt_gatt_client_set_security(struct bt_gatt_client *client, int level);
 int bt_gatt_client_get_security(struct bt_gatt_client *client);
+
+unsigned int bt_gatt_client_idle_register(struct bt_gatt_client *client,
+					bt_gatt_client_idle_callback_t callback,
+					void *user_data,
+					bt_gatt_client_destroy_func_t destroy);
+bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client,
+						unsigned int id);
+bool bt_gatt_client_set_retry(struct bt_gatt_client *client,
+					unsigned int id,
+					bool retry);
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index ba47c75..b357634 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -58,7 +58,7 @@ struct gatt_db {
 	struct bt_crypto *crypto;
 	uint8_t hash[16];
 	unsigned int hash_id;
-	uint16_t next_handle;
+	uint16_t last_handle;
 	struct queue *services;
 
 	struct queue *notify_list;
@@ -255,11 +255,82 @@ struct gatt_db *gatt_db_new(void)
 	db->crypto = bt_crypto_new();
 	db->services = queue_new();
 	db->notify_list = queue_new();
-	db->next_handle = 0x0001;
+	db->last_handle = 0x0000;
 
 	return gatt_db_ref(db);
 }
 
+static void service_clone(void *data, void *user_data)
+{
+	struct gatt_db_service *service = data;
+	struct gatt_db *db = user_data;
+	struct gatt_db_service *clone;
+	int i;
+
+	clone = new0(struct gatt_db_service, 1);
+	clone->db = db;
+	clone->active = service->active;
+	clone->num_handles = service->num_handles;
+	clone->attributes = new0(struct gatt_db_attribute *,
+					service->num_handles);
+
+	/* Clone attributes */
+	for (i = 0; i < service->num_handles; i++) {
+		struct gatt_db_attribute *attr = service->attributes[i];
+
+		/* Only clone values for characteristics declaration since that
+		 * is considered when calculating the db hash.
+		 */
+		if (bt_uuid_len(&attr->uuid) != 2) {
+			clone->attributes[i] = new_attribute(clone,
+							attr->handle,
+							&attr->uuid,
+							NULL, 0);
+			continue;
+		}
+
+		/* Attribute values that are used for generating the hash needs
+		 * to be cloned as well.
+		 */
+		switch (attr->uuid.value.u16) {
+		case GATT_PRIM_SVC_UUID:
+		case GATT_SND_SVC_UUID:
+		case GATT_INCLUDE_UUID:
+		case GATT_CHARAC_UUID:
+			clone->attributes[i] = new_attribute(clone,
+							attr->handle,
+							&attr->uuid,
+							attr->value,
+							attr->value_len);
+			break;
+		default:
+			clone->attributes[i] = new_attribute(clone,
+							attr->handle,
+							&attr->uuid,
+							NULL, 0);
+			break;
+		}
+	}
+
+	queue_push_tail(db->services, clone);
+}
+
+struct gatt_db *gatt_db_clone(struct gatt_db *db)
+{
+	struct gatt_db *clone;
+
+	if (!db)
+		return NULL;
+
+	clone = gatt_db_new();
+	if (!clone)
+		return NULL;
+
+	queue_foreach(db->services, service_clone, clone);
+
+	return clone;
+}
+
 static void notify_destroy(void *data)
 {
 	struct notify *notify = data;
@@ -356,14 +427,15 @@ static bool db_hash_update(void *user_data)
 
 	db->hash_id = 0;
 
-	if (!db->next_handle)
+	if (gatt_db_isempty(db))
 		return false;
 
-	hash.iov = new0(struct iovec, db->next_handle);
+	hash.iov = new0(struct iovec, db->last_handle + 1);
 	hash.i = 0;
 
 	gatt_db_foreach_service(db, NULL, service_gen_hash_m, &hash);
-	bt_crypto_gatt_hash(db->crypto, hash.iov, db->next_handle, db->hash);
+	bt_crypto_gatt_hash(db->crypto, hash.iov, db->last_handle + 1,
+				db->hash);
 
 	for (i = 0; i < hash.i; i++)
 		free(hash.iov[i].iov_base);
@@ -624,7 +696,7 @@ bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle,
 
 done:
 	if (gatt_db_isempty(db))
-		db->next_handle = 0;
+		db->last_handle = 0;
 
 	return true;
 }
@@ -700,7 +772,7 @@ struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
 		return NULL;
 
 	if (!handle)
-		handle = db->next_handle;
+		handle = db->last_handle + 1;
 
 	if (num_handles < 1 || (handle + num_handles - 1) > UINT16_MAX)
 		return NULL;
@@ -747,8 +819,8 @@ struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
 	service->attributes[0]->handle = handle;
 	service->num_handles = num_handles;
 
-	/* Fast-forward next_handle if the new service was added to the end */
-	db->next_handle = MAX(handle + num_handles, db->next_handle);
+	/* Fast-forward last_handle if the new service was added to the end */
+	db->last_handle = MAX(handle + num_handles - 1, db->last_handle);
 
 	return service->attributes[0];
 
@@ -824,28 +896,45 @@ bool gatt_db_set_authorize(struct gatt_db *db, gatt_db_authorize_cb_t cb,
 	return true;
 }
 
-static uint16_t get_attribute_index(struct gatt_db_service *service,
+static uint16_t service_get_attribute_index(struct gatt_db_service *service,
+							uint16_t *handle,
 							int end_offset)
 {
 	int i = 0;
 
-	/* Here we look for first free attribute index with given offset */
-	while (i < (service->num_handles - end_offset) &&
+	if (!service || !service->attributes[0] || !handle)
+		return 0;
+
+	if (*handle) {
+		/* Check if handle is in within service range */
+		if (*handle < service->attributes[0]->handle)
+			return 0;
+
+		/* Return index based on given handle */
+		i = *handle - service->attributes[0]->handle;
+	} else {
+		/* Here we look for first free attribute index with given
+		 * offset.
+		 */
+		while (i < (service->num_handles - end_offset) &&
 						service->attributes[i])
-		i++;
+			i++;
+	}
 
-	return i == (service->num_handles - end_offset) ? 0 : i;
-}
+	if (i >= (service->num_handles - end_offset))
+		return 0;
 
-static uint16_t get_handle_at_index(struct gatt_db_service *service,
-								int index)
-{
-	return service->attributes[index]->handle;
+	/* Set handle based on the index */
+	if (!(*handle))
+		*handle = service->attributes[0]->handle + i;
+
+	return i;
 }
 
 static struct gatt_db_attribute *
 service_insert_characteristic(struct gatt_db_service *service,
 					uint16_t handle,
+					uint16_t value_handle,
 					const bt_uuid_t *uuid,
 					uint32_t permissions,
 					uint8_t properties,
@@ -853,6 +942,7 @@ service_insert_characteristic(struct gatt_db_service *service,
 					gatt_db_write_t write_func,
 					void *user_data)
 {
+	struct gatt_db_attribute **chrc;
 	uint8_t value[MAX_CHAR_DECL_VALUE_LEN];
 	uint16_t len = 0;
 	int i;
@@ -873,37 +963,48 @@ service_insert_characteristic(struct gatt_db_service *service,
 	if (handle == UINT16_MAX)
 		return NULL;
 
-	i = get_attribute_index(service, 1);
+	i = service_get_attribute_index(service, &handle, 1);
 	if (!i)
 		return NULL;
 
-	if (!handle)
-		handle = get_handle_at_index(service, i - 1) + 2;
-
 	value[0] = properties;
 	len += sizeof(properties);
 
 	/* We set handle of characteristic value, which will be added next */
-	put_le16(handle, &value[1]);
+	put_le16(value_handle, &value[1]);
 	len += sizeof(uint16_t);
 	len += uuid_to_le(uuid, &value[3]);
 
-	service->attributes[i] = new_attribute(service, handle - 1,
+	service->attributes[i] = new_attribute(service, handle,
 							&characteristic_uuid,
 							value, len);
 	if (!service->attributes[i])
 		return NULL;
 
-	set_attribute_data(service->attributes[i], NULL, NULL, BT_ATT_PERM_READ, NULL);
+	chrc = &service->attributes[i];
+	set_attribute_data(service->attributes[i], NULL, NULL, BT_ATT_PERM_READ,
+				NULL);
 
-	i++;
+	i = service_get_attribute_index(service, &value_handle, 0);
+	if (!i) {
+		free(*chrc);
+		*chrc = NULL;
+		return NULL;
+	}
 
-	service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
+	service->attributes[i] = new_attribute(service, value_handle, uuid,
+						NULL, 0);
 	if (!service->attributes[i]) {
-		free(service->attributes[i - 1]);
+		free(*chrc);
+		*chrc = NULL;
 		return NULL;
 	}
 
+	/* Update handle of characteristic value_handle if it has changed */
+	put_le16(value_handle, &value[1]);
+	if (memcmp((*chrc)->value, value, len))
+		memcpy((*chrc)->value, value, len);
+
 	set_attribute_data(service->attributes[i], read_func, write_func,
 							permissions, user_data);
 
@@ -913,6 +1014,7 @@ service_insert_characteristic(struct gatt_db_service *service,
 struct gatt_db_attribute *
 gatt_db_insert_characteristic(struct gatt_db *db,
 					uint16_t handle,
+					uint16_t value_handle,
 					const bt_uuid_t *uuid,
 					uint32_t permissions,
 					uint8_t properties,
@@ -926,7 +1028,8 @@ gatt_db_insert_characteristic(struct gatt_db *db,
 	if (!attrib)
 		return NULL;
 
-	return service_insert_characteristic(attrib->service, handle, uuid,
+	return service_insert_characteristic(attrib->service, handle,
+						value_handle, uuid,
 						permissions, properties,
 						read_func, write_func,
 						user_data);
@@ -935,6 +1038,7 @@ gatt_db_insert_characteristic(struct gatt_db *db,
 struct gatt_db_attribute *
 gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
 					uint16_t handle,
+					uint16_t value_handle,
 					const bt_uuid_t *uuid,
 					uint32_t permissions,
 					uint8_t properties,
@@ -945,7 +1049,8 @@ gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
 	if (!attrib)
 		return NULL;
 
-	return service_insert_characteristic(attrib->service, handle, uuid,
+	return service_insert_characteristic(attrib->service, handle,
+						value_handle, uuid,
 						permissions, properties,
 						read_func, write_func,
 						user_data);
@@ -963,7 +1068,7 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
 	if (!attrib)
 		return NULL;
 
-	return service_insert_characteristic(attrib->service, 0, uuid,
+	return service_insert_characteristic(attrib->service, 0, 0, uuid,
 						permissions, properties,
 						read_func, write_func,
 						user_data);
@@ -980,17 +1085,10 @@ service_insert_descriptor(struct gatt_db_service *service,
 {
 	int i;
 
-	i = get_attribute_index(service, 0);
+	i = service_get_attribute_index(service, &handle, 0);
 	if (!i)
 		return NULL;
 
-	/* Check if handle is in within service range */
-	if (handle && handle <= service->attributes[0]->handle)
-		return NULL;
-
-	if (!handle)
-		handle = get_handle_at_index(service, i - 1) + 1;
-
 	service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
 	if (!service->attributes[i])
 		return NULL;
@@ -1150,17 +1248,10 @@ service_insert_included(struct gatt_db_service *service, uint16_t handle,
 		len += include->value_len;
 	}
 
-	index = get_attribute_index(service, 0);
+	index = service_get_attribute_index(service, &handle, 0);
 	if (!index)
 		return NULL;
 
-	/* Check if handle is in within service range */
-	if (handle && handle <= service->attributes[0]->handle)
-		return NULL;
-
-	if (!handle)
-		handle = get_handle_at_index(service, index - 1) + 1;
-
 	service->attributes[index] = new_attribute(service, handle,
 							&included_service_uuid,
 							value, len);
@@ -1549,7 +1640,7 @@ static int gatt_db_attribute_get_index(const struct gatt_db_attribute *attrib)
 	return -1;
 }
 
-static struct gatt_db_attribute *
+struct gatt_db_attribute *
 gatt_db_attribute_get_value(struct gatt_db_attribute *attrib)
 {
 	struct gatt_db_service *service;
@@ -1559,18 +1650,18 @@ gatt_db_attribute_get_value(struct gatt_db_attribute *attrib)
 		return NULL;
 
 	index = gatt_db_attribute_get_index(attrib);
-	if (index < 0)
+	if (index <= 0)
 		return NULL;
 
 	service = attrib->service;
 
 	if (!bt_uuid_cmp(&characteristic_uuid, &attrib->uuid))
-		index++;
-	else if (bt_uuid_cmp(&characteristic_uuid,
+		return service->attributes[index + 1];
+	else if (!bt_uuid_cmp(&characteristic_uuid,
 				&service->attributes[index - 1]->uuid))
-		return NULL;
+		return service->attributes[index];
 
-	return service->attributes[index];
+	return gatt_db_attribute_get_value(service->attributes[index - 1]);
 }
 
 void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib,
@@ -1712,6 +1803,15 @@ uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib)
 	return attrib->handle;
 }
 
+struct gatt_db_attribute *
+gatt_db_attribute_get_service(const struct gatt_db_attribute *attrib)
+{
+	if (!attrib)
+		return NULL;
+
+	return attrib->service->attributes[0];
+}
+
 bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib,
 							bt_uuid_t *uuid)
 {
@@ -2095,7 +2195,7 @@ bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
 {
 	uint8_t err = 0;
 
-	if (!attrib || !func)
+	if (!attrib || (!func && attrib->write_func))
 		return false;
 
 	if (attrib->write_func) {
@@ -2158,7 +2258,8 @@ bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
 	memcpy(&attrib->value[offset], value, len);
 
 done:
-	func(attrib, err, user_data);
+	if (func)
+		func(attrib, err, user_data);
 
 	return true;
 }
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 41464ad..dc2daf7 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -12,6 +12,7 @@ struct gatt_db;
 struct gatt_db_attribute;
 
 struct gatt_db *gatt_db_new(void);
+struct gatt_db *gatt_db_clone(struct gatt_db *db);
 
 struct gatt_db *gatt_db_ref(struct gatt_db *db);
 void gatt_db_unref(struct gatt_db *db);
@@ -63,6 +64,7 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
 struct gatt_db_attribute *
 gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
 					uint16_t handle,
+					uint16_t value_handle,
 					const bt_uuid_t *uuid,
 					uint32_t permissions,
 					uint8_t properties,
@@ -73,6 +75,7 @@ gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
 struct gatt_db_attribute *
 gatt_db_insert_characteristic(struct gatt_db *db,
 					uint16_t handle,
+					uint16_t value_handle,
 					const bt_uuid_t *uuid,
 					uint32_t permissions,
 					uint8_t properties,
@@ -225,6 +228,9 @@ const bt_uuid_t *gatt_db_attribute_get_type(
 
 uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib);
 
+struct gatt_db_attribute *
+gatt_db_attribute_get_service(const struct gatt_db_attribute *attrib);
+
 bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib,
 							bt_uuid_t *uuid);
 
@@ -281,6 +287,8 @@ bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
 bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib,
 						unsigned int id, int err);
 
+struct gatt_db_attribute *
+gatt_db_attribute_get_value(struct gatt_db_attribute *attrib);
 struct gatt_db_attribute *
 gatt_db_attribute_get_ccc(struct gatt_db_attribute *attrib);
 
diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 85cff30..b30ec8c 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2014  Google Inc.
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -49,6 +50,7 @@ struct async_read_op {
 	struct bt_gatt_server *server;
 	uint8_t opcode;
 	bool done;
+	uint16_t mtu;
 	uint8_t *pdu;
 	size_t pdu_len;
 	size_t value_len;
@@ -105,6 +107,7 @@ struct bt_gatt_server {
 	unsigned int read_multiple_vl_id;
 	unsigned int prep_write_id;
 	unsigned int exec_write_id;
+	unsigned int signed_write_cmd_id;
 
 	uint8_t min_enc_size;
 
@@ -154,6 +157,7 @@ static void bt_gatt_server_free(struct bt_gatt_server *server)
 	bt_att_unregister(server->att, server->read_multiple_vl_id);
 	bt_att_unregister(server->att, server->prep_write_id);
 	bt_att_unregister(server->att, server->exec_write_id);
+	bt_att_unregister(server->att, server->signed_write_cmd_id);
 
 	queue_destroy(server->prep_queue, prep_write_data_destroy);
 
@@ -225,7 +229,7 @@ static bool encode_read_by_grp_type_rsp(struct gatt_db *db, struct queue *q,
 		 * value is seen.
 		 */
 		if (iter == 0) {
-			data_val_len = MIN(MIN((unsigned)mtu - 6, 251),
+			data_val_len = MIN(MIN((unsigned int)mtu - 6, 251),
 								value.iov_len);
 			pdu[0] = data_val_len + 4;
 			iter++;
@@ -263,15 +267,14 @@ static void gatt_log(struct bt_gatt_server *server, const char *format, ...)
 	va_end(ap);
 }
 
-static void read_by_grp_type_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void read_by_grp_type_cb(struct bt_att_chan *chan, uint16_t mtu,
+					uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t start, end;
 	bt_uuid_t type;
 	bt_uuid_t prim, snd;
-	uint16_t mtu = bt_att_get_mtu(server->att);
 	uint8_t rsp_pdu[mtu];
 	uint16_t rsp_len;
 	uint8_t ecode = 0;
@@ -356,11 +359,8 @@ static void read_by_type_read_complete_cb(struct gatt_db_attribute *attr,
 						size_t len, void *user_data)
 {
 	struct async_read_op *op = user_data;
-	struct bt_gatt_server *server = op->server;
-	uint16_t mtu;
 	uint16_t handle;
 
-	mtu = bt_att_get_mtu(server->att);
 	handle = gatt_db_attribute_get_handle(attr);
 
 	/* Terminate the operation if there was an error */
@@ -372,7 +372,7 @@ static void read_by_type_read_complete_cb(struct gatt_db_attribute *attr,
 	}
 
 	if (op->pdu_len == 0) {
-		op->value_len = MIN(MIN((unsigned) mtu - 4, 253), len);
+		op->value_len = MIN(MIN((unsigned int)op->mtu - 4, 253), len);
 		op->pdu[0] = op->value_len + 2;
 		op->pdu_len++;
 	} else if (len != op->value_len) {
@@ -381,7 +381,7 @@ static void read_by_type_read_complete_cb(struct gatt_db_attribute *attr,
 	}
 
 	/* Stop if this would surpass the MTU */
-	if (op->pdu_len + op->value_len + 2 > (unsigned) mtu - 1) {
+	if (op->pdu_len + op->value_len + 2 > (unsigned int) op->mtu - 1) {
 		op->done = true;
 		goto done;
 	}
@@ -392,7 +392,7 @@ static void read_by_type_read_complete_cb(struct gatt_db_attribute *attr,
 
 	op->pdu_len += op->value_len + 2;
 
-	if (op->pdu_len == (unsigned) mtu - 1)
+	if (op->pdu_len == (unsigned int) op->mtu - 1)
 		op->done = true;
 
 done:
@@ -488,9 +488,9 @@ error:
 	async_read_op_destroy(op);
 }
 
-static void read_by_type_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void read_by_type_cb(struct bt_att_chan *chan, uint16_t mtu,
+				uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t start, end;
@@ -533,7 +533,8 @@ static void read_by_type_cb(struct bt_att_chan *chan, uint8_t opcode,
 	}
 
 	op = new0(struct async_read_op, 1);
-	op->pdu = malloc(bt_att_get_mtu(server->att));
+	op->mtu = mtu;
+	op->pdu = malloc(mtu);
 	if (!op->pdu) {
 		free(op);
 		ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
@@ -608,13 +609,12 @@ static bool encode_find_info_rsp(struct gatt_db *db, struct queue *q,
 	return true;
 }
 
-static void find_info_cb(struct bt_att_chan *chan, uint8_t opcode,
+static void find_info_cb(struct bt_att_chan *chan, uint16_t mtu, uint8_t opcode,
 					const void *pdu, uint16_t length,
 					void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t start, end;
-	uint16_t mtu = bt_att_get_mtu(server->att);
 	uint8_t rsp_pdu[mtu];
 	uint16_t rsp_len;
 	uint8_t ecode = 0;
@@ -706,14 +706,13 @@ static void find_by_type_val_att_cb(struct gatt_db_attribute *attrib,
 	data->len += 4;
 }
 
-static void find_by_type_val_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void find_by_type_val_cb(struct bt_att_chan *chan, uint16_t mtu,
+					uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t start, end, uuid16;
 	struct find_by_type_val_data data;
-	uint16_t mtu = bt_att_get_mtu(server->att);
 	uint8_t rsp_pdu[mtu];
 	uint16_t ehandle = 0;
 	bt_uuid_t uuid;
@@ -776,7 +775,8 @@ static void write_complete_cb(struct gatt_db_attribute *attr, int err,
 	struct bt_gatt_server *server = op->server;
 	uint16_t handle;
 
-	if (op->opcode == BT_ATT_OP_WRITE_CMD) {
+	if (op->opcode == BT_ATT_OP_WRITE_CMD ||
+			op->opcode == BT_ATT_OP_SIGNED_WRITE_CMD) {
 		async_write_op_destroy(op);
 		return;
 	}
@@ -817,8 +817,8 @@ static uint8_t check_length(uint16_t length, uint16_t offset)
 	return 0;
 }
 
-static void write_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
-					uint16_t length, void *user_data)
+static void write_cb(struct bt_att_chan *chan, uint16_t mtu, uint8_t opcode,
+			const void *pdu, uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	struct gatt_db_attribute *attr;
@@ -845,7 +845,7 @@ static void write_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
 	DBG(server, "Write %s - handle: 0x%04x",
 		(opcode == BT_ATT_OP_WRITE_REQ) ? "Req" : "Cmd", handle);
 
-	ecode = check_length(length, 0);
+	ecode = check_length(length - 2, 0);
 	if (ecode)
 		goto error;
 
@@ -904,12 +904,10 @@ static void read_complete_cb(struct gatt_db_attribute *attr, int err,
 	struct async_read_op *op = user_data;
 	struct bt_gatt_server *server = op->server;
 	uint8_t rsp_opcode;
-	uint16_t mtu;
 	uint16_t handle;
 
 	DBG(server, "Read Complete: err %d", err);
 
-	mtu = bt_att_get_mtu(server->att);
 	handle = gatt_db_attribute_get_handle(attr);
 
 	if (err) {
@@ -921,13 +919,14 @@ static void read_complete_cb(struct gatt_db_attribute *attr, int err,
 	rsp_opcode = get_read_rsp_opcode(op->opcode);
 
 	bt_att_chan_send_rsp(op->chan, rsp_opcode, len ? value : NULL,
-					MIN((unsigned int) mtu - 1, len));
+					MIN((unsigned int) op->mtu - 1, len));
 	async_read_op_destroy(op);
 }
 
 static void handle_read_req(struct bt_att_chan *chan,
-				struct bt_gatt_server *server, uint8_t opcode,
-				uint16_t handle, uint16_t offset)
+				struct bt_gatt_server *server, uint16_t mtu,
+				uint8_t opcode, uint16_t handle,
+				uint16_t offset)
 {
 	struct gatt_db_attribute *attr;
 	uint8_t ecode;
@@ -954,6 +953,7 @@ static void handle_read_req(struct bt_att_chan *chan,
 	op->chan = chan;
 	op->opcode = opcode;
 	op->server = bt_gatt_server_ref(server);
+	op->mtu = mtu;
 
 	if (gatt_db_attribute_read(attr, offset, opcode, server->att,
 							read_complete_cb, op))
@@ -968,8 +968,8 @@ error:
 	bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);
 }
 
-static void read_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
-					uint16_t length, void *user_data)
+static void read_cb(struct bt_att_chan *chan, uint16_t mtu, uint8_t opcode,
+			const void *pdu, uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t handle;
@@ -982,10 +982,10 @@ static void read_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
 
 	handle = get_le16(pdu);
 
-	handle_read_req(chan, server, opcode, handle, 0);
+	handle_read_req(chan, server, mtu, opcode, handle, 0);
 }
 
-static void read_blob_cb(struct bt_att_chan *chan, uint8_t opcode,
+static void read_blob_cb(struct bt_att_chan *chan, uint16_t mtu, uint8_t opcode,
 					const void *pdu, uint16_t length,
 					void *user_data)
 {
@@ -1001,7 +1001,7 @@ static void read_blob_cb(struct bt_att_chan *chan, uint8_t opcode,
 	handle = get_le16(pdu);
 	offset = get_le16(pdu + 2);
 
-	handle_read_req(chan, server, opcode, handle, offset);
+	handle_read_req(chan, server, mtu, opcode, handle, offset);
 }
 
 struct read_mult_data {
@@ -1101,6 +1101,7 @@ error:
 
 static struct read_mult_data *read_mult_data_new(struct bt_gatt_server *server,
 						struct bt_att_chan *chan,
+						uint16_t mtu,
 						uint8_t opcode,
 						uint16_t num_handles)
 {
@@ -1114,16 +1115,16 @@ static struct read_mult_data *read_mult_data_new(struct bt_gatt_server *server,
 	data->server = server;
 	data->num_handles = num_handles;
 	data->cur_handle = 0;
-	data->mtu = bt_att_get_mtu(server->att);
+	data->mtu = mtu;
 	data->length = 0;
 	data->rsp_data = new0(uint8_t, data->mtu - 1);
 
 	return data;
 }
 
-static void read_multiple_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void read_multiple_cb(struct bt_att_chan *chan, uint16_t mtu,
+				uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	struct gatt_db_attribute *attr;
@@ -1137,7 +1138,7 @@ static void read_multiple_cb(struct bt_att_chan *chan, uint8_t opcode,
 		goto error;
 	}
 
-	data = read_mult_data_new(server, chan, opcode, length / 2);
+	data = read_mult_data_new(server, chan, mtu, opcode, length / 2);
 
 	for (i = 0; i < data->num_handles; i++)
 		data->handles[i] = get_le16(pdu + i * 2);
@@ -1300,9 +1301,9 @@ static void prep_write_complete_cb(struct gatt_db_attribute *attr, int err,
 	free(pwcd);
 }
 
-static void prep_write_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void prep_write_cb(struct bt_att_chan *chan, uint16_t mtu,
+				uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t handle = 0;
@@ -1332,7 +1333,7 @@ static void prep_write_cb(struct bt_att_chan *chan, uint8_t opcode,
 
 	DBG(server, "Prep Write Req - handle: 0x%04x", handle);
 
-	ecode = check_length(length, offset);
+	ecode = check_length(length - 4, offset);
 	if (ecode)
 		goto error;
 
@@ -1432,9 +1433,9 @@ static bool find_no_reliable_characteristic(const void *data,
 	return !prep_data->reliable_supported;
 }
 
-static void exec_write_cb(struct bt_att_chan *chan, uint8_t opcode,
-					const void *pdu, uint16_t length,
-					void *user_data)
+static void exec_write_cb(struct bt_att_chan *chan, uint16_t mtu,
+				uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	struct exec_data *data;
@@ -1495,9 +1496,9 @@ error:
 	bt_att_chan_send_error_rsp(chan, opcode, ehandle, ecode);
 }
 
-static void exchange_mtu_cb(struct bt_att_chan *chan, uint8_t opcode,
-				const void *pdu, uint16_t length,
-				void *user_data)
+static void exchange_mtu_cb(struct bt_att_chan *chan, uint16_t mtu,
+				uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 	uint16_t client_rx_mtu;
@@ -1627,6 +1628,14 @@ static bool gatt_server_register_att_handlers(struct bt_gatt_server *server)
 	if (!server->exec_write_id)
 		return NULL;
 
+	/* Signed Write Command */
+	server->signed_write_cmd_id = bt_att_register(server->att,
+						BT_ATT_OP_SIGNED_WRITE_CMD,
+						write_cb,
+						server, NULL);
+	if (!server->signed_write_cmd_id)
+		return false;
+
 	return true;
 }
 
@@ -1785,7 +1794,9 @@ bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
 		length = MIN(data->len - data->offset, length);
 	}
 
-	memcpy(data->pdu + data->offset, value, length);
+	if (value)
+		memcpy(data->pdu + data->offset, value, length);
+
 	data->offset += length;
 
 	if (multiple) {
@@ -1808,8 +1819,10 @@ bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
 	return result;
 
 error:
-	if (data)
+	if (data) {
+		free(data->pdu);
 		free(data);
+	}
 
 	return false;
 }
diff --git a/src/shared/lc3.h b/src/shared/lc3.h
index fd9eb15..e7a9277 100644
--- a/src/shared/lc3.h
+++ b/src/shared/lc3.h
@@ -4,21 +4,17 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2024 NXP
  *
  */
 
-#define LTV(_type, _bytes...) \
-	{ \
-		.len = 1 + sizeof((uint8_t []) { _bytes }), \
-		.type = _type, \
-		.data = { _bytes }, \
-	}
+#include "src/shared/bap-defs.h"
 
 #define LC3_ID			0x06
 
-#define LC3_BASE		0x01
+#define LC3_TYPE_BASE		0x01
 
-#define LC3_FREQ		(LC3_BASE)
+#define LC3_FREQ		LC3_TYPE_BASE
 #define LC3_FREQ_8KHZ		BIT(0)
 #define LC3_FREQ_11KHZ		BIT(1)
 #define LC3_FREQ_16KHZ		BIT(2)
@@ -36,7 +32,7 @@
 					LC3_FREQ_44KHZ | \
 					LC3_FREQ_48KHZ)
 
-#define LC3_DURATION		(LC3_BASE + 1)
+#define LC3_DURATION		(LC3_TYPE_BASE + 1)
 #define LC3_DURATION_7_5	BIT(0)
 #define LC3_DURATION_10		BIT(1)
 #define LC3_DURATION_ANY	(LC3_DURATION_7_5 | LC3_DURATION_10)
@@ -44,21 +40,19 @@
 #define LC3_DURATION_PREFER_10	BIT(5)
 
 
-#define LC3_CHAN_COUNT		(LC3_BASE + 2)
+#define LC3_CHAN_COUNT		(LC3_TYPE_BASE + 2)
 #define LC3_CHAN_COUNT_SUPPORT	BIT(0)
 
-#define LC3_FRAME_LEN		(LC3_BASE + 3)
+#define LC3_FRAME_LEN		(LC3_TYPE_BASE + 3)
 
-#define LC3_FRAME_COUNT		(LC3_BASE + 4)
+#define LC3_FRAME_COUNT		(LC3_TYPE_BASE + 4)
 
 #define LC3_CAPABILITIES(_freq, _duration, _chan_count, _len_min, _len_max) \
-	{ \
-		LTV(LC3_FREQ, _freq), \
-		LTV(LC3_DURATION, _duration), \
-		LTV(LC3_CHAN_COUNT, _chan_count), \
-		LTV(LC3_FRAME_LEN, _len_min, _len_min >> 8, \
-				_len_max, _len_max >> 8), \
-	}
+	UTIL_IOV_INIT(0x02, LC3_FREQ, _freq, _freq >> 8, \
+			0x02, LC3_DURATION, _duration, \
+			0x02, LC3_CHAN_COUNT, _chan_count, \
+			0x05, LC3_FRAME_LEN, _len_min, _len_min >> 8, \
+			_len_max, _len_max >> 8)
 
 #define LC3_CONFIG_BASE		0x01
 
@@ -76,37 +70,1128 @@
 #define LC3_CONFIG_DURATION_7_5	0x00
 #define LC3_CONFIG_DURATION_10	0x01
 
-#define LC3_CONFIG_CHAN_ALLOC	(LC3_CONFIG_BASE + 2)
+#define LC3_CONFIG_CHAN_ALLOC		(LC3_CONFIG_BASE + 2)
+#define LC3_CONFIG_CHAN_ALLOC_LEN	0x05
 
 #define LC3_CONFIG_FRAME_LEN	(LC3_CONFIG_BASE + 3)
 
 #define LC3_CONFIG(_freq, _duration, _len) \
-	{ \
-		LTV(LC3_CONFIG_FREQ, _freq), \
-		LTV(LC3_CONFIG_DURATION, _duration), \
-		LTV(LC3_CONFIG_FRAME_LEN, _len, _len >> 8), \
-	}
+	UTIL_IOV_INIT(0x02, LC3_CONFIG_FREQ, _freq, \
+			0x02, LC3_CONFIG_DURATION, _duration, \
+			0x03, LC3_CONFIG_FRAME_LEN, _len, _len >> 8)
 
-#define LC3_CONFIG_8KHZ(_duration, _len) \
+#define LC3_AC_BITS(_ac) (BIT(_ac) - 1)
+
+#define LC3_CONFIG_AC(_freq, _duration, _len, _ac) \
+	UTIL_IOV_INIT(0x02, LC3_CONFIG_FREQ, _freq, \
+			0x02, LC3_CONFIG_DURATION, _duration, \
+			0x03, LC3_CONFIG_FRAME_LEN, _len, _len >> 8, \
+			0x05, LC3_CONFIG_CHAN_ALLOC, LC3_AC_BITS(_ac), \
+			LC3_AC_BITS(_ac) >> 8 & 0xff, \
+			LC3_AC_BITS(_ac) >> 16 & 0xff, \
+			LC3_AC_BITS(_ac) >> 24 & 0xff)
+
+#define LC3_CONFIG_8(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_8KHZ, _duration, _len)
 
-#define LC3_CONFIG_11KHZ(_duration, _len) \
+#define LC3_CONFIG_8_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_8KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_11(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_11KHZ, _duration, _len)
 
-#define LC3_CONFIG_16KHZ(_duration, _len) \
+#define LC3_CONFIG_11_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_11KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_16(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_16KHZ, _duration, _len)
 
-#define LC3_CONFIG_22KHZ(_duration, _len) \
+#define LC3_CONFIG_16_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_16KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_22(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_22KHZ, _duration, _len)
 
-#define LC3_CONFIG_24KHZ(_duration, _len) \
+#define LC3_CONFIG_22_AC(_duration, _len) \
+	LC3_CONFIG(LC3_CONFIG_FREQ_22KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_24(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_24KHZ, _duration, _len)
 
-#define LC3_CONFIG_32KHZ(_duration, _len) \
+#define LC3_CONFIG_24_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_24KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_32(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_32KHZ, _duration, _len)
 
-#define LC3_CONFIG_44KHZ(_duration, _len) \
+#define LC3_CONFIG_32_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_32KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_44(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_44KHZ, _duration, _len)
 
-#define LC3_CONFIG_48KHZ(_duration, _len) \
+#define LC3_CONFIG_44_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_44KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_48(_duration, _len) \
 	LC3_CONFIG(LC3_CONFIG_FREQ_48KHZ, _duration, _len)
+
+#define LC3_CONFIG_48_AC(_duration, _len, _ac) \
+	LC3_CONFIG_AC(LC3_CONFIG_FREQ_48KHZ, _duration, _len, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_8_1 26u
+
+#define LC3_CONFIG_8_1 \
+	LC3_CONFIG_8(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_8_1)
+
+#define LC3_CONFIG_8_1_AC(_ac) \
+	LC3_CONFIG_8_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_8_1, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_8_2 30u
+
+#define LC3_CONFIG_8_2 \
+	LC3_CONFIG_8(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_8_2 )
+
+#define LC3_CONFIG_8_2_AC(_ac) \
+	LC3_CONFIG_8_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_8_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_16_1 30u
+
+#define LC3_CONFIG_16_1 \
+	LC3_CONFIG_16(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_16_1)
+
+#define LC3_CONFIG_16_1_AC(_ac) \
+	LC3_CONFIG_16_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_16_1, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_16_2 40u
+
+#define LC3_CONFIG_16_2 \
+	LC3_CONFIG_16(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_16_2)
+
+#define LC3_CONFIG_16_2_AC(_ac) \
+	LC3_CONFIG_16_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_16_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_24_1 45u
+
+#define LC3_CONFIG_24_1 \
+	LC3_CONFIG_24(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_24_1)
+
+#define LC3_CONFIG_24_1_AC(_ac) \
+	LC3_CONFIG_24_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_24_1, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_24_2 60u
+
+#define LC3_CONFIG_24_2 \
+	LC3_CONFIG_24(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_24_2)
+
+#define LC3_CONFIG_24_2_AC(_ac) \
+	LC3_CONFIG_24_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_24_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_32_1 60u
+
+#define LC3_CONFIG_32_1 \
+	LC3_CONFIG_32(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_32_1)
+
+#define LC3_CONFIG_32_1_AC(_ac) \
+	LC3_CONFIG_32_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_32_1, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_32_2 80u
+
+#define LC3_CONFIG_32_2 \
+	LC3_CONFIG_32(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_32_2)
+
+#define LC3_CONFIG_32_2_AC(_ac) \
+	LC3_CONFIG_32_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_32_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_44_1 98u
+
+#define LC3_CONFIG_44_1 \
+	LC3_CONFIG_44(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_44_1)
+
+#define LC3_CONFIG_44_1_AC(_ac) \
+	LC3_CONFIG_44_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_44_1, \
+			 _ac)
+
+#define LC3_CONFIG_FRAME_LEN_44_2 130u
+
+#define LC3_CONFIG_44_2 \
+	LC3_CONFIG_44(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_44_2)
+
+#define LC3_CONFIG_44_2_AC(_ac) \
+	LC3_CONFIG_44_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_44_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_1 75u
+
+#define LC3_CONFIG_48_1 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_1)
+
+#define LC3_CONFIG_48_1_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_1, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_2 100u
+
+#define LC3_CONFIG_48_2 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_2)
+
+#define LC3_CONFIG_48_2_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_2, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_3 90u
+
+#define LC3_CONFIG_48_3 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_3)
+
+#define LC3_CONFIG_48_3_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_3, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_4 120u
+
+#define LC3_CONFIG_48_4 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_4)
+
+#define LC3_CONFIG_48_4_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_4, _ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_5 117u
+
+#define LC3_CONFIG_48_5 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_5)
+
+#define LC3_CONFIG_48_5_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_5, \
+			_ac)
+
+#define LC3_CONFIG_FRAME_LEN_48_6 155u
+
+#define LC3_CONFIG_48_6 \
+	LC3_CONFIG_48(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_6)
+
+#define LC3_CONFIG_48_6_AC(_ac) \
+	LC3_CONFIG_48_AC(LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_6, \
+			_ac)
+
+#define BASE(_pd, _sgrp, _nbis, _cfg...) \
+	_pd & 0xff, _pd >> 8, _pd >> 16, \
+	_sgrp, \
+	_nbis, \
+	_cfg
+
+#define BASE_LC3(_pd, _sgrp, _nbis, _cc...) \
+	BASE(_pd, _sgrp, _nbis, \
+		0x06, 0x00, 0x00, 0x00, 0x00, \
+		_cc)
+
+#define LC3_CFG(_freq, _dur, _len) \
+	0x0a, \
+	0x02, LC3_CONFIG_FREQ, _freq, \
+	0x02, LC3_CONFIG_DURATION, _dur, \
+	0x03, LC3_CONFIG_FRAME_LEN, _len, _len >> 8
+
+#define LC3_CFG_8_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_8KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_8_1)
+
+#define BASE_LC3_8_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_8_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_8_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_8KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_8_2)
+
+#define BASE_LC3_8_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_8_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_16_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_16KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_16_1)
+
+#define BASE_LC3_16_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_16_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_16_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_16KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_16_2)
+
+#define BASE_LC3_16_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_16_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_24_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_24KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_24_1)
+
+#define BASE_LC3_24_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_24_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_24_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_24KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_24_2)
+
+#define BASE_LC3_24_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_24_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_32_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_32KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_32_1)
+
+#define BASE_LC3_32_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_32_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_32_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_32KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_32_2)
+
+#define BASE_LC3_32_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_32_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_44_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_44KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_44_1)
+
+#define BASE_LC3_44_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_44_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_44_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_44KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_44_2)
+
+#define BASE_LC3_44_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_44_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_1 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_48_1)
+
+#define BASE_LC3_48_1 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_1, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_2 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_48_2)
+
+#define BASE_LC3_48_2 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_2, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_3 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_48_3)
+
+#define BASE_LC3_48_3 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_3, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_4 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_48_4)
+
+#define BASE_LC3_48_4 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_4, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_5 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_7_5, \
+		LC3_CONFIG_FRAME_LEN_48_5)
+
+#define BASE_LC3_48_5 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_5, 0x00, 0x01, 0x00)
+
+#define LC3_CFG_48_6 \
+	LC3_CFG(LC3_CONFIG_FREQ_48KHZ, \
+		LC3_CONFIG_DURATION_10, \
+		LC3_CONFIG_FRAME_LEN_48_6)
+
+#define BASE_LC3_48_6 \
+	BASE_LC3(40000, 1, 1, LC3_CFG_48_6, 0x00, 0x01, 0x00)
+
+#define BASE_VS(_cc) \
+	BASE(40000, 1, 1, \
+		0xFF, 0x00, 0x00, 0x00, 0x00, \
+		_cc, 0x00, 0x01, 0x00)
+
+#define BASE_LC3_8_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_8_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_8_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_8_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_16_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_16_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_16_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_16_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_24_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_24_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_24_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_24_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_32_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_32_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_32_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_32_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_44_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_44_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_44_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_44_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_1_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_1, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_2_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_2, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_3_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_3, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_4_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_4, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_5_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_5, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_LC3_48_6_MBIS \
+	BASE_LC3(40000, 1, 2, LC3_CFG_48_6, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define BASE_VS_MBIS(_cc) \
+	BASE(40000, 1, 2, \
+		0xFF, 0x00, 0x00, 0x00, 0x00, \
+		_cc, 0x00, 0x01, 0x00, 0x02, 0x00)
+
+#define LC3_QOS_UNFRAMED	0x00
+#define LC3_QOS_FRAMED		0x01
+
+#define LC3_QOS_UCAST(_frame, _pd, _t_lat, _interval, _lat, _sdu, _rtn) \
+{ \
+	.ucast.cig_id = 0x00, \
+	.ucast.cis_id = 0x00, \
+	.ucast.framing = _frame, \
+	.ucast.delay = _pd, \
+	.ucast.target_latency = _t_lat, \
+	.ucast.io_qos.interval = _interval, \
+	.ucast.io_qos.latency = _lat, \
+	.ucast.io_qos.sdu = _sdu, \
+	.ucast.io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
+	.ucast.io_qos.rtn = _rtn, \
+}
+
+#define LC3_QOS_UCAST_7_5_UNFRAMED(_pd, _t_lat, _lat, _sdu, _rtn) \
+	LC3_QOS_UCAST(LC3_QOS_UNFRAMED, _pd, _t_lat, 7500u, _lat, _sdu, _rtn)
+
+#define LC3_QOS_UCAST_10_UNFRAMED(_pd, _t_lat, _lat, _sdu, _rtn) \
+	LC3_QOS_UCAST(LC3_QOS_UNFRAMED, _pd, _t_lat, 10000u, _lat, _sdu, _rtn)
+
+#define LC3_QOS_UCAST_FRAMED(_pd, _t_lat, _interval, _lat, _sdu, _rtn) \
+	LC3_QOS_UCAST(LC3_QOS_FRAMED, _pd, _t_lat, _interval, _lat, _sdu, _rtn)
+
+#define LC3_QOS_8_1_1_LATENCY 8u
+#define LC3_QOS_8_1_1_RTN 2u
+
+#define LC3_QOS_8_1_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_8_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_1, \
+					LC3_QOS_8_1_1_RTN)
+#define LC3_QOS_8_1_1 LC3_QOS_8_1_1_AC(1)
+
+#define LC3_QOS_8_1_2_LATENCY 75u
+#define LC3_QOS_8_1_2_RTN 13u
+
+#define LC3_QOS_8_1_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_8_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_1, \
+					LC3_QOS_8_1_2_RTN)
+#define LC3_QOS_8_1_2 LC3_QOS_8_1_2_AC(1)
+
+#define LC3_QOS_8_2_1_LATENCY 10u
+#define LC3_QOS_8_2_1_RTN 2u
+
+#define LC3_QOS_8_2_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_8_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_2, \
+					LC3_QOS_8_2_1_RTN)
+#define LC3_QOS_8_2_1 LC3_QOS_8_2_1_AC(1)
+
+#define LC3_QOS_8_2_2_LATENCY 95u
+#define LC3_QOS_8_2_2_RTN 13u
+
+#define LC3_QOS_8_2_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_8_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_2, \
+					LC3_QOS_8_2_2_RTN)
+#define LC3_QOS_8_2_2 LC3_QOS_8_2_2_AC(1)
+
+#define LC3_QOS_16_1_1_LATENCY 8u
+#define LC3_QOS_16_1_1_RTN 2u
+
+#define LC3_QOS_16_1_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_1, \
+					LC3_QOS_16_1_1_RTN)
+#define LC3_QOS_16_1_1 LC3_QOS_16_1_1_AC(1)
+
+#define LC3_QOS_16_1_2_LATENCY 75u
+#define LC3_QOS_16_1_2_RTN 13u
+
+#define LC3_QOS_16_1_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_1, \
+					LC3_QOS_16_1_2_RTN)
+#define LC3_QOS_16_1_2 LC3_QOS_16_1_2_AC(1)
+
+#define LC3_QOS_16_1_GS_LATENCY 15u
+#define LC3_QOS_16_1_GS_RTN 1u
+#define LC3_QOS_16_1_GS \
+	LC3_QOS_UCAST_7_5_UNFRAMED(60000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_1_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_16_1, \
+					LC3_QOS_16_1_GS_RTN)
+
+#define LC3_QOS_16_2_1_LATENCY 10u
+#define LC3_QOS_16_2_1_RTN 2u
+
+#define LC3_QOS_16_2_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_2, \
+					LC3_QOS_16_2_1_RTN)
+#define LC3_QOS_16_2_1 LC3_QOS_16_2_1_AC(1)
+
+#define LC3_QOS_16_2_2_LATENCY 95u
+#define LC3_QOS_16_2_2_RTN 13u
+
+#define LC3_QOS_16_2_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_2, \
+					LC3_QOS_16_2_2_RTN)
+#define LC3_QOS_16_2_2 LC3_QOS_16_2_2_AC(1)
+
+#define LC3_QOS_16_2_GS_LATENCY 20u
+#define LC3_QOS_16_2_GS_RTN 1u
+#define LC3_QOS_16_2_GS \
+	LC3_QOS_UCAST_10_UNFRAMED(60000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_16_2_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_16_2, \
+					LC3_QOS_16_2_GS_RTN)
+
+#define LC3_QOS_24_1_1_LATENCY 8u
+#define LC3_QOS_24_1_1_RTN 2u
+
+#define LC3_QOS_24_1_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_24_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_1, \
+					LC3_QOS_24_1_1_RTN)
+#define LC3_QOS_24_1_1 LC3_QOS_24_1_1_AC(1)
+
+#define LC3_QOS_24_1_2_LATENCY 75u
+#define LC3_QOS_24_1_2_RTN 13u
+
+#define LC3_QOS_24_1_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_24_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_1, \
+					LC3_QOS_24_1_2_RTN)
+#define LC3_QOS_24_1_2 LC3_QOS_24_1_2_AC(1)
+
+#define LC3_QOS_24_2_1_LATENCY 10u
+#define LC3_QOS_24_2_1_RTN 2u
+
+#define LC3_QOS_24_2_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_24_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_2, \
+					LC3_QOS_24_2_1_RTN)
+#define LC3_QOS_24_2_1 LC3_QOS_24_2_1_AC(1)
+
+#define LC3_QOS_24_2_2_LATENCY 95u
+#define LC3_QOS_24_2_2_RTN 13u
+
+#define LC3_QOS_24_2_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_24_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_2, \
+					LC3_QOS_24_2_2_RTN)
+#define LC3_QOS_24_2_2 LC3_QOS_24_2_2_AC(1)
+
+#define LC3_QOS_32_1_1_LATENCY 8u
+#define LC3_QOS_32_1_1_RTN 2u
+
+#define LC3_QOS_32_1_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_1_RTN)
+#define LC3_QOS_32_1_1 LC3_QOS_32_1_1_AC(1)
+
+#define LC3_QOS_32_1_2_LATENCY 75u
+#define LC3_QOS_32_1_2_RTN 13u
+
+#define LC3_QOS_32_1_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_2_RTN)
+#define LC3_QOS_32_1_2 LC3_QOS_32_1_2_AC(1)
+
+#define LC3_QOS_32_1_GS_LATENCY 15u
+#define LC3_QOS_32_1_GS_RTN 1u
+#define LC3_QOS_32_1_GS \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_1_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_GS_RTN)
+
+#define LC3_QOS_32_1_GR_LATENCY 15u
+#define LC3_QOS_32_1_GR_RTN 1u
+#define LC3_QOS_32_1_GR_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_32_1_GS_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_GS_RTN)
+#define LC3_QOS_32_1_GR LC3_QOS_32_1_GR_AC(1)
+
+#define LC3_QOS_32_2_1_LATENCY 10u
+#define LC3_QOS_32_2_1_RTN 2u
+
+#define LC3_QOS_32_2_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_1_RTN)
+#define LC3_QOS_32_2_1 LC3_QOS_32_2_1_AC(1)
+
+#define LC3_QOS_32_2_2_LATENCY 95u
+#define LC3_QOS_32_2_2_RTN 13u
+
+#define LC3_QOS_32_2_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_2_RTN)
+#define LC3_QOS_32_2_2 LC3_QOS_32_2_2_AC(1)
+
+#define LC3_QOS_32_2_GS_LATENCY 20u
+#define LC3_QOS_32_2_GS_RTN 1u
+#define LC3_QOS_32_2_GS \
+	LC3_QOS_UCAST_10_UNFRAMED(60000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_32_2_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_GS_RTN)
+
+#define LC3_QOS_32_2_GR_LATENCY 20u
+#define LC3_QOS_32_2_GR_RTN 1u
+#define LC3_QOS_32_2_GR_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_32_2_GR_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_GR_RTN)
+#define LC3_QOS_32_2_GR LC3_QOS_32_2_GR_AC(1)
+
+#define LC3_QOS_44_1_INTERVAL 8163u
+#define LC3_QOS_44_1_1_LATENCY 24u
+#define LC3_QOS_44_1_1_RTN 5u
+
+#define LC3_QOS_44_1_1_AC(_ac) \
+	LC3_QOS_UCAST_FRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_44_1_INTERVAL, \
+					LC3_QOS_44_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_1, \
+					LC3_QOS_44_1_1_RTN)
+#define LC3_QOS_44_1_1 LC3_QOS_44_1_1_AC(1)
+
+#define LC3_QOS_44_1_2_LATENCY 80u
+#define LC3_QOS_44_1_2_RTN 13u
+
+#define LC3_QOS_44_1_2_AC(_ac) \
+	LC3_QOS_UCAST_FRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_44_1_INTERVAL, \
+					LC3_QOS_44_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_1, \
+					LC3_QOS_44_1_2_RTN)
+#define LC3_QOS_44_1_2 LC3_QOS_44_1_2_AC(1)
+
+#define LC3_QOS_44_2_INTERVAL 10884u
+#define LC3_QOS_44_2_1_LATENCY 31u
+#define LC3_QOS_44_2_1_RTN 5u
+
+#define LC3_QOS_44_2_1_AC(_ac) \
+	LC3_QOS_UCAST_FRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_44_2_INTERVAL, \
+					LC3_QOS_44_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_2, \
+					LC3_QOS_44_2_1_RTN)
+#define LC3_QOS_44_2_1 LC3_QOS_44_2_1_AC(1)
+
+#define LC3_QOS_44_2_2_LATENCY 85u
+#define LC3_QOS_44_2_2_RTN 13u
+
+#define LC3_QOS_44_2_2_AC(_ac) \
+	LC3_QOS_UCAST_FRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_44_2_INTERVAL, \
+					LC3_QOS_44_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_2, \
+					LC3_QOS_44_2_2_RTN)
+#define LC3_QOS_44_2_2 LC3_QOS_44_2_2_AC(1)
+
+#define LC3_QOS_48_1_1_LATENCY 15u
+#define LC3_QOS_48_1_1_RTN 5u
+
+#define LC3_QOS_48_1_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_1,\
+					LC3_QOS_48_1_1_RTN)
+#define LC3_QOS_48_1_1 LC3_QOS_48_1_1_AC(1)
+
+#define LC3_QOS_48_1_2_LATENCY 75u
+#define LC3_QOS_48_1_2_RTN 13u
+
+#define LC3_QOS_48_1_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_1_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_1, \
+					LC3_QOS_48_1_2_RTN)
+#define LC3_QOS_48_1_2 LC3_QOS_48_1_2_AC(1)
+
+#define LC3_QOS_48_1_GS_LATENCY 15u
+#define LC3_QOS_48_1_GS_RTN 1u
+
+#define LC3_QOS_48_1_GS \
+	LC3_QOS_UCAST_7_5_UNFRAMED(60000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_1_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_48_1, \
+					LC3_QOS_48_1_GS_RTN)
+
+#define LC3_QOS_48_1_GR_LATENCY 15u
+#define LC3_QOS_48_1_GR_RTN 1u
+
+#define LC3_QOS_48_1_GR_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_48_1_GR_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_1, \
+					LC3_QOS_48_1_GR_RTN)
+#define LC3_QOS_48_1_GR LC3_QOS_48_1_GR_AC(1)
+
+#define LC3_QOS_48_2_1_LATENCY 20u
+#define LC3_QOS_48_2_1_RTN 5u
+
+#define LC3_QOS_48_2_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_1_RTN)
+#define LC3_QOS_48_2_1 LC3_QOS_48_2_1_AC(1)
+
+#define LC3_QOS_48_2_2_LATENCY 95u
+#define LC3_QOS_48_2_2_RTN 13u
+
+#define LC3_QOS_48_2_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_2_RTN)
+#define LC3_QOS_48_2_2 LC3_QOS_48_2_2_AC(1)
+
+#define LC3_QOS_48_2_GS_LATENCY 20u
+#define LC3_QOS_48_2_GS_RTN 1u
+
+#define LC3_QOS_48_2_GS \
+	LC3_QOS_UCAST_10_UNFRAMED(60000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_2_GS_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_GS_RTN)
+
+#define LC3_QOS_48_2_GR_LATENCY 20u
+#define LC3_QOS_48_2_GR_RTN 1u
+
+#define LC3_QOS_48_2_GR_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_48_2_GR_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_GR_RTN)
+#define LC3_QOS_48_2_GR LC3_QOS_48_2_GR_AC(1)
+
+#define LC3_QOS_48_3_1_LATENCY 15u
+#define LC3_QOS_48_3_1_RTN 5u
+
+#define LC3_QOS_48_3_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_3_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_3, \
+					LC3_QOS_48_3_1_RTN)
+#define LC3_QOS_48_3_1 LC3_QOS_48_3_1_AC(1)
+
+#define LC3_QOS_48_3_2_LATENCY 75u
+#define LC3_QOS_48_3_2_RTN 13u
+
+#define LC3_QOS_48_3_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_3_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_3, \
+					LC3_QOS_48_3_2_RTN)
+#define LC3_QOS_48_3_2 LC3_QOS_48_3_2_AC(1)
+
+#define LC3_QOS_48_3_GR_LATENCY 15u
+#define LC3_QOS_48_3_GR_RTN 1u
+
+#define LC3_QOS_48_3_GR_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_48_3_GR_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_3, \
+					LC3_QOS_48_3_GR_RTN)
+#define LC3_QOS_48_3_GR LC3_QOS_48_3_GR_AC(1)
+
+#define LC3_QOS_48_4_1_LATENCY 20u
+#define LC3_QOS_48_4_1_RTN 5u
+
+#define LC3_QOS_48_4_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_4_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_4, \
+					LC3_QOS_48_4_1_RTN)
+#define LC3_QOS_48_4_1 LC3_QOS_48_4_1_AC(1)
+
+#define LC3_QOS_48_4_2_LATENCY 100u
+#define LC3_QOS_48_4_2_RTN 13u
+
+#define LC3_QOS_48_4_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_4_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_4, \
+					LC3_QOS_48_4_2_RTN)
+#define LC3_QOS_48_4_2 LC3_QOS_48_4_2_AC(1)
+
+#define LC3_QOS_48_4_GR_LATENCY 20u
+#define LC3_QOS_48_4_GR_RTN 1u
+
+#define LC3_QOS_48_4_GR_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(10000u, BT_BAP_CONFIG_LATENCY_LOW, \
+					LC3_QOS_48_4_GR_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_4, \
+					LC3_QOS_48_4_GR_RTN)
+#define LC3_QOS_48_4_GR LC3_QOS_48_4_GR_AC(1)
+
+#define LC3_QOS_48_5_1_LATENCY 15u
+#define LC3_QOS_48_5_1_RTN 5u
+
+#define LC3_QOS_48_5_1_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_5_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_5, \
+					LC3_QOS_48_5_1_RTN)
+#define LC3_QOS_48_5_1 LC3_QOS_48_5_1_AC(1)
+
+#define LC3_QOS_48_5_2_LATENCY 75u
+#define LC3_QOS_48_5_2_RTN 13u
+
+#define LC3_QOS_48_5_2_AC(_ac) \
+	LC3_QOS_UCAST_7_5_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_5_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_5, \
+					LC3_QOS_48_5_2_RTN)
+#define LC3_QOS_48_5_2 LC3_QOS_48_5_2_AC(1)
+
+#define LC3_QOS_48_6_1_LATENCY 20u
+#define LC3_QOS_48_6_1_RTN 5u
+
+#define LC3_QOS_48_6_1_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_6_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_6, \
+					LC3_QOS_48_6_1_RTN)
+#define LC3_QOS_48_6_1 LC3_QOS_48_6_1_AC(1)
+
+#define LC3_QOS_48_6_2_LATENCY 100u
+#define LC3_QOS_48_6_2_RTN 13u
+
+#define LC3_QOS_48_6_2_AC(_ac) \
+	LC3_QOS_UCAST_10_UNFRAMED(40000u, BT_BAP_CONFIG_LATENCY_BALANCED, \
+					LC3_QOS_48_6_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_6, \
+					LC3_QOS_48_6_2_RTN)
+#define LC3_QOS_48_6_2 LC3_QOS_48_6_2_AC(1)
+
+#define LC3_QOS_BCAST(_frame, _pd, _interval, _lat, _sdu, _rtn) \
+{ \
+	.bcast.big = 0x00, \
+	.bcast.bis = 0x00, \
+	.bcast.framing = _frame, \
+	.bcast.delay = _pd, \
+	.bcast.io_qos.interval = _interval, \
+	.bcast.io_qos.latency = _lat, \
+	.bcast.io_qos.sdu = _sdu, \
+	.bcast.io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
+	.bcast.io_qos.rtn = _rtn, \
+}
+
+#define LC3_QOS_BCAST_7_5_UNFRAMED(_pd, _lat, _sdu, _rtn) \
+	LC3_QOS_BCAST(LC3_QOS_UNFRAMED, _pd, 7500u, _lat, _sdu, _rtn)
+
+#define LC3_QOS_BCAST_10_UNFRAMED(_pd, _lat, _sdu, _rtn) \
+	LC3_QOS_BCAST(LC3_QOS_UNFRAMED, _pd, 10000u, _lat, _sdu, _rtn)
+
+#define LC3_QOS_BCAST_FRAMED(_pd, _interval, _lat, _sdu, _rtn) \
+	LC3_QOS_BCAST(LC3_QOS_FRAMED, _pd, _interval, _lat, _sdu, _rtn)
+
+#define LC3_QOS_8_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_8_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_1, \
+					LC3_QOS_8_1_1_RTN)
+#define LC3_QOS_8_1_1_B LC3_QOS_8_1_1_B_AC(1)
+
+#define LC3_QOS_8_1_2_B_LATENCY 75u
+#define LC3_QOS_8_1_2_B_RTN 4u
+#define LC3_QOS_8_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_8_1_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_1, \
+					LC3_QOS_8_1_2_B_RTN)
+#define LC3_QOS_8_1_2_B LC3_QOS_8_1_2_B_AC(1)
+
+#define LC3_QOS_8_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_8_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_2, \
+					LC3_QOS_8_2_1_RTN)
+#define LC3_QOS_8_2_1_B LC3_QOS_8_2_1_B_AC(1)
+
+#define LC3_QOS_8_2_2_B_LATENCY 60u
+#define LC3_QOS_8_2_2_B_RTN 4u
+#define LC3_QOS_8_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_8_2_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_8_2, \
+					LC3_QOS_8_2_2_B_RTN)
+#define LC3_QOS_8_2_2_B LC3_QOS_8_2_2_B_AC(1)
+
+#define LC3_QOS_16_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_16_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_1, \
+					LC3_QOS_16_1_1_RTN)
+#define LC3_QOS_16_1_1_B LC3_QOS_16_1_1_B_AC(1)
+
+#define LC3_QOS_16_1_2_B_LATENCY 45u
+#define LC3_QOS_16_1_2_B_RTN 4u
+#define LC3_QOS_16_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_16_1_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_1, \
+					LC3_QOS_16_1_2_B_RTN)
+#define LC3_QOS_16_1_2_B LC3_QOS_16_1_2_B_AC(1)
+
+#define LC3_QOS_16_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_16_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_2, \
+					LC3_QOS_16_2_1_RTN)
+#define LC3_QOS_16_2_1_B LC3_QOS_16_2_1_B_AC(1)
+
+#define LC3_QOS_16_2_2_B_LATENCY 60u
+#define LC3_QOS_16_2_2_B_RTN 4u
+#define LC3_QOS_16_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_16_2_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_16_2, \
+					LC3_QOS_16_2_2_B_RTN)
+#define LC3_QOS_16_2_2_B LC3_QOS_16_2_2_B_AC(1)
+
+#define LC3_QOS_24_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_24_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_1, \
+					LC3_QOS_24_1_1_RTN)
+#define LC3_QOS_24_1_1_B LC3_QOS_24_1_1_B_AC(1)
+
+#define LC3_QOS_24_1_2_B_LATENCY 45u
+#define LC3_QOS_24_1_2_B_RTN 4u
+#define LC3_QOS_24_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_24_1_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_1, \
+					LC3_QOS_24_1_2_B_RTN)
+#define LC3_QOS_24_1_2_B LC3_QOS_24_1_2_B_AC(1)
+
+#define LC3_QOS_24_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_24_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_2, \
+					LC3_QOS_24_2_1_RTN)
+#define LC3_QOS_24_2_1_B LC3_QOS_24_2_1_B_AC(1)
+
+#define LC3_QOS_24_2_2_B_LATENCY 60u
+#define LC3_QOS_24_2_2_B_RTN 4u
+#define LC3_QOS_24_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_24_2_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_24_2, \
+					LC3_QOS_24_2_2_B_RTN)
+#define LC3_QOS_24_2_2_B LC3_QOS_24_2_2_B_AC(1)
+
+#define LC3_QOS_32_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_32_1_1_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_1_RTN)
+#define LC3_QOS_32_1_1_B LC3_QOS_32_1_1_B_AC(1)
+
+#define LC3_QOS_32_1_2_B_LATENCY 45u
+#define LC3_QOS_32_1_2_B_RTN 4u
+#define LC3_QOS_32_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_32_1_2_B_LATENCY, \
+					LC3_CONFIG_FRAME_LEN_32_1, \
+					LC3_QOS_32_1_2_B_RTN)
+#define LC3_QOS_32_1_2_B LC3_QOS_32_1_2_B_AC(1)
+
+#define LC3_QOS_32_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_32_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_1_RTN)
+#define LC3_QOS_32_2_1_B LC3_QOS_32_2_1_B_AC(1)
+
+#define LC3_QOS_32_2_2_B_LATENCY 60u
+#define LC3_QOS_32_2_2_B_RTN 4u
+#define LC3_QOS_32_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_32_2_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_32_2, \
+					LC3_QOS_32_2_2_B_RTN)
+#define LC3_QOS_32_2_2_B LC3_QOS_32_2_2_B_AC(1)
+
+#define LC3_QOS_44_1_1_B_RTN 4u
+#define LC3_QOS_44_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_FRAMED(40000u, LC3_QOS_44_1_INTERVAL, \
+					LC3_QOS_44_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_1, \
+					LC3_QOS_44_1_1_B_RTN)
+#define LC3_QOS_44_1_1_B LC3_QOS_44_1_1_B_AC(1)
+
+#define LC3_QOS_44_1_2_B_LATENCY 54u
+#define LC3_QOS_44_1_2_B_RTN 4u
+#define LC3_QOS_44_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_FRAMED(40000u, LC3_QOS_44_1_INTERVAL, \
+					LC3_QOS_44_1_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_1, \
+					LC3_QOS_44_1_2_B_RTN)
+#define LC3_QOS_44_1_2_B LC3_QOS_44_1_2_B_AC(1)
+
+#define LC3_QOS_44_2_1_B_RTN 4u
+#define LC3_QOS_44_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_FRAMED(40000u, LC3_QOS_44_2_INTERVAL, \
+					LC3_QOS_44_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_2, \
+					LC3_QOS_44_2_1_B_RTN)
+#define LC3_QOS_44_2_1_B LC3_QOS_44_2_1_B_AC(1)
+
+#define LC3_QOS_44_2_2_B_LATENCY 60u
+#define LC3_QOS_44_2_2_B_RTN 4u
+#define LC3_QOS_44_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_FRAMED(40000u, LC3_QOS_44_2_INTERVAL, \
+					LC3_QOS_44_2_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_44_2, \
+					LC3_QOS_44_2_2_RTN)
+#define LC3_QOS_44_2_2_B LC3_QOS_44_2_2_B_AC(1)
+
+#define LC3_QOS_48_1_1_B_RTN 4u
+#define LC3_QOS_48_1_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_1_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_1,\
+					LC3_QOS_48_1_1_B_RTN)
+#define LC3_QOS_48_1_1_B LC3_QOS_48_1_1_B_AC(1)
+
+#define LC3_QOS_48_1_2_B_LATENCY 50u
+#define LC3_QOS_48_1_2_B_RTN 4u
+#define LC3_QOS_48_1_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_1_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_1, \
+					LC3_QOS_48_1_2_B_RTN)
+#define LC3_QOS_48_1_2_B LC3_QOS_48_1_2_B_AC(1)
+
+#define LC3_QOS_48_2_1_B_RTN 4u
+#define LC3_QOS_48_2_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_2_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_1_B_RTN)
+#define LC3_QOS_48_2_1_B LC3_QOS_48_2_1_B_AC(1)
+
+#define LC3_QOS_48_2_2_B_LATENCY 65u
+#define LC3_QOS_48_2_2_B_RTN 4u
+#define LC3_QOS_48_2_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_2_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_2, \
+					LC3_QOS_48_2_2_B_RTN)
+#define LC3_QOS_48_2_2_B LC3_QOS_48_2_2_B_AC(1)
+
+#define LC3_QOS_48_3_1_B_RTN 4u
+#define LC3_QOS_48_3_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_3_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_3, \
+					LC3_QOS_48_3_1_B_RTN)
+#define LC3_QOS_48_3_1_B LC3_QOS_48_3_1_B_AC(1)
+
+#define LC3_QOS_48_3_2_B_LATENCY 50u
+#define LC3_QOS_48_3_2_B_RTN 4u
+#define LC3_QOS_48_3_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_3_2_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_3, \
+					LC3_QOS_48_3_2_RTN)
+#define LC3_QOS_48_3_2_B LC3_QOS_48_3_2_B_AC(1)
+
+#define LC3_QOS_48_4_1_B_RTN 4u
+#define LC3_QOS_48_4_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_4_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_4, \
+					LC3_QOS_48_4_1_B_RTN)
+#define LC3_QOS_48_4_1_B LC3_QOS_48_4_1_B_AC(1)
+
+#define LC3_QOS_48_4_2_B_LATENCY 65u
+#define LC3_QOS_48_4_2_B_RTN 4u
+#define LC3_QOS_48_4_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_4_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_4, \
+					LC3_QOS_48_4_2_B_RTN)
+#define LC3_QOS_48_4_2_B LC3_QOS_48_4_2_B_AC(1)
+
+#define LC3_QOS_48_5_1_B_RTN 4u
+#define LC3_QOS_48_5_1_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_5_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_5, \
+					LC3_QOS_48_5_1_B_RTN)
+#define LC3_QOS_48_5_1_B LC3_QOS_48_5_1_B_AC(1)
+
+#define LC3_QOS_48_5_2_B_LATENCY 50u
+#define LC3_QOS_48_5_2_B_RTN 4u
+#define LC3_QOS_48_5_2_B_AC(_ac) \
+	LC3_QOS_BCAST_7_5_UNFRAMED(40000u, LC3_QOS_48_5_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_5, \
+					LC3_QOS_48_5_2_B_RTN)
+#define LC3_QOS_48_5_2_B LC3_QOS_48_5_2_B_AC(1)
+
+#define LC3_QOS_48_6_1_B_RTN 5u
+#define LC3_QOS_48_6_1_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_6_1_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_6, \
+					LC3_QOS_48_6_1_B_RTN)
+#define LC3_QOS_48_6_1_B LC3_QOS_48_6_1_B_AC(1)
+
+#define LC3_QOS_48_6_2_B_LATENCY 65u
+#define LC3_QOS_48_6_2_B_RTN 4u
+#define LC3_QOS_48_6_2_B_AC(_ac) \
+	LC3_QOS_BCAST_10_UNFRAMED(40000u, LC3_QOS_48_6_2_B_LATENCY, \
+					(_ac) * LC3_CONFIG_FRAME_LEN_48_6, \
+					LC3_QOS_48_6_2_B_RTN)
+#define LC3_QOS_48_6_2_B LC3_QOS_48_6_2_B_AC(1)
diff --git a/src/shared/log.c b/src/shared/log.c
index 3f18e80..22b9850 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -135,7 +135,7 @@ int bt_log_vprintf(uint16_t index, const char *label, int level,
 	int len;
 
 	len = vasprintf(&str, format, ap);
-	if (len < 0)
+	if (len < 0 || !str)
 		return errno;
 
 	len = strlen(str);
diff --git a/src/shared/mainloop-notify.c b/src/shared/mainloop-notify.c
index 33be3cf..1198951 100644
--- a/src/shared/mainloop-notify.c
+++ b/src/shared/mainloop-notify.c
@@ -15,6 +15,7 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <errno.h>
+#include <limits.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -130,7 +131,7 @@ static bool signal_read(struct io *io, void *user_data)
 	fd = io_get_fd(io);
 
 	result = read(fd, &si, sizeof(si));
-	if (result != sizeof(si))
+	if (result != sizeof(si) || si.ssi_signo > INT_MAX)
 		return false;
 
 	if (data && data->func)
diff --git a/src/shared/mcp.c b/src/shared/mcp.c
index b3726eb..20a540a 100644
--- a/src/shared/mcp.c
+++ b/src/shared/mcp.c
@@ -600,6 +600,9 @@ static unsigned int mcp_send(struct bt_mcp *mcp, uint8_t operation)
 
 unsigned int bt_mcp_play(struct bt_mcp *mcp)
 {
+	if (!mcp)
+		return 0;
+
 	if (!(mcp->session.cp_op_supported & BT_MCS_CMD_PLAY_SUPPORTED))
 		return -ENOTSUP;
 
@@ -610,6 +613,9 @@ unsigned int bt_mcp_play(struct bt_mcp *mcp)
 
 unsigned int bt_mcp_pause(struct bt_mcp *mcp)
 {
+	if (!mcp)
+		return 0;
+
 	if (!(mcp->session.cp_op_supported & BT_MCS_CMD_PAUSE_SUPPORTED))
 		return -ENOTSUP;
 
@@ -620,6 +626,9 @@ unsigned int bt_mcp_pause(struct bt_mcp *mcp)
 
 unsigned int bt_mcp_stop(struct bt_mcp *mcp)
 {
+	if (!mcp)
+		return 0;
+
 	if (!(mcp->session.cp_op_supported & BT_MCS_CMD_STOP_SUPPORTED))
 		return -ENOTSUP;
 
@@ -628,10 +637,41 @@ unsigned int bt_mcp_stop(struct bt_mcp *mcp)
 	return mcp_send(mcp, BT_MCS_CMD_STOP);
 }
 
+unsigned int bt_mcp_next_track(struct bt_mcp *mcp)
+{
+	if (!mcp)
+		return 0;
+
+	if (!(mcp->session.cp_op_supported & BT_MCS_CMD_NEXT_TRACK_SUPPORTED))
+		return -ENOTSUP;
+
+	DBG(mcp, "mcp %p", mcp);
+
+	return mcp_send(mcp, BT_MCS_CMD_NEXT_TRACK);
+}
+
+unsigned int bt_mcp_previous_track(struct bt_mcp *mcp)
+{
+	if (!mcp)
+		return 0;
+
+	if (!(mcp->session.cp_op_supported & BT_MCS_CMD_PREV_TRACK_SUPPORTED))
+		return -ENOTSUP;
+
+	DBG(mcp, "mcp %p", mcp);
+
+	return mcp_send(mcp, BT_MCS_CMD_PREV_TRACK);
+}
+
 static void mcp_mp_set_player_name(struct bt_mcp *mcp, const uint8_t *value,
 					uint16_t length)
 {
-	struct event_callback *cb = mcp->cb;
+	struct event_callback *cb;
+
+	if (!mcp)
+		return;
+
+	cb = mcp->cb;
 
 	if (cb && cb->cbs && cb->cbs->player_name)
 		cb->cbs->player_name(mcp, value, length);
@@ -640,7 +680,12 @@ static void mcp_mp_set_player_name(struct bt_mcp *mcp, const uint8_t *value,
 static void mcp_mp_set_track_title(struct bt_mcp *mcp, const uint8_t *value,
 					uint16_t length)
 {
-	struct event_callback *cb = mcp->cb;
+	struct event_callback *cb;
+
+	if (!mcp)
+		return;
+
+	cb = mcp->cb;
 
 	if (cb && cb->cbs && cb->cbs->track_title)
 		cb->cbs->track_title(mcp, value, length);
@@ -648,7 +693,12 @@ static void mcp_mp_set_track_title(struct bt_mcp *mcp, const uint8_t *value,
 
 static void mcp_mp_set_title_duration(struct bt_mcp *mcp, int32_t duration)
 {
-	struct event_callback *cb = mcp->cb;
+	struct event_callback *cb;
+
+	if (!mcp)
+		return;
+
+	cb = mcp->cb;
 
 	DBG(mcp, "Track Duration 0x%08x", duration);
 
@@ -658,7 +708,12 @@ static void mcp_mp_set_title_duration(struct bt_mcp *mcp, int32_t duration)
 
 static void mcp_mp_set_title_position(struct bt_mcp *mcp, int32_t position)
 {
-	struct event_callback *cb = mcp->cb;
+	struct event_callback *cb;
+
+	if (!mcp)
+		return;
+
+	cb = mcp->cb;
 
 	DBG(mcp, "Track Position 0x%08x", position);
 
@@ -668,7 +723,12 @@ static void mcp_mp_set_title_position(struct bt_mcp *mcp, int32_t position)
 
 static void mcp_mp_set_media_state(struct bt_mcp *mcp, uint8_t state)
 {
-	struct event_callback *cb = mcp->cb;
+	struct event_callback *cb;
+
+	if (!mcp)
+		return;
+
+	cb = mcp->cb;
 
 	DBG(mcp, "Media State 0x%02x", state);
 
@@ -1292,6 +1352,9 @@ void bt_mcp_set_event_callbacks(struct bt_mcp *mcp,
 {
 	struct event_callback *cb;
 
+	if (!mcp)
+		return;
+
 	if (mcp->cb)
 		free(mcp->cb);
 
@@ -1377,6 +1440,9 @@ done:
 
 void bt_mcp_register(struct gatt_db *db)
 {
+	if (!db)
+		return;
+
 	mcp_db_new(db);
 }
 
@@ -1384,6 +1450,9 @@ bool bt_mcp_attach(struct bt_mcp *mcp, struct bt_gatt_client *client)
 {
 	bt_uuid_t uuid;
 
+	if (!mcp)
+		return false;
+
 	DBG(mcp, "mcp %p", mcp);
 
 	mcp->client = bt_gatt_client_clone(client);
@@ -1412,6 +1481,9 @@ bool bt_mcp_attach(struct bt_mcp *mcp, struct bt_gatt_client *client)
 
 void bt_mcp_detach(struct bt_mcp *mcp)
 {
+	if (!mcp)
+		return;
+
 	DBG(mcp, "%p", mcp);
 
 	bt_gatt_client_unref(mcp->client);
diff --git a/src/shared/mcp.h b/src/shared/mcp.h
index a2cd6fc..ee57ed4 100644
--- a/src/shared/mcp.h
+++ b/src/shared/mcp.h
@@ -59,3 +59,5 @@ void *bt_mcp_get_user_data(struct bt_mcp *mcp);
 unsigned int bt_mcp_play(struct bt_mcp *mcp);
 unsigned int bt_mcp_pause(struct bt_mcp *mcp);
 unsigned int bt_mcp_stop(struct bt_mcp *mcp);
+unsigned int bt_mcp_next_track(struct bt_mcp *mcp);
+unsigned int bt_mcp_previous_track(struct bt_mcp *mcp);
diff --git a/src/shared/micp.c b/src/shared/micp.c
new file mode 100644
index 0000000..1c34e9d
--- /dev/null
+++ b/src/shared/micp.c
@@ -0,0 +1,894 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  NXP Semiconductors. All rights reserved.
+ *
+ */
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+#include "src/shared/timeout.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/gatt-helpers.h"
+#include "src/shared/micp.h"
+
+#define DBG(_micp, fmt, arg...) \
+	micp_debug(_micp, "%s:%s() " fmt, __FILE__, __func__, ##arg)
+
+/* Application error codes */
+#define MICP_ERROR_MUTE_DISABLED            0x80
+#define MICP_ERROR_VALUE_NOT_ALLOWED        0x13
+#define BT_ATT_ERROR_OPCODE_NOT_SUPPORTED   0x81
+
+/* Mute char values */
+#define MICS_NOT_MUTED  0x00
+#define MICS_MUTED      0x01
+#define MICS_DISABLED   0x02
+
+static struct queue *micp_db;
+static struct queue *micp_cbs;
+static struct queue *sessions;
+
+struct bt_micp_cb {
+	unsigned int id;
+	bt_micp_func_t attached;
+	bt_micp_func_t detached;
+	void *user_data;
+};
+
+typedef void (*micp_func_t)(struct bt_micp *micp, bool success,
+				uint8_t att_ecode, const uint8_t *value,
+				uint16_t length, void *user_data);
+
+struct bt_micp_pending {
+	unsigned int id;
+	struct bt_micp *micp;
+	micp_func_t func;
+	void *userdata;
+};
+
+struct bt_micp_ready {
+	unsigned int id;
+	bt_micp_ready_func_t func;
+	bt_micp_destroy_func_t destroy;
+	void *data;
+};
+
+typedef void (*micp_notify_t)(struct bt_micp *micp, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data);
+
+struct bt_micp_notify {
+	unsigned int id;
+	struct bt_micp *micp;
+	micp_notify_t func;
+	void *user_data;
+};
+
+static void *iov_pull_mem(struct iovec *iov, size_t len)
+{
+	void *data = iov->iov_base;
+
+	if (iov->iov_len < len)
+		return NULL;
+
+	iov->iov_base += len;
+	iov->iov_len -= len;
+
+	return data;
+}
+
+static struct bt_micp_db *micp_get_mdb(struct bt_micp *micp)
+{
+	if (!micp)
+		return NULL;
+
+	if (micp->ldb)
+		return micp->ldb;
+
+	return NULL;
+}
+
+static uint8_t *mdb_get_mute_state(struct bt_micp_db *vdb)
+{
+	if (!vdb->mics)
+		return NULL;
+
+	return &(vdb->mics->mute_stat);
+}
+
+struct bt_mics *micp_get_mics(struct bt_micp *micp)
+{
+	if (!micp)
+		return NULL;
+
+	if (micp->rdb->mics)
+		return micp->rdb->mics;
+
+	micp->rdb->mics = new0(struct bt_mics, 1);
+	micp->rdb->mics->mdb = micp->rdb;
+
+	return micp->rdb->mics;
+}
+
+static void micp_detached(void *data, void *user_data)
+{
+	struct bt_micp_cb *cb = data;
+	struct bt_micp *micp = user_data;
+
+	cb->detached(micp, cb->user_data);
+}
+
+void bt_micp_detach(struct bt_micp *micp)
+{
+	if (!queue_remove(sessions, micp))
+		return;
+
+	bt_gatt_client_idle_unregister(micp->client, micp->idle_id);
+	bt_gatt_client_unref(micp->client);
+	micp->client = NULL;
+
+	queue_foreach(micp_cbs, micp_detached, micp);
+}
+
+static void micp_db_free(void *data)
+{
+	struct bt_micp_db *mdb = data;
+
+	if (!mdb)
+		return;
+
+	gatt_db_unref(mdb->db);
+
+	free(mdb->mics);
+	free(mdb);
+}
+
+static void micp_ready_free(void *data)
+{
+	struct bt_micp_ready *ready = data;
+
+	if (ready->destroy)
+		ready->destroy(ready->data);
+
+	free(ready);
+}
+
+static void micp_free(void *data)
+{
+	struct bt_micp *micp = data;
+
+	bt_micp_detach(micp);
+
+	micp_db_free(micp->rdb);
+
+	queue_destroy(micp->notify, free);
+	queue_destroy(micp->pending, NULL);
+	queue_destroy(micp->ready_cbs, micp_ready_free);
+
+	free(micp);
+}
+
+bool bt_micp_set_user_data(struct bt_micp *micp, void *user_data)
+{
+
+	if (!micp)
+		return false;
+
+	micp->user_data = user_data;
+
+	return true;
+}
+
+static bool micp_db_match(const void *data, const void *match_data)
+{
+	const struct bt_micp_db *mdb = data;
+	const struct gatt_db *db = match_data;
+
+	return (mdb->db == db);
+}
+
+struct bt_att *bt_micp_get_att(struct bt_micp *micp)
+{
+	if (!micp)
+		return NULL;
+
+	if (micp->att)
+		return micp->att;
+
+	return bt_gatt_client_get_att(micp->client);
+}
+
+struct bt_micp *bt_micp_ref(struct bt_micp *micp)
+{
+	if (!micp)
+		return NULL;
+
+	__sync_fetch_and_add(&micp->ref_count, 1);
+
+	return micp;
+}
+
+void bt_micp_unref(struct bt_micp *micp)
+{
+	if (!micp)
+		return;
+
+	if (__sync_sub_and_fetch(&micp->ref_count, 1))
+		return;
+
+	micp_free(micp);
+}
+
+static void micp_debug(struct bt_micp *micp, const char *format, ...)
+{
+	va_list ap;
+
+	if (!micp || !format || !micp->debug_func)
+		return;
+
+	va_start(ap, format);
+	util_debug_va(micp->debug_func, micp->debug_data, format, ap);
+	va_end(ap);
+}
+
+static void micp_disconnected(int err, void *user_data)
+{
+	struct bt_micp *micp = user_data;
+
+	DBG(micp, "micp %p disconnected err %d", micp, err);
+
+	bt_micp_detach(micp);
+}
+
+static struct bt_micp *micp_get_session(struct bt_att *att, struct gatt_db *db)
+{
+	const struct queue_entry *entry;
+	struct bt_micp *micp;
+
+	for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
+		struct bt_micp *micp = entry->data;
+
+		if (att == bt_micp_get_att(micp))
+			return micp;
+	}
+
+	micp = bt_micp_new(db, NULL);
+	micp->att = att;
+
+	bt_att_register_disconnect(att, micp_disconnected, micp, NULL);
+
+	bt_micp_attach(micp, NULL);
+
+	return micp;
+}
+
+static void mics_mute_read(struct gatt_db_attribute *attrib,
+			unsigned int id, uint16_t offset,
+			uint8_t opcode, struct bt_att *att,
+			void *user_data)
+{
+	struct bt_mics *mics = user_data;
+	struct iovec iov;
+
+	iov.iov_base = &mics->mute_stat;
+	iov.iov_len = sizeof(mics->mute_stat);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+								  iov.iov_len);
+}
+
+static uint8_t mics_not_muted(struct bt_mics *mics, struct bt_micp *micp,
+							  struct iovec *iov)
+{
+	struct bt_micp_db *mdb;
+	uint8_t *mute_state;
+
+	DBG(micp, "Mute state OP: Not Muted");
+
+	mdb = micp_get_mdb(micp);
+	if (!mdb) {
+		DBG(micp, "error: MDB not available");
+		return 0;
+	}
+
+	mute_state = mdb_get_mute_state(mdb);
+	if (!mute_state) {
+		DBG(micp, "Error : Mute State not available");
+		return 0;
+	}
+
+	*mute_state = MICS_NOT_MUTED;
+
+	gatt_db_attribute_notify(mdb->mics->ms, (void *)mute_state,
+				sizeof(uint8_t), bt_micp_get_att(micp));
+
+	return 0;
+}
+
+static uint8_t mics_muted(struct bt_mics *mics, struct bt_micp *micp,
+						  struct iovec *iov)
+{
+	struct bt_micp_db *mdb;
+	uint8_t *mute_state;
+
+	DBG(micp, "Mute state OP: Muted");
+
+	mdb = micp_get_mdb(micp);
+	if (!mdb) {
+		DBG(micp, "error: MDB not available");
+		return 0;
+	}
+
+	mute_state = mdb_get_mute_state(mdb);
+
+	*mute_state = MICS_MUTED;
+
+	gatt_db_attribute_notify(mdb->mics->ms, (void *)mute_state,
+				sizeof(uint8_t), bt_micp_get_att(micp));
+
+	return 0;
+}
+
+#define MICS_OP(_str, _op, _size, _func) \
+	{                                    \
+		.str = _str,                     \
+		.op = _op,                       \
+		.size = _size,                   \
+		.func = _func,                   \
+	}
+
+struct mics_op_handler {
+	const char *str;
+	uint8_t op;
+	size_t size;
+	uint8_t (*func)(struct bt_mics *mics, struct bt_micp *micp,
+					struct iovec *iov);
+} micp_handlers[] = {
+	MICS_OP("Not Muted", MICS_NOT_MUTED,
+			sizeof(uint8_t), mics_not_muted),
+	MICS_OP("Muted", MICS_MUTED,
+			sizeof(uint8_t), mics_muted),
+	{}};
+
+static void mics_mute_write(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 bt_mics *mics = user_data;
+	struct bt_micp *micp = micp_get_session(att, mics->mdb->db);
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = len,
+	};
+	uint8_t *micp_op, *mute_state;
+	struct mics_op_handler *handler;
+	uint8_t ret = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+	struct bt_micp_db *mdb;
+
+	DBG(micp, "MICS Mute Char write: len: %ld: %ld", len, iov.iov_len);
+
+	if (offset) {
+		DBG(micp, "invalid offset: %d", offset);
+		ret = BT_ATT_ERROR_INVALID_OFFSET;
+		goto respond;
+	}
+
+	if (len < sizeof(*micp_op)) {
+		DBG(micp, "invalid length: %ld < %ld sizeof(param)", len,
+			sizeof(*micp_op));
+		ret = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto respond;
+	}
+
+	micp_op = iov_pull_mem(&iov, sizeof(*micp_op));
+	if (!micp_op) {
+		DBG(micp, "iov_pull_mem() returned NULL");
+		goto respond;
+	}
+
+	if ((*micp_op == MICS_DISABLED) || (*micp_op != MICS_NOT_MUTED
+		&& *micp_op != MICS_MUTED)) {
+		DBG(micp, "Invalid operation - MICS DISABLED/RFU mics op:%d",
+					micp_op);
+		ret = MICP_ERROR_VALUE_NOT_ALLOWED;
+		goto respond;
+	}
+
+	mdb = micp_get_mdb(micp);
+	if (!mdb) {
+		DBG(micp, "error: MDB not available");
+		goto respond;
+	}
+
+	mute_state = mdb_get_mute_state(mdb);
+	if (*mute_state == MICS_DISABLED) {
+		DBG(micp, "state: MICS DISABLED , can not write value: %d",
+				*micp_op);
+		ret = MICP_ERROR_MUTE_DISABLED;
+		goto respond;
+	}
+
+	for (handler = micp_handlers; handler && handler->str; handler++) {
+		DBG(micp, "handler->op: %d micp_op: %d iov.iov_len: %ld",
+					handler->op, *micp_op, iov.iov_len);
+		if (handler->op != *micp_op)
+			continue;
+
+		if (len < handler->size) {
+			DBG(micp, "invalid len %ld : %ld < %ld handler->size",
+			len, iov.iov_len, handler->size);
+			ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+			goto respond;
+		}
+
+		break;
+	}
+
+	if (handler && handler->str) {
+		DBG(micp, "%s", handler->str);
+
+		ret = handler->func(mics, micp, &iov);
+	} else {
+		DBG(micp, "unknown opcode 0x%02x", *micp_op);
+		ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+	}
+
+respond:
+	gatt_db_attribute_write_result(attrib, id, ret);
+}
+
+static struct bt_mics *mics_new(struct gatt_db *db)
+{
+	struct bt_mics *mics;
+	bt_uuid_t uuid;
+
+	if (!db)
+		return NULL;
+
+	mics = new0(struct bt_mics, 1);
+
+	mics->mute_stat = MICS_MUTED;
+
+	/* Populate DB with MICS attributes */
+	bt_uuid16_create(&uuid, MICS_UUID);
+	mics->service = gatt_db_add_service(db, &uuid, true, 4);
+
+	bt_uuid16_create(&uuid, MUTE_CHRC_UUID);
+	mics->ms = gatt_db_service_add_characteristic(mics->service,
+				&uuid,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+				BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE
+				| BT_GATT_CHRC_PROP_NOTIFY,
+				mics_mute_read, mics_mute_write,
+				mics);
+
+	mics->ms_ccc = gatt_db_service_add_ccc(mics->service,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	gatt_db_service_set_active(mics->service, true);
+
+	return mics;
+}
+
+static struct bt_micp_db *micp_db_new(struct gatt_db *db)
+{
+	struct bt_micp_db *mdb;
+
+	if (!db)
+		return NULL;
+
+	mdb = new0(struct bt_micp_db, 1);
+	mdb->db = gatt_db_ref(db);
+
+	if (!micp_db)
+		micp_db = queue_new();
+
+	mdb->mics = mics_new(db);
+	mdb->mics->mdb = mdb;
+
+	queue_push_tail(micp_db, mdb);
+
+	return mdb;
+}
+
+static struct bt_micp_db *micp_get_db(struct gatt_db *db)
+{
+	struct bt_micp_db *mdb;
+
+	mdb = queue_find(micp_db, micp_db_match, db);
+	if (mdb)
+		return mdb;
+
+	return micp_db_new(db);
+}
+
+void bt_micp_add_db(struct gatt_db *db)
+{
+	micp_db_new(db);
+}
+
+bool bt_micp_set_debug(struct bt_micp *micp, bt_micp_debug_func_t func,
+			void *user_data, bt_micp_destroy_func_t destroy)
+{
+	if (!micp)
+		return false;
+
+	if (micp->debug_destroy)
+		micp->debug_destroy(micp->debug_data);
+
+	micp->debug_func = func;
+	micp->debug_destroy = destroy;
+	micp->debug_data = user_data;
+
+	return true;
+}
+
+unsigned int bt_micp_register(bt_micp_func_t attached, bt_micp_func_t detached,
+							  void *user_data)
+{
+	struct bt_micp_cb *cb;
+	static unsigned int id;
+
+	if (!attached && !detached)
+		return 0;
+
+	if (!micp_cbs)
+		micp_cbs = queue_new();
+
+	cb = new0(struct bt_micp_cb, 1);
+	cb->id = ++id ? id : ++id;
+	cb->attached = attached;
+	cb->detached = detached;
+	cb->user_data = user_data;
+
+	queue_push_tail(micp_cbs, cb);
+
+	return cb->id;
+}
+
+static bool match_id(const void *data, const void *match_data)
+{
+	const struct bt_micp_cb *cb = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (cb->id == id);
+}
+
+bool bt_micp_unregister(unsigned int id)
+{
+	struct bt_micp_cb *cb;
+
+	cb = queue_remove_if(micp_cbs, match_id, UINT_TO_PTR(id));
+	if (!cb)
+		return false;
+
+	free(cb);
+
+	return true;
+}
+
+struct bt_micp *bt_micp_new(struct gatt_db *ldb, struct gatt_db *rdb)
+{
+	struct bt_micp *micp;
+	struct bt_micp_db *mdb;
+
+	if (!ldb)
+		return NULL;
+
+	mdb = micp_get_db(ldb);
+	if (!mdb)
+		return NULL;
+
+	micp = new0(struct bt_micp, 1);
+	micp->ldb = mdb;
+	micp->pending = queue_new();
+	micp->ready_cbs = queue_new();
+	micp->notify = queue_new();
+
+	if (!rdb)
+		goto done;
+
+	mdb = new0(struct bt_micp_db, 1);
+	mdb->db = gatt_db_ref(rdb);
+
+	micp->rdb = mdb;
+
+done:
+	bt_micp_ref(micp);
+
+	return micp;
+}
+
+static void micp_pending_destroy(void *data)
+{
+	struct bt_micp_pending *pending = data;
+	struct bt_micp *micp = pending->micp;
+
+	if (queue_remove_if(micp->pending, NULL, pending))
+		free(pending);
+}
+
+static void micp_pending_complete(bool success, uint8_t att_ecode,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct bt_micp_pending *pending = user_data;
+
+	if (pending->func)
+		pending->func(pending->micp, success, att_ecode, value, length,
+					  pending->userdata);
+}
+
+static void micp_read_value(struct bt_micp *micp, uint16_t value_handle,
+				micp_func_t func, void *user_data)
+{
+	struct bt_micp_pending *pending;
+
+	pending = new0(struct bt_micp_pending, 1);
+	pending->micp = micp;
+	pending->func = func;
+	pending->userdata = user_data;
+
+	pending->id = bt_gatt_client_read_value(micp->client, value_handle,
+					micp_pending_complete, pending,
+					micp_pending_destroy);
+
+	if (!pending->id) {
+		DBG(micp, "unable to send read request");
+		free(pending);
+		return;
+	}
+
+	queue_push_tail(micp->pending, pending);
+}
+
+static void micp_register(uint16_t att_ecode, void *user_data)
+{
+	struct bt_micp_notify *notify = user_data;
+
+	if (att_ecode)
+		DBG(notify->micp, "MICP register failed 0x%04x", att_ecode);
+}
+
+static void micp_notify(uint16_t value_handle, const uint8_t *value,
+				uint16_t length, void *user_data)
+{
+	struct bt_micp_notify *notify = user_data;
+
+	if (notify->func)
+		notify->func(notify->micp, value_handle, value, length,
+					 notify->user_data);
+}
+
+static void micp_notify_destroy(void *data)
+{
+	struct bt_micp_notify *notify = data;
+	struct bt_micp *micp = notify->micp;
+
+	if (queue_remove_if(micp->notify, NULL, notify))
+		free(notify);
+}
+
+static unsigned int micp_register_notify(struct bt_micp *micp,
+					uint16_t value_handle,
+					micp_notify_t func,
+					void *user_data)
+{
+	struct bt_micp_notify *notify;
+
+	notify = new0(struct bt_micp_notify, 1);
+	notify->micp = micp;
+	notify->func = func;
+	notify->user_data = user_data;
+
+	notify->id = bt_gatt_client_register_notify(micp->client,
+					value_handle, micp_register,
+					micp_notify, notify,
+					micp_notify_destroy);
+	if (!notify->id) {
+		DBG(micp, "Unable to register for notifications");
+		free(notify);
+		return 0;
+	}
+
+	queue_push_tail(micp->notify, notify);
+
+	return notify->id;
+}
+
+static void micp_mute_state_notify(struct bt_micp *micp, uint16_t value_handle,
+					const uint8_t *value, uint16_t length,
+					void *user_data)
+{
+	uint8_t mute_state;
+
+	memcpy(&mute_state, value, sizeof(mute_state));
+
+	DBG(micp, "Mute state: 0x%x", mute_state);
+}
+
+static void read_mute_state(struct bt_micp *micp, bool success,
+					uint8_t att_ecode, const uint8_t *value,
+					uint16_t length, void *user_data)
+{
+	uint8_t *mute_state;
+	struct iovec iov = {
+		.iov_base = (void *)value,
+		.iov_len = length,
+	};
+
+	if (!success) {
+		DBG(micp, "Unable to read Mute state: error 0x%02x", att_ecode);
+		return;
+	}
+
+	mute_state = iov_pull_mem(&iov, sizeof(uint8_t));
+	if (mute_state == NULL) {
+		DBG(micp, "Unable to get Mute state");
+		return;
+	}
+
+	DBG(micp, "Mute state: %x", *mute_state);
+}
+
+static void foreach_mics_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_micp *micp = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_mute;
+	struct bt_mics *mics;
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+			NULL, NULL, &uuid))
+		return;
+
+	bt_uuid16_create(&uuid_mute, MUTE_CHRC_UUID);
+	if (!bt_uuid_cmp(&uuid, &uuid_mute)) {
+		DBG(micp, "MICS Mute characteristic found: handle 0x%04x",
+				value_handle);
+
+		mics = micp_get_mics(micp);
+		if (!mics || mics->ms)
+			return;
+
+		mics->ms = attr;
+
+		micp_read_value(micp, value_handle, read_mute_state, micp);
+
+		micp->mute_id = micp_register_notify(micp, value_handle,
+						micp_mute_state_notify, NULL);
+	}
+}
+
+static void foreach_mics_service(struct gatt_db_attribute *attr,
+					void *user_data)
+{
+	struct bt_micp *micp = user_data;
+	struct bt_mics *mics = micp_get_mics(micp);
+
+	mics->service = attr;
+
+	gatt_db_service_set_claimed(attr, true);
+	gatt_db_service_foreach_char(attr, foreach_mics_char, micp);
+}
+
+unsigned int bt_micp_ready_register(struct bt_micp *micp,
+				bt_micp_ready_func_t func, void *user_data,
+				bt_micp_destroy_func_t destroy)
+{
+	struct bt_micp_ready *ready;
+	static unsigned int id;
+
+	DBG(micp, "bt_micp_ready_register_Entry\n");
+	if (!micp)
+		return 0;
+
+	ready = new0(struct bt_micp_ready, 1);
+	ready->id = ++id ? id : ++id;
+	ready->func = func;
+	ready->destroy = destroy;
+	ready->data = user_data;
+
+	queue_push_tail(micp->ready_cbs, ready);
+
+	return ready->id;
+}
+
+static bool match_ready_id(const void *data, const void *match_data)
+{
+	const struct bt_micp_ready *ready = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (ready->id == id);
+}
+
+bool bt_micp_ready_unregister(struct bt_micp *micp, unsigned int id)
+{
+	struct bt_micp_ready *ready;
+
+	ready = queue_remove_if(micp->ready_cbs, match_ready_id,
+						UINT_TO_PTR(id));
+	if (!ready)
+		return false;
+
+	micp_ready_free(ready);
+
+	return true;
+}
+
+static struct bt_micp *bt_micp_ref_safe(struct bt_micp *micp)
+{
+	if (!micp || !micp->ref_count)
+		return NULL;
+
+	return bt_micp_ref(micp);
+}
+
+static void micp_notify_ready(struct bt_micp *micp)
+{
+	const struct queue_entry *entry;
+
+	if (!bt_micp_ref_safe(micp))
+		return;
+
+	for (entry = queue_get_entries(micp->ready_cbs); entry;
+							entry = entry->next) {
+		struct bt_micp_ready *ready = entry->data;
+
+		ready->func(micp, ready->data);
+	}
+
+	bt_micp_unref(micp);
+}
+
+static void micp_idle(void *data)
+{
+	struct bt_micp *micp = data;
+
+	micp->idle_id = 0;
+	micp_notify_ready(micp);
+}
+
+bool bt_micp_attach(struct bt_micp *micp, struct bt_gatt_client *client)
+{
+	bt_uuid_t uuid;
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, micp);
+
+	if (!client)
+		return true;
+
+	if (micp->client)
+		return false;
+
+	micp->client = bt_gatt_client_clone(client);
+	if (!micp->client)
+		return false;
+
+	bt_gatt_client_idle_register(micp->client, micp_idle, micp, NULL);
+
+	bt_uuid16_create(&uuid, MICS_UUID);
+	gatt_db_foreach_service(micp->ldb->db, &uuid, foreach_mics_service,
+						micp);
+	return true;
+}
diff --git a/src/shared/micp.h b/src/shared/micp.h
new file mode 100644
index 0000000..c881ade
--- /dev/null
+++ b/src/shared/micp.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  NXP Semiconductors. All rights reserved.
+ *
+ */
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "src/shared/io.h"
+#include "src/shared/gatt-client.h"
+
+struct bt_mics;
+struct bt_micp;
+
+typedef void (*bt_micp_ready_func_t)(struct bt_micp *micp, void *user_data);
+typedef void (*bt_micp_destroy_func_t)(void *user_data);
+typedef void (*bt_micp_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_micp_func_t)(struct bt_micp *micp, void *user_data);
+
+struct bt_micp_db {
+	struct gatt_db *db;
+	struct bt_mics *mics;
+};
+
+struct bt_mics {
+	struct bt_micp_db *mdb;
+	uint8_t mute_stat;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *ms;
+	struct gatt_db_attribute *ms_ccc;
+};
+
+struct bt_micp {
+	int ref_count;
+	struct bt_micp_db *ldb;
+	struct bt_micp_db *rdb;
+	struct bt_gatt_client *client;
+	struct bt_att *att;
+	unsigned int mute_id;
+
+	unsigned int idle_id;
+	uint8_t mute;
+
+	struct queue *notify;
+	struct queue *pending;
+	struct queue *ready_cbs;
+
+	bt_micp_debug_func_t debug_func;
+	bt_micp_destroy_func_t debug_destroy;
+
+	void *debug_data;
+	void *user_data;
+};
+
+struct bt_micp *bt_micp_ref(struct bt_micp *micp);
+void bt_micp_unref(struct bt_micp *micp);
+
+void bt_micp_add_db(struct gatt_db *db);
+
+bool bt_micp_attach(struct bt_micp *micp, struct bt_gatt_client *client);
+void bt_micp_detach(struct bt_micp *micp);
+
+bool bt_micp_set_debug(struct bt_micp *micp, bt_micp_debug_func_t func,
+		void *user_data, bt_micp_destroy_func_t destroy);
+
+struct bt_att *bt_micp_get_att(struct bt_micp *micp);
+
+bool bt_micp_set_user_data(struct bt_micp *micp, void *user_data);
+
+/* session related functions */
+unsigned int bt_micp_register(bt_micp_func_t attached, bt_micp_func_t detached,
+					void *user_data);
+unsigned int bt_micp_ready_register(struct bt_micp *micp,
+				bt_micp_ready_func_t func, void *user_data,
+				bt_micp_destroy_func_t destroy);
+bool bt_micp_ready_unregister(struct bt_micp *micp, unsigned int id);
+
+bool bt_micp_unregister(unsigned int id);
+struct bt_micp *bt_micp_new(struct gatt_db *ldb, struct gatt_db *rdb);
+struct bt_mics *micp_get_mics(struct bt_micp *micp);
diff --git a/src/shared/ringbuf.c b/src/shared/ringbuf.c
index 3dc7ed7..1b7adbb 100644
--- a/src/shared/ringbuf.c
+++ b/src/shared/ringbuf.c
@@ -237,7 +237,7 @@ int ringbuf_vprintf(struct ringbuf *ringbuf, const char *format, va_list ap)
 		ringbuf->in_tracing(ringbuf->buffer + offset, end,
 							ringbuf->in_data);
 
-	if (len - end > 0) {
+	if ((size_t) len > end) {
 		/* Put the remainder of string at the beginning */
 		memcpy(ringbuf->buffer, str + end, len - end);
 
diff --git a/src/shared/shell.c b/src/shared/shell.c
index 0639c78..a8fa876 100644
--- a/src/shared/shell.c
+++ b/src/shared/shell.c
@@ -4,7 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2017  Intel Corporation. All rights reserved.
- *
+ *  Copyright 2024 NXP
  *
  */
 
@@ -24,6 +24,7 @@
 #include <sys/signalfd.h>
 #include <wordexp.h>
 #include <getopt.h>
+#include <fcntl.h>
 
 #include <readline/readline.h>
 #include <readline/history.h>
@@ -59,6 +60,11 @@ struct bt_shell_prompt_input {
 	void *user_data;
 };
 
+struct input {
+	struct io *io;
+	FILE *f;
+};
+
 static struct {
 	bool init;
 	char *name;
@@ -69,7 +75,11 @@ static struct {
 	bool zsh;
 	bool monitor;
 	int timeout;
-	struct io *input;
+	int init_fd;
+	struct queue *inputs;
+
+	char *line;
+	struct queue *queue;
 
 	bool saved_prompt;
 	bt_shell_prompt_input_func saved_func;
@@ -252,6 +262,162 @@ static void cmd_export(int argc, char *argv[])
 	}
 }
 
+static int bt_shell_queue_exec(char *line)
+{
+	int err;
+
+	/* Ignore comments */
+	if (line[0] == '#')
+		return 0;
+
+	/* Queue if already executing */
+	if (data.line) {
+		/* Check if prompt is being held then release using the line */
+		if (!bt_shell_release_prompt(line)) {
+			bt_shell_printf("%s\n", line);
+			return 0;
+		}
+
+		queue_push_tail(data.queue, strdup(line));
+		return 0;
+	}
+
+	bt_shell_printf("%s\n", line);
+
+	err = bt_shell_exec(line);
+	if (!err)
+		data.line = strdup(line);
+
+	return err;
+}
+
+static bool bt_shell_input_line(struct input *input)
+{
+	int fd;
+	char *line = NULL;
+	size_t len = 0;
+	ssize_t nread;
+
+	fd = io_get_fd(input->io);
+
+	if (fd < 0) {
+		printf("io_get_fd() returned %d\n", fd);
+		return false;
+	}
+
+	if (fd == STDIN_FILENO) {
+		rl_callback_read_char();
+		return true;
+	}
+
+	if (!input->f) {
+		input->f = fdopen(fd, "r");
+		if (!input->f) {
+			printf("fdopen: %s (%d)\n", strerror(errno), errno);
+			return false;
+		}
+	}
+
+	nread = getline(&line, &len, input->f);
+	if (nread > 0) {
+		int err;
+
+		if (line[nread - 1] == '\n')
+			line[nread - 1] = '\0';
+
+		err = bt_shell_queue_exec(line);
+		if (err < 0)
+			printf("%s: %s (%d)\n", line, strerror(-err), -err);
+	} else if (input->f) {
+		fclose(input->f);
+		input->f = NULL;
+	}
+
+	free(line);
+
+	return input->f ? true : false;
+}
+
+static bool input_read(struct io *io, void *user_data)
+{
+	return bt_shell_input_line(user_data);
+}
+
+static bool input_hup(struct io *io, void *user_data)
+{
+	if (queue_remove(data.inputs, user_data)) {
+		if (!queue_isempty(data.inputs))
+			return false;
+	}
+
+	mainloop_quit();
+
+	return false;
+}
+
+static struct input *input_new(int fd)
+{
+	struct input *input;
+	struct io *io;
+
+	io = io_new(fd);
+	if (!io)
+		return false;
+
+	input = new0(struct input, 1);
+	input->io = io;
+
+	queue_push_tail(data.inputs, input);
+
+	return input;
+}
+
+static bool bt_shell_input_attach(int fd)
+{
+	struct input *input;
+	struct queue *queue;
+
+	input = input_new(fd);
+	if (!input)
+		return false;
+
+	/* Save executing queue so input lines can be placed in the correct
+	 * order.
+	 */
+	queue = data.queue;
+	data.queue = queue_new();
+
+	while (bt_shell_input_line(input));
+
+	/* Push existing input lines back into the executing queue */
+	while (!queue_isempty(queue))
+		queue_push_tail(data.queue, queue_pop_head(queue));
+
+	queue_destroy(queue, free);
+
+	return true;
+}
+
+static void cmd_script(int argc, char *argv[])
+{
+	int fd;
+
+	fd = open(argv[1], O_RDONLY);
+	if (fd < 0) {
+		printf("Unable to open %s: %s (%d)\n", argv[1],
+						strerror(errno), errno);
+		bt_shell_noninteractive_quit(EXIT_FAILURE);
+		return;
+	}
+
+	printf("Running script %s...\n", argv[1]);
+
+	if (!bt_shell_input_attach(fd))
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
 static const struct bt_shell_menu_entry default_menu[] = {
 	{ "back",         NULL,       cmd_back, "Return to main menu", NULL,
 							NULL, cmd_back_exists },
@@ -265,6 +431,7 @@ static const struct bt_shell_menu_entry default_menu[] = {
 					"Display help about this program" },
 	{ "export",       NULL,       cmd_export,
 						"Print environment variables" },
+	{ "script",       "<filename>", cmd_script, "Run script" },
 	{ }
 };
 
@@ -535,7 +702,7 @@ void bt_shell_printf(const char *fmt, ...)
 	char *saved_line;
 	int saved_point;
 
-	if (!data.input)
+	if (queue_isempty(data.inputs))
 		return;
 
 	if (data.mode) {
@@ -552,8 +719,7 @@ void bt_shell_printf(const char *fmt, ...)
 		saved_line = rl_copy_text(0, rl_end);
 		if (!data.saved_prompt)
 			rl_save_prompt();
-		rl_replace_line("", 0);
-		rl_redisplay();
+		rl_reset_line_state();
 	}
 
 	va_start(args, fmt);
@@ -571,11 +737,29 @@ void bt_shell_printf(const char *fmt, ...)
 			rl_restore_prompt();
 		rl_replace_line(saved_line, 0);
 		rl_point = saved_point;
-		rl_forced_update_display();
+		rl_redisplay();
 		free(saved_line);
 	}
 }
 
+void bt_shell_echo(const char *fmt, ...)
+{
+	va_list args;
+	char *str;
+	int ret;
+
+	va_start(args, fmt);
+	ret = vasprintf(&str, fmt, args);
+	va_end(args);
+
+	if (ret < 0)
+		return;
+
+	rl_save_prompt();
+	bt_shell_set_prompt(str, COLOR_HIGHLIGHT);
+	rl_restore_prompt();
+}
+
 static void print_string(const char *str, void *user_data)
 {
 	bt_shell_printf("%s\n", str);
@@ -586,7 +770,7 @@ void bt_shell_hexdump(const unsigned char *buf, size_t len)
 	util_hexdump(' ', buf, len, print_string, NULL);
 }
 
-void bt_shell_usage()
+void bt_shell_usage(void)
 {
 	if (!data.exec)
 		return;
@@ -595,6 +779,40 @@ void bt_shell_usage()
 					data.exec->arg ? data.exec->arg : "");
 }
 
+static void bt_shell_dequeue_exec(void)
+{
+	int err;
+
+	if (!data.line)
+		return;
+
+	free(data.line);
+	data.line = NULL;
+
+	data.line = queue_pop_head(data.queue);
+	if (!data.line)
+		return;
+
+	bt_shell_printf("%s\n", data.line);
+
+	if (!bt_shell_release_prompt(data.line)) {
+		/* If a prompt was released with this line,
+		 * try to release all the other prompts,
+		 * if any are left. Otherwise, the next
+		 * line will be executed on
+		 * bt_shell_noninteractive_quit.
+		 */
+		if (data.saved_prompt)
+			bt_shell_dequeue_exec();
+
+		return;
+	}
+
+	err = bt_shell_exec(data.line);
+	if (err)
+		bt_shell_dequeue_exec();
+}
+
 static void prompt_input(const char *str, bt_shell_prompt_input_func func,
 							void *user_data)
 {
@@ -603,7 +821,7 @@ static void prompt_input(const char *str, bt_shell_prompt_input_func func,
 	data.saved_user_data = user_data;
 
 	rl_save_prompt();
-	bt_shell_set_prompt(str);
+	bt_shell_set_prompt(str, COLOR_HIGHLIGHT);
 }
 
 void bt_shell_prompt_input(const char *label, const char *msg,
@@ -641,6 +859,13 @@ void bt_shell_prompt_input(const char *label, const char *msg,
 	prompt_input(str, func, user_data);
 
 	free(str);
+
+	if (data.line && !queue_isempty(data.queue))
+		/* If a prompt was set to receive input and
+		 * data is already available, try to execute
+		 * the line and release the prompt.
+		 */
+		bt_shell_dequeue_exec();
 }
 
 static void prompt_free(void *data)
@@ -686,8 +911,6 @@ int bt_shell_release_prompt(const char *input)
 
 static void rl_handler(char *input)
 {
-	HIST_ENTRY *last;
-
 	if (!input) {
 		rl_insert_text("quit");
 		rl_redisplay();
@@ -696,20 +919,13 @@ static void rl_handler(char *input)
 		return;
 	}
 
-	if (!strlen(input))
+	/* Ignore empty/comment lines */
+	if (!strlen(input) || input[0] == '#')
 		goto done;
 
 	if (!bt_shell_release_prompt(input))
 		goto done;
 
-	last = history_get(history_length + history_base - 1);
-	/* append only if input is different from previous command */
-	if (!last || strcmp(input, last->line))
-		add_history(input);
-
-	if (data.monitor)
-		bt_log_printf(0xffff, data.name, LOG_INFO, "%s", input);
-
 	bt_shell_exec(input);
 
 done:
@@ -966,20 +1182,13 @@ static char **shell_completion(const char *text, int start, int end)
 	return matches;
 }
 
-static bool io_hup(struct io *io, void *user_data)
-{
-	mainloop_quit();
-
-	return false;
-}
-
 static void signal_callback(int signum, void *user_data)
 {
 	static bool terminated = false;
 
 	switch (signum) {
 	case SIGINT:
-		if (data.input && !data.mode) {
+		if (!queue_isempty(data.inputs) && !data.mode) {
 			rl_replace_line("", 0);
 			rl_crlf();
 			rl_on_new_line();
@@ -1071,6 +1280,7 @@ static void rl_init(void)
 static const struct option main_options[] = {
 	{ "version",	no_argument, 0, 'v' },
 	{ "help",	no_argument, 0, 'h' },
+	{ "init-script", required_argument, 0, 's' },
 	{ "timeout",	required_argument, 0, 't' },
 	{ "monitor",	no_argument, 0, 'm' },
 	{ "zsh-complete",	no_argument, 0, 'z' },
@@ -1092,6 +1302,7 @@ static void usage(int argc, char **argv, const struct bt_shell_opt *opt)
 	printf("\t--monitor \tEnable monitor output\n"
 		"\t--timeout \tTimeout in seconds for non-interactive mode\n"
 		"\t--version \tDisplay version\n"
+		"\t--init-script \tInit script file\n"
 		"\t--help \t\tDisplay help\n");
 }
 
@@ -1110,9 +1321,9 @@ void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt)
 	if (opt) {
 		memcpy(options + offset, opt->options,
 				sizeof(struct option) * opt->optno);
-		snprintf(optstr, sizeof(optstr), "+mhvt:%s", opt->optstr);
+		snprintf(optstr, sizeof(optstr), "+mhvs:t:%s", opt->optstr);
 	} else
-		snprintf(optstr, sizeof(optstr), "+mhvt:");
+		snprintf(optstr, sizeof(optstr), "+mhvs:t:");
 
 	data.name = strrchr(argv[0], '/');
 	if (!data.name)
@@ -1120,6 +1331,8 @@ void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt)
 	else
 		data.name = strdup(++data.name);
 
+	data.init_fd = -1;
+
 	while ((c = getopt_long(argc, argv, optstr, options, &index)) != -1) {
 		switch (c) {
 		case 'v':
@@ -1132,6 +1345,14 @@ void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt)
 			data.argv = &cmplt;
 			data.mode = 1;
 			goto done;
+		case 's':
+			if (optarg && data.init_fd < 0) {
+				data.init_fd = open(optarg, O_RDONLY);
+				if (data.init_fd < 0)
+					printf("Unable to open %s: %s (%d)\n",
+						optarg, strerror(errno), errno);
+			}
+			break;
 		case 't':
 			if (optarg)
 				data.timeout = strtol(optarg, &endptr, 0);
@@ -1157,13 +1378,15 @@ void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt)
 				}
 			}
 
-			if (c != opt->options[index - offset].val) {
-				usage(argc, argv, opt);
-				exit(EXIT_SUCCESS);
-				return;
-			}
+			if (opt && index >= 0 && (size_t)index >= offset) {
+				if (c != opt->options[index - offset].val) {
+					usage(argc, argv, opt);
+					exit(EXIT_SUCCESS);
+					return;
+				}
 
-			*opt->optarg[index - offset] = optarg ? : "";
+				*opt->optarg[index - offset] = optarg ? : "";
+			}
 		}
 
 		index = -1;
@@ -1185,6 +1408,8 @@ done:
 	rl_init();
 
 	data.init = true;
+	data.inputs = queue_new();
+	data.queue = queue_new();
 	data.prompts = queue_new();
 }
 
@@ -1221,14 +1446,35 @@ int bt_shell_run(void)
 
 int bt_shell_exec(const char *input)
 {
+	HIST_ENTRY *last;
 	wordexp_t w;
 	int err;
 
 	if (!input)
 		return 0;
 
-	if (wordexp(input, &w, WRDE_NOCMD))
-		return -ENOEXEC;
+	last = history_get(history_length + history_base - 1);
+	/* append only if input is different from previous command */
+	if (!last || strcmp(input, last->line))
+		add_history(input);
+
+	if (data.monitor)
+		bt_log_printf(0xffff, data.name, LOG_INFO, "%s", input);
+
+	err = wordexp(input, &w, WRDE_NOCMD);
+	switch (err) {
+	case WRDE_BADCHAR:
+		return -EBADMSG;
+	case WRDE_BADVAL:
+	case WRDE_SYNTAX:
+		return -EINVAL;
+	case WRDE_NOSPACE:
+		return -ENOMEM;
+	case WRDE_CMDSUB:
+		if (wordexp(input, &w, 0))
+			return -ENOEXEC;
+		break;
+	};
 
 	if (w.we_wordc == 0) {
 		wordfree(&w);
@@ -1242,6 +1488,17 @@ int bt_shell_exec(const char *input)
 	return err;
 }
 
+static void input_destroy(void *data)
+{
+	struct input *input = data;
+
+	if (input->f)
+		fclose(input->f);
+
+	io_destroy(input->io);
+	free(input);
+}
+
 void bt_shell_cleanup(void)
 {
 	bt_shell_release_prompt("");
@@ -1257,6 +1514,10 @@ void bt_shell_cleanup(void)
 
 	rl_cleanup();
 
+	queue_destroy(data.inputs, input_destroy);
+	data.inputs = NULL;
+	queue_destroy(data.queue, free);
+	data.queue = NULL;
 	queue_destroy(data.prompts, prompt_free);
 	data.prompts = NULL;
 
@@ -1274,8 +1535,10 @@ void bt_shell_quit(int status)
 
 void bt_shell_noninteractive_quit(int status)
 {
-	if (!data.mode || data.timeout)
+	if (!data.mode || data.timeout) {
+		bt_shell_dequeue_exec();
 		return;
+	}
 
 	bt_shell_quit(status);
 }
@@ -1309,19 +1572,26 @@ bool bt_shell_add_submenu(const struct bt_shell_menu *menu)
 	return true;
 }
 
-void bt_shell_set_prompt(const char *string)
+void bt_shell_set_prompt(const char *string, const char *color)
 {
+	char *prompt;
+
 	if (!data.init || data.mode)
 		return;
 
-	rl_set_prompt(string);
-	rl_redisplay();
-}
+	/* Envelope color within RL_PROMPT_START_IGNORE (\001) and
+	 * RL_PROMPT_END_IGNORE (\002) so readline can properly calculate the
+	 * prompt length.
+	 */
+	if (!color || asprintf(&prompt, "\001%s\002%s\001%s\002", color, string,
+				COLOR_OFF) < 0) {
+		rl_set_prompt(string);
+	} else {
+		rl_set_prompt(prompt);
+		free(prompt);
+	}
 
-static bool input_read(struct io *io, void *user_data)
-{
-	rl_callback_read_char();
-	return true;
+	rl_redisplay();
 }
 
 static bool shell_quit(void *data)
@@ -1333,21 +1603,17 @@ static bool shell_quit(void *data)
 
 bool bt_shell_attach(int fd)
 {
-	struct io *io;
+	struct input *input;
 
-	/* TODO: Allow more than one input? */
-	if (data.input)
+	input = input_new(fd);
+	if (!input)
 		return false;
 
-	io = io_new(fd);
-
 	if (!data.mode) {
-		io_set_read_handler(io, input_read, NULL, NULL);
-		io_set_disconnect_handler(io, io_hup, NULL, NULL);
+		io_set_read_handler(input->io, input_read, input, NULL);
+		io_set_disconnect_handler(input->io, input_hup, input, NULL);
 	}
 
-	data.input = io;
-
 	if (data.mode) {
 		if (shell_exec(data.argc, data.argv) < 0) {
 			bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -1357,6 +1623,12 @@ bool bt_shell_attach(int fd)
 		if (data.timeout)
 			timeout_add(data.timeout * 1000, shell_quit, NULL,
 								NULL);
+	} else if (data.init_fd >= 0) {
+		int fd = data.init_fd;
+
+		data.init_fd = -1;
+		if (!bt_shell_attach(fd))
+			return false;
 	}
 
 	return true;
@@ -1364,11 +1636,10 @@ bool bt_shell_attach(int fd)
 
 bool bt_shell_detach(void)
 {
-	if (!data.input)
+	if (queue_isempty(data.inputs))
 		return false;
 
-	io_destroy(data.input);
-	data.input = NULL;
+	queue_remove_all(data.inputs, NULL, NULL, input_destroy);
 
 	return true;
 }
@@ -1421,3 +1692,8 @@ void *bt_shell_get_env(const char *name)
 
 	return env->value;
 }
+
+int bt_shell_get_timeout(void)
+{
+	return data.timeout;
+}
diff --git a/src/shared/shell.h b/src/shared/shell.h
index 8baa285..e431db9 100644
--- a/src/shared/shell.h
+++ b/src/shared/shell.h
@@ -10,14 +10,14 @@
 #include <getopt.h>
 #include <stdbool.h>
 
-#define COLOR_OFF	"\001\x1B[0m\002"
-#define COLOR_RED	"\001\x1B[0;91m\002"
-#define COLOR_GREEN	"\001\x1B[0;92m\002"
-#define COLOR_YELLOW	"\001\x1B[0;93m\002"
-#define COLOR_BLUE	"\001\x1B[0;94m\002"
-#define COLOR_BOLDGRAY	"\001\x1B[1;30m\002"
-#define COLOR_BOLDWHITE	"\001\x1B[1;37m\002"
-#define COLOR_HIGHLIGHT	"\001\x1B[1;39m\002"
+#define COLOR_OFF	"\x1B[0m"
+#define COLOR_RED	"\x1B[0;91m"
+#define COLOR_GREEN	"\x1B[0;92m"
+#define COLOR_YELLOW	"\x1B[0;93m"
+#define COLOR_BLUE	"\x1B[0;94m"
+#define COLOR_BOLDGRAY	"\x1B[1;30m"
+#define COLOR_BOLDWHITE	"\x1B[1;37m"
+#define COLOR_HIGHLIGHT	"\x1B[1;39m"
 
 struct bt_shell_menu;
 
@@ -66,10 +66,12 @@ bool bt_shell_add_submenu(const struct bt_shell_menu *menu);
 
 bool bt_shell_remove_submenu(const struct bt_shell_menu *menu);
 
-void bt_shell_set_prompt(const char *string);
+void bt_shell_set_prompt(const char *string, const char *color);
 
 void bt_shell_printf(const char *fmt,
 				...) __attribute__((format(printf, 1, 2)));
+void bt_shell_echo(const char *fmt,
+				...) __attribute__((format(printf, 1, 2)));
 void bt_shell_hexdump(const unsigned char *buf, size_t len);
 void bt_shell_usage(void);
 
@@ -83,4 +85,6 @@ bool bt_shell_detach(void);
 void bt_shell_set_env(const char *name, void *value);
 void *bt_shell_get_env(const char *name);
 
+int bt_shell_get_timeout(void);
+
 void bt_shell_cleanup(void);
diff --git a/src/shared/tester.c b/src/shared/tester.c
index e88dfab..56c8cba 100644
--- a/src/shared/tester.c
+++ b/src/shared/tester.c
@@ -89,6 +89,7 @@ struct test_case {
 	tester_data_func_t test_func;
 	tester_data_func_t teardown_func;
 	tester_data_func_t post_teardown_func;
+	tester_data_func_t io_complete_func;
 	gdouble start_time;
 	gdouble end_time;
 	unsigned int timeout;
@@ -562,6 +563,38 @@ void tester_pre_setup_failed(void)
 	g_idle_add(done_callback, test);
 }
 
+void tester_pre_setup_abort(void)
+{
+	struct test_case *test;
+
+	if (!test_current)
+		return;
+
+	test = test_current->data;
+
+	if (test->stage != TEST_STAGE_PRE_SETUP)
+		return;
+
+	if (test->timeout_id > 0) {
+		timeout_remove(test->timeout_id);
+		test->timeout_id = 0;
+	}
+
+	print_progress(test->name, COLOR_YELLOW, "not run");
+
+	g_idle_add(done_callback, test);
+}
+
+bool tester_pre_setup_skip_by_default(void)
+{
+	if (!option_prefix && !option_string) {
+		tester_pre_setup_abort();
+		return true;
+	}
+
+	return false;
+}
+
 void tester_setup_complete(void)
 {
 	struct test_case *test;
@@ -621,6 +654,9 @@ static void test_result(enum test_result result)
 		test->timeout_id = 0;
 	}
 
+	if (test->result == TEST_RESULT_FAILED)
+		result = TEST_RESULT_FAILED;
+
 	test->result = result;
 	switch (result) {
 	case TEST_RESULT_PASSED:
@@ -913,6 +949,13 @@ static bool test_io_send(struct io *io, void *user_data)
 
 	g_assert_cmpint(len, ==, iov->iov_len);
 
+	if (!test->iovcnt && test->io_complete_func) {
+		test->io_complete_func(test->test_data);
+	} else if (test->iovcnt && !test->iov->iov_base) {
+		test_get_iov(test);
+		return test_io_send(io, user_data);
+	}
+
 	return false;
 }
 
@@ -937,10 +980,15 @@ static bool test_io_recv(struct io *io, void *user_data)
 
 	g_assert_cmpint(len, ==, iov->iov_len);
 
+	if (memcmp(buf, iov->iov_base, len))
+		tester_monitor('!', 0x0004, 0x0000, iov->iov_base, len);
+
 	g_assert(memcmp(buf, iov->iov_base, len) == 0);
 
 	if (test->iovcnt)
 		io_set_write_handler(io, test_io_send, NULL, NULL);
+	else if (test->io_complete_func)
+		test->io_complete_func(test->test_data);
 
 	return true;
 }
@@ -1004,6 +1052,13 @@ void tester_io_send(void)
 		io_set_write_handler(ios[1], test_io_send, NULL, NULL);
 }
 
+void tester_io_set_complete_func(tester_data_func_t func)
+{
+	struct test_case *test = tester_get_test();
+
+	test->io_complete_func = func;
+}
+
 int tester_run(void)
 {
 	int ret;
diff --git a/src/shared/tester.h b/src/shared/tester.h
index c28f61e..1f81384 100644
--- a/src/shared/tester.h
+++ b/src/shared/tester.h
@@ -21,6 +21,8 @@
 		.iov_len = sizeof(data(args)), \
 	}
 
+#define IOV_NULL {}
+
 void tester_init(int *argc, char ***argv);
 int tester_run(void);
 
@@ -57,6 +59,8 @@ void *tester_get_data(void);
 
 void tester_pre_setup_complete(void);
 void tester_pre_setup_failed(void);
+void tester_pre_setup_abort(void);
+bool tester_pre_setup_skip_by_default(void);
 
 void tester_setup_complete(void);
 void tester_setup_failed(void);
@@ -78,3 +82,4 @@ void tester_wait(unsigned int seconds, tester_wait_func_t func,
 
 struct io *tester_setup_io(const struct iovec *iov, int iovcnt);
 void tester_io_send(void);
+void tester_io_set_complete_func(tester_data_func_t func);
diff --git a/src/shared/uhid.c b/src/shared/uhid.c
index 1f15443..20bd267 100644
--- a/src/shared/uhid.c
+++ b/src/shared/uhid.c
@@ -26,11 +26,30 @@
 
 #define UHID_DEVICE_FILE "/dev/uhid"
 
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
+struct uhid_replay {
+	bool active;
+	struct queue *out;
+	struct queue *in;
+	struct queue *rout;
+	struct queue *rin;
+};
+
 struct bt_uhid {
 	int ref_count;
 	struct io *io;
 	unsigned int notify_id;
+	bool notifying;
 	struct queue *notify_list;
+	struct queue *input;
+	uint8_t type;
+	bool created;
+	unsigned int start_id;
+	bool started;
+	struct uhid_replay *replay;
 };
 
 struct uhid_notify {
@@ -38,8 +57,21 @@ struct uhid_notify {
 	uint32_t event;
 	bt_uhid_callback_t func;
 	void *user_data;
+	bool removed;
 };
 
+static void uhid_replay_free(struct uhid_replay *replay)
+{
+	if (!replay)
+		return;
+
+	queue_destroy(replay->rin, NULL);
+	queue_destroy(replay->in, free);
+	queue_destroy(replay->rout, NULL);
+	queue_destroy(replay->out, free);
+	free(replay);
+}
+
 static void uhid_free(struct bt_uhid *uhid)
 {
 	if (uhid->io)
@@ -48,6 +80,11 @@ static void uhid_free(struct bt_uhid *uhid)
 	if (uhid->notify_list)
 		queue_destroy(uhid->notify_list, free);
 
+	if (uhid->input)
+		queue_destroy(uhid->input, free);
+
+	uhid_replay_free(uhid->replay);
+
 	free(uhid);
 }
 
@@ -63,6 +100,64 @@ static void notify_handler(void *data, void *user_data)
 		notify->func(ev, notify->user_data);
 }
 
+static struct uhid_replay *uhid_replay_new(void)
+{
+	struct uhid_replay *replay = new0(struct uhid_replay, 1);
+
+	replay->out = queue_new();
+	replay->in = queue_new();
+
+	return replay;
+}
+
+static int bt_uhid_record(struct bt_uhid *uhid, bool input,
+					struct uhid_event *ev)
+{
+	if (!uhid)
+		return -EINVAL;
+
+	/* Capture input events in replay mode and send the next replay event */
+	if (uhid->replay && uhid->replay->active && input) {
+		queue_pop_head(uhid->replay->rin);
+		bt_uhid_replay(uhid);
+		return -EALREADY;
+	}
+
+	if (!uhid->replay)
+		uhid->replay = uhid_replay_new();
+
+	if (input)
+		queue_push_tail(uhid->replay->in,
+					util_memdup(ev, sizeof(*ev)));
+	else
+		queue_push_tail(uhid->replay->out,
+					util_memdup(ev, sizeof(*ev)));
+
+	return 0;
+}
+
+static bool match_removed(const void *a, const void *b)
+{
+	const struct uhid_notify *notify = a;
+
+	return notify->removed;
+}
+
+static void uhid_notify(struct bt_uhid *uhid, struct uhid_event *ev)
+{
+	/* Add a reference to the uhid to ensure it doesn't get freed while at
+	 * notify_handler.
+	 */
+	bt_uhid_ref(uhid);
+
+	uhid->notifying = true;
+	queue_foreach(uhid->notify_list, notify_handler, ev);
+	uhid->notifying = false;
+	queue_remove_all(uhid->notify_list, match_removed, NULL, free);
+
+	bt_uhid_unref(uhid);
+}
+
 static bool uhid_read_handler(struct io *io, void *user_data)
 {
 	struct bt_uhid *uhid = user_data;
@@ -83,7 +178,14 @@ static bool uhid_read_handler(struct io *io, void *user_data)
 	if ((size_t) len < sizeof(ev.type))
 		return false;
 
-	queue_foreach(uhid->notify_list, notify_handler, &ev);
+	switch (ev.type) {
+	case UHID_GET_REPORT:
+	case UHID_SET_REPORT:
+		bt_uhid_record(uhid, false, &ev);
+		break;
+	}
+
+	uhid_notify(uhid, &ev);
 
 	return true;
 }
@@ -169,7 +271,7 @@ unsigned int bt_uhid_register(struct bt_uhid *uhid, uint32_t event,
 		return 0;
 
 	notify = new0(struct uhid_notify, 1);
-	notify->id = uhid->notify_id++;
+	notify->id = ++uhid->notify_id ? uhid->notify_id : ++uhid->notify_id;
 	notify->event = event;
 	notify->func = func;
 	notify->user_data = user_data;
@@ -206,23 +308,47 @@ bool bt_uhid_unregister(struct bt_uhid *uhid, unsigned int id)
 	return true;
 }
 
+static bool match_not_id(const void *a, const void *b)
+{
+	const struct uhid_notify *notify = a;
+	unsigned int id = PTR_TO_UINT(b);
+
+	return notify->id != id;
+}
+
+static void uhid_notify_removed(void *data, void *user_data)
+{
+	struct uhid_notify *notify = data;
+	struct bt_uhid *uhid = user_data;
+
+	/* Skip marking start_id as removed since that is not removed with
+	 * unregister all.
+	 */
+	if (notify->id == uhid->start_id)
+		return;
+
+	notify->removed = true;
+}
+
 bool bt_uhid_unregister_all(struct bt_uhid *uhid)
 {
 	if (!uhid)
 		return false;
 
-	queue_remove_all(uhid->notify_list, NULL, NULL, free);
+	if (!uhid->notifying)
+		queue_remove_all(uhid->notify_list, match_not_id,
+				UINT_TO_PTR(uhid->start_id), free);
+	else
+		queue_foreach(uhid->notify_list, uhid_notify_removed, uhid);
+
 	return true;
 }
 
-int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
+static int uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
 {
 	ssize_t len;
 	struct iovec iov;
 
-	if (!uhid->io)
-		return -ENOTCONN;
-
 	iov.iov_base = (void *) ev;
 	iov.iov_len = sizeof(*ev);
 
@@ -233,3 +359,277 @@ int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
 	/* uHID kernel driver does not handle partial writes */
 	return len != sizeof(*ev) ? -EIO : 0;
 }
+
+int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
+{
+	if (!uhid || !ev)
+		return -EINVAL;
+
+	if (!uhid->io)
+		return -ENOTCONN;
+
+	return uhid_send(uhid, ev);
+}
+
+static bool input_dequeue(const void *data, const void *match_data)
+{
+	struct uhid_event *ev = (void *)data;
+	struct bt_uhid *uhid = (void *)match_data;
+
+	return bt_uhid_send(uhid, ev) == 0;
+}
+
+static void uhid_start(struct uhid_event *ev, void *user_data)
+{
+	struct bt_uhid *uhid = user_data;
+
+	uhid->started = true;
+
+	/* dequeue input events send while UHID_CREATE2 was in progress */
+	queue_remove_all(uhid->input, input_dequeue, uhid, free);
+}
+
+int bt_uhid_create(struct bt_uhid *uhid, const char *name, bdaddr_t *src,
+			bdaddr_t *dst, uint32_t vendor, uint32_t product,
+			uint32_t version, uint32_t country, uint8_t type,
+			void *rd_data, size_t rd_size)
+{
+	struct uhid_event ev;
+	int err;
+
+	if (!uhid || !name || rd_size > sizeof(ev.u.create2.rd_data))
+		return -EINVAL;
+
+	if (uhid->created)
+		return 0;
+
+	/* Register callback for UHID_START if not registered yet */
+	if (!uhid->start_id) {
+		uhid->start_id = bt_uhid_register(uhid, UHID_START, uhid_start,
+									uhid);
+		if (!uhid->start_id)
+			return -ENOMEM;
+	}
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_CREATE2;
+	strncpy((char *) ev.u.create2.name, name,
+			sizeof(ev.u.create2.name) - 1);
+	if (src)
+		sprintf((char *)ev.u.create2.phys,
+			"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+			src->b[5], src->b[4], src->b[3], src->b[2], src->b[1],
+			src->b[0]);
+	if (dst)
+		sprintf((char *)ev.u.create2.uniq,
+			"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+			dst->b[5], dst->b[4], dst->b[3], dst->b[2], dst->b[1],
+			dst->b[0]);
+	ev.u.create2.vendor = vendor;
+	ev.u.create2.product = product;
+	ev.u.create2.version = version;
+	ev.u.create2.country = country;
+	ev.u.create2.bus = BUS_BLUETOOTH;
+	if (rd_size)
+		memcpy(ev.u.create2.rd_data, rd_data, rd_size);
+	ev.u.create2.rd_size = rd_size;
+
+	err = bt_uhid_send(uhid, &ev);
+	if (err)
+		return err;
+
+	uhid->created = true;
+	uhid->started = false;
+	uhid->type = type;
+
+	return 0;
+}
+
+bool bt_uhid_created(struct bt_uhid *uhid)
+{
+	if (!uhid)
+		return false;
+
+	return uhid->created;
+}
+
+bool bt_uhid_started(struct bt_uhid *uhid)
+{
+	if (!uhid)
+		return false;
+
+	return uhid->started;
+}
+
+int bt_uhid_input(struct bt_uhid *uhid, uint8_t number, const void *data,
+			size_t size)
+{
+	struct uhid_event ev;
+	struct uhid_input2_req *req = &ev.u.input2;
+	size_t len = 0;
+
+	if (!uhid)
+		return -EINVAL;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_INPUT2;
+
+	if (number) {
+		req->data[len++] = number;
+		req->size = 1 + MIN(size, sizeof(req->data) - 1);
+	} else
+		req->size = MIN(size, sizeof(req->data));
+
+	if (data && size)
+		memcpy(&req->data[len], data, req->size - len);
+
+	/* Queue events if UHID_START has not been received yet */
+	if (!uhid->started) {
+		if (!uhid->input)
+			uhid->input = queue_new();
+
+		queue_push_tail(uhid->input, util_memdup(&ev, sizeof(ev)));
+		return 0;
+	}
+
+	return bt_uhid_send(uhid, &ev);
+}
+
+int bt_uhid_set_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t status)
+{
+	struct uhid_event ev;
+	struct uhid_set_report_reply_req *rsp = &ev.u.set_report_reply;
+
+	if (!uhid)
+		return false;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_SET_REPORT_REPLY;
+	rsp->id = id;
+	rsp->err = status;
+
+	if (bt_uhid_record(uhid, true, &ev) == -EALREADY)
+		return 0;
+
+	return bt_uhid_send(uhid, &ev);
+}
+
+int bt_uhid_get_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t number,
+				uint8_t status, const void *data, size_t size)
+{
+	struct uhid_event ev;
+	struct uhid_get_report_reply_req *rsp = &ev.u.get_report_reply;
+	size_t len = 0;
+
+	if (!uhid)
+		return false;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_GET_REPORT_REPLY;
+	rsp->id = id;
+	rsp->err = status;
+
+	if (!data || !size)
+		goto done;
+
+	if (number) {
+		rsp->data[len++] = number;
+		rsp->size += MIN(size, sizeof(rsp->data) - 1);
+	} else
+		rsp->size = MIN(size, sizeof(ev.u.input.data));
+
+	memcpy(&rsp->data[len], data, rsp->size - len);
+
+done:
+	if (bt_uhid_record(uhid, true, &ev) == -EALREADY)
+		return 0;
+
+	return bt_uhid_send(uhid, &ev);
+}
+
+int bt_uhid_destroy(struct bt_uhid *uhid, bool force)
+{
+	struct uhid_event ev;
+	int err;
+
+	if (!uhid)
+		return -EINVAL;
+
+	/* Cleanup input queue */
+	queue_destroy(uhid->input, free);
+	uhid->input = NULL;
+
+	/* Force destroy for non-keyboard devices - keyboards are not destroyed
+	 * on disconnect since they can glitch on reconnection losing
+	 * keypresses.
+	 */
+	if (!force && uhid->type != BT_UHID_KEYBOARD)
+		force = true;
+
+	if (!uhid->created || !force)
+		return 0;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_DESTROY;
+
+	err = bt_uhid_send(uhid, &ev);
+	if (err < 0)
+		return err;
+
+	uhid->created = false;
+	uhid_replay_free(uhid->replay);
+	uhid->replay = NULL;
+
+	return err;
+}
+
+static void queue_append(void *data, void *user_data)
+{
+	queue_push_tail(user_data, data);
+}
+
+static struct queue *queue_dup(struct queue *q)
+{
+	struct queue *dup;
+
+	if (!q || queue_isempty(q))
+		return NULL;
+
+	dup = queue_new();
+
+	queue_foreach(q, queue_append, dup);
+
+	return dup;
+}
+
+int bt_uhid_replay(struct bt_uhid *uhid)
+{
+	struct uhid_event *ev;
+
+	if (!uhid || !uhid->started)
+		return -EINVAL;
+
+	if (!uhid->replay)
+		return 0;
+
+	if (uhid->replay->active)
+		goto resend;
+
+	uhid->replay->active = true;
+	queue_destroy(uhid->replay->rin, NULL);
+	uhid->replay->rin = queue_dup(uhid->replay->in);
+
+	queue_destroy(uhid->replay->rout, NULL);
+	uhid->replay->rout = queue_dup(uhid->replay->out);
+
+resend:
+	ev = queue_pop_head(uhid->replay->rout);
+	if (!ev) {
+		uhid->replay->active = false;
+		return 0;
+	}
+
+	uhid_notify(uhid, ev);
+
+	return 0;
+}
diff --git a/src/shared/uhid.h b/src/shared/uhid.h
index 55ae839..e76a6e2 100644
--- a/src/shared/uhid.h
+++ b/src/shared/uhid.h
@@ -11,9 +11,35 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <linux/uhid.h>
+#include <bluetooth/bluetooth.h>
 
 struct bt_uhid;
 
+enum {
+	BT_UHID_NONE = 0,
+	BT_UHID_KEYBOARD,
+	BT_UHID_MOUSE,
+	BT_UHID_GAMING,
+	BT_UHID_TABLET
+};
+
+static inline uint8_t bt_uhid_icon_to_type(const char *icon)
+{
+	if (!icon)
+		return BT_UHID_NONE;
+
+	if (!strcmp(icon, "input-keyboard"))
+		return BT_UHID_KEYBOARD;
+	else if (!strcmp(icon, "input-mouse"))
+		return BT_UHID_MOUSE;
+	else if (!strcmp(icon, "input-gaming"))
+		return BT_UHID_GAMING;
+	else if (!strcmp(icon, "input-tablet"))
+		return BT_UHID_TABLET;
+	else
+		return BT_UHID_NONE;
+}
+
 struct bt_uhid *bt_uhid_new_default(void);
 struct bt_uhid *bt_uhid_new(int fd);
 
@@ -29,3 +55,16 @@ bool bt_uhid_unregister(struct bt_uhid *uhid, unsigned int id);
 bool bt_uhid_unregister_all(struct bt_uhid *uhid);
 
 int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev);
+int bt_uhid_create(struct bt_uhid *uhid, const char *name, bdaddr_t *src,
+			bdaddr_t *dst, uint32_t vendor, uint32_t product,
+			uint32_t version, uint32_t country, uint8_t type,
+			void *rd_data, size_t rd_size);
+bool bt_uhid_created(struct bt_uhid *uhid);
+bool bt_uhid_started(struct bt_uhid *uhid);
+int bt_uhid_input(struct bt_uhid *uhid, uint8_t number, const void *data,
+			size_t size);
+int bt_uhid_set_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t status);
+int bt_uhid_get_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t number,
+				uint8_t status, const void *data, size_t size);
+int bt_uhid_destroy(struct bt_uhid *uhid, bool force);
+int bt_uhid_replay(struct bt_uhid *uhid);
diff --git a/src/shared/util.c b/src/shared/util.c
index 0a0308c..6e7634a 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2012-2014  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -28,6 +29,13 @@
 #include <sys/random.h>
 #endif
 
+#include <lib/bluetooth.h>
+
+/* define MAX_INPUT for musl */
+#ifndef MAX_INPUT
+#define MAX_INPUT _POSIX_MAX_INPUT
+#endif
+
 #include "src/shared/util.h"
 
 void *util_malloc(size_t size)
@@ -130,6 +138,148 @@ void util_hexdump(const char dir, const unsigned char *buf, size_t len,
 	}
 }
 
+/* Helper to print debug information of bitfields */
+uint64_t util_debug_bit(const char *label, uint64_t val,
+				const struct util_bit_debugger *table,
+				util_debug_func_t function, void *user_data)
+{
+	uint64_t mask = val;
+	int i;
+
+	for (i = 0; table[i].str; i++) {
+		if (val & (((uint64_t) 1) << table[i].bit)) {
+			util_debug(function, user_data, "%s%s", label,
+							table[i].str);
+			mask &= ~(((uint64_t) 1) << table[i].bit);
+		}
+	}
+
+	return mask;
+}
+
+static const struct util_ltv_debugger*
+ltv_debugger(const struct util_ltv_debugger *debugger, size_t num, uint8_t type)
+{
+	size_t i;
+
+	if (!debugger || !num)
+		return NULL;
+
+	for (i = 0; i < num; i++) {
+		const struct util_ltv_debugger *debug = &debugger[i];
+
+		if (debug->type == type)
+			return debug;
+	}
+
+	return NULL;
+}
+
+/* Helper to itertate over LTV entries */
+bool util_ltv_foreach(const uint8_t *data, uint8_t len, uint8_t *type,
+			util_ltv_func_t func, void *user_data)
+{
+	struct iovec iov;
+	int i;
+
+	if (!func || !data)
+		return false;
+
+	iov.iov_base = (void *) data;
+	iov.iov_len = len;
+
+	for (i = 0; iov.iov_len; i++) {
+		uint8_t l, t, *v;
+
+		if (!util_iov_pull_u8(&iov, &l))
+			return false;
+
+		if (!l) {
+			func(i, l, 0, NULL, user_data);
+			continue;
+		}
+
+		if (!util_iov_pull_u8(&iov, &t))
+			return false;
+
+		l--;
+
+		if (l) {
+			v = util_iov_pull_mem(&iov, l);
+			if (!v)
+				return false;
+		} else
+			v = NULL;
+
+		if (!type || *type == t)
+			func(i, l, t, v, user_data);
+	}
+
+	return true;
+}
+
+/* Helper to add l,t,v data in an iovec struct */
+void util_ltv_push(struct iovec *output, uint8_t l, uint8_t t, void *v)
+{
+	output->iov_base = realloc(output->iov_base, output->iov_len + l + 2);
+	util_iov_push_u8(output, l + 1);
+	util_iov_push_u8(output, t);
+	util_iov_push_mem(output, l, v);
+}
+
+/* Helper to print debug information of LTV entries */
+bool util_debug_ltv(const uint8_t *data, uint8_t len,
+			const struct util_ltv_debugger *debugger, size_t num,
+			util_debug_func_t function, void *user_data)
+{
+	struct iovec iov;
+	int i;
+
+	iov.iov_base = (void *) data;
+	iov.iov_len = len;
+
+	for (i = 0; iov.iov_len; i++) {
+		uint8_t l, t, *v;
+		const struct util_ltv_debugger *debug;
+
+		if (!util_iov_pull_u8(&iov, &l)) {
+			util_debug(function, user_data,
+					"Unable to pull length");
+			return false;
+		}
+
+		if (!l) {
+			util_debug(function, user_data, "#%d: len 0x%02x",
+					i, l);
+			continue;
+		}
+
+		if (!util_iov_pull_u8(&iov, &t)) {
+			util_debug(function, user_data, "Unable to pull type");
+			return false;
+		}
+
+		util_debug(function, user_data, "#%d: len 0x%02x type 0x%02x",
+					i, l, t);
+
+		l--;
+
+		v = util_iov_pull_mem(&iov, l);
+		if (!v) {
+			util_debug(function, user_data, "Unable to pull value");
+			return false;
+		}
+
+		debug = ltv_debugger(debugger, num, t);
+		if (debug)
+			debug->func(v, l, function, user_data);
+		else
+			util_hexdump(' ', (void *)v, l, function, user_data);
+	}
+
+	return true;
+}
+
 /* Helper for getting the dirent type in case readdir returns DT_UNKNOWN */
 unsigned char util_get_dt(const char *parent, const char *name)
 {
@@ -189,6 +339,351 @@ void util_clear_uid(uint64_t *bitmap, uint8_t id)
 	*bitmap &= ~(((uint64_t)1) << (id - 1));
 }
 
+struct iovec *util_iov_dup(const struct iovec *iov, size_t cnt)
+{
+	struct iovec *dup;
+	size_t i;
+
+	if (!iov)
+		return NULL;
+
+	dup = new0(struct iovec, cnt);
+
+	for (i = 0; i < cnt; i++)
+		util_iov_memcpy(&dup[i], iov[i].iov_base, iov[i].iov_len);
+
+	return dup;
+}
+
+int util_iov_memcmp(const struct iovec *iov1, const struct iovec *iov2)
+{
+	if (!iov1)
+		return 1;
+
+	if (!iov2)
+		return -1;
+
+	if (iov1->iov_len != iov2->iov_len)
+		return iov1->iov_len - iov2->iov_len;
+
+	return memcmp(iov1->iov_base, iov2->iov_base, iov1->iov_len);
+}
+
+void util_iov_memcpy(struct iovec *iov, void *src, size_t len)
+{
+	if (!iov || !src || !len)
+		return;
+
+	iov->iov_base = realloc(iov->iov_base, len);
+	iov->iov_len = len;
+	memcpy(iov->iov_base, src, len);
+}
+
+void util_iov_free(struct iovec *iov, size_t cnt)
+{
+	size_t i;
+
+	if (!iov)
+		return;
+
+	for (i = 0; i < cnt; i++)
+		free(iov[i].iov_base);
+
+	free(iov);
+}
+
+void *util_iov_push(struct iovec *iov, size_t len)
+{
+	void *data;
+
+	if (!iov)
+		return NULL;
+
+	data = iov->iov_base + iov->iov_len;
+	iov->iov_len += len;
+
+	return data;
+}
+
+void *util_iov_push_mem(struct iovec *iov, size_t len, const void *data)
+{
+	void *p;
+
+	p = util_iov_push(iov, len);
+	if (!p)
+		return NULL;
+
+	if (data)
+		memcpy(p, data, len);
+
+	return p;
+}
+
+void *util_iov_push_le64(struct iovec *iov, uint64_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_le64(val, p);
+
+	return p;
+}
+
+void *util_iov_push_be64(struct iovec *iov, uint64_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_be64(val, p);
+
+	return p;
+}
+
+void *util_iov_push_le32(struct iovec *iov, uint32_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_le32(val, p);
+
+	return p;
+}
+
+void *util_iov_push_be32(struct iovec *iov, uint32_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_be32(val, p);
+
+	return p;
+}
+
+void *util_iov_push_le24(struct iovec *iov, uint32_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(uint24_t));
+	if (!p)
+		return NULL;
+
+	put_le24(val, p);
+
+	return p;
+}
+
+void *util_iov_push_be24(struct iovec *iov, uint32_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(uint24_t));
+	if (!p)
+		return NULL;
+
+	put_le24(val, p);
+
+	return p;
+}
+
+void *util_iov_push_le16(struct iovec *iov, uint16_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_le16(val, p);
+
+	return p;
+}
+
+void *util_iov_push_be16(struct iovec *iov, uint16_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_be16(val, p);
+
+	return p;
+}
+
+void *util_iov_push_u8(struct iovec *iov, uint8_t val)
+{
+	void *p;
+
+	p = util_iov_push(iov, sizeof(val));
+	if (!p)
+		return NULL;
+
+	put_u8(val, p);
+
+	return p;
+}
+
+void *util_iov_append(struct iovec *iov, const void *data, size_t len)
+{
+	iov->iov_base = realloc(iov->iov_base, iov->iov_len + len);
+	return util_iov_push_mem(iov, len, data);
+}
+
+struct iovec *util_iov_new(void *data, size_t len)
+{
+	struct iovec *iov;
+
+	iov = new0(struct iovec, 1);
+	util_iov_append(iov, data, len);
+
+	return iov;
+}
+
+void *util_iov_pull(struct iovec *iov, size_t len)
+{
+	if (!iov)
+		return NULL;
+
+	if (iov->iov_len < len)
+		return NULL;
+
+	iov->iov_base += len;
+	iov->iov_len -= len;
+
+	return iov->iov_base;
+}
+
+void *util_iov_pull_mem(struct iovec *iov, size_t len)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, len))
+		return data;
+
+	return NULL;
+}
+
+void *util_iov_pull_le64(struct iovec *iov, uint64_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_le64(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_be64(struct iovec *iov, uint64_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_be64(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_le32(struct iovec *iov, uint32_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_le32(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_be32(struct iovec *iov, uint32_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_be32(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_le24(struct iovec *iov, uint32_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(uint24_t))) {
+		*val = get_le24(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_be24(struct iovec *iov, uint32_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(uint24_t))) {
+		*val = get_be24(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_le16(struct iovec *iov, uint16_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_le16(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_be16(struct iovec *iov, uint16_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_be16(data);
+		return data;
+	}
+
+	return NULL;
+}
+
+void *util_iov_pull_u8(struct iovec *iov, uint8_t *val)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, sizeof(*val))) {
+		*val = get_u8(data);
+		return data;
+	}
+
+	return NULL;
+}
+
 static const struct {
 	uint16_t uuid;
 	const char *str;
@@ -344,7 +839,12 @@ static const struct {
 	{ 0x1850, "Published Audio Capabilities"		},
 	{ 0x1851, "Basic Audio Announcement"			},
 	{ 0x1852, "Broadcast Audio Announcement"		},
-	/* 0x1853 to 0x27ff undefined */
+	{ 0x1853, "Common Audio"				},
+	{ 0x1854, "Hearing Aid"					},
+	{ 0x1855, "Telephony and Media Audio"			},
+	{ 0x1856, "Public Broadcast Announcement"		},
+	{ 0x1858, "Gaming Audio"				},
+	/* 0x1857 to 0x27ff undefined */
 	{ 0x2800, "Primary Service"				},
 	{ 0x2801, "Secondary Service"				},
 	{ 0x2802, "Include"					},
@@ -578,6 +1078,7 @@ static const struct {
 	{ 0x2b29, "Client Supported Features"			},
 	{ 0x2b2A, "Database Hash"				},
 	{ 0x2b3a, "Server Supported Features"			},
+	{ 0x2b51, "Telephony and Media Audio Profile Role"	},
 	{ 0x2b77, "Audio Input State"				},
 	{ 0x2b78, "Gain Settings Attribute"			},
 	{ 0x2b79, "Audio Input Type"				},
@@ -592,6 +1093,9 @@ static const struct {
 	{ 0x2b82, "Volume Offset Control Point"			},
 	{ 0x2b83, "Audio Output Description"			},
 	{ 0x2b84, "Set Identity Resolving Key"			},
+	{ 0x2b85, "Coordinated Set Size"			},
+	{ 0x2b86, "Set Member Lock"				},
+	{ 0x2b87, "Set Member Rank"				},
 	{ 0x2b93, "Media Player Name"				},
 	{ 0x2b94, "Media Player Icon Object ID"			},
 	{ 0x2b95, "Media Player Icon URL"			},
@@ -645,6 +1149,14 @@ static const struct {
 	{ 0x2bcc, "Source Audio Locations"			},
 	{ 0x2bcd, "Available Audio Contexts"			},
 	{ 0x2bce, "Supported Audio Contexts"			},
+	{ 0x2bda, "Hearing Aid Features"			},
+	{ 0x2bdb, "Hearing Aid Preset Control Point"		},
+	{ 0x2bdc, "Active Preset Index"				},
+	{ 0x2c00, "GMAP Role"					},
+	{ 0x2c01, "UGG Features"				},
+	{ 0x2c02, "UGT Features"				},
+	{ 0x2c03, "BGS Features"				},
+	{ 0x2c03, "BGR Features"				},
 	/* vendor defined */
 	{ 0xfeff, "GN Netcom"					},
 	{ 0xfefe, "GN ReSound A/S"				},
@@ -1064,9 +1576,23 @@ static const struct {
 	{ 0xfd60, "Sercomm Corporation"				},
 	{ 0xfd5f, "Oculus VR, LLC"				},
 	/* SDO defined */
-	{ 0xfffc, "AirFuel Alliance"				},
-	{ 0xfffe, "Alliance for Wireless Power (A4WP)"		},
-	{ 0xfffd, "Fast IDentity Online Alliance (FIDO)"	},
+	{ 0xfccc, "Wi-Fi Easy Connect Specification"		},
+	{ 0xffef, "Wi-Fi Direct Specification"			},
+	{ 0xfff0, "Public Key Open Credential (PKOC)"		},
+	{ 0xfff1, "ICCE Digital Key"				},
+	{ 0xfff2, "Aliro"					},
+	{ 0xfff3, "FiRa Consortium"				},
+	{ 0xfff4, "FiRa Consortium"				},
+	{ 0xfff5, "Car Connectivity Consortium, LLC"		},
+	{ 0xfff6, "Matter Profile ID"				},
+	{ 0xfff7, "Zigbee Direct"				},
+	{ 0xfff8, "Mopria Alliance BLE"				},
+	{ 0xfff9, "FIDO2 Secure Client-To-Authenticator Transport" },
+	{ 0xfffa, "ASTM Remote ID"				},
+	{ 0xfffb, "Direct Thread Commissioning"			},
+	{ 0xfffc, "Wireless Power Transfer (WPT)"		},
+	{ 0xfffd, "Universal Second Factor Authenticator"	},
+	{ 0xfffe, "Wireless Power Transfer"			},
 	{ }
 };
 
@@ -1151,6 +1677,8 @@ static const struct {
 	{ "a6695ace-ee7f-4fb9-881a-5fac66c629af", "BlueZ Offload Codecs"},
 	{ "6fbaf188-05e0-496a-9885-d6ddfdb4e03e",
 		"BlueZ Experimental ISO Socket"},
+	{ "69518c4c-b69f-4679-8bc1-c021b47b5733",
+		"BlueZ Experimental Poll Errqueue"},
 	{ }
 };
 
@@ -1357,3 +1885,65 @@ int strsuffix(const char *str, const char *suffix)
 
 	return strncmp(str + len - suffix_len, suffix, suffix_len);
 }
+
+char *strstrip(char *str)
+{
+	size_t size;
+	char *end;
+
+	if (!str)
+		return NULL;
+
+	size = strlen(str);
+	if (!size)
+		return str;
+
+	end = str + size - 1;
+	while (end >= str && isspace(*end))
+		end--;
+	*(end + 1) = '\0';
+
+	while (*str && isspace(*str))
+		str++;
+
+	return str;
+}
+
+bool strisutf8(const char *str, size_t len)
+{
+	size_t i = 0;
+
+	while (i < len) {
+		unsigned char c = str[i];
+		size_t size = 0;
+
+		/* Check the first byte to determine the number of bytes in the
+		 * UTF-8 character.
+		 */
+		if ((c & 0x80) == 0x00)
+			size = 1;
+		else if ((c & 0xE0) == 0xC0)
+			size = 2;
+		else if ((c & 0xF0) == 0xE0)
+			size = 3;
+		else if ((c & 0xF8) == 0xF0)
+			size = 4;
+		else
+			/* Invalid UTF-8 sequence */
+			return false;
+
+		/* Check the following bytes to ensure they have the correct
+		 * format.
+		 */
+		for (size_t j = 1; j < size; ++j) {
+			if (i + j > len || (str[i + j] & 0xC0) != 0x80)
+				/* Invalid UTF-8 sequence */
+				return false;
+		}
+
+		/* Move to the next character */
+		i += size;
+	}
+
+	return true;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 554481e..f2ca4f2 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2012-2014  Intel Corporation. All rights reserved.
+ *  Copyright 2023-2024 NXP
  *
  *
  */
@@ -11,10 +12,12 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <alloca.h>
 #include <byteswap.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/uio.h>
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 #define BIT(n)  (1 << (n))
@@ -82,10 +85,12 @@ do {						\
 	}))
 
 #define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
-#define malloc0(n) (calloc((n), 1))
+#define malloc0(n) (calloc(1, (n)))
 
 char *strdelimit(char *str, char *del, char c);
 int strsuffix(const char *str, const char *suffix);
+char *strstrip(char *str);
+bool strisutf8(const char *str, size_t length);
 
 void *util_malloc(size_t size);
 void *util_memdup(const void *src, size_t size);
@@ -102,6 +107,45 @@ void util_debug(util_debug_func_t function, void *user_data,
 void util_hexdump(const char dir, const unsigned char *buf, size_t len,
 				util_debug_func_t function, void *user_data);
 
+#define UTIL_BIT_DEBUG(_bit, _str) \
+{ \
+	.bit = _bit, \
+	.str = _str, \
+}
+
+struct util_bit_debugger {
+	uint64_t bit;
+	const char *str;
+};
+
+uint64_t util_debug_bit(const char *label, uint64_t val,
+				const struct util_bit_debugger *table,
+				util_debug_func_t func, void *user_data);
+
+#define UTIL_LTV_DEBUG(_type, _func) \
+{ \
+	.type = _type, \
+	.func = _func, \
+}
+
+struct util_ltv_debugger {
+	uint8_t  type;
+	void (*func)(const uint8_t *data, uint8_t len,
+			util_debug_func_t func, void *user_data);
+};
+
+void util_ltv_push(struct iovec *output, uint8_t l, uint8_t t, void *v);
+
+bool util_debug_ltv(const uint8_t *data, uint8_t len,
+			const struct util_ltv_debugger *debugger, size_t num,
+			util_debug_func_t function, void *user_data);
+
+typedef void (*util_ltv_func_t)(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data);
+
+bool util_ltv_foreach(const uint8_t *data, uint8_t len, uint8_t *type,
+			util_ltv_func_t func, void *user_data);
+
 unsigned char util_get_dt(const char *parent, const char *name);
 
 ssize_t util_getrandom(void *buf, size_t buflen, unsigned int flags);
@@ -109,6 +153,43 @@ ssize_t util_getrandom(void *buf, size_t buflen, unsigned int flags);
 uint8_t util_get_uid(uint64_t *bitmap, uint8_t max);
 void util_clear_uid(uint64_t *bitmap, uint8_t id);
 
+#define util_data(args...) ((const unsigned char[]) { args })
+
+#define UTIL_IOV_INIT(args...) \
+{ \
+	.iov_base = (void *)util_data(args), \
+	.iov_len = sizeof(util_data(args)), \
+}
+
+struct iovec *util_iov_dup(const struct iovec *iov, size_t cnt);
+int util_iov_memcmp(const struct iovec *iov1, const struct iovec *iov2);
+void util_iov_memcpy(struct iovec *iov, void *src, size_t len);
+void *util_iov_push(struct iovec *iov, size_t len);
+void *util_iov_push_mem(struct iovec *iov, size_t len, const void *data);
+void *util_iov_push_le64(struct iovec *iov, uint64_t val);
+void *util_iov_push_be64(struct iovec *iov, uint64_t val);
+void *util_iov_push_le32(struct iovec *iov, uint32_t val);
+void *util_iov_push_be32(struct iovec *iov, uint32_t val);
+void *util_iov_push_le24(struct iovec *iov, uint32_t val);
+void *util_iov_push_be24(struct iovec *iov, uint32_t val);
+void *util_iov_push_le16(struct iovec *iov, uint16_t val);
+void *util_iov_push_be16(struct iovec *iov, uint16_t val);
+void *util_iov_push_u8(struct iovec *iov, uint8_t val);
+void *util_iov_append(struct iovec *iov, const void *data, size_t len);
+struct iovec *util_iov_new(void *data, size_t len);
+void *util_iov_pull(struct iovec *iov, size_t len);
+void *util_iov_pull_mem(struct iovec *iov, size_t len);
+void *util_iov_pull_le64(struct iovec *iov, uint64_t *val);
+void *util_iov_pull_be64(struct iovec *iov, uint64_t *val);
+void *util_iov_pull_le32(struct iovec *iov, uint32_t *val);
+void *util_iov_pull_be32(struct iovec *iov, uint32_t *val);
+void *util_iov_pull_le24(struct iovec *iov, uint32_t *val);
+void *util_iov_pull_be24(struct iovec *iov, uint32_t *val);
+void *util_iov_pull_le16(struct iovec *iov, uint16_t *val);
+void *util_iov_pull_be16(struct iovec *iov, uint16_t *val);
+void *util_iov_pull_u8(struct iovec *iov, uint8_t *val);
+void util_iov_free(struct iovec *iov, size_t cnt);
+
 const char *bt_uuid16_to_str(uint16_t uuid);
 const char *bt_uuid32_to_str(uint32_t uuid);
 const char *bt_uuid128_to_str(const uint8_t uuid[16]);
@@ -169,6 +250,11 @@ static inline uint64_t get_be64(const void *ptr)
 	return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
 }
 
+static inline void put_u8(uint8_t val, void *dst)
+{
+	put_unaligned(val, (uint8_t *) dst);
+}
+
 static inline void put_le16(uint16_t val, void *dst)
 {
 	put_unaligned(cpu_to_le16(val), (uint16_t *) dst);
diff --git a/src/shared/vcp.c b/src/shared/vcp.c
index 5459cf8..cfc4266 100644
--- a/src/shared/vcp.c
+++ b/src/shared/vcp.c
@@ -32,13 +32,93 @@
 
 #define VCP_STEP_SIZE 1
 
+#define VOCS_VOL_OFFSET_UPPER_LIMIT	 255
+#define VOCS_VOL_OFFSET_LOWER_LIMIT	-255
+
 /* Apllication Error Code */
 #define BT_ATT_ERROR_INVALID_CHANGE_COUNTER	0x80
 #define BT_ATT_ERROR_OPCODE_NOT_SUPPORTED	0x81
+#define BT_ATT_ERROR_VALUE_OUT_OF_RANGE		0x82
+#define BT_ATT_AICS_ERROR_VALUE_OUT_OF_RANGE	0x83
+#define BT_ATT_AICS_ERROR_MUTE_DISABLED			0x82
+#define BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED	0x84
+
+#define BT_VCP_NA                   BIT(0)
+#define BT_VCP_FRONT_LEFT           BIT(1)
+#define BT_VCP_FRONT_RIGHT          BIT(2)
+#define BT_VCP_FRONT_CENTER         BIT(3)
+#define BT_VCP_LOW_FRQ_EFF_1        BIT(4)
+#define BT_VCP_BACK_LEFT            BIT(5)
+#define BT_VCP_BACK_RIGHT           BIT(6)
+#define BT_VCP_FRONT_LEFT_CENTER    BIT(7)
+#define BT_VCP_FRONT_RIGHT_CENTER   BIT(8)
+#define BT_VCP_BACK_CENTER          BIT(9)
+#define BT_VCP_LOW_FRQ_EFF_2        BIT(10)
+#define BT_VCP_SIDE_LEFT            BIT(11)
+#define BT_VCP_SIDE_RIGHT           BIT(12)
+#define BT_VCP_TOP_FRONT_LEFT       BIT(13)
+#define BT_VCP_TOP_FRONT_RIGHT      BIT(14)
+#define BT_VCP_TOP_FRONT_CENTER     BIT(15)
+#define BT_VCP_TOP_CENTER           BIT(16)
+#define BT_VCP_TOP_BACK_LEFT        BIT(17)
+#define BT_VCP_TOP_BACK_RIGHT       BIT(18)
+#define BT_VCP_TOP_SIDE_LEFT        BIT(19)
+#define BT_VCP_TOP_SIDE_RIGHT       BIT(20)
+#define BT_VCP_TOP_BACK_CENTER      BIT(21)
+#define BT_VCP_BOTTOM_FRONT_CENTER  BIT(22)
+#define BT_VCP_BOTTOM_FRONT_LEFT    BIT(23)
+#define BT_VCP_BOTTOM_FRONT_RIGHT   BIT(24)
+#define BT_VCP_FRONT_LEFT_WIDE      BIT(25)
+#define BT_VCP_FRONT_RIGHT_WIDE     BIT(26)
+#define BT_VCP_LEFT_SURROUND        BIT(27)
+#define BT_VCP_RIGHT_SURROUND       BIT(28)
+
+#define VCS_TOTAL_NUM_HANDLES	11
+#define AICS_TOTAL_NUM_HANDLES	16
+
+/* AICS Audio Input Type Values */
+#define AICS_AUD_IP_TYPE_UNSPECIFIED		0x00
+#define AICS_AUD_IP_TYPE_BLUETOOTH		0x01
+#define AICS_AUD_IP_TYPE_MICROPHONE		0x02
+#define AICS_AUD_IP_TYPE_ANALOG		0x03
+#define AICS_AUD_IP_TYPE_DIGITAL		0x04
+#define AICS_AUD_IP_TYPE_RADIO			0x05
+#define AICS_AUD_IP_TYPE_STREAMING		0x06
+#define AICS_AUD_IP_TYPE_AMBIENT		0x07
+
+/* AICS Audio Input Status Values */
+#define AICS_AUD_IP_STATUS_INACTIVE	0x00
+#define AICS_AUD_IP_STATUS_ACTIVE	0x01
+
+/* AICS Audio Input Control Point Opcodes */
+#define BT_AICS_SET_GAIN_SETTING		0x01
+#define BT_AICS_UNMUTE				0x02
+#define BT_AICS_MUTE				0x03
+#define BT_AICS_SET_MANUAL_GAIN_MODE		0x04
+#define BT_AICS_SET_AUTO_GAIN_MODE		0x05
+
+/* AICS Gain Mode Field Value */
+#define AICS_GAIN_MODE_MANUAL_ONLY		0x00
+#define AICS_GAIN_MODE_AUTO_ONLY		0x01
+#define AICS_GAIN_MODE_MANUAL			0x02
+#define AICS_GAIN_MODE_AUTO			0x03
+
+/* AICS Mute Field Values */
+#define AICS_NOT_MUTED	0x00
+#define AICS_MUTED	0x01
+#define AICS_DISABLED	0x02
+
+#define AICS_GAIN_SETTING_UNITS	1
+#define AICS_GAIN_SETTING_MAX_VALUE	127
+#define AICS_GAIN_SETTING_MIN_VALUE	-128
+
+#define AICS_GAIN_SETTING_DEFAULT_VALUE	88
 
 struct bt_vcp_db {
 	struct gatt_db *db;
 	struct bt_vcs *vcs;
+	struct bt_vocs *vocs;
+	struct bt_aics *aics;
 };
 
 typedef void (*vcp_func_t)(struct bt_vcp *vcp, bool success, uint8_t att_ecode,
@@ -57,11 +137,21 @@ struct bt_vcs_param {
 	uint8_t	change_counter;
 } __packed;
 
+struct bt_vocs_param {
+	uint8_t	op;
+	uint8_t	change_counter;
+} __packed;
+
 struct bt_vcs_ab_vol {
 	uint8_t	change_counter;
 	uint8_t	vol_set;
 } __packed;
 
+struct bt_vocs_set_vol_off {
+	uint8_t	change_counter;
+	int16_t set_vol_offset;
+} __packed;
+
 struct bt_vcp_cb {
 	unsigned int id;
 	bt_vcp_func_t attached;
@@ -89,6 +179,14 @@ struct bt_vcp {
 	unsigned int vstate_id;
 	unsigned int vflag_id;
 
+	unsigned int state_id;
+	unsigned int audio_loc_id;
+	unsigned int ao_dec_id;
+
+	unsigned int aics_ip_state_id;
+	unsigned int aics_ip_status_id;
+	unsigned int aics_ip_descr_id;
+
 	struct queue *notify;
 	struct queue *pending;
 
@@ -120,6 +218,64 @@ struct bt_vcs {
 	struct gatt_db_attribute *vf_ccc;
 };
 
+/* Contains local bt_vcp_db */
+struct vol_offset_state {
+	int16_t vol_offset;
+	uint8_t counter;
+} __packed;
+
+struct bt_vocs {
+	struct bt_vcp_db *vdb;
+	struct vol_offset_state *vostate;
+	uint32_t vocs_audio_loc;
+	char *vocs_ao_dec;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *vos;
+	struct gatt_db_attribute *vos_ccc;
+	struct gatt_db_attribute *voal;
+	struct gatt_db_attribute *voal_ccc;
+	struct gatt_db_attribute *vo_cp;
+	struct gatt_db_attribute *voaodec;
+	struct gatt_db_attribute *voaodec_ccc;
+};
+
+struct aud_ip_st {
+	int8_t	gain_setting;
+	uint8_t	mute;
+	uint8_t	gain_mode;
+	uint8_t	chg_counter;
+} __packed;
+
+struct gain_setting_prop {
+	uint8_t	gain_setting_units;
+	int8_t	gain_setting_min;
+	int8_t	gain_setting_max;
+} __packed;
+
+struct bt_aics_set_gain_setting {
+	uint8_t change_counter;
+	int8_t gain_setting;
+} __packed;
+
+struct bt_aics {
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *aud_ipst;
+	struct gain_setting_prop *gain_settingprop;
+	uint8_t	aud_input_type;
+	uint8_t	aud_input_status;
+	char *aud_input_descr;
+	struct gatt_db_attribute *service;
+	struct gatt_db_attribute *aud_ip_state;
+	struct gatt_db_attribute *aud_ip_state_ccc;
+	struct gatt_db_attribute *gain_stting_prop;
+	struct gatt_db_attribute *aud_ip_type;
+	struct gatt_db_attribute *aud_ip_status;
+	struct gatt_db_attribute *aud_ip_status_ccc;
+	struct gatt_db_attribute *aud_ip_cp;
+	struct gatt_db_attribute *aud_ip_dscrptn;
+	struct gatt_db_attribute *aud_ip_dscrptn_ccc;
+};
+
 static struct queue *vcp_db;
 static struct queue *vcp_cbs;
 static struct queue *sessions;
@@ -159,6 +315,17 @@ static struct vol_state *vdb_get_vstate(struct bt_vcp_db *vdb)
 	return NULL;
 }
 
+static struct vol_offset_state *vdb_get_vostate(struct bt_vcp_db *vdb)
+{
+	if (!vdb->vocs)
+		return NULL;
+
+	if (vdb->vocs->vostate)
+		return vdb->vocs->vostate;
+
+	return NULL;
+}
+
 static struct bt_vcs *vcp_get_vcs(struct bt_vcp *vcp)
 {
 	if (!vcp)
@@ -173,6 +340,34 @@ static struct bt_vcs *vcp_get_vcs(struct bt_vcp *vcp)
 	return vcp->rdb->vcs;
 }
 
+static struct bt_vocs *vcp_get_vocs(struct bt_vcp *vcp)
+{
+	if (!vcp)
+		return NULL;
+
+	if (vcp->rdb->vocs)
+		return vcp->rdb->vocs;
+
+	vcp->rdb->vocs = new0(struct bt_vocs, 1);
+	vcp->rdb->vocs->vdb = vcp->rdb;
+
+	return vcp->rdb->vocs;
+}
+
+static struct bt_aics *vcp_get_aics(struct bt_vcp *vcp)
+{
+	if (!vcp)
+		return NULL;
+
+	if (vcp->rdb->aics)
+		return vcp->rdb->aics;
+
+	vcp->rdb->aics = new0(struct bt_aics, 1);
+	vcp->rdb->aics->vdb = vcp->rdb;
+
+	return vcp->rdb->aics;
+}
+
 static void vcp_detached(void *data, void *user_data)
 {
 	struct bt_vcp_cb *cb = data;
@@ -202,6 +397,8 @@ static void vcp_db_free(void *data)
 	gatt_db_unref(vdb->db);
 
 	free(vdb->vcs);
+	free(vdb->vocs);
+	free(vdb->aics);
 	free(vdb);
 }
 
@@ -583,6 +780,57 @@ static uint8_t vcs_mute(struct bt_vcs *vcs, struct bt_vcp *vcp,
 	return 0;
 }
 
+static uint8_t vocs_set_vol_offset(struct bt_vocs *vocs, struct bt_vcp *vcp,
+				struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct vol_offset_state *vstate, state;
+	struct bt_vocs_set_vol_off *req;
+
+	DBG(vcp, "Set Volume Offset");
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		return 0;
+	}
+
+	vstate = vdb_get_vostate(vdb);
+	if (!vstate) {
+		DBG(vcp, "error: VSTATE not available");
+		return 0;
+	}
+
+	req = iov_pull_mem(iov, sizeof(*req));
+	if (!req)
+		return 0;
+
+	if (req->change_counter != vstate->counter) {
+		DBG(vcp, "Change Counter Mismatch Volume not decremented!");
+		return BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+	}
+
+	vstate->vol_offset = le16_to_cpu(req->set_vol_offset);
+
+	if (vstate->vol_offset > VOCS_VOL_OFFSET_UPPER_LIMIT ||
+		vstate->vol_offset < VOCS_VOL_OFFSET_LOWER_LIMIT) {
+		DBG(vcp, "error: Value Out of Range");
+		return BT_ATT_ERROR_VALUE_OUT_OF_RANGE;
+	}
+
+	/* Increment Change Counter */
+	vstate->counter = -~vstate->counter;
+
+	/* Notify change */
+	state.vol_offset = req->set_vol_offset;
+	state.counter = vstate->counter;
+
+	gatt_db_attribute_notify(vdb->vocs->vos, (void *)&state, sizeof(state),
+				 bt_vcp_get_att(vcp));
+
+	return 0;
+}
+
 #define	BT_VCS_REL_VOL_DOWN		0x00
 #define	BT_VCS_REL_VOL_UP		0x01
 #define	BT_VCS_UNMUTE_REL_VOL_DOWN	0x02
@@ -591,6 +839,8 @@ static uint8_t vcs_mute(struct bt_vcs *vcs, struct bt_vcp *vcp,
 #define	BT_VCS_UNMUTE			0x05
 #define	BT_VCS_MUTE			0x06
 
+#define BT_VOCS_SET_VOL_OFFSET	0x01
+
 #define VCS_OP(_str, _op, _size, _func) \
 	{ \
 		.str = _str, \
@@ -623,6 +873,26 @@ struct vcs_op_handler {
 	{}
 };
 
+#define VOCS_OP(_str, _op, _size, _func) \
+	{ \
+		.str = _str, \
+		.op = _op, \
+		.size = _size, \
+		.func = _func, \
+	}
+
+struct vocs_op_handler {
+	const char *str;
+	uint8_t	op;
+	size_t	size;
+	uint8_t	(*func)(struct bt_vocs *vocs, struct bt_vcp *vcp,
+			struct iovec *iov);
+} vocp_handlers[] = {
+	VOCS_OP("Set Volume Offset", BT_VOCS_SET_VOL_OFFSET,
+		sizeof(uint8_t), vocs_set_vol_offset),
+	{}
+};
+
 static void vcs_cp_write(struct gatt_db_attribute *attrib,
 				unsigned int id, uint16_t offset,
 				const uint8_t *value, size_t len,
@@ -655,6 +925,10 @@ static void vcs_cp_write(struct gatt_db_attribute *attrib,
 	}
 
 	vcp_op = iov_pull_mem(&iov, sizeof(*vcp_op));
+	if (!vcp_op) {
+		DBG(vcp, "iov_pull_mem() returned NULL");
+		goto respond;
+	}
 
 	for (handler = vcp_handlers; handler && handler->str; handler++) {
 		if (handler->op != *vcp_op)
@@ -683,6 +957,70 @@ respond:
 	gatt_db_attribute_write_result(attrib, id, ret);
 }
 
+static void vocs_cp_write(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 bt_vocs *vocs = user_data;
+	struct bt_vcp *vcp = vcp_get_session(att, vocs->vdb->db);
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = len,
+	};
+	uint8_t	*vcp_op;
+	struct vocs_op_handler *handler;
+	uint8_t ret = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+
+	DBG(vcp, "VOCP Control Point Write");
+
+	if (offset) {
+		DBG(vcp, "invalid offset %d", offset);
+		ret = BT_ATT_ERROR_INVALID_OFFSET;
+		goto respond;
+	}
+
+	if (len < sizeof(*vcp_op)) {
+		DBG(vcp, "invalid len %ld < %ld sizeof(*param)", len,
+							sizeof(*vcp_op));
+		ret = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto respond;
+	}
+
+	vcp_op = iov_pull_mem(&iov, sizeof(*vcp_op));
+	if (!vcp_op) {
+		DBG(vcp, "iov_pull_mem() returned NULL");
+		goto respond;
+	}
+
+	for (handler = vocp_handlers; handler && handler->str; handler++) {
+		if (handler->op != *vcp_op)
+			continue;
+
+		if (iov.iov_len < handler->size) {
+			DBG(vcp, "invalid len %ld < %ld handler->size", len,
+			    handler->size);
+			ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+			goto respond;
+		}
+
+		break;
+	}
+
+	if (handler && handler->str) {
+		DBG(vcp, "%s", handler->str);
+
+		ret = handler->func(vocs, vcp, &iov);
+	} else {
+		DBG(vcp, "Unknown opcode 0x%02x", *vcp_op);
+		ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+	}
+
+respond:
+	gatt_db_attribute_write_result(attrib, id, ret);
+}
+
 static void vcs_state_read(struct gatt_db_attribute *attrib,
 				unsigned int id, uint16_t offset,
 				uint8_t opcode, struct bt_att *att,
@@ -698,6 +1036,21 @@ static void vcs_state_read(struct gatt_db_attribute *attrib,
 							iov.iov_len);
 }
 
+static void vocs_state_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_vocs *vocs = user_data;
+	struct vol_offset_state state;
+
+	state.vol_offset = cpu_to_le16(vocs->vostate->vol_offset);
+	state.counter = vocs->vostate->counter;
+
+	gatt_db_attribute_read_result(attrib, id, 0, (void *)&state,
+					sizeof(state));
+}
+
 static void vcs_flag_read(struct gatt_db_attribute *attrib,
 				unsigned int id, uint16_t offset,
 				uint8_t opcode, struct bt_att *att,
@@ -713,78 +1066,775 @@ static void vcs_flag_read(struct gatt_db_attribute *attrib,
 							iov.iov_len);
 }
 
-static struct bt_vcs *vcs_new(struct gatt_db *db)
+static void vocs_voal_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
 {
-	struct bt_vcs *vcs;
-	struct vol_state *vstate;
-	bt_uuid_t uuid;
+	struct bt_vocs *vocs = user_data;
+	uint32_t loc;
 
-	if (!db)
-		return NULL;
+	loc = cpu_to_le32(vocs->vocs_audio_loc);
 
-	vcs = new0(struct bt_vcs, 1);
+	gatt_db_attribute_read_result(attrib, id, 0, (void *)&loc,
+							sizeof(loc));
+}
 
-	vstate = new0(struct vol_state, 1);
+static void vocs_voaodec_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_vocs *vocs = user_data;
+	struct iovec iov;
 
-	vcs->vstate = vstate;
-	vcs->vol_flag = USERSET_VOLUME_SETTING;
+	iov.iov_base = vocs->vocs_ao_dec;
+	iov.iov_len = strlen(vocs->vocs_ao_dec);
 
-	/* Populate DB with VCS attributes */
-	bt_uuid16_create(&uuid, VCS_UUID);
-	vcs->service = gatt_db_add_service(db, &uuid, true, 9);
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
 
-	bt_uuid16_create(&uuid, VOL_STATE_CHRC_UUID);
-	vcs->vs = gatt_db_service_add_characteristic(vcs->service,
-					&uuid,
-					BT_ATT_PERM_READ,
-					BT_GATT_CHRC_PROP_READ |
-					BT_GATT_CHRC_PROP_NOTIFY,
-					vcs_state_read, NULL,
-					vcs);
+static void aics_input_state_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_aics *aics = user_data;
+	struct iovec iov;
 
-	vcs->vs_ccc = gatt_db_service_add_ccc(vcs->service,
-					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	iov.iov_base = aics->aud_ipst;
+	iov.iov_len = sizeof(*aics->aud_ipst);
 
-	bt_uuid16_create(&uuid, VOL_CP_CHRC_UUID);
-	vcs->vol_cp = gatt_db_service_add_characteristic(vcs->service,
-					&uuid,
-					BT_ATT_PERM_WRITE,
-					BT_GATT_CHRC_PROP_WRITE,
-					NULL, vcs_cp_write,
-					vcs);
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
 
-	bt_uuid16_create(&uuid, VOL_FLAG_CHRC_UUID);
-	vcs->vf = gatt_db_service_add_characteristic(vcs->service,
-					&uuid,
-					BT_ATT_PERM_READ,
-					BT_GATT_CHRC_PROP_READ |
-					BT_GATT_CHRC_PROP_NOTIFY,
-					vcs_flag_read, NULL,
-					vcs);
+static void aics_gain_setting_prop_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_aics *aics = user_data;
+	struct iovec iov;
 
-	vcs->vf_ccc = gatt_db_service_add_ccc(vcs->service,
-					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	iov.iov_base = aics->gain_settingprop;
+	iov.iov_len = sizeof(*aics->gain_settingprop);
 
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
 
-	gatt_db_service_set_active(vcs->service, true);
+static void aics_audio_input_type_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_aics *aics = user_data;
+	struct iovec iov;
 
-	return vcs;
+	iov.iov_base = &aics->aud_input_type;
+	iov.iov_len = sizeof(aics->aud_input_type);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
 }
 
-static struct bt_vcp_db *vcp_db_new(struct gatt_db *db)
+static void aics_input_status_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
 {
-	struct bt_vcp_db *vdb;
+	struct bt_aics *aics = user_data;
+	struct iovec iov;
 
-	if (!db)
-		return NULL;
+	iov.iov_base = &aics->aud_input_status;
+	iov.iov_len = sizeof(aics->aud_input_status);
 
-	vdb = new0(struct bt_vcp_db, 1);
-	vdb->db = gatt_db_ref(db);
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
+
+static struct aud_ip_st *vdb_get_audipst(struct bt_vcp_db *vdb)
+{
+	if (!vdb->aics)
+		return NULL;
+
+	if (vdb->aics->aud_ipst)
+		return vdb->aics->aud_ipst;
+
+	return NULL;
+}
+
+static struct gain_setting_prop *vdb_get_gainsettingprop(
+					struct bt_vcp_db *vdb)
+{
+	if (!vdb->aics)
+		return NULL;
+
+	if (vdb->aics->gain_settingprop)
+		return vdb->aics->gain_settingprop;
+
+	return NULL;
+}
+
+static uint8_t aics_set_gain_setting(struct bt_aics *aics,
+				struct bt_vcp *vcp, struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *audipst;
+	struct bt_aics_set_gain_setting *req;
+	struct gain_setting_prop *gainsettngprop;
+	uint8_t	ret = 1;
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		ret = 0;
+		goto respond;
+	}
+
+	audipst = vdb_get_audipst(vdb);
+	if (!audipst) {
+		DBG(vcp, "error: Audio Input State value is not available");
+		ret = 0;
+		goto respond;
+
+	}
+
+	req = iov_pull_mem(iov, sizeof(*req));
+	if (!req) {
+		ret = 0;
+		goto respond;
+
+	}
+
+	if (req->change_counter != audipst->chg_counter) {
+		DBG(vcp, "Change Counter Mismatch Audio Input State!");
+		ret = BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+		goto respond;
+	}
+
+	if (audipst->gain_mode != AICS_GAIN_MODE_MANUAL_ONLY &&
+		audipst->gain_mode != AICS_GAIN_MODE_MANUAL) {
+		DBG(vcp, "Gain Mode is not Manual only or Manual");
+		ret = BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED;
+		goto respond;
+	}
+
+	gainsettngprop = vdb_get_gainsettingprop(vdb);
+	if (req->gain_setting > gainsettngprop->gain_setting_max ||
+		req->gain_setting < gainsettngprop->gain_setting_min) {
+		DBG(vcp, "error: Value Out of Range");
+		ret = BT_ATT_AICS_ERROR_VALUE_OUT_OF_RANGE;
+		goto respond;
+	}
+
+	audipst->gain_setting = req->gain_setting;
+	/*Increment Change Counter*/
+	audipst->chg_counter = -~audipst->chg_counter;
+	gatt_db_attribute_notify(vdb->aics->aud_ip_state, (void *)audipst,
+				sizeof(struct aud_ip_st),
+				bt_vcp_get_att(vcp));
+	ret = 0;
+
+respond:
+	return ret;
+}
+
+static uint8_t aics_unmute(struct bt_aics *aics, struct bt_vcp *vcp,
+							struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *audipst;
+	uint8_t *change_counter;
+	uint8_t	ret = 1;
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		ret = 0;
+		goto respond;
+
+	}
+
+	audipst = vdb_get_audipst(vdb);
+	if (!audipst) {
+		DBG(vcp, "error: Audio Input State value is not available");
+		ret = 0;
+		goto respond;
+
+	}
+	change_counter = iov_pull_mem(iov, sizeof(*change_counter));
+	if (!change_counter) {
+		ret = 0;
+		goto respond;
+
+	}
+
+	if (*change_counter != audipst->chg_counter) {
+		DBG(vcp, "Change Counter Mismatch Audio Input State!");
+		ret = BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+		goto respond;
+	}
+
+	if (audipst->mute == AICS_DISABLED) {
+		DBG(vcp, "Mute state is Disabled!");
+		ret = BT_ATT_AICS_ERROR_MUTE_DISABLED;
+		goto respond;
+	}
+
+	audipst->mute = AICS_NOT_MUTED;
+	/*Increment Change Counter*/
+	audipst->chg_counter = -~audipst->chg_counter;
+	gatt_db_attribute_notify(vdb->aics->aud_ip_state, (void *)audipst,
+				sizeof(struct aud_ip_st),
+				bt_vcp_get_att(vcp));
+	ret = 0;
+
+respond:
+	return ret;
+}
+
+static uint8_t aics_mute(struct bt_aics *aics, struct bt_vcp *vcp,
+						struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *audipst;
+	uint8_t *change_counter;
+	uint8_t	ret = 1;
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		ret = 0;
+		goto respond;
+	}
+
+	audipst = vdb_get_audipst(vdb);
+	if (!audipst) {
+		DBG(vcp, "error: Audio Input State value is not available");
+		ret = 0;
+		goto respond;
+	}
+	change_counter = iov_pull_mem(iov, sizeof(*change_counter));
+	if (!change_counter) {
+		ret = 0;
+		goto respond;
+	}
+
+	if (*change_counter != audipst->chg_counter) {
+		DBG(vcp, "Change Counter Mismatch Audio Input State!");
+		ret = BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+		goto respond;
+	}
+
+	if (audipst->mute == AICS_DISABLED) {
+		DBG(vcp, "Mute state is Disabled!");
+		ret = BT_ATT_AICS_ERROR_MUTE_DISABLED;
+		goto respond;
+	}
+
+	audipst->mute = AICS_MUTED;
+	/*Increment Change Counter*/
+	audipst->chg_counter = -~audipst->chg_counter;
+	gatt_db_attribute_notify(vdb->aics->aud_ip_state, (void *)audipst,
+				sizeof(struct aud_ip_st),
+				bt_vcp_get_att(vcp));
+	ret = 0;
+
+respond:
+	return ret;
+}
+
+static uint8_t aics_set_manual_gain_mode(struct bt_aics *aics,
+				struct bt_vcp *vcp, struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *audipst;
+	uint8_t *change_counter;
+	uint8_t	ret = 1;
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		ret = 0;
+		goto respond;
+	}
+
+	audipst = vdb_get_audipst(vdb);
+	if (!audipst) {
+		DBG(vcp, "error: Audio Input State value is not available");
+		ret = 0;
+		goto respond;
+	}
+
+	change_counter = iov_pull_mem(iov, sizeof(*change_counter));
+	if (!change_counter) {
+		ret = 0;
+		goto respond;
+	}
+
+	if (*change_counter != audipst->chg_counter) {
+		DBG(vcp, "Change Counter Mismatch Audio Input State!");
+		ret = BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+		goto respond;
+	}
+
+	if (audipst->gain_mode == AICS_GAIN_MODE_AUTO_ONLY ||
+		audipst->gain_mode == AICS_GAIN_MODE_MANUAL_ONLY) {
+		DBG(vcp, "error!! gain mode is Automatic only or Manual only");
+		ret = BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED;
+		goto respond;
+	}
+
+	if (audipst->gain_mode == AICS_GAIN_MODE_AUTO) {
+		audipst->gain_mode = AICS_GAIN_MODE_MANUAL;
+		/*Increment Change Counter*/
+		audipst->chg_counter = -~audipst->chg_counter;
+		gatt_db_attribute_notify(vdb->aics->aud_ip_state,
+					(void *)audipst,
+					sizeof(struct aud_ip_st),
+					bt_vcp_get_att(vcp));
+		ret = 0;
+	} else {
+		DBG(vcp,
+		"error!! Gain mode field value not Automatic");
+		ret = BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED;
+	}
+
+respond:
+	return ret;
+}
+
+static uint8_t aics_set_auto_gain_mode(struct bt_aics *aics, struct bt_vcp *vcp,
+				struct iovec *iov)
+{
+	struct bt_vcp_db *vdb;
+	struct aud_ip_st *audipst;
+	uint8_t *change_counter;
+	uint8_t	ret = 1;
+
+	vdb = vcp_get_vdb(vcp);
+	if (!vdb) {
+		DBG(vcp, "error: VDB not available");
+		ret = 0;
+		goto respond;
+	}
+
+	audipst = vdb_get_audipst(vdb);
+	if (!audipst) {
+		DBG(vcp, "error: Audio Input State value is not available");
+		ret = 0;
+		goto respond;
+	}
+	change_counter = iov_pull_mem(iov, sizeof(*change_counter));
+	if (!change_counter) {
+		ret = 0;
+		goto respond;
+	}
+
+	if (*change_counter != audipst->chg_counter) {
+		DBG(vcp, "Change Counter Mismatch Audio Input State!");
+		ret = BT_ATT_ERROR_INVALID_CHANGE_COUNTER;
+		goto respond;
+	}
+
+	if (audipst->gain_mode == AICS_GAIN_MODE_AUTO_ONLY ||
+		audipst->gain_mode == AICS_GAIN_MODE_MANUAL_ONLY) {
+		DBG(vcp, "error!! gain mode is Automatic only or Manual only");
+		ret = BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED;
+		goto respond;
+	}
+
+	if (audipst->gain_mode == AICS_GAIN_MODE_MANUAL) {
+		audipst->gain_mode = AICS_GAIN_MODE_AUTO;
+		/*Increment Change Counter*/
+		audipst->chg_counter = -~audipst->chg_counter;
+		gatt_db_attribute_notify(vdb->aics->aud_ip_state,
+				(void *)audipst,
+				sizeof(struct aud_ip_st), bt_vcp_get_att(vcp));
+		ret = 0;
+	} else {
+		DBG(vcp, "error!! Gain mode field value is not Manual");
+		ret = BT_ATT_AICS_ERROR_GAIN_MODE_CHANGE_NOT_ALLOWED;
+	}
+
+respond:
+	return ret;
+}
+
+#define AICS_OP(_str, _op, _size, _func) \
+	{ \
+			.str = _str, \
+			.op = _op, \
+			.size = _size, \
+			.func = _func, \
+	}
+
+struct aics_op_handler {
+		const char *str;
+		uint8_t op;
+		size_t  size;
+		uint8_t (*func)(struct bt_aics *aics, struct bt_vcp *vcp,
+				struct iovec *iov);
+} aics_handlers[] = {
+		AICS_OP("Set Gain Setting", BT_AICS_SET_GAIN_SETTING,
+				sizeof(struct bt_aics_set_gain_setting),
+				aics_set_gain_setting),
+		AICS_OP("Unmute", BT_AICS_UNMUTE,
+				sizeof(uint8_t), aics_unmute),
+		AICS_OP("Mute", BT_AICS_MUTE,
+				sizeof(uint8_t), aics_mute),
+		AICS_OP("Set Manual Gain Mode", BT_AICS_SET_MANUAL_GAIN_MODE,
+				sizeof(uint8_t), aics_set_manual_gain_mode),
+		AICS_OP("Set Automatic Gain Mode", BT_AICS_SET_AUTO_GAIN_MODE,
+				sizeof(uint8_t), aics_set_auto_gain_mode),
+	{}
+};
+
+static void aics_ip_cp_write(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 bt_aics *aics = user_data;
+	struct bt_vcp *vcp = vcp_get_session(att, aics->vdb->db);
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = len,
+	};
+	uint8_t	*aics_op;
+	struct aics_op_handler *handler;
+	uint8_t ret = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+
+	DBG(vcp, "AICS Control Point Write");
+
+	if (offset) {
+		DBG(vcp, "invalid offset %d", offset);
+		ret = BT_ATT_ERROR_INVALID_OFFSET;
+		goto respond;
+	}
+
+	if (len < sizeof(*aics_op)) {
+		DBG(vcp, "invalid len %ld < %ld sizeof(*param)", len,
+							sizeof(*aics_op));
+		ret = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto respond;
+	}
+
+	aics_op = iov_pull_mem(&iov, sizeof(*aics_op));
+	if (!aics_op) {
+		DBG(vcp, "iov_pull_mem() returned NULL");
+		goto respond;
+	}
+
+	for (handler = aics_handlers; handler && handler->str; handler++) {
+		if (handler->op != *aics_op)
+			continue;
+
+		if (iov.iov_len < handler->size) {
+			DBG(vcp, "invalid len %ld < %ld handler->size", len,
+				handler->size);
+			ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+			goto respond;
+		}
+
+		break;
+	}
+
+	if (handler && handler->str) {
+		DBG(vcp, "%s", handler->str);
+
+		ret = handler->func(aics, vcp, &iov);
+	} else {
+		DBG(vcp, "Unknown opcode 0x%02x", *aics_op);
+		ret = BT_ATT_ERROR_OPCODE_NOT_SUPPORTED;
+	}
+
+respond:
+	gatt_db_attribute_write_result(attrib, id, ret);
+}
+
+static void aics_input_descr_read(struct gatt_db_attribute *attrib,
+				unsigned int id, uint16_t offset,
+				uint8_t opcode, struct bt_att *att,
+				void *user_data)
+{
+	struct bt_aics *aics = user_data;
+	struct iovec iov;
+
+	iov.iov_base = aics->aud_input_descr;
+	iov.iov_len = strlen(aics->aud_input_descr);
+
+	gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+							iov.iov_len);
+}
+
+static void aics_input_descr_write(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)
+{
+	/* TODO : AICS optional feature */
+}
+
+static struct bt_vcs *vcs_new(struct gatt_db *db, struct bt_vcp_db *vdb)
+{
+	struct bt_vcs *vcs;
+	struct vol_state *vstate;
+	bt_uuid_t uuid;
+
+	if (!db)
+		return NULL;
+
+	vcs = new0(struct bt_vcs, 1);
+
+	vstate = new0(struct vol_state, 1);
+
+	vcs->vstate = vstate;
+	vcs->vol_flag = USERSET_VOLUME_SETTING;
+
+	/* Populate DB with VCS attributes */
+	bt_uuid16_create(&uuid, VCS_UUID);
+	vcs->service = gatt_db_add_service(db, &uuid, true,
+						VCS_TOTAL_NUM_HANDLES);
+	gatt_db_service_add_included(vcs->service, vdb->vocs->service);
+	gatt_db_service_set_active(vdb->vocs->service, true);
+	gatt_db_service_add_included(vcs->service, vdb->aics->service);
+	gatt_db_service_set_active(vdb->aics->service, true);
+
+	bt_uuid16_create(&uuid, VOL_STATE_CHRC_UUID);
+	vcs->vs = gatt_db_service_add_characteristic(vcs->service,
+					&uuid,
+					BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					vcs_state_read, NULL,
+					vcs);
+
+	vcs->vs_ccc = gatt_db_service_add_ccc(vcs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, VOL_CP_CHRC_UUID);
+	vcs->vol_cp = gatt_db_service_add_characteristic(vcs->service,
+					&uuid,
+					BT_ATT_PERM_WRITE,
+					BT_GATT_CHRC_PROP_WRITE,
+					NULL, vcs_cp_write,
+					vcs);
+
+	bt_uuid16_create(&uuid, VOL_FLAG_CHRC_UUID);
+	vcs->vf = gatt_db_service_add_characteristic(vcs->service,
+					&uuid,
+					BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					vcs_flag_read, NULL,
+					vcs);
+
+	vcs->vf_ccc = gatt_db_service_add_ccc(vcs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+
+	gatt_db_service_set_active(vcs->service, true);
+
+	return vcs;
+}
+
+static struct bt_vocs *vocs_new(struct gatt_db *db)
+{
+	struct bt_vocs *vocs;
+	struct vol_offset_state *vostate;
+	bt_uuid_t uuid;
+
+	if (!db)
+		return NULL;
+
+	vocs = new0(struct bt_vocs, 1);
+
+	vostate = new0(struct vol_offset_state, 1);
+
+	vocs->vostate = vostate;
+	vocs->vocs_audio_loc = BT_VCP_FRONT_LEFT;
+	vocs->vocs_ao_dec = "Left Speaker";
+
+	/* Populate DB with VOCS attributes */
+	bt_uuid16_create(&uuid, VOL_OFFSET_CS_UUID);
+
+	vocs->service = gatt_db_add_service(db, &uuid, false, 12);
+
+	bt_uuid16_create(&uuid, VOCS_STATE_CHAR_UUID);
+	vocs->vos = gatt_db_service_add_characteristic(vocs->service,
+					&uuid,
+					BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					vocs_state_read, NULL,
+					vocs);
+
+	vocs->vos_ccc = gatt_db_service_add_ccc(vocs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, VOCS_AUDIO_LOC_CHRC_UUID);
+	vocs->voal = gatt_db_service_add_characteristic(vocs->service,
+					&uuid,
+					BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					vocs_voal_read, NULL,
+					vocs);
+
+	vocs->voal_ccc = gatt_db_service_add_ccc(vocs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, VOCS_CP_CHRC_UUID);
+	vocs->vo_cp = gatt_db_service_add_characteristic(vocs->service,
+					&uuid,
+					BT_ATT_PERM_WRITE,
+					BT_GATT_CHRC_PROP_WRITE,
+					NULL, vocs_cp_write,
+					vocs);
+
+	bt_uuid16_create(&uuid, VOCS_AUDIO_OP_DESC_CHAR_UUID);
+	vocs->voaodec = gatt_db_service_add_characteristic(vocs->service,
+					&uuid,
+					BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_NOTIFY,
+					vocs_voaodec_read, NULL,
+					vocs);
+
+	vocs->voaodec_ccc = gatt_db_service_add_ccc(vocs->service,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	return vocs;
+}
+
+static struct bt_aics *aics_new(struct gatt_db *db)
+{
+	struct bt_aics *aics;
+	struct aud_ip_st *aics_aud_ip_st;
+	struct gain_setting_prop *aics_gain_settng_prop;
+	char *ip_descr;
+	char ip_descr_str[] = "Blueooth";
+	bt_uuid_t uuid;
+
+	if (!db)
+		return NULL;
+
+	aics = new0(struct bt_aics, 1);
+
+	aics_aud_ip_st = new0(struct aud_ip_st, 1);
+	aics_gain_settng_prop = new0(struct gain_setting_prop, 1);
+	ip_descr = malloc(256);
+	memset(ip_descr, 0, 256);
+
+	aics_aud_ip_st->mute = AICS_NOT_MUTED;
+	aics_aud_ip_st->gain_mode = AICS_GAIN_MODE_MANUAL;
+	aics_aud_ip_st->gain_setting = AICS_GAIN_SETTING_DEFAULT_VALUE;
+	aics->aud_ipst = aics_aud_ip_st;
+	aics_gain_settng_prop->gain_setting_units = AICS_GAIN_SETTING_UNITS;
+	aics_gain_settng_prop->gain_setting_max = AICS_GAIN_SETTING_MAX_VALUE;
+	aics_gain_settng_prop->gain_setting_min = AICS_GAIN_SETTING_MIN_VALUE;
+	aics->gain_settingprop = aics_gain_settng_prop;
+	aics->aud_input_type =	AICS_AUD_IP_TYPE_BLUETOOTH;
+	aics->aud_input_status = AICS_AUD_IP_STATUS_ACTIVE;
+	memcpy(ip_descr, ip_descr_str, strlen(ip_descr_str));
+	aics->aud_input_descr = ip_descr;
+
+	/* Populate DB with AICS attributes */
+	bt_uuid16_create(&uuid, AUDIO_INPUT_CS_UUID);
+	aics->service = gatt_db_add_service(db, &uuid, false,
+					AICS_TOTAL_NUM_HANDLES);
+
+	bt_uuid16_create(&uuid, AICS_INPUT_STATE_CHAR_UUID);
+	aics->aud_ip_state = gatt_db_service_add_characteristic(aics->service,
+				&uuid,
+				BT_ATT_PERM_READ,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_NOTIFY,
+				aics_input_state_read,
+				NULL,
+				aics);
+	aics->aud_ip_state_ccc = gatt_db_service_add_ccc(aics->service,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, AICS_GAIN_SETTING_PROP_CHAR_UUID);
+	aics->gain_stting_prop = gatt_db_service_add_characteristic(
+				aics->service,
+				&uuid,
+				BT_ATT_PERM_READ,
+				BT_GATT_CHRC_PROP_READ,
+				aics_gain_setting_prop_read, NULL,
+				aics);
+
+	bt_uuid16_create(&uuid, AICS_AUDIO_INPUT_TYPE_CHAR_UUID);
+	aics->aud_ip_type = gatt_db_service_add_characteristic(aics->service,
+				&uuid,
+				BT_ATT_PERM_READ,
+				BT_GATT_CHRC_PROP_READ,
+				aics_audio_input_type_read, NULL,
+				aics);
+
+	bt_uuid16_create(&uuid, AICS_INPUT_STATUS_CHAR_UUID);
+	aics->aud_ip_status = gatt_db_service_add_characteristic(aics->service,
+				&uuid,
+				BT_ATT_PERM_READ,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_NOTIFY,
+				aics_input_status_read, NULL,
+				aics);
+	aics->aud_ip_status_ccc = gatt_db_service_add_ccc(aics->service,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	bt_uuid16_create(&uuid, AICS_AUDIO_INPUT_CP_CHRC_UUID);
+	aics->aud_ip_cp = gatt_db_service_add_characteristic(aics->service,
+				&uuid,
+				BT_ATT_PERM_WRITE,
+				BT_GATT_CHRC_PROP_WRITE,
+				NULL, aics_ip_cp_write,
+				aics);
+
+	bt_uuid16_create(&uuid, AICS_INPUT_DESCR_CHAR_UUID);
+	aics->aud_ip_dscrptn = gatt_db_service_add_characteristic(aics->service,
+				&uuid,
+				BT_ATT_PERM_READ |
+				BT_ATT_PERM_WRITE,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP |
+				BT_GATT_CHRC_PROP_NOTIFY,
+				aics_input_descr_read,
+				aics_input_descr_write,
+				aics);
+	aics->aud_ip_dscrptn_ccc = gatt_db_service_add_ccc(aics->service,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+	return aics;
+}
+
+static struct bt_vcp_db *vcp_db_new(struct gatt_db *db)
+{
+	struct bt_vcp_db *vdb;
+
+	if (!db)
+		return NULL;
+
+	vdb = new0(struct bt_vcp_db, 1);
+	vdb->db = gatt_db_ref(db);
 
 	if (!vcp_db)
 		vcp_db = queue_new();
 
-	vdb->vcs = vcs_new(db);
+	vdb->vocs = vocs_new(db);
+	vdb->vocs->vdb = vdb;
+
+	vdb->aics = aics_new(db);
+	vdb->aics->vdb = vdb;
+
+	vdb->vcs = vcs_new(db, vdb);
 	vdb->vcs->vdb = vdb;
 
 	queue_push_tail(vcp_db, vdb);
@@ -902,13 +1952,54 @@ static void vcp_vstate_notify(struct bt_vcp *vcp, uint16_t value_handle,
 				const uint8_t *value, uint16_t length,
 				void *user_data)
 {
-	struct vol_state vstate;
+	struct vol_state vstate;
+
+	memcpy(&vstate, value, sizeof(struct vol_state));
+
+	DBG(vcp, "Vol Settings 0x%x", vstate.vol_set);
+	DBG(vcp, "Mute Status 0x%x", vstate.mute);
+	DBG(vcp, "Vol Counter 0x%x", vstate.counter);
+}
+
+static void vcp_voffset_state_notify(struct bt_vcp *vcp, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct vol_offset_state vostate;
+
+	memcpy(&vostate, value, sizeof(struct vol_offset_state));
+
+	DBG(vcp, "Vol Offset 0x%x", vostate.vol_offset);
+	DBG(vcp, "Vol Offset Counter 0x%x", vostate.counter);
+}
+
+static void vcp_audio_loc_notify(struct bt_vcp *vcp, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	uint32_t *vocs_audio_loc_n = malloc(sizeof(uint32_t));
+	*vocs_audio_loc_n = 0;
+
+	if (value != NULL)
+		memcpy(vocs_audio_loc_n, value, sizeof(uint32_t));
+
+	DBG(vcp, "VOCS Audio Location 0x%x", *vocs_audio_loc_n);
+
+	free(vocs_audio_loc_n);
+}
+
+
+static void vcp_audio_descriptor_notify(struct bt_vcp *vcp,
+					uint16_t value_handle,
+					const uint8_t *value,
+					uint16_t length,
+					void *user_data)
+{
+	char vocs_audio_dec_n[256] = {'\0'};
 
-	memcpy(&vstate, value, sizeof(struct vol_state));
+	memcpy(vocs_audio_dec_n, value, length);
 
-	DBG(vcp, "Vol Settings 0x%x", vstate.vol_set);
-	DBG(vcp, "Mute Status 0x%x", vstate.mute);
-	DBG(vcp, "Vol Counter 0x%x", vstate.counter);
+	DBG(vcp, "VOCS Audio Descriptor 0x%s", *vocs_audio_dec_n);
 }
 
 static void vcp_vflag_notify(struct bt_vcp *vcp, uint16_t value_handle,
@@ -972,6 +2063,90 @@ static void read_vol_state(struct bt_vcp *vcp, bool success, uint8_t att_ecode,
 	DBG(vcp, "Vol Counter:%x", vs->counter);
 }
 
+static void read_vol_offset_state(struct bt_vcp *vcp, bool success,
+				  uint8_t att_ecode,
+				  const uint8_t *value, uint16_t length,
+				  void *user_data)
+{
+	struct vol_offset_state *vos;
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = length,
+	};
+
+	if (!success) {
+		DBG(vcp, "Unable to read Vol Offset State: error 0x%02x",
+		    att_ecode);
+		return;
+	}
+
+	vos = iov_pull_mem(&iov, sizeof(*vos));
+	if (!vos) {
+		DBG(vcp, "Unable to get Vol Offset State");
+		return;
+	}
+
+	DBG(vcp, "Vol Offset: 0x%04x", le16_to_cpu(vos->vol_offset));
+	DBG(vcp, "Vol Counter: 0x%02x", vos->counter);
+}
+
+static void read_vocs_audio_location(struct bt_vcp *vcp, bool success,
+				     uint8_t att_ecode,
+				     const uint8_t *value, uint16_t length,
+				     void *user_data)
+{
+	uint32_t vocs_audio_loc;
+	struct iovec iov;
+
+	if (!value) {
+		DBG(vcp, "Unable to get VOCS Audio Location");
+		return;
+	}
+
+	if (!success) {
+		DBG(vcp, "Unable to read VOCS Audio Location: error 0x%02x",
+		    att_ecode);
+		return;
+	}
+
+	iov.iov_base = (void *)value;
+	iov.iov_len = length;
+
+	if (!util_iov_pull_le32(&iov, &vocs_audio_loc)) {
+		DBG(vcp, "Invalid size for VOCS Audio Location");
+		return;
+	}
+
+	DBG(vcp, "VOCS Audio Loc: 0x%8x", vocs_audio_loc);
+}
+
+
+static void read_vocs_audio_descriptor(struct bt_vcp *vcp, bool success,
+				       uint8_t att_ecode,
+				       const uint8_t *value, uint16_t length,
+				       void *user_data)
+{
+	char *vocs_ao_dec_r;
+
+	if (!value) {
+		DBG(vcp, "Unable to get VOCS Audio Location");
+		return;
+	}
+
+	if (!success) {
+		DBG(vcp, "Unable to read VOCS Audio Descriptor: error 0x%02x",
+			att_ecode);
+		return;
+	}
+
+	vocs_ao_dec_r = util_memdup(value, length + 1);
+	memset(vocs_ao_dec_r + length, 0, 1);
+
+	DBG(vcp, "VOCS Audio Descriptor: %s", vocs_ao_dec_r);
+	free(vocs_ao_dec_r);
+	vocs_ao_dec_r = NULL;
+}
+
 static void vcp_pending_destroy(void *data)
 {
 	struct bt_vcp_pending *pending = data;
@@ -1128,6 +2303,385 @@ static void foreach_vcs_char(struct gatt_db_attribute *attr, void *user_data)
 	}
 }
 
+static void foreach_vocs_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_vcp *vcp = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_vostate, uuid_audio_loc, uuid_vo_cp,
+			uuid_audio_op_decs;
+	struct bt_vocs *vocs;
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
+		return;
+
+	bt_uuid16_create(&uuid_vostate, VOCS_STATE_CHAR_UUID);
+	bt_uuid16_create(&uuid_audio_loc, VOCS_AUDIO_LOC_CHRC_UUID);
+	bt_uuid16_create(&uuid_vo_cp, VOCS_CP_CHRC_UUID);
+	bt_uuid16_create(&uuid_audio_op_decs, VOCS_AUDIO_OP_DESC_CHAR_UUID);
+
+	if (!bt_uuid_cmp(&uuid, &uuid_vostate)) {
+		DBG(vcp, "VOCS Vol state found: handle 0x%04x", value_handle);
+
+		vocs = vcp_get_vocs(vcp);
+		if (!vocs || vocs->vos)
+			return;
+
+		vocs->vos = attr;
+
+		vcp_read_value(vcp, value_handle, read_vol_offset_state, vcp);
+
+		vcp->state_id = vcp_register_notify(vcp, value_handle,
+					vcp_voffset_state_notify, NULL);
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_audio_loc)) {
+		DBG(vcp, "VOCS Volume Audio Location found: handle 0x%04x",
+			value_handle);
+
+		vocs = vcp_get_vocs(vcp);
+		if (!vocs || vocs->voal)
+			return;
+
+		vocs->voal = attr;
+
+		vcp_read_value(vcp, value_handle, read_vocs_audio_location,
+				       vcp);
+
+		vcp->audio_loc_id = vcp_register_notify(vcp, value_handle,
+						vcp_audio_loc_notify, NULL);
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_vo_cp)) {
+		DBG(vcp, "VOCS Volume CP found: handle 0x%04x", value_handle);
+
+		vocs = vcp_get_vocs(vcp);
+		if (!vocs || vocs->vo_cp)
+			return;
+
+		vocs->vo_cp = attr;
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_audio_op_decs)) {
+		DBG(vcp, "VOCS Vol Audio Descriptor found: handle 0x%04x",
+			value_handle);
+
+		vocs = vcp_get_vocs(vcp);
+		if (!vocs || vocs->voaodec)
+			return;
+
+		vocs->voaodec = attr;
+
+		vcp_read_value(vcp, value_handle, read_vocs_audio_descriptor,
+			       vcp);
+		vcp->ao_dec_id = vcp_register_notify(vcp, value_handle,
+					vcp_audio_descriptor_notify, NULL);
+
+	}
+
+}
+
+static void read_aics_audio_ip_state(struct bt_vcp *vcp, bool success,
+				  uint8_t att_ecode,
+				  const uint8_t *value, uint16_t length,
+				  void *user_data)
+{
+	struct aud_ip_st *ip_st;
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = length,
+	};
+
+	if (!success) {
+		DBG(vcp, "Unable to read Audio Input State: error 0x%02x",
+			att_ecode);
+		return;
+	}
+
+	ip_st = iov_pull_mem(&iov, sizeof(*ip_st));
+	if (!ip_st) {
+		DBG(vcp, "Unable to get Audio Input State");
+		return;
+	}
+
+	DBG(vcp, "Audio Input State, Gain Setting:%d", ip_st->gain_setting);
+	DBG(vcp, "Audio Input State, Mute:%x", ip_st->mute);
+	DBG(vcp, "Audio Input State, Gain Mode:%x", ip_st->gain_mode);
+	DBG(vcp, "Audio Input State, Change Counter:%x", ip_st->chg_counter);
+}
+
+static void aics_ip_state_notify(struct bt_vcp *vcp, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	struct aud_ip_st ip_st;
+
+	memcpy(&ip_st, value, sizeof(struct aud_ip_st));
+
+	DBG(vcp, "Audio Input State, Gain Setting:%d", ip_st.gain_setting);
+	DBG(vcp, "Audio Input State, Mute:%x", ip_st.mute);
+	DBG(vcp, "Audio Input State, Gain Mode:%x", ip_st.gain_mode);
+	DBG(vcp, "Audio Input State, Change Counter:%x", ip_st.chg_counter);
+}
+
+static void read_aics_gain_setting_prop(struct bt_vcp *vcp, bool success,
+					 uint8_t att_ecode,
+					 const uint8_t *value, uint16_t length,
+					 void *user_data)
+{
+	struct gain_setting_prop *aics_gain_setting_prop;
+	struct iovec iov = {
+		.iov_base = (void *) value,
+		.iov_len = length,
+	};
+
+	if (!value) {
+		DBG(vcp, "Unable to get Gain Setting Properties Char");
+		return;
+	}
+
+	if (!success) {
+		DBG(vcp,
+		"Unable to read Gain Setting Properties Char: 0x%02x",
+		att_ecode);
+		return;
+	}
+
+	aics_gain_setting_prop = iov_pull_mem(&iov,
+				sizeof(*aics_gain_setting_prop));
+	if (!aics_gain_setting_prop) {
+		DBG(vcp, "Unable to get Gain Setting Properties Char");
+		return;
+	}
+
+	DBG(vcp, "Gain Setting Properties, Units: %x",
+				aics_gain_setting_prop->gain_setting_units);
+	DBG(vcp, "Gain Setting Properties,  Min Value: %d",
+				aics_gain_setting_prop->gain_setting_min);
+	DBG(vcp, "Gain Setting Properties,  Max Value: %d",
+				aics_gain_setting_prop->gain_setting_max);
+}
+
+static void read_aics_aud_ip_type(struct bt_vcp *vcp, bool success,
+					 uint8_t att_ecode,
+					 const uint8_t *value, uint16_t length,
+					 void *user_data)
+{
+	uint8_t ip_type;
+
+	if (!success) {
+		DBG(vcp,
+		"Unable to read Audio Input Type Char: error 0x%02x",
+		att_ecode);
+		return;
+	}
+
+	memcpy(&ip_type, value, length);
+
+	DBG(vcp, "Audio Input Type : %x", ip_type);
+}
+
+static void read_aics_audio_ip_status(struct bt_vcp *vcp, bool success,
+					 uint8_t att_ecode,
+					 const uint8_t *value, uint16_t length,
+					 void *user_data)
+{
+	uint8_t ip_status;
+
+	if (!success) {
+		DBG(vcp,
+		"Unable to read Audio Input Status Char: 0x%02x", att_ecode);
+		return;
+	}
+
+	memcpy(&ip_status, value, length);
+
+	DBG(vcp, "Audio Input Status : %x", ip_status);
+}
+
+static void aics_ip_status_notify(struct bt_vcp *vcp, uint16_t value_handle,
+				const uint8_t *value,
+				uint16_t length,
+				void *user_data)
+{
+	uint8_t	ip_status;
+
+	memcpy(&ip_status, value, length);
+
+	DBG(vcp, "Audio Input Status, %x", ip_status);
+}
+
+static void read_aics_audio_ip_description(struct bt_vcp *vcp, bool success,
+					   uint8_t att_ecode,
+					   const uint8_t *value,
+					   uint16_t length,
+					   void *user_data)
+{
+	char *ip_descrptn;
+
+	if (!value) {
+		DBG(vcp, "Unable to get Audio Input Description");
+		return;
+	}
+
+	if (!success) {
+		DBG(vcp,
+			"Unable to read Audio Input Description Char: error 0x%02x",
+			att_ecode);
+		return;
+	}
+
+	ip_descrptn = util_memdup(value, length + 1);
+	memset(ip_descrptn + length, 0, 1);
+
+	DBG(vcp, "Audio Input Description: %s", ip_descrptn);
+	free(ip_descrptn);
+	ip_descrptn = NULL;
+}
+
+static void aics_audio_ip_desr_notify(struct bt_vcp *vcp, uint16_t value_handle,
+				const uint8_t *value, uint16_t length,
+				void *user_data)
+{
+	char *aud_ip_desr;
+
+	aud_ip_desr = malloc(length+1);
+	memset(aud_ip_desr, 0, length+1);
+	memcpy(aud_ip_desr, value, length);
+
+	DBG(vcp, "Audio Input Description Notify, %s", aud_ip_desr);
+	free(aud_ip_desr);
+	aud_ip_desr = NULL;
+}
+
+static void foreach_aics_char(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_vcp *vcp = user_data;
+	uint16_t value_handle;
+	bt_uuid_t uuid, uuid_ipstate, uuid_gain_setting_prop, uuid_ip_type,
+			uuid_ip_status, uuid_ip_cp, uuid_ip_decs;
+	struct bt_aics *aics;
+
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+						NULL, NULL, &uuid))
+		return;
+
+	bt_uuid16_create(&uuid_ipstate, AICS_INPUT_STATE_CHAR_UUID);
+	bt_uuid16_create(&uuid_gain_setting_prop,
+					AICS_GAIN_SETTING_PROP_CHAR_UUID);
+	bt_uuid16_create(&uuid_ip_type, AICS_AUDIO_INPUT_TYPE_CHAR_UUID);
+	bt_uuid16_create(&uuid_ip_status, AICS_INPUT_STATUS_CHAR_UUID);
+	bt_uuid16_create(&uuid_ip_cp, AICS_AUDIO_INPUT_CP_CHRC_UUID);
+	bt_uuid16_create(&uuid_ip_decs, AICS_INPUT_DESCR_CHAR_UUID);
+
+
+	if (!bt_uuid_cmp(&uuid, &uuid_ipstate)) {
+		DBG(vcp,
+			"AICS Audio Input State Char found: handle 0x%04x",
+			value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->aud_ip_state)
+			return;
+
+		aics->aud_ip_state = attr;
+
+		vcp_read_value(vcp, value_handle,
+					read_aics_audio_ip_state, vcp);
+
+		vcp->aics_ip_state_id = vcp_register_notify(vcp, value_handle,
+					aics_ip_state_notify, NULL);
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_gain_setting_prop)) {
+		DBG(vcp,
+			"AICS Gain Setting Properties Char found: handle 0x%04x",
+			value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->gain_stting_prop)
+			return;
+
+		aics->gain_stting_prop = attr;
+
+		vcp_read_value(vcp, value_handle, read_aics_gain_setting_prop,
+					   vcp);
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_ip_type)) {
+		DBG(vcp, "AICS Audio Input Type Char found: handle 0x%04x",
+			value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->aud_ip_type)
+			return;
+
+		aics->aud_ip_type = attr;
+
+		vcp_read_value(vcp, value_handle, read_aics_aud_ip_type,
+					   vcp);
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_ip_status)) {
+		DBG(vcp,
+			"AICS Audio Input Status Char found: handle 0x%04x",
+			value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->aud_ip_status)
+			return;
+
+		aics->aud_ip_status = attr;
+
+		vcp_read_value(vcp, value_handle,
+				read_aics_audio_ip_status, vcp);
+
+		vcp->aics_ip_status_id = vcp_register_notify(vcp, value_handle,
+					aics_ip_status_notify, NULL);
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_ip_cp)) {
+		DBG(vcp, "AICS Input CP found: handle 0x%04x", value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->aud_ip_cp)
+			return;
+
+		aics->aud_ip_cp = attr;
+
+		return;
+	}
+
+	if (!bt_uuid_cmp(&uuid, &uuid_ip_decs)) {
+		DBG(vcp,
+			"AICS Audio Input Description Char found: handle 0x%04x",
+			value_handle);
+
+		aics = vcp_get_aics(vcp);
+		if (!aics || aics->aud_ip_dscrptn)
+			return;
+
+		aics->aud_ip_dscrptn = attr;
+
+		vcp_read_value(vcp, value_handle,
+				read_aics_audio_ip_description, vcp);
+		vcp->aics_ip_descr_id = vcp_register_notify(vcp, value_handle,
+					aics_audio_ip_desr_notify, NULL);
+	}
+}
+
 static void foreach_vcs_service(struct gatt_db_attribute *attr,
 						void *user_data)
 {
@@ -1141,6 +2695,38 @@ static void foreach_vcs_service(struct gatt_db_attribute *attr,
 	gatt_db_service_foreach_char(attr, foreach_vcs_char, vcp);
 }
 
+static void foreach_vocs_service(struct gatt_db_attribute *attr,
+						void *user_data)
+{
+	struct bt_vcp *vcp = user_data;
+	struct bt_vocs *vocs = vcp_get_vocs(vcp);
+
+	if (!vocs || !attr)
+		return;
+
+	vocs->service = attr;
+
+	gatt_db_service_set_claimed(attr, true);
+
+	gatt_db_service_foreach_char(attr, foreach_vocs_char, vcp);
+}
+
+static void foreach_aics_service(struct gatt_db_attribute *attr,
+						void *user_data)
+{
+	struct bt_vcp *vcp = user_data;
+	struct bt_aics *aics = vcp_get_aics(vcp);
+
+	if (!aics || !attr)
+		return;
+
+	aics->service = attr;
+
+	gatt_db_service_set_claimed(attr, true);
+
+	gatt_db_service_foreach_char(attr, foreach_aics_char, vcp);
+}
+
 bool bt_vcp_attach(struct bt_vcp *vcp, struct bt_gatt_client *client)
 {
 	bt_uuid_t uuid;
@@ -1161,7 +2747,13 @@ bool bt_vcp_attach(struct bt_vcp *vcp, struct bt_gatt_client *client)
 		return false;
 
 	bt_uuid16_create(&uuid, VCS_UUID);
-	gatt_db_foreach_service(vcp->ldb->db, &uuid, foreach_vcs_service, vcp);
+	gatt_db_foreach_service(vcp->rdb->db, &uuid, foreach_vcs_service, vcp);
+
+	bt_uuid16_create(&uuid, VOL_OFFSET_CS_UUID);
+	gatt_db_foreach_service(vcp->rdb->db, &uuid, foreach_vocs_service, vcp);
+
+	bt_uuid16_create(&uuid, AUDIO_INPUT_CS_UUID);
+	gatt_db_foreach_service(vcp->rdb->db, &uuid, foreach_aics_service, vcp);
 
 	return true;
 }
diff --git a/src/storage.c b/src/storage.c
index 6e69be9..187ba15 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <time.h>
+#include <limits.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 
diff --git a/src/textfile.c b/src/textfile.c
index a5b9e73..8188d2e 100644
--- a/src/textfile.c
+++ b/src/textfile.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <limits.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
@@ -126,10 +127,10 @@ static inline char *find_key(char *map, size_t size, const char *key, size_t len
 	while (ptrlen > len + 1) {
 		int cmp = (icase) ? strncasecmp(ptr, key, len) : strncmp(ptr, key, len);
 		if (cmp == 0) {
-			if (ptr == map && *(ptr + len) == ' ')
-				return ptr;
-
-			if ((*(ptr - 1) == '\r' || *(ptr - 1) == '\n') &&
+			if (ptr == map) {
+				if (*(ptr + len) == ' ')
+					return ptr;
+			} else if ((*(ptr - 1) == '\r' || *(ptr - 1) == '\n') &&
 							*(ptr + len) == ' ')
 				return ptr;
 		}
diff --git a/test-driver b/test-driver
new file mode 100755
index 0000000..be73b80
--- /dev/null
+++ b/test-driver
@@ -0,0 +1,153 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 2011-2021 Free Software Foundation, Inc.
+#
+# 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, 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, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name NAME --log-file PATH --trs-file PATH
+              [--expect-failure {yes|no}] [--color-tests {yes|no}]
+              [--enable-hard-errors {yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+See the GNU Automake documentation for information.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here. We create the file first, then append to it,
+# to ameliorate tests themselves also writing to the log file. Our tests
+# don't, but others can (automake bug#35762).
+: >"$log_file"
+"$@" >>"$log_file" 2>&1
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  tweaked_estatus=1
+else
+  tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>"$log_file"
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/test/agent.py b/test/agent.py
index 57a7418..450fb20 100755
--- a/test/agent.py
+++ b/test/agent.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/example-adv-monitor b/test/example-adv-monitor
deleted file mode 100644
index a405fc7..0000000
--- a/test/example-adv-monitor
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import argparse
-import dbus
-import dbus.mainloop.glib
-import dbus.service
-import json
-import time
-
-from threading import Thread
-
-try:
-    from gi.repository import GObject  # python3
-except ImportError:
-    import gobject as GObject  # python2
-
-DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
-DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'
-
-BLUEZ_SERVICE_NAME = 'org.bluez'
-
-ADV_MONITOR_MANAGER_IFACE = 'org.bluez.AdvertisementMonitorManager1'
-ADV_MONITOR_IFACE = 'org.bluez.AdvertisementMonitor1'
-ADV_MONITOR_APP_BASE_PATH = '/org/bluez/example/adv_monitor_app'
-
-
-class AdvMonitor(dbus.service.Object):
-
-    # Indexes of the Monitor object parameters in a monitor data list.
-    MONITOR_TYPE = 0
-    RSSI_FILTER = 1
-    PATTERNS = 2
-
-    # Indexes of the RSSI filter parameters in a monitor data list.
-    RSSI_H_THRESH = 0
-    RSSI_H_TIMEOUT = 1
-    RSSI_L_THRESH = 2
-    RSSI_L_TIMEOUT = 3
-
-    # Indexes of the Patterns filter parameters in a monitor data list.
-    PATTERN_START_POS = 0
-    PATTERN_AD_TYPE = 1
-    PATTERN_DATA = 2
-
-    def __init__(self, bus, app_path, monitor_id, monitor_data):
-        self.path = app_path + '/monitor' + str(monitor_id)
-        self.bus = bus
-
-        self._set_type(monitor_data[self.MONITOR_TYPE])
-        self._set_rssi(monitor_data[self.RSSI_FILTER])
-        self._set_patterns(monitor_data[self.PATTERNS])
-
-        super(AdvMonitor, self).__init__(self.bus, self.path)
-
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-
-    def get_properties(self):
-        properties = dict()
-        properties['Type'] = dbus.String(self.monitor_type)
-        properties['RSSIHighThreshold'] = dbus.Int16(self.rssi_h_thresh)
-        properties['RSSIHighTimeout'] = dbus.UInt16(self.rssi_h_timeout)
-        properties['RSSILowThreshold'] = dbus.Int16(self.rssi_l_thresh)
-        properties['RSSILowTimeout'] = dbus.UInt16(self.rssi_l_timeout)
-        properties['Patterns'] = dbus.Array(self.patterns, signature='(yyay)')
-        return {ADV_MONITOR_IFACE: properties}
-
-
-    def _set_type(self, monitor_type):
-        self.monitor_type = monitor_type
-
-
-    def _set_rssi(self, rssi):
-        self.rssi_h_thresh = rssi[self.RSSI_H_THRESH]
-        self.rssi_h_timeout = rssi[self.RSSI_H_TIMEOUT]
-        self.rssi_l_thresh = rssi[self.RSSI_L_THRESH]
-        self.rssi_l_timeout = rssi[self.RSSI_L_TIMEOUT]
-
-
-    def _set_patterns(self, patterns):
-        self.patterns = []
-        for pattern in patterns:
-            start_pos = dbus.Byte(pattern[self.PATTERN_START_POS])
-            ad_type = dbus.Byte(pattern[self.PATTERN_AD_TYPE])
-            ad_data = []
-            for byte in pattern[self.PATTERN_DATA]:
-                ad_data.append(dbus.Byte(byte))
-            adv_pattern = dbus.Struct((start_pos, ad_type, ad_data),
-                                      signature='yyay')
-            self.patterns.append(adv_pattern)
-
-
-    def remove_monitor(self):
-        self.remove_from_connection()
-
-
-    @dbus.service.method(DBUS_PROP_IFACE,
-                         in_signature='s',
-                         out_signature='a{sv}')
-    def GetAll(self, interface):
-        print('{}: {} GetAll'.format(self.path, interface))
-        if interface != ADV_MONITOR_IFACE:
-            print('{}: GetAll: Invalid arg {}'.format(self.path, interface))
-            return {}
-
-        return self.get_properties()[ADV_MONITOR_IFACE]
-
-
-    @dbus.service.method(ADV_MONITOR_IFACE,
-                         in_signature='',
-                         out_signature='')
-    def Activate(self):
-        print('{}: Monitor Activated'.format(self.path))
-
-
-    @dbus.service.method(ADV_MONITOR_IFACE,
-                         in_signature='',
-                         out_signature='')
-    def Release(self):
-        print('{}: Monitor Released'.format(self.path))
-
-
-    @dbus.service.method(ADV_MONITOR_IFACE,
-                         in_signature='o',
-                         out_signature='')
-    def DeviceFound(self, device):
-        print('{}: {} Device Found'.format(self.path, device))
-
-
-    @dbus.service.method(ADV_MONITOR_IFACE,
-                         in_signature='o',
-                         out_signature='')
-    def DeviceLost(self, device):
-        print('{}: {} Device Lost'.format(self.path, device))
-
-
-class AdvMonitorApp(dbus.service.Object):
-
-    def __init__(self, bus, advmon_manager, app_id):
-        self.bus = bus
-        self.advmon_mgr = advmon_manager
-        self.app_path = ADV_MONITOR_APP_BASE_PATH + str(app_id)
-
-        self.monitors = dict()
-
-        super(AdvMonitorApp, self).__init__(self.bus, self.app_path)
-
-
-    def get_app_path(self):
-        return dbus.ObjectPath(self.app_path)
-
-
-    def add_monitor(self, monitor_data):
-        monitor_id = 0
-        while monitor_id in self.monitors:
-            monitor_id += 1
-
-        monitor = AdvMonitor(self.bus, self.app_path, monitor_id, monitor_data)
-
-        # Emit the InterfacesAdded signal once the Monitor object is created.
-        self.InterfacesAdded(monitor.get_path(), monitor.get_properties())
-
-        self.monitors[monitor_id] = monitor
-
-        return monitor_id
-
-
-    def remove_monitor(self, monitor_id):
-        monitor = self.monitors.pop(monitor_id, None)
-        if not monitor:
-            return False
-
-        # Emit the InterfacesRemoved signal before removing the Monitor object.
-        self.InterfacesRemoved(monitor.get_path(),
-                               monitor.get_properties().keys())
-
-        monitor.remove_monitor()
-
-        return True
-
-
-    def register_app(self):
-        self.register_successful = None
-
-        def register_cb():
-            print('{}: RegisterMonitor successful'.format(self.app_path))
-            self.register_successful = True
-
-        def register_error_cb(error):
-            print('{}: RegisterMonitor failed: {}'.format(self.app_path,
-                                                          str(error)))
-            self.register_successful = False
-
-        self.advmon_mgr.RegisterMonitor(self.get_app_path(),
-                                        reply_handler=register_cb,
-                                        error_handler=register_error_cb)
-
-        # Wait for the reply.
-        while self.register_successful is None:
-            pass
-
-        return self.register_successful
-
-
-    def unregister_app(self):
-        self.unregister_successful = None
-
-        def unregister_cb():
-            print('{}: UnregisterMonitor successful'.format(self.app_path))
-            self.unregister_successful = True
-
-        def unregister_error_cb(error):
-            print('{}: UnregisterMonitor failed: {}'.format(self.app_path,
-                                                            str(error)))
-            self.unregister_successful = False
-
-        self.advmon_mgr.UnregisterMonitor(self.get_app_path(),
-                                          reply_handler=unregister_cb,
-                                          error_handler=unregister_error_cb)
-
-        # Wait for the reply.
-        while self.unregister_successful is None:
-            pass
-
-        return self.unregister_successful
-
-
-    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
-    def GetManagedObjects(self):
-        print('{}: GetManagedObjects'.format(self.app_path))
-        objects = dict()
-        for monitor_id in self.monitors:
-            monitor = self.monitors[monitor_id]
-            objects[monitor.get_path()] = monitor.get_properties()
-
-        return objects
-
-
-    @dbus.service.signal(DBUS_OM_IFACE, signature='oa{sa{sv}}')
-    def InterfacesAdded(self, object_path, interfaces_and_properties):
-        # Invoking this method emits the InterfacesAdded signal,
-        # nothing needs to be done here.
-        return
-
-
-    @dbus.service.signal(DBUS_OM_IFACE, signature='oas')
-    def InterfacesRemoved(self, object_path, interfaces):
-        # Invoking this method emits the InterfacesRemoved signal,
-        # nothing needs to be done here.
-        return
-
-
-def read_adapter_supported_monitor_types(adapter_props):
-    types = json.dumps(adapter_props.Get(ADV_MONITOR_MANAGER_IFACE,
-                       'SupportedMonitorTypes',
-                       dbus_interface=DBUS_PROP_IFACE))
-    return json.loads(types)
-
-
-def read_adapter_supported_monitor_features(adapter_props):
-    features = json.dumps(adapter_props.Get(ADV_MONITOR_MANAGER_IFACE,
-                          'SupportedFeatures',
-                          dbus_interface=DBUS_PROP_IFACE))
-    return json.loads(features)
-
-
-def print_supported_types_and_features(adapter_props):
-    supported_types = read_adapter_supported_monitor_types(adapter_props)
-    for supported_type in supported_types:
-        print(supported_type)
-
-    supported_features = read_adapter_supported_monitor_features(adapter_props)
-    for supported_feature in supported_features:
-        print(supported_feature)
-
-
-def find_advmon_mgr(bus, adapter):
-    return dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
-                          ADV_MONITOR_MANAGER_IFACE)
-
-
-def find_adapter(bus):
-    remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
-                                DBUS_OM_IFACE)
-    objects = remote_om.GetManagedObjects()
-
-    adapter = None
-    adapter_props = None
-
-    for o, props in objects.items():
-        if ADV_MONITOR_MANAGER_IFACE in props:
-            adapter = o
-            break
-
-    if adapter:
-        # Turn on the bluetooth adapter.
-        adapter_props = dbus.Interface(
-                                bus.get_object(BLUEZ_SERVICE_NAME, adapter),
-                                DBUS_PROP_IFACE)
-        adapter_props.Set('org.bluez.Adapter1', 'Powered', dbus.Boolean(1))
-
-    return adapter, adapter_props
-
-
-def test(bus, mainloop, advmon_mgr, app_id):
-    # Create an App instance.
-    app = AdvMonitorApp(bus, advmon_mgr, app_id)
-
-    # Create two monitor objects before registering the app. No Activate() or
-    # Release() should get called yet as the app is not registered.
-    data0 = [
-        'invalid_patterns',
-        [-50, 1, -70, 1],
-        [[0, 0x03, [0x12, 0x18]]] # Service Class UUID is 0x1812 (HOG)
-    ]
-    data1 = [
-        'or_patterns',
-        [127, 0, 127, 0],
-        [[5, 0x09, [ord('_')]]] # 5th character of the Local Name is '_'
-    ]
-    monitor0 = app.add_monitor(data0)
-    monitor1 = app.add_monitor(data1)
-
-    # Register the app root path to expose advertisement monitors.
-    # Release() should get called on monitor0 - incorrect monitor type.
-    # Activate() should get called on monitor1.
-    ret = app.register_app()
-    if not ret:
-        print('RegisterMonitor failed.')
-        mainloop.quit()
-        exit(-1)
-
-    # Create two more monitor objects.
-    # Release() should get called on monitor2 - incorrect RSSI Filter values.
-    # Activate() should get called on monitor3.
-    data2 = [
-        'or_patterns',
-        [-50, 1, -30, 1],
-        [[0, 0x19, [0xC2, 0x03]]] # Appearance is 0xC203 (Mouse)
-    ]
-    data3 = [
-        'or_patterns',
-        [-50, 1, -70, 1],
-        [[0, 0x03, [0x12, 0x18]], [0, 0x19, [0xC2, 0x03]]]
-    ]
-    monitor2 = app.add_monitor(data2)
-    monitor3 = app.add_monitor(data3)
-
-    # Run until user hits the 'Enter' key. If any peer device is advertising
-    # during this time, DeviceFound() should get triggered for monitors
-    # matching the advertisements.
-    raw_input('Press "Enter" key to quit...\n')
-
-    # Remove a monitor. DeviceFound() for this monitor should not get
-    # triggered any more.
-    app.remove_monitor(monitor1)
-
-    # Unregister the app. Release() should get invoked on active monitors,
-    # monitor3 in this case.
-    app.unregister_app()
-
-    mainloop.quit()
-
-
-def main(app_id):
-    # Initialize threads in gobject/dbus-glib before creating local threads.
-    GObject.threads_init()
-    dbus.mainloop.glib.threads_init()
-
-    # Arrange for the GLib main loop to be the default.
-    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-    bus = dbus.SystemBus()
-    mainloop = GObject.MainLoop()
-
-    # Find bluetooth adapter and power it on.
-    adapter, adapter_props = find_adapter(bus)
-    if not adapter or not adapter_props:
-        print('Bluetooth adapter not found.')
-        exit(-1)
-
-    # Read supported types and find AdvertisementMonitorManager1 interface.
-    print_supported_types_and_features(adapter_props)
-    advmon_mgr = find_advmon_mgr(bus, adapter)
-    if not advmon_mgr :
-        print('AdvertisementMonitorManager1 interface not found.')
-        exit(-1)
-
-    Thread(target=test, args=(bus, mainloop, advmon_mgr, app_id)).start()
-
-    mainloop.run() # blocks until mainloop.quit() is called
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--app_id', default=0, type=int, help='use this App-ID '
-                        'for creating dbus objects (default: 0)')
-    args = parser.parse_args()
-
-    main(args.app_id)
diff --git a/test/example-advertisement b/test/example-advertisement
index 5f022ee..9107012 100755
--- a/test/example-advertisement
+++ b/test/example-advertisement
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/example-battery-provider b/test/example-battery-provider
deleted file mode 100755
index 1522a5e..0000000
--- a/test/example-battery-provider
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import dbus
-import dbus.exceptions
-import dbus.mainloop.glib
-import dbus.service
-
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
-import sys
-
-mainloop = None
-app = None
-bus = None
-
-BLUEZ_SERVICE_NAME = 'org.bluez'
-DBUS_OM_IFACE =      'org.freedesktop.DBus.ObjectManager'
-DBUS_PROP_IFACE =    'org.freedesktop.DBus.Properties'
-
-BATTERY_PROVIDER_MANAGER_IFACE = 'org.bluez.BatteryProviderManager1'
-BATTERY_PROVIDER_IFACE = 'org.bluez.BatteryProvider1'
-BATTERY_PROVIDER_PATH = '/path/to/provider'
-
-BATTERY_PATH1 = '11_11_11_11_11_11'
-BATTERY_PATH2 = '22_22_22_22_22_22'
-BATTERY_PATH3 = '33_33_33_33_33_33'
-
-class InvalidArgsException(dbus.exceptions.DBusException):
-    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'
-
-
-class Application(dbus.service.Object):
-    def __init__(self, bus):
-        self.path = BATTERY_PROVIDER_PATH
-        self.services = []
-        self.batteries = []
-        dbus.service.Object.__init__(self, bus, self.path)
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    def add_battery(self, battery):
-        self.batteries.append(battery)
-        self.InterfacesAdded(battery.get_path(), battery.get_properties())
-        GObject.timeout_add(1000, drain_battery, battery)
-
-    def remove_battery(self, battery):
-        self.batteries.remove(battery)
-        self.InterfacesRemoved(battery.get_path(), [BATTERY_PROVIDER_IFACE])
-
-    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
-    def GetManagedObjects(self):
-        response = {}
-        print('GetManagedObjects called')
-
-        for battery in self.batteries:
-            response[battery.get_path()] = battery.get_properties()
-
-        return response
-
-    @dbus.service.signal(DBUS_OM_IFACE, signature='oa{sa{sv}}')
-    def InterfacesAdded(self, object_path, interfaces_and_properties):
-        return
-
-    @dbus.service.signal(DBUS_OM_IFACE, signature='oas')
-    def InterfacesRemoved(self, object_path, interfaces):
-        return
-
-
-class Battery(dbus.service.Object):
-    """
-    org.bluez.BatteryProvider1 interface implementation
-    """
-    def __init__(self, bus, dev, percentage, source = None):
-        self.path = BATTERY_PROVIDER_PATH + '/dev_' + dev
-        self.dev_path = '/org/bluez/hci0/dev_' + dev
-        self.bus = bus
-        self.percentage = percentage
-        self.source = source
-        dbus.service.Object.__init__(self, bus, self.path)
-
-    def get_battery_properties(self):
-        properties = {}
-        if self.percentage != None:
-            properties['Percentage'] = dbus.Byte(self.percentage)
-        if self.source != None:
-            properties['Source'] = self.source
-        properties['Device'] = dbus.ObjectPath(self.dev_path)
-        return properties
-
-    def get_properties(self):
-        return { BATTERY_PROVIDER_IFACE: self.get_battery_properties() }
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    def set_percentage(self, percentage):
-        if percentage < 0 or percentage > 100:
-            print('percentage not valid')
-            return
-
-        self.percentage = percentage
-        print('battery %s percentage %d' % (self.path, self.percentage))
-        self.PropertiesChanged(
-                BATTERY_PROVIDER_IFACE, self.get_battery_properties())
-
-    @dbus.service.method(DBUS_PROP_IFACE,
-                         in_signature='s',
-                         out_signature='a{sv}')
-    def GetAll(self, interface):
-        if interface != BATTERY_PROVIDER_IFACE:
-            raise InvalidArgsException()
-
-        return self.get_properties()[BATTERY_PROVIDER_IFACE]
-
-    @dbus.service.signal(DBUS_PROP_IFACE, signature='sa{sv}')
-    def PropertiesChanged(self, interface, properties):
-        return
-
-
-def add_late_battery():
-    app.add_battery(Battery(bus, BATTERY_PATH3, 70, 'Protocol 2'))
-
-
-def drain_battery(battery):
-    new_percentage = 100
-    if battery.percentage != None:
-        new_percentage = battery.percentage - 5
-        if new_percentage < 0:
-            new_percentage = 0
-
-    battery.set_percentage(new_percentage)
-
-    if new_percentage <= 0:
-        return False
-
-    return True
-
-def register_provider_cb():
-    print('Battery Provider registered')
-
-    # Battery added early right after RegisterBatteryProvider succeeds
-    app.add_battery(Battery(bus, BATTERY_PATH2, None))
-    # Battery added later
-    GObject.timeout_add(5000, add_late_battery)
-
-
-def register_provider_error_cb(error):
-    print('Failed to register Battery Provider: ' + str(error))
-    mainloop.quit()
-
-
-def find_manager(bus):
-    remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
-                               DBUS_OM_IFACE)
-    objects = remote_om.GetManagedObjects()
-
-    for o, props in objects.items():
-        if BATTERY_PROVIDER_MANAGER_IFACE in props.keys():
-            return o
-
-    return None
-
-
-def unregister_provider_cb():
-    print('Battery Provider unregistered')
-
-
-def unregister_provider_error_cb(error):
-    print('Failed to unregister Battery Provider: ' + str(error))
-
-
-def unregister_battery_provider(battery_provider_manager):
-    battery_provider_manager.UnregisterBatteryProvider(BATTERY_PROVIDER_PATH,
-                                    reply_handler=unregister_provider_cb,
-                                    error_handler=unregister_provider_error_cb)
-
-
-def remove_battery(app, battery):
-    app.remove_battery(battery)
-
-
-"""
-Simulates an application registering to BlueZ as a Battery Provider providing
-fake batteries drained periodically.
-"""
-def main():
-    global mainloop, bus, app
-
-    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-    bus = dbus.SystemBus()
-
-    manager_path = find_manager(bus)
-    if not manager_path:
-        print('BatteryProviderManager1 interface not found')
-        return
-
-    print('BatteryProviderManager1 path = ', manager_path)
-
-    battery_provider_manager = dbus.Interface(
-            bus.get_object(BLUEZ_SERVICE_NAME, manager_path),
-            BATTERY_PROVIDER_MANAGER_IFACE)
-
-    app = Application(bus)
-
-    # Battery pre-added before RegisterBatteryProvider
-    battery1 = Battery(bus, BATTERY_PATH1, 87, 'Protocol 1')
-    app.add_battery(battery1)
-
-    mainloop = GObject.MainLoop()
-
-    print('Registering Battery Provider...')
-
-    battery_provider_manager.RegisterBatteryProvider(BATTERY_PROVIDER_PATH,
-                                    reply_handler=register_provider_cb,
-                                    error_handler=register_provider_error_cb)
-
-    # Unregister the Battery Provider after an arbitrary amount of time
-    GObject.timeout_add(
-            12000, unregister_battery_provider, battery_provider_manager)
-    # Simulate battery removal by a provider
-    GObject.timeout_add(8000, remove_battery, app, battery1)
-
-    mainloop.run()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/test/example-endpoint b/test/example-endpoint
deleted file mode 100644
index 16651c6..0000000
--- a/test/example-endpoint
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import sys
-import dbus
-import dbus.exceptions
-import dbus.service
-import dbus.mainloop.glib
-
-import array
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
-import bluezutils
-
-ENDPOINT_IFACE =     'org.bluez.MediaEndpoint1'
-DBUS_OM_IFACE =      'org.freedesktop.DBus.ObjectManager'
-DBUS_PROP_IFACE =    'org.freedesktop.DBus.Properties'
-
-A2DP_SOURCE_UUID =   '0000110A-0000-1000-8000-00805F9B34FB'
-A2DP_SINK_UUID =     '0000110B-0000-1000-8000-00805F9B34FB'
-
-SBC_CODEC = dbus.Byte(0x00)
-#Channel Modes: Mono DualChannel Stereo JointStereo
-#Frequencies: 16Khz 32Khz 44.1Khz 48Khz
-#Subbands: 4 8
-#Blocks: 4 8 12 16
-#Bitpool Range: 2-64
-SBC_CAPABILITIES = dbus.Array([dbus.Byte(0xff), dbus.Byte(0xff), dbus.Byte(2), dbus.Byte(64)])
-# JointStereo 44.1Khz Subbands: Blocks: 16 Bitpool Range: 2-32
-SBC_CONFIGURATION = dbus.Array([dbus.Byte(0x21), dbus.Byte(0x15), dbus.Byte(2), dbus.Byte(32)])
-
-MP3_CODEC = dbus.Byte(0x01)
-#Channel Modes: Mono DualChannel Stereo JointStereo
-#Frequencies: 32Khz 44.1Khz 48Khz
-#CRC: YES
-#Layer: 3
-#Bit Rate: All except Free format
-#VBR: Yes
-#Payload Format: RFC-2250
-MP3_CAPABILITIES = dbus.Array([dbus.Byte(0x3f), dbus.Byte(0x07), dbus.Byte(0xff), dbus.Byte(0xfe)])
-# JointStereo 44.1Khz Layer: 3 Bit Rate: VBR Format: RFC-2250
-MP3_CONFIGURATION = dbus.Array([dbus.Byte(0x21), dbus.Byte(0x02), dbus.Byte(0x00), dbus.Byte(0x80)])
-
-PCM_CODEC = dbus.Byte(0x00)
-PCM_CONFIGURATION = dbus.Array([], signature="ay")
-
-CVSD_CODEC = dbus.Byte(0x01)
-
-class Rejected(dbus.DBusException):
-    _dbus_error_name = "org.bluez.Error.Rejected"
-
-class InvalidArgsException(dbus.exceptions.DBusException):
-    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'
-
-class Endpoint(dbus.service.Object):
-    def __init__(self, bus, path, properties, configuration):
-        self.path = path
-        self.bus = bus
-        self.properties = properties
-        self.configuration = configuration
-        self.exit_on_release = True
-        dbus.service.Object.__init__(self, bus, self.path)
-
-    def get_properties(self):
-        return self.properties
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    @dbus.service.method(DBUS_PROP_IFACE, in_signature='s',
-                         out_signature='a{sv}')
-    def GetAll(self, interface):
-        if interface != ENDPOINT_IFACE:
-            raise InvalidArgsException()
-
-        return self.get_properties()
-
-    def set_exit_on_release(self, exit_on_release):
-        self.exit_on_release = exit_on_release
-
-    def default_configuration(self, configuration):
-        self.configuration = configuration
-
-    @dbus.service.method(ENDPOINT_IFACE, in_signature="", out_signature="")
-    def Release(self):
-        print("Release")
-        if self.exit_on_release:
-            mainloop.quit()
-
-    @dbus.service.method(ENDPOINT_IFACE, in_signature="o", out_signature="")
-    def ClearConfiguration(self, transport):
-        print("ClearConfiguration (%s)" % (transport))
-
-    @dbus.service.method(ENDPOINT_IFACE, in_signature="oay", out_signature="")
-    def SetConfiguration(self, transport, config):
-        print("SetConfiguration (%s, %s)" % (transport, config))
-        return
-
-    @dbus.service.method(ENDPOINT_IFACE, in_signature="ay", out_signature="ay")
-    def SelectConfiguration(self, caps):
-        print("SelectConfiguration (%s)" % (caps))
-        return self.configuration
-
-class Application(dbus.service.Object):
-    def __init__(self, bus, path, properties, configuration):
-        self.path = '/'
-        self.endpoints = []
-        dbus.service.Object.__init__(self, bus, self.path)
-        self.add_endpoint(Endpoint(bus, path, properties, configuration))
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    def add_endpoint(self, endpoint):
-        self.endpoints.append(endpoint)
-
-    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
-    def GetManagedObjects(self):
-        response = {}
-        print('GetManagedObjects')
-
-        for endpoint in self.endpoints:
-            response[endpoint.get_path()] = { ENDPOINT_IFACE:
-                                              endpoint.get_properties() }
-
-        return response
-
-def register_app_cb():
-    print('Media application registered')
-
-
-def register_app_error_cb(error):
-    print('Failed to register application: ' + str(error))
-    mainloop.quit()
-
-if __name__ == '__main__':
-    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-    bus = dbus.SystemBus()
-
-    if len(sys.argv) > 1:
-            path = bluezutils.find_adapter(sys.argv[1]).object_path
-    else:
-            path = bluezutils.find_adapter().object_path
-
-    media = dbus.Interface(bus.get_object("org.bluez", path),
-                           "org.bluez.Media1")
-
-
-    properties = dbus.Dictionary({ "UUID" : A2DP_SOURCE_UUID,
-                                   "Codec" : SBC_CODEC,
-                                   "DelayReporting" : True,
-                                   "Capabilities" : SBC_CAPABILITIES })
-
-    configuration = SBC_CONFIGURATION
-
-    if len(sys.argv) > 2:
-        if sys.argv[2] == "sbcsink":
-            properties = dbus.Dictionary({ "UUID" : A2DP_SINK_UUID,
-                                           "Codec" : SBC_CODEC,
-                                           "DelayReporting" : True,
-                                           "Capabilities" : SBC_CAPABILITIES })
-        if sys.argv[2] == "mp3source":
-            properties = dbus.Dictionary({ "UUID" : A2DP_SOURCE_UUID,
-                                           "Codec" : MP3_CODEC,
-                                           "Capabilities" : MP3_CAPABILITIES })
-            configuration = MP3_CONFIGURATION
-        if sys.argv[2] == "mp3sink":
-            properties = dbus.Dictionary({ "UUID" : A2DP_SINK_UUID,
-                                           "Codec" : MP3_CODEC,
-                                           "Capabilities" : MP3_CAPABILITIES })
-            configuration = MP3_CONFIGURATION
-
-    print(properties)
-
-    path = "/test/endpoint"
-    app = Application(bus, path, properties, configuration)
-    mainloop = GObject.MainLoop()
-
-    media.RegisterApplication(app.get_path(), {},
-                                reply_handler=register_app_cb,
-                                error_handler=register_app_error_cb)
-    mainloop.run()
diff --git a/test/example-gatt-client b/test/example-gatt-client
index 5e6bef9..38ca97e 100755
--- a/test/example-gatt-client
+++ b/test/example-gatt-client
@@ -2,10 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import dbus
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
+from gi.repository import GLib
 import sys
 
 from dbus.mainloop.glib import DBusGMainLoop
@@ -189,7 +186,7 @@ def main():
     global bus
     bus = dbus.SystemBus()
     global mainloop
-    mainloop = GObject.MainLoop()
+    mainloop = GLib.MainLoop()
 
     om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'), DBUS_OM_IFACE)
     om.connect_to_signal('InterfacesRemoved', interfaces_removed_cb)
diff --git a/test/example-gatt-server b/test/example-gatt-server
index 77231c3..83b7009 100755
--- a/test/example-gatt-server
+++ b/test/example-gatt-server
@@ -7,10 +7,7 @@ import dbus.mainloop.glib
 import dbus.service
 
 import array
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
+from gi.repository import GLib
 import sys
 
 from random import randint
@@ -305,7 +302,7 @@ class HeartRateMeasurementChrc(Characteristic):
         if not self.notifying:
             return
 
-        GObject.timeout_add(1000, self.hr_msrmt_cb)
+        GLib.timeout_add(1000, self.hr_msrmt_cb)
 
     def StartNotify(self):
         if self.notifying:
@@ -392,7 +389,7 @@ class BatteryLevelCharacteristic(Characteristic):
                 service)
         self.notifying = False
         self.battery_lvl = 100
-        GObject.timeout_add(5000, self.drain_battery)
+        GLib.timeout_add(5000, self.drain_battery)
 
     def notify_battery_level(self):
         if not self.notifying:
@@ -649,7 +646,7 @@ def main():
 
     app = Application(bus)
 
-    mainloop = GObject.MainLoop()
+    mainloop = GLib.MainLoop()
 
     print('Registering GATT application...')
 
diff --git a/test/example-player b/test/example-player
deleted file mode 100644
index 1497d11..0000000
--- a/test/example-player
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-from __future__ import print_function
-
-import os
-import sys
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
-import bluezutils
-
-PLAYER_IFACE =       'org.mpris.MediaPlayer2.Player'
-DBUS_OM_IFACE =      'org.freedesktop.DBus.ObjectManager'
-DBUS_PROP_IFACE =    'org.freedesktop.DBus.Properties'
-
-class InvalidArgsException(dbus.exceptions.DBusException):
-    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'
-
-class Player(dbus.service.Object):
-    def __init__(self, bus, path, obj):
-        self.path = path
-        dbus.service.Object.__init__(self, bus, self.path)
-
-        if obj != None:
-            mp = dbus.Interface(bus.get_object("org.bluez", obj),
-                                                "org.bluez.MediaPlayer1")
-            prop = dbus.Interface(bus.get_object("org.bluez", obj),
-                                  "org.freedesktop.DBus.Properties")
-
-            self.properties = prop.GetAll("org.bluez.MediaPlayer1")
-
-            bus.add_signal_receiver(self.properties_changed, path = obj,
-                            dbus_interface = "org.freedesktop.DBus.Properties",
-                            signal_name = "PropertiesChanged")
-        else:
-            self.track = dbus.Dictionary({"xesam:title" : "Title",
-                                     "xesam:artist" : ["Artist"],
-                                     "xesam:album" : "Album",
-                                     "xesam:genre" : ["Genre"],
-                                     "xesam:trackNumber" : dbus.Int32(1),
-                                     "mpris:length" : dbus.Int64(10000) },
-                                     signature="sv")
-
-            self.properties = dbus.Dictionary({"PlaybackStatus" : "playing",
-                                        "Identity" : "SimplePlayer",
-                                        "LoopStatus" : "None",
-                                        "Rate" : dbus.Double(1.0),
-                                        "Shuffle" : dbus.Boolean(False),
-                                        "Metadata" : self.track,
-                                        "Volume" : dbus.Double(1.0),
-                                        "Position" : dbus.Int64(0),
-                                        "MinimumRate" : dbus.Double(1.0),
-                                        "MaximumRate" : dbus.Double(1.0),
-                                        "CanGoNext" : dbus.Boolean(False),
-                                        "CanGoPrevious" : dbus.Boolean(False),
-                                        "CanPlay" : dbus.Boolean(False),
-                                        "CanSeek" : dbus.Boolean(False),
-                                        "CanControl" : dbus.Boolean(False),
-                                        },
-                                        signature="sv")
-
-        print('Register media player with:\n\tProperties: %s' \
-              % (self.properties))
-        handler = InputHandler(self)
-        GObject.io_add_watch(sys.stdin, GObject.IO_IN, handler.handle)
-
-    @dbus.service.method("org.freedesktop.DBus.Properties",
-                         in_signature="ssv", out_signature="")
-    def Set(self, interface, key, value):
-        print("Set (%s, %s)" % (key, value), file=sys.stderr)
-        return
-
-    def get_properties(self):
-        return self.properties
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    @dbus.service.method("org.freedesktop.DBus.Properties",
-                         in_signature='s', out_signature='a{sv}')
-    def GetAll(self, interface):
-        if interface != PLAYER_IFACE:
-            raise InvalidArgsException()
-
-        return self.get_properties()
-
-    @dbus.service.signal("org.freedesktop.DBus.Properties",
-                         signature="sa{sv}as")
-    def PropertiesChanged(self, interface, properties,
-                          invalidated = dbus.Array()):
-        """PropertiesChanged(interface, properties, invalidated)
-
-        Send a PropertiesChanged signal. 'properties' is a dictionary
-        containing string parameters as specified in doc/media-api.txt.
-        """
-        pass
-
-    def help(self, func):
-        help(self.__class__.__dict__[func])
-
-    def properties_changed(self, interface, properties, invalidated):
-        print("properties_changed(%s, %s)" % (properties, invalidated))
-
-        self.PropertiesChanged(interface, properties, invalidated)
-
-class InputHandler:
-    commands = { 'PropertiesChanged': '(interface, properties)',
-                        'help': '(cmd)' }
-    def __init__(self, player):
-        self.player = player
-        print('\n\nAvailable commands:')
-        for cmd in self.commands:
-                print('\t', cmd, self.commands[cmd], sep='')
-
-        print("\nUse python syntax to pass arguments to available methods.\n" \
-                "E.g.: PropertiesChanged({'Metadata' : {'Title': 'My title', \
-                'Album': 'my album' }})")
-        self.prompt()
-
-    def prompt(self):
-        print('\n>>> ', end='')
-        sys.stdout.flush()
-
-    def handle(self, fd, condition):
-        s = os.read(fd.fileno(), 1024).strip()
-        try:
-            cmd = s[:s.find('(')]
-            if not cmd in self.commands:
-                print("Unknown command ", cmd)
-        except ValueError:
-            print("Malformed command")
-            return True
-        try:
-            exec "self.player.%s" % s
-        except Exception as e:
-            print(e)
-            pass
-        self.prompt()
-        return True
-
-class Application(dbus.service.Object):
-    def __init__(self, bus, path, obj):
-        self.path = '/'
-        self.players = []
-        dbus.service.Object.__init__(self, bus, self.path)
-        self.add_player(Player(bus, path, obj))
-
-    def get_path(self):
-        return dbus.ObjectPath(self.path)
-
-    def add_player(self, player):
-        self.players.append(player)
-
-    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
-    def GetManagedObjects(self):
-        response = {}
-        print('GetManagedObjects')
-
-        for player in self.players:
-            response[player.get_path()] = { PLAYER_IFACE:
-                                            player.get_properties() }
-
-        return response
-
-def register_app_cb():
-    print('Media application registered')
-
-
-def register_app_error_cb(error):
-    print('Failed to register application: ' + str(error))
-    mainloop.quit()
-
-if __name__ == '__main__':
-    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-    bus = dbus.SystemBus()
-
-    if len(sys.argv) > 1:
-        path = bluezutils.find_adapter(sys.argv[1]).object_path
-    else:
-        path = bluezutils.find_adapter().object_path
-
-    media = dbus.Interface(bus.get_object("org.bluez", path),
-                           "org.bluez.Media1")
-
-    path = "/test/player"
-
-    if len(sys.argv) > 2:
-        app = Application(bus, path, sys.argv[2])
-    else:
-        app = Application(bus, path, None)
-
-    mainloop = GObject.MainLoop()
-
-    media.RegisterApplication(app.get_path(), {},
-                                reply_handler=register_app_cb,
-                                error_handler=register_app_error_cb)
-
-    mainloop.run()
diff --git a/test/exchange-business-cards b/test/exchange-business-cards
deleted file mode 100755
index 9a3aa29..0000000
--- a/test/exchange-business-cards
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import sys
-import dbus
-
-bus = dbus.SessionBus()
-client = dbus.Interface(bus.get_object("org.bluez.obex", "/org/bluez/obex"),
-					"org.bluez.obex.Client")
-
-if (len(sys.argv) < 4):
-	print "Usage: %s <device> <clientfile> <file>" % (sys.argv[0])
-	sys.exit(1)
-
-print "Creating Session"
-path = client.CreateSession(sys.argv[1], { "Target": "OPP" })
-opp = dbus.Interface(bus.get_object("org.bluez.obex", path),
-					"org.bluez.obex.ObjectPush")
-
-opp.ExchangeBusinessCards(sys.argv[2], sys.argv[3])
diff --git a/test/ftp-client b/test/ftp-client
index ef756ab..e37c027 100755
--- a/test/ftp-client
+++ b/test/ftp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-managed-objects b/test/get-managed-objects
deleted file mode 100755
index 5125ee5..0000000
--- a/test/get-managed-objects
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import dbus
-
-bus = dbus.SystemBus()
-
-manager = dbus.Interface(bus.get_object("org.bluez", "/"),
-					"org.freedesktop.DBus.ObjectManager")
-
-objects = manager.GetManagedObjects()
-
-for path in objects.keys():
-	print("[ %s ]" % (path))
-
-	interfaces = objects[path]
-
-	for interface in interfaces.keys():
-		if interface in ["org.freedesktop.DBus.Introspectable",
-					"org.freedesktop.DBus.Properties"]:
-			continue
-
-		print("    %s" % (interface))
-
-		properties = interfaces[interface]
-
-		for key in properties.keys():
-			print("      %s = %s" % (key, properties[key]))
diff --git a/test/get-obex-capabilities b/test/get-obex-capabilities
deleted file mode 100755
index a7980a4..0000000
--- a/test/get-obex-capabilities
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import sys
-import dbus
-
-bus = dbus.SessionBus()
-client = dbus.Interface(bus.get_object("org.bluez.obex", "/org/bluez/obex"),
-					"org.bluez.obex.Client")
-
-if (len(sys.argv) < 3):
-	print "Usage: %s <device> <target>" % (sys.argv[0])
-	sys.exit(1)
-
-print "Creating Session"
-session_path = client.CreateSession(sys.argv[1], { "Target": sys.argv[2] })
-session = dbus.Interface(bus.get_object("org.bluez.obex", session_path),
-					"org.bluez.obex.Session")
-
-print session.GetCapabilities()
diff --git a/test/list-devices b/test/list-devices
index 618d286..a24c31c 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/list-folders b/test/list-folders
deleted file mode 100755
index b4e3f10..0000000
--- a/test/list-folders
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import sys
-import dbus
-
-
-def list_folder(folder):
-	bus = dbus.SessionBus()
-	client = dbus.Interface(bus.get_object("org.bluez.obex",
-						"/org/bluez/obex"),
-						"org.bluez.obex.Client")
-
-	path = client.CreateSession(sys.argv[1], { "Target": "ftp" })
-
-	ftp = dbus.Interface(bus.get_object("org.bluez.obex", path),
-				"org.bluez.obex.FileTransfer")
-
-	if folder:
-		for node in folder.split("/"):
-			ftp.ChangeFolder(node)
-
-	for i in ftp.ListFolder():
-		if i["Type"] == "folder":
-			print "%s/" % (i["Name"])
-		else:
-			print "%s" % (i["Name"])
-
-
-if __name__ == '__main__':
-
-	if len(sys.argv) < 2:
-		print "Usage: %s <device> [folder]" % (sys.argv[0])
-		sys.exit(1)
-
-	folder = None
-	if len(sys.argv) == 3:
-		folder = sys.argv[2]
-
-	list_folder(folder)
diff --git a/test/map-client b/test/map-client
index f44f512..b7369b0 100755
--- a/test/map-client
+++ b/test/map-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/monitor-bluetooth b/test/monitor-bluetooth
index 99f3c85..347c91a 100755
--- a/test/monitor-bluetooth
+++ b/test/monitor-bluetooth
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/opp-client b/test/opp-client
index 4f00a41..deb02c7 100755
--- a/test/opp-client
+++ b/test/opp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/pbap-client b/test/pbap-client
index e6cafdd..6dada4a 100755
--- a/test/pbap-client
+++ b/test/pbap-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/sap_client.py b/test/sap_client.py
index fed13ae..2da46ee 100644
--- a/test/sap_client.py
+++ b/test/sap_client.py
@@ -165,7 +165,7 @@ class SAPParam_ConnectionStatus(SAPParam):
 
     def __validate(self):
         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04):
-            print "Warning. ConnectionStatus value in reserved range (0x%x)" % self.value
+            print("Warning. ConnectionStatus value in reserved range (0x%x)" % self.value)
 
     def deserialize(self,  buf):
         ret = SAPParam.deserialize(self, buf)
@@ -183,7 +183,7 @@ class SAPParam_ResultCode(SAPParam):
 
     def __validate(self):
         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07):
-            print "Warning. ResultCode value in reserved range (0x%x)" % self.value
+            print("Warning. ResultCode value in reserved range (0x%x)" % self.value)
 
     def deserialize(self,  buf):
         ret = SAPParam.deserialize(self, buf)
@@ -201,7 +201,7 @@ class SAPParam_DisconnectionType(SAPParam):
 
     def __validate(self):
         if self.value is not None and self.value not in (0x00,  0x01):
-            print "Warning. DisconnectionType value in reserved range (0x%x)" % self.value
+            print("Warning. DisconnectionType value in reserved range (0x%x)" % self.value)
 
     def deserialize(self,  buf):
         ret = SAPParam.deserialize(self, buf)
@@ -227,7 +227,7 @@ class SAPParam_StatusChange(SAPParam):
 
     def __validate(self):
         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05):
-            print "Warning. StatusChange value in reserved range (0x%x)" % self.value
+            print("Warning. StatusChange value in reserved range (0x%x)" % self.value)
 
     def deserialize(self,  buf):
         ret = SAPParam.deserialize(self, buf)
@@ -245,7 +245,7 @@ class SAPParam_TransportProtocol(SAPParam):
 
     def __validate(self):
         if self.value is not None and self.value not in (0x00,  0x01):
-            print "Warning. TransportProtoco value in reserved range (0x%x)" % self.value
+            print("Warning. TransportProtoco value in reserved range (0x%x)" % self.value)
 
     def deserialize(self,  buf):
         ret = SAPParam.deserialize(self, buf)
@@ -728,7 +728,7 @@ class SAPClient:
         self.port = first_match["port"]
         self.host = first_match["host"]
 
-        print "SAP Service found on %s(%s)" % first_match["name"] % self.host
+        print("SAP Service found on %s(%s)" % first_match["name"] % self.host)
 
     def __connectRFCOMM(self):
         self.sock=BluetoothSocket( RFCOMM )
@@ -739,19 +739,19 @@ class SAPClient:
     def __sendMsg(self, msg):
         if isinstance(msg,  SAPMessage):
             s = msg.serialize()
-            print "\tTX: " + msg.getContent()
+            print("\tTX: " + msg.getContent())
             return self.sock.send(s.tostring())
 
     def __rcvMsg(self,  msg):
         if isinstance(msg,  SAPMessage):
-            print "\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id)
+            print("\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id))
             data = self.sock.recv(self.bufsize)
             if data:
                 if msg.deserialize(array('B',data)):
-                    print "\tRX: len(%d) %s" % (len(data), msg.getContent())
+                    print("\tRX: len(%d) %s" % (len(data), msg.getContent()))
                     return msg
                 else:
-                    print "msg: %s" % array('B',data)
+                    print("msg: %s" % array('B',data))
                     raise BluetoothError ("Message deserialization failed.")
             else:
                 raise BluetoothError ("Timeout. No data received.")
@@ -797,8 +797,8 @@ class SAPClient:
                     return False
             else:
                 return False
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_disconnectByClient(self, timeout=0):
@@ -808,8 +808,8 @@ class SAPClient:
             time.sleep(timeout) # let srv to close rfcomm
             self.__disconnectRFCOMM()
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_disconnectByServer(self, timeout=0):
@@ -823,8 +823,8 @@ class SAPClient:
 
             return self.proc_disconnectByClient(timeout)
 
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_transferAPDU(self,  apdu = "Sample APDU command"):
@@ -832,8 +832,8 @@ class SAPClient:
             self.__sendMsg(SAPMessage_TRANSFER_APDU_REQ(apdu))
             params = self.__rcvMsg(SAPMessage_TRANSFER_APDU_RESP()).getParams()
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_transferATR(self):
@@ -841,8 +841,8 @@ class SAPClient:
             self.__sendMsg(SAPMessage_TRANSFER_ATR_REQ())
             params = self.__rcvMsg(SAPMessage_TRANSFER_ATR_RESP()).getParams()
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_powerSimOff(self):
@@ -850,8 +850,8 @@ class SAPClient:
             self.__sendMsg(SAPMessage_POWER_SIM_OFF_REQ())
             params = self.__rcvMsg(SAPMessage_POWER_SIM_OFF_RESP()).getParams()
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_powerSimOn(self):
@@ -862,8 +862,8 @@ class SAPClient:
                 return self.proc_transferATR()
 
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_resetSim(self):
@@ -874,23 +874,23 @@ class SAPClient:
                 return self.proc_transferATR()
 
             return True
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_reportStatus(self):
         try:
             params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_transferCardReaderStatus(self):
         try:
             self.__sendMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_REQ())
             params = self.__rcvMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_RESP()).getParams()
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_errorResponse(self):
@@ -899,8 +899,8 @@ class SAPClient:
             self.__sendMsg(SAPMessage_CONNECT_REQ())
 
             params = self.__rcvMsg(SAPMessage_ERROR_RESP()).getParams()
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
     def proc_setTransportProtocol(self,  protocol = 0):
@@ -922,8 +922,8 @@ class SAPClient:
             else:
                 return False
 
-        except BluetoothError , e:
-            print "Error. " +str(e)
+        except BluetoothError as e:
+            print("Error. " +str(e))
             return False
 
 if __name__ == "__main__":
diff --git a/test/simple-agent b/test/simple-agent
index 4fdaff1..09437eb 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-endpoint b/test/simple-endpoint
index 463f124..eace428 100755
--- a/test/simple-endpoint
+++ b/test/simple-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-obex-agent b/test/simple-obex-agent
deleted file mode 100755
index 064f6d3..0000000
--- a/test/simple-obex-agent
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import sys
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
-
-BUS_NAME = 'org.bluez.obex'
-PATH = '/org/bluez/obex'
-AGENT_MANAGER_INTERFACE = 'org.bluez.obex.AgentManager1'
-AGENT_INTERFACE = 'org.bluez.obex.Agent1'
-TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
-
-def ask(prompt):
-	try:
-		return raw_input(prompt)
-	except:
-		return input(prompt)
-
-class Agent(dbus.service.Object):
-	def __init__(self, conn=None, obj_path=None):
-		dbus.service.Object.__init__(self, conn, obj_path)
-		self.pending_auth = False
-
-	@dbus.service.method(AGENT_INTERFACE, in_signature="o",
-							out_signature="s")
-	def AuthorizePush(self, path):
-		transfer = dbus.Interface(bus.get_object(BUS_NAME, path),
-					'org.freedesktop.DBus.Properties')
-		properties = transfer.GetAll(TRANSFER_INTERFACE);
-
-		self.pending_auth = True
-		auth = ask("Authorize (%s, %s) (Y/n):" % (path,
-							properties['Name']))
-
-		if auth == "n" or auth == "N":
-			self.pending_auth = False
-			raise dbus.DBusException(
-					"org.bluez.obex.Error.Rejected: "
-					"Not Authorized")
-
-		self.pending_auth = False
-
-		return properties['Name']
-
-	@dbus.service.method(AGENT_INTERFACE, in_signature="",
-							out_signature="")
-	def Cancel(self):
-		print("Authorization Canceled")
-		self.pending_auth = False
-
-if __name__ == '__main__':
-	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-	bus = dbus.SessionBus()
-	manager = dbus.Interface(bus.get_object(BUS_NAME, PATH),
-						AGENT_MANAGER_INTERFACE)
-
-	path = "/test/agent"
-	agent = Agent(bus, path)
-
-	mainloop = GObject.MainLoop()
-
-	manager.RegisterAgent(path)
-	print("Agent registered")
-
-	cont = True
-	while cont:
-		try:
-			mainloop.run()
-		except KeyboardInterrupt:
-			if agent.pending_auth:
-				agent.Cancel()
-			elif len(transfers) > 0:
-				for a in transfers:
-					a.cancel()
-			else:
-				cont = False
-
-	# manager.UnregisterAgent(path)
-	# print "Agent unregistered"
diff --git a/test/simple-player b/test/simple-player
index 9268284..8a1cb1e 100755
--- a/test/simple-player
+++ b/test/simple-player
@@ -1,7 +1,7 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-from __future__ import print_function
+
 
 import os
 import sys
@@ -78,7 +78,7 @@ class Player(dbus.service.Object):
 		"""PropertiesChanged(interface, properties, invalidated)
 
 		Send a PropertiesChanged signal. 'properties' is a dictionary
-		containing string parameters as specified in doc/media-api.txt.
+		containing string parameters as specified in doc/media-api.rst.
 		"""
 		pass
 
@@ -119,7 +119,7 @@ class InputHandler:
 			return True
 
 		try:
-			exec "self.player.%s" % s
+			exec("self.player.%s" % s)
 		except Exception as e:
 			print(e)
 			pass
diff --git a/test/test-adapter b/test/test-adapter
index c56ba95..27aff27 100755
--- a/test/test-adapter
+++ b/test/test-adapter
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-device b/test/test-device
index c840f05..8b1eb86 100755
--- a/test/test-device
+++ b/test/test-device
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-discovery b/test/test-discovery
index 54fc514..6959e7b 100755
--- a/test/test-discovery
+++ b/test/test-discovery
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-gatt-profile b/test/test-gatt-profile
index a973ae1..64ff3e5 100755
--- a/test/test-gatt-profile
+++ b/test/test-gatt-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health b/test/test-health
index 3e16c41..f26def9 100755
--- a/test/test-health
+++ b/test/test-health
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health-sink b/test/test-health-sink
index 13b9a6b..fcdc58e 100755
--- a/test/test-health-sink
+++ b/test/test-health-sink
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-hfp b/test/test-hfp
index 11e328e..e1edac0 100755
--- a/test/test-hfp
+++ b/test/test-hfp
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-join b/test/test-join
deleted file mode 100644
index 9697950..0000000
--- a/test/test-join
+++ /dev/null
@@ -1,436 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import sys
-import struct
-import numpy
-import dbus
-import dbus.service
-import dbus.exceptions
-
-from threading import Timer
-import time
-
-try:
-  from gi.repository import GObject
-except ImportError:
-  import gobject as GObject
-from dbus.mainloop.glib import DBusGMainLoop
-
-import agent
-
-MESH_SERVICE_NAME = 'org.bluez.mesh'
-DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'
-DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
-
-MESH_NETWORK_IFACE = 'org.bluez.mesh.Network1'
-MESH_NODE_IFACE = 'org.bluez.mesh.Node1'
-MESH_APPLICATION_IFACE = 'org.bluez.mesh.Application1'
-MESH_ELEMENT_IFACE = 'org.bluez.mesh.Element1'
-
-APP_COMPANY_ID = 0x05f1
-APP_PRODUCT_ID = 0x0001
-APP_VERSION_ID = 0x0001
-
-VENDOR_ID_NONE = 0xffff
-
-mesh_net = None
-app = None
-bus = None
-mainloop = None
-node = None
-
-token = None
-
-def generic_error_cb(error):
-	print('D-Bus call failed: ' + str(error))
-
-def generic_reply_cb():
-	print('D-Bus call done')
-
-def unwrap(item):
-	if isinstance(item, dbus.Boolean):
-		return bool(item)
-	if isinstance(item, (dbus.UInt16, dbus.Int16,
-			 dbus.UInt32, dbus.Int32,
-			 dbus.UInt64, dbus.Int64)):
-		return int(item)
-	if isinstance(item, dbus.Byte):
-		return bytes([int(item)])
-	if isinstance(item, dbus.String):
-		return item
-	if isinstance(item, (dbus.Array, list, tuple)):
-		return [unwrap(x) for x in item]
-	if isinstance(item, (dbus.Dictionary, dict)):
-		return dict([(unwrap(x), unwrap(y)) for x, y in item.items()])
-
-	print('Dictionary item not handled')
-	print(type(item))
-	return item
-
-def join_cb():
-	print('Join procedure started')
-
-def join_error_cb(reason):
-	print('Join procedure failed: ', reason)
-
-def attach_app_cb(node_path, dict_array):
-	print('Mesh application registered ', node_path)
-
-	obj = bus.get_object(MESH_SERVICE_NAME, node_path)
-
-	global node
-	node = dbus.Interface(obj, MESH_NODE_IFACE)
-
-	els = unwrap(dict_array)
-	print("Get Elements")
-
-	for el in els:
-		idx = struct.unpack('b', el[0])[0]
-		print('Configuration for Element ', end='')
-		print(idx)
-
-		models = el[1]
-		element = app.get_element(idx)
-		element.set_model_config(models)
-
-def attach_app_error_cb(error):
-	print('Failed to register application: ' + str(error))
-	mainloop.quit()
-
-def attach(token):
-	print('Attach')
-	mesh_net.Attach(app.get_path(), token,
-					reply_handler=attach_app_cb,
-					error_handler=attach_app_error_cb)
-
-def interfaces_removed_cb(object_path, interfaces):
-	if not mesh_net:
-		return
-
-	if object_path == mesh_net[2]:
-		print('Service was removed')
-	mainloop.quit()
-
-def send_response(path, dest, key, data):
-	print('send response ', end='')
-	print(data)
-	node.Send(path, dest, key, data, reply_handler=generic_reply_cb,
-					error_handler=generic_error_cb)
-
-def send_publication(path, model_id, data):
-	print('send publication ', end='')
-	print(data)
-	node.Publish(path, model_id, data, reply_handler=generic_reply_cb,
-			error_handler=generic_error_cb)
-
-class PubTimer():
-	def __init__(self):
-		self.seconds = None
-		self.func = None
-		self.thread = None
-		self.busy = False
-
-	def _timeout_cb(self):
-		self.func()
-		self.busy = True
-		self._schedule_timer()
-		self.busy =False
-
-	def _schedule_timer(self):
-		self.thread = Timer(self.seconds, self._timeout_cb)
-		self.thread.start()
-
-	def start(self, seconds, func):
-		self.func = func
-		self.seconds = seconds
-		if not self.busy:
-			self._schedule_timer()
-
-	def cancel(self):
-		print('Cancel timer')
-		if self.thread is not None:
-			print('Cancel thread')
-			self.thread.cancel()
-			self.thread = None
-
-class Application(dbus.service.Object):
-
-	def __init__(self, bus):
-		self.path = '/example'
-		self.agent = None
-		self.elements = []
-		dbus.service.Object.__init__(self, bus, self.path)
-
-	def set_agent(self, agent):
-		self.agent = agent
-
-	def get_path(self):
-		return dbus.ObjectPath(self.path)
-
-	def add_element(self, element):
-		self.elements.append(element)
-
-	def get_element(self, idx):
-		for ele in self.elements:
-			if ele.get_index() == idx:
-				return ele
-
-	def get_properties(self):
-		return {
-			MESH_APPLICATION_IFACE: {
-			'CompanyID': dbus.UInt16(APP_COMPANY_ID),
-			'ProductID': dbus.UInt16(APP_PRODUCT_ID),
-			'VersionID': dbus.UInt16(APP_VERSION_ID)
-			}
-		}
-
-	@dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
-
-	def GetManagedObjects(self):
-		response = {}
-		print('GetManagedObjects')
-		response[self.path] = self.get_properties()
-		response[self.agent.get_path()] = self.agent.get_properties()
-		for element in self.elements:
-			response[element.get_path()] = element.get_properties()
-		return response
-
-	@dbus.service.method(MESH_APPLICATION_IFACE,
-					in_signature="t", out_signature="")
-
-	def JoinComplete(self, value):
-		global token
-		print('JoinComplete ', value)
-
-		token = value
-		attach(token)
-
-	@dbus.service.method(MESH_APPLICATION_IFACE,
-					in_signature="s", out_signature="")
-
-	def JoinFailed(self, value):
-		print('JoinFailed ', value)
-		token = value
-
-class Element(dbus.service.Object):
-	PATH_BASE = '/example/ele'
-
-	def __init__(self, bus, index):
-		self.path = self.PATH_BASE + format(index, '02x')
-		print(self.path)
-		self.models = []
-		self.bus = bus
-		self.index = index
-		dbus.service.Object.__init__(self, bus, self.path)
-
-	def _get_sig_models(self):
-		ids = []
-		for model in self.models:
-			id = model.get_id()
-			vendor = model.get_vendor()
-			if vendor == VENDOR_ID_NONE:
-				ids.append(id)
-		return ids
-
-	def _get_v_models(self):
-		ids = []
-		for model in self.models:
-			id = model.get_id()
-			v = model.get_vendor()
-			if v != VENDOR_ID_NONE:
-				vendor_id = (v, id)
-				ids.append(vendor_id)
-		return ids
-
-	def get_properties(self):
-		vendor_models = self._get_v_models()
-		sig_models = self._get_sig_models()
-
-		return {
-			MESH_ELEMENT_IFACE: {
-			'Index': dbus.Byte(self.index),
-			'Models': dbus.Array(sig_models, 'q'),
-			'VendorModels': dbus.Array(vendor_models, '(qq)'),
-			}
-		}
-
-	def add_model(self, model):
-		model.set_path(self.path)
-		self.models.append(model)
-
-	def get_index(self):
-		return self.index
-
-	def set_model_config(self, configs):
-		print('Set element models config')
-		for config in configs:
-			mod_id = config[0]
-			self.UpdateModelConfiguration(mod_id, config[1])
-
-	@dbus.service.method(MESH_ELEMENT_IFACE,
-					in_signature="qqvay", out_signature="")
-	def MessageReceived(self, source, key, destination, data):
-		print('Message Received on Element %d, src=%04x, dst=%s' %
-						self.index, source, destination)
-		for model in self.models:
-			model.process_message(source, key, data)
-
-	@dbus.service.method(MESH_ELEMENT_IFACE,
-					in_signature="qa{sv}", out_signature="")
-
-	def UpdateModelConfiguration(self, model_id, config):
-		print('UpdateModelConfig ', end='')
-		print(hex(model_id))
-		for model in self.models:
-			if model_id == model.get_id():
-				model.set_config(config)
-				return
-
-	@dbus.service.method(MESH_ELEMENT_IFACE,
-					in_signature="", out_signature="")
-
-	def get_path(self):
-		return dbus.ObjectPath(self.path)
-
-class Model():
-	def __init__(self, model_id):
-		self.cmd_ops = []
-		self.model_id = model_id
-		self.vendor = VENDOR_ID_NONE
-		self.bindings = []
-		self.pub_period = 0
-		self.pub_id = 0
-		self.path = None
-
-	def set_path(self, path):
-		self.path = path
-
-	def get_id(self):
-		return self.model_id
-
-	def get_vendor(self):
-		return self.vendor
-
-	def process_message(self, source, key, data):
-		print('Model process message')
-
-	def set_publication(self, period):
-		self.pub_period = period
-
-	def set_config(self, config):
-		if 'Bindings' in config:
-			self.bindings = config.get('Bindings')
-			print('Bindings: ', end='')
-			print(self.bindings)
-		if 'PublicationPeriod' in config:
-			self.set_publication(config.get('PublicationPeriod'))
-			print('Model publication period ', end='')
-			print(self.pub_period, end='')
-			print(' ms')
-		if 'Subscriptions' in config:
-			self.print_subscriptions(config.get('Subscriptions'))
-
-	def print_subscriptions(self, subscriptions):
-		print('Model subscriptions ', end='')
-		for sub in subscriptions:
-			if isinstance(sub, int):
-				print('%04x' % sub, end=' ')
-
-			if isinstance(sub, list):
-				label = uuid.UUID(bytes=b''.join(sub))
-				print(label, end=' ')
-		print()
-
-class OnOffServer(Model):
-	def __init__(self, model_id):
-		Model.__init__(self, model_id)
-		self.cmd_ops = { 0x8201, # get
-				 0x8202, # set
-				 0x8203 } # set unacknowledged
-
-		print("OnOff Server ", end="")
-		self.state = 0
-		print('State ', end='')
-		self.timer = PubTimer()
-
-	def process_message(self, source, key, data):
-		datalen = len(data)
-		print('OnOff Server process message len ', datalen)
-
-		if datalen!=2 and datalen!=3:
-			return
-
-		if datalen==2:
-			op_tuple=struct.unpack('<H',bytes(data))
-			opcode = op_tuple[0]
-			if opcode != 0x8201:
-				print(hex(opcode))
-				return
-			print('Get state')
-		elif datalen==3:
-			opcode,self.state=struct.unpack('<HB',bytes(data))
-			if opcode != 0x8202 and opcode != 0x8203:
-				print(hex(opcode))
-				return
-			print('Set state: ', end='')
-			print(self.state)
-
-		rsp_data = struct.pack('<HB', 0x8204, self.state)
-		send_response(self.path, source, key, rsp_data)
-
-	def publish(self):
-		print('Publish')
-		data = struct.pack('B', self.state)
-		send_publication(self.path, self.model_id, data)
-
-	def set_publication(self, period):
-		if period == 0:
-			self.pub_period = 0
-			self.timer.cancel()
-			return
-
-		# We do not handle ms in this example
-		if period < 1000:
-			return
-
-		self.pub_period = period
-		self.timer.start(period/1000, self.publish)
-
-def main():
-
-	DBusGMainLoop(set_as_default=True)
-
-	global bus
-	bus = dbus.SystemBus()
-	global mainloop
-	global app
-	global mesh_net
-
-	mesh_net = dbus.Interface(bus.get_object(MESH_SERVICE_NAME,
-						 "/org/bluez/mesh"),
-						 MESH_NETWORK_IFACE)
-	mesh_net.connect_to_signal('InterfacesRemoved', interfaces_removed_cb)
-
-	app = Application(bus)
-	prov_agent = agent.Agent(bus)
-	app.set_agent(prov_agent)
-	first_ele = Element(bus, 0x00)
-	first_ele.add_model(OnOffServer(0x1000))
-	app.add_element(first_ele)
-
-	mainloop = GObject.MainLoop()
-
-	print('Join')
-	caps = ["out-numeric"]
-	oob = ["other"]
-	uuid = bytearray.fromhex("0a0102030405060708090A0B0C0D0E0F")
-	print(uuid)
-	mesh_net.Join(app.get_path(), uuid,
-			reply_handler=join_cb,
-			error_handler=join_error_cb)
-
-	mainloop.run()
-
-if __name__ == '__main__':
-	main()
diff --git a/test/test-manager b/test/test-manager
index 3fa7205..a93819e 100755
--- a/test/test-manager
+++ b/test/test-manager
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-nap b/test/test-nap
index d5c757b..76cde74 100755
--- a/test/test-nap
+++ b/test/test-nap
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-network b/test/test-network
index acc7dff..67be861 100755
--- a/test/test-network
+++ b/test/test-network
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-profile b/test/test-profile
index af1e23f..7d92f39 100755
--- a/test/test-profile
+++ b/test/test-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-sap-server b/test/test-sap-server
index ddb1efe..161a4bf 100755
--- a/test/test-sap-server
+++ b/test/test-sap-server
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/tools/advtest.c b/tools/advtest.c
index de036e7..9ef69ed 100644
--- a/tools/advtest.c
+++ b/tools/advtest.c
@@ -13,6 +13,13 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
 #include <getopt.h>
 
 #include "lib/bluetooth.h"
@@ -32,6 +39,9 @@
 			"\xe1\x23\x99\xc1\xca\x9a\xc3\x31"
 #define SCAN_IRK	"\xfa\x73\x09\x11\x3f\x03\x37\x0f" \
 			"\xf4\xf9\x93\x1e\xf9\xa3\x63\xa6"
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
 
 static struct mgmt *mgmt;
 static uint16_t index1 = MGMT_INDEX_NONE;
@@ -43,13 +53,73 @@ static struct bt_hci *scan_dev;
 
 static void print_rpa(const uint8_t addr[6])
 {
-	printf("  Address:  %02x:%02x:%02x:%02x:%02x:%02x\n",
+	printf("  RSI:\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
 					addr[5], addr[4], addr[3],
 					addr[2], addr[1], addr[0]);
 	printf("    Random: %02x%02x%02x\n", addr[3], addr[4], addr[5]);
 	printf("    Hash:   %02x%02x%02x\n", addr[0], addr[1], addr[2]);
 }
 
+static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
+{
+	size_t i, len;
+
+	len = MIN((strlen(hexstr) / 2), buflen);
+	memset(buf, 0, len);
+
+	for (i = 0; i < len; i++)
+		if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1)
+			continue;
+
+
+	return len;
+}
+
+static bool get_random_bytes(void *buf, size_t num_bytes)
+{
+	ssize_t len;
+	int fd;
+
+	fd = open("/dev/urandom", O_RDONLY);
+	if (fd < 0)
+		return false;
+
+	len = read(fd, buf, num_bytes);
+
+	close(fd);
+
+	if (len < 0)
+		return false;
+
+	return true;
+}
+
+static void generate_rsi(char *val)
+{
+	uint8_t sirk[16], hash[3];
+	uint8_t  rsi[6] = {0};
+
+	hex2bin(val, sirk, sizeof(sirk));
+
+	get_random_bytes(&rsi[3], 3);
+
+	rsi[5] &= 0x3f; /* Clear 2 msb */
+	rsi[5] |= 0x40; /* Set 2nd msb */
+
+	crypto = bt_crypto_new();
+	if (!crypto) {
+		fprintf(stderr, "Failed to open crypto interface\n");
+		mainloop_exit_failure();
+		return;
+	}
+
+	bt_crypto_ah(crypto, sirk, rsi + 3, hash);
+	memcpy(rsi, hash, 3);
+
+	print_rpa(rsi);
+}
+
+
 static void scan_le_adv_report(const void *data, uint8_t size,
 							void *user_data)
 {
@@ -351,9 +421,11 @@ static void usage(void)
 	printf("\tadvtest [options]\n");
 	printf("options:\n"
 		"\t-h, --help             Show help options\n");
+	printf(" \t-i  <128bit SIRK>,     Generate RSI ADV Data\n");
 }
 
 static const struct option main_options[] = {
+	{ "hash",   no_argument,       NULL, 'i' },
 	{ "version",   no_argument,       NULL, 'v' },
 	{ "help",      no_argument,       NULL, 'h' },
 	{ }
@@ -366,11 +438,15 @@ int main(int argc ,char *argv[])
 	for (;;) {
 		int opt;
 
-		opt = getopt_long(argc, argv, "vh", main_options, NULL);
+		opt = getopt_long(argc, argv, "i:vh", main_options, NULL);
 		if (opt < 0)
 			break;
 
 		switch (opt) {
+		case 'i':
+			printf("SIRK: %s\n", optarg);
+			generate_rsi(optarg);
+			return EXIT_SUCCESS;
 		case 'v':
 			printf("%s\n", VERSION);
 			return EXIT_SUCCESS;
diff --git a/tools/avtest.c b/tools/avtest.c
index ca37b3b..5ac3418 100644
--- a/tools/avtest.c
+++ b/tools/avtest.c
@@ -188,7 +188,8 @@ static void dump_buffer(const unsigned char *buf, int len)
 }
 
 static void process_avdtp(int srv_sk, int sk, unsigned char reject,
-								int fragment)
+								int fragment,
+								int reject_code)
 {
 	unsigned char buf[672];
 	ssize_t len;
@@ -284,7 +285,8 @@ static void process_avdtp(int srv_sk, int sk, unsigned char reject,
 			if (reject == AVDTP_SET_CONFIGURATION) {
 				hdr->message_type = AVDTP_MSG_TYPE_REJECT;
 				buf[2] = buf[4];
-				buf[3] = 0x13; /* SEP In Use */
+				buf[3] = reject_code ? reject_code :
+							0x13; /* SEP In Use */
 				printf("Rejecting set configuration command\n");
 				len = write(sk, buf, 4);
 			} else {
@@ -443,7 +445,8 @@ static int set_minimum_mtu(int sk)
 	return 0;
 }
 
-static void do_listen(const bdaddr_t *src, unsigned char reject, int fragment)
+static void do_listen(const bdaddr_t *src, unsigned char reject, int fragment,
+							int reject_code)
 {
 	struct sockaddr_l2 addr;
 	socklen_t optlen;
@@ -483,7 +486,7 @@ static void do_listen(const bdaddr_t *src, unsigned char reject, int fragment)
 			continue;
 		}
 
-		process_avdtp(sk, nsk, reject, fragment);
+		process_avdtp(sk, nsk, reject, fragment, reject_code);
 
 		if (media_sock >= 0) {
 			close(media_sock);
@@ -709,6 +712,7 @@ static void usage(void)
 	printf("Options:\n"
 		"\t--device <hcidev>    HCI device\n"
 		"\t--reject <command>   Reject command\n"
+		"\t--reject-code <code> Reject code to use\n"
 		"\t--send <command>     Send command\n"
 		"\t--preconf            Configure stream before actual command\n"
 		"\t--wait <N>           Wait N seconds before exiting\n"
@@ -720,6 +724,7 @@ static struct option main_options[] = {
 	{ "help",	0, 0, 'h' },
 	{ "device",	1, 0, 'i' },
 	{ "reject",	1, 0, 'r' },
+	{ "reject-code",	1, 0, 'R' },
 	{ "send",	1, 0, 's' },
 	{ "invalid",	1, 0, 'f' },
 	{ "preconf",	0, 0, 'c' },
@@ -764,12 +769,12 @@ int main(int argc, char *argv[])
 	unsigned char cmd = 0x00;
 	bdaddr_t src, dst;
 	int opt, mode = MODE_NONE, sk, invalid = 0, preconf = 0, fragment = 0;
-	int avctp = 0, wait_before_exit = 0;
+	int avctp = 0, wait_before_exit = 0, reject_code = 0;
 
 	bacpy(&src, BDADDR_ANY);
 	bacpy(&dst, BDADDR_ANY);
 
-	while ((opt = getopt_long(argc, argv, "+i:r:s:f:hcFCw:",
+	while ((opt = getopt_long(argc, argv, "+i:r:s:f:hcFCw:R:",
 						main_options, NULL)) != EOF) {
 		switch (opt) {
 		case 'i':
@@ -809,6 +814,10 @@ int main(int argc, char *argv[])
 			wait_before_exit = atoi(optarg);
 			break;
 
+		case 'R':
+			reject_code = atoi(optarg);
+			break;
+
 		case 'h':
 		default:
 			usage();
@@ -826,7 +835,7 @@ int main(int argc, char *argv[])
 
 	switch (mode) {
 	case MODE_REJECT:
-		do_listen(&src, cmd, fragment);
+		do_listen(&src, cmd, fragment, reject_code);
 		break;
 	case MODE_SEND:
 		sk = do_connect(&src, &dst, avctp, fragment);
diff --git a/tools/bdaddr.1 b/tools/bdaddr.1
new file mode 100644
index 0000000..2e74fa3
--- /dev/null
+++ b/tools/bdaddr.1
@@ -0,0 +1,94 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BDADDR" "1" "Sep 27, 2005" "BlueZ" "Linux System Administration"
+.SH NAME
+bdaddr \- Utility for changing the Bluetooth device address
+.SH SYNOPSIS
+.sp
+\fBbdaddr\fP
+.sp
+\fBbdaddr\fP \-h
+.sp
+\fBbdaddr\fP [\-i <\fIdev\fP>] [\-r] [\-t] [\fInew_bdaddr\fP]
+.SH DESCRIPTION
+.sp
+\fBbdaddr(1)\fP is used to query or set the local Bluetooth device address
+(BD_ADDR). If run with no arguments, \fBbdaddr\fP prints the chip manufacturer\(aqs
+name, and the current BD_ADDR. If the IEEE OUI index file \(dqoui.txt\(dq is
+installed on the system, the BD_ADDR owner will be displayed. If the optional
+[\fInew_bdaddr\fP]  argument is given, the device will be reprogrammed with that
+address. This can either be permanent or temporary, as specified by the \-t
+flag. In both cases, the device must be reset before the new address will
+become active. This can be done with a \(aqsoft\(aq reset by specifying the  \-r
+flag, or a \(aqhard\(aq reset by removing and replugging the device. A \(aqhard\(aq reset
+will cause the address to revert to the current non\-volatile value.
+.sp
+\fBbdaddr\fP uses manufacturer specific commands to set the address, and is
+therefore device specific. For this reason, not all devices are supported,
+and not all options are supported on all devices. Current supported
+manufacturers are: \fBEricsson\fP, \fBCambridge Silicon Radio (CSR)\fP,
+\fBTexas  Instruments (TI)\fP, \fBZeevo\fP and \fBST Microelectronics (ST)\fP\&.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-h
+Gives a list of possible commands.
+.TP
+.BI \-i \ <dev>
+Specify a particular device to operate on. If not specified,
+default is the first available device.
+.TP
+.B  \-r
+Reset device and make new BD_ADDR active.  CSR devices only.
+.TP
+.B  \-t
+Temporary change. Do not write to non\-volatile memory.
+CSR devices only.
+.UNINDENT
+.SH FILES
+.INDENT 0.0
+.TP
+.B /usr/share/misc/oui.txt
+IEEE Organizationally Unique Identifier consolidated file.
+Manually update from:  <http://standards.ieee.org/regauth/oui/oui.txt> 
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann <marcel@holtmann.org>, Adam Laurie <adam@algroup.co.uk>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/bdaddr.c b/tools/bdaddr.c
index bc0478d..de17416 100644
--- a/tools/bdaddr.c
+++ b/tools/bdaddr.c
@@ -303,6 +303,7 @@ static struct {
 	{ 48,		st_write_bd_addr,	generic_reset_device	},
 	{ 57,		ericsson_write_bd_addr,	generic_reset_device	},
 	{ 72,		mrvl_write_bd_addr,	generic_reset_device	},
+	{ 305,		bcm_write_bd_addr,	generic_reset_device	},
 	{ 65535,	NULL,			NULL			},
 };
 
diff --git a/tools/bluemoon.c b/tools/bluemoon.c
index f50107a..9aaf642 100644
--- a/tools/bluemoon.c
+++ b/tools/bluemoon.c
@@ -18,6 +18,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include <getopt.h>
 #include <sys/stat.h>
 #include <sys/param.h>
diff --git a/tools/bluetooth-logger.service.in b/tools/bluetooth-logger.service.in
index 0090027..d6df676 100644
--- a/tools/bluetooth-logger.service.in
+++ b/tools/bluetooth-logger.service.in
@@ -4,7 +4,7 @@ ConditionPathIsDirectory=/sys/class/bluetooth
 
 [Service]
 Type=simple
-ExecStart=@pkglibexecdir@/btmon-logger -p -b /var/log/bluetooth/hci.log
+ExecStart=@PKGLIBEXECDIR@/btmon-logger -p -b /var/log/bluetooth/hci.log
 NotifyAccess=main
 CapabilityBoundingSet=CAP_NET_RAW
 LimitNPROC=1
diff --git a/tools/bluetooth-player.c b/tools/bluetooth-player.c
index eba104d..83045ca 100644
--- a/tools/bluetooth-player.c
+++ b/tools/bluetooth-player.c
@@ -33,21 +33,20 @@
 #include "src/shared/shell.h"
 #include "client/player.h"
 
-#define PROMPT_ON	COLOR_BLUE "[bluetooth]" COLOR_OFF "# "
-#define PROMPT_OFF	"[bluetooth]# "
+#define PROMPT	"[bluetooth]# "
 
 static DBusConnection *dbus_conn;
 
 static void connect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_attach(fileno(stdin));
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT, COLOR_BLUE);
 }
 
 static void disconnect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_detach();
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT, NULL);
 }
 
 int main(int argc, char *argv[])
@@ -56,7 +55,7 @@ int main(int argc, char *argv[])
 	int status;
 
 	bt_shell_init(argc, argv, NULL);
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT, NULL);
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
diff --git a/tools/btattach.1 b/tools/btattach.1
new file mode 100644
index 0000000..f504dc8
--- /dev/null
+++ b/tools/btattach.1
@@ -0,0 +1,123 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BTATTACH" "1" "November 2015" "BlueZ" "Linux System Administration"
+.SH NAME
+btattach \- Attach serial devices to BlueZ stack
+.SH SYNOPSIS
+.sp
+\fBbtattach\fP [\fB\-B\fP \fIdevice\fP] [\fB\-A\fP \fIdevice\fP] [\fB\-P\fP \fIprotocol\fP] [\fB\-R\fP]
+.SH DESCRIPTION
+.sp
+\fBbtattach(1)\fP is used to attach a serial UART to the Bluetooth stack as a
+transport interface.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-B \ device\fR,\fB \ \-\-brder \ device
+Attach a BR/EDR controller
+.TP
+.BI \-A \ device\fR,\fB \ \-\-amp \ device
+Attach an AMP controller
+.TP
+.BI \-P \ protocol\fR,\fB \ \-\-protocol \ protocol
+Specify the protocol type for talking to the
+device.
+.sp
+Supported values are:
+.UNINDENT
+.TS
+box center;
+l.
+T{
+\fIprotocol\fP
+T}
+_
+T{
+h4
+T}
+_
+T{
+bcsp
+T}
+_
+T{
+3wire
+T}
+_
+T{
+h4ds
+T}
+_
+T{
+ll
+T}
+_
+T{
+ath3k
+T}
+_
+T{
+intel
+T}
+_
+T{
+bcm
+T}
+_
+T{
+qca
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-S \ baudrate\fR,\fB \ \-\-speed \ baudrate
+Specify wich baudrate to use
+.TP
+.B  \-N\fP,\fB  \-\-noflowctl
+Disable flow control
+.TP
+.B  \-v\fP,\fB  \-\-version
+Show version
+.TP
+.B  \-h\fP,\fB  \-\-help
+Show help options
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index 58a03bd..b47914d 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -33,6 +33,7 @@
 #include "src/shared/queue.h"
 #include "src/shared/gatt-db.h"
 #include "src/shared/gatt-client.h"
+#include "src/shared/gatt-helpers.h"
 
 #define ATT_CID 4
 
@@ -57,6 +58,7 @@ struct client {
 	struct bt_gatt_client *gatt;
 
 	unsigned int reliable_session_id;
+	bool sec_retry;
 };
 
 static void print_prompt(void)
@@ -172,6 +174,7 @@ static struct client *client_create(int fd, uint16_t mtu)
 		fprintf(stderr, "Failed to allocate memory for client\n");
 		return NULL;
 	}
+	cli->sec_retry = true;
 
 	cli->att = bt_att_new(fd, false);
 	if (!cli->att) {
@@ -488,6 +491,7 @@ static void cmd_read_multiple(struct client *cli, char *cmd_str)
 	char *argv[512];
 	int i;
 	char *endptr = NULL;
+	unsigned int id;
 
 	if (!bt_gatt_client_is_ready(cli->gatt)) {
 		printf("GATT client not initialized\n");
@@ -514,9 +518,12 @@ static void cmd_read_multiple(struct client *cli, char *cmd_str)
 		}
 	}
 
-	if (!bt_gatt_client_read_multiple(cli->gatt, value, argc,
-						read_multiple_cb, NULL, NULL))
+	id = bt_gatt_client_read_multiple(cli->gatt, value, argc,
+						read_multiple_cb, NULL, NULL);
+	if (!id)
 		printf("Failed to initiate read multiple procedure\n");
+	else if (!cli->sec_retry)
+		bt_gatt_client_set_retry(cli->gatt, id, false);
 
 	free(value);
 }
@@ -558,6 +565,7 @@ static void cmd_read_value(struct client *cli, char *cmd_str)
 	int argc = 0;
 	uint16_t handle;
 	char *endptr = NULL;
+	unsigned int id;
 
 	if (!bt_gatt_client_is_ready(cli->gatt)) {
 		printf("GATT client not initialized\n");
@@ -575,9 +583,12 @@ static void cmd_read_value(struct client *cli, char *cmd_str)
 		return;
 	}
 
-	if (!bt_gatt_client_read_value(cli->gatt, handle, read_cb,
-								NULL, NULL))
+	id = bt_gatt_client_read_value(cli->gatt, handle, read_cb,
+					NULL, NULL);
+	if (!id)
 		printf("Failed to initiate read value procedure\n");
+	else if (!cli->sec_retry)
+		bt_gatt_client_set_retry(cli->gatt, id, false);
 }
 
 static void read_long_value_usage(void)
@@ -592,6 +603,7 @@ static void cmd_read_long_value(struct client *cli, char *cmd_str)
 	uint16_t handle;
 	uint16_t offset;
 	char *endptr = NULL;
+	unsigned int id;
 
 	if (!bt_gatt_client_is_ready(cli->gatt)) {
 		printf("GATT client not initialized\n");
@@ -616,9 +628,12 @@ static void cmd_read_long_value(struct client *cli, char *cmd_str)
 		return;
 	}
 
-	if (!bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb,
-								NULL, NULL))
+	id = bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb,
+								NULL, NULL);
+	if (!id)
 		printf("Failed to initiate read long value procedure\n");
+	else if (!cli->sec_retry)
+		bt_gatt_client_set_retry(cli->gatt, id, false);
 }
 
 static void write_value_usage(void)
@@ -659,6 +674,7 @@ static void cmd_write_value(struct client *cli, char *cmd_str)
 	uint8_t *value = NULL;
 	bool without_response = false;
 	bool signed_write = false;
+	unsigned int id;
 
 	if (!bt_gatt_client_is_ready(cli->gatt)) {
 		printf("GATT client not initialized\n");
@@ -740,10 +756,13 @@ static void cmd_write_value(struct client *cli, char *cmd_str)
 		goto done;
 	}
 
-	if (!bt_gatt_client_write_value(cli->gatt, handle, value, length,
+	id = bt_gatt_client_write_value(cli->gatt, handle, value, length,
 								write_cb,
-								NULL, NULL))
+								NULL, NULL);
+	if (!id)
 		printf("Failed to initiate write procedure\n");
+	else if (!cli->sec_retry)
+		bt_gatt_client_set_retry(cli->gatt, id, false);
 
 done:
 	free(value);
@@ -789,6 +808,7 @@ static void cmd_write_long_value(struct client *cli, char *cmd_str)
 	int length;
 	uint8_t *value = NULL;
 	bool reliable_writes = false;
+	unsigned int id;
 
 	if (!bt_gatt_client_is_ready(cli->gatt)) {
 		printf("GATT client not initialized\n");
@@ -863,11 +883,14 @@ static void cmd_write_long_value(struct client *cli, char *cmd_str)
 		}
 	}
 
-	if (!bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle,
+	id = bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle,
 							offset, value, length,
 							write_long_cb,
-							NULL, NULL))
+							NULL, NULL);
+	if (!id)
 		printf("Failed to initiate long write procedure\n");
+	else if (!cli->sec_retry)
+		bt_gatt_client_set_retry(cli->gatt, id, false);
 
 	free(value);
 }
@@ -999,12 +1022,18 @@ done:
 							value, length,
 							write_long_cb, NULL,
 							NULL);
-	if (!cli->reliable_session_id)
+	if (!cli->reliable_session_id) {
 		printf("Failed to proceed prepare write\n");
-	else
+	} else {
+		if (!cli->sec_retry)
+			bt_gatt_client_set_retry(cli->gatt,
+						cli->reliable_session_id,
+						false);
+
 		printf("Prepare write success.\n"
 				"Session id: %d to be used on next write\n",
 						cli->reliable_session_id);
+	}
 
 	free(value);
 }
@@ -1236,6 +1265,36 @@ static void cmd_get_security(struct client *cli, char *cmd_str)
 		printf("Security level: %u\n", level);
 }
 
+static void set_security_retry_usage(void)
+{
+	printf("Usage: set-security-retry <y/n>\n"
+		"e.g.:\n"
+		"\tset-security-retry n\n");
+}
+
+static void cmd_set_security_retry(struct client *cli, char *cmd_str)
+{
+	char *argv[2];
+	int argc = 0;
+
+	if (!bt_gatt_client_is_ready(cli->gatt)) {
+		printf("GATT client not initialized\n");
+		return;
+	}
+
+	if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) {
+		set_security_retry_usage();
+		return;
+	}
+
+	if (argv[0][0] == 'y')
+		cli->sec_retry = true;
+	else if (argv[0][0] == 'n')
+		cli->sec_retry = false;
+	else
+		printf("Invalid argument: %s\n", argv[0]);
+}
+
 static bool convert_sign_key(char *optarg, uint8_t key[16])
 {
 	int i;
@@ -1295,6 +1354,166 @@ static void cmd_set_sign_key(struct client *cli, char *cmd_str)
 		set_sign_key_usage();
 }
 
+static void search_service_cb(bool success, uint8_t att_ecode,
+					struct bt_gatt_result *result,
+					void *user_data)
+{
+	struct bt_gatt_iter iter;
+	uint16_t start_handle, end_handle;
+	uint128_t u128;
+	bt_uuid_t uuid;
+	char uuid_str[MAX_LEN_UUID_STR];
+
+	if (!success) {
+		PRLOG("\nService discovery failed: %s (0x%02x)\n",
+				ecode_to_string(att_ecode), att_ecode);
+		return;
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result))
+		return;
+
+	printf("\n");
+	while (bt_gatt_iter_next_service(&iter, &start_handle, &end_handle,
+						u128.data)) {
+		bt_uuid128_create(&uuid, u128);
+		bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
+		printf("Found start handle: 0x%04x, end handle: 0x%04x, "
+			"UUID: %s\n",
+			start_handle, end_handle, uuid_str);
+	}
+	PRLOG("\n");
+}
+
+static void cmd_search_all_primary_services(struct client *cli, char *cmd_str)
+{
+	if (!bt_gatt_client_is_ready(cli->gatt)) {
+		printf("GATT client not initialized\n");
+		return;
+	}
+
+	bt_gatt_discover_all_primary_services(bt_gatt_client_get_att(cli->gatt),
+						NULL,
+						search_service_cb,
+						NULL,
+						NULL);
+}
+
+static void search_service_usage(void)
+{
+	printf("Usage: search-service <uuid>\n"
+		"e.g.:\n"
+		"\tsearch-service 1800\n");
+}
+
+static void cmd_search_service(struct client *cli, char *cmd_str)
+{
+	char *argv[2];
+	int argc = 0;
+	bt_uuid_t uuid;
+
+	if (!bt_gatt_client_is_ready(cli->gatt)) {
+		printf("GATT client not initialized\n");
+		return;
+	}
+
+	if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) {
+		search_service_usage();
+		return;
+	}
+
+	if (bt_string_to_uuid(&uuid, argv[0]) < 0) {
+		printf("Invalid UUID: %s\n", argv[0]);
+		return;
+	}
+
+	bt_gatt_discover_primary_services(bt_gatt_client_get_att(cli->gatt),
+						&uuid, 0x0001, 0xFFFF,
+						search_service_cb,
+						NULL,
+						NULL);
+}
+
+static void search_characteristics_usage(void)
+{
+	printf("Usage: search-characteristics <start_hanlde> <end_handle> "
+		"<uuid>\n"
+		"e.g.:\n"
+		"\tsearch-characteristics 0x0001 0xFFFF 1800\n");
+}
+
+static void search_characteristics_cb(bool success, uint8_t att_ecode,
+					struct bt_gatt_result *result,
+					void *user_data)
+{
+	struct bt_gatt_iter iter;
+	uint16_t handle, length;
+	const uint8_t *value;
+	int i;
+
+	if (!success) {
+		PRLOG("\nCharacteristics discovery failed: %s (0x%02x)\n",
+				ecode_to_string(att_ecode), att_ecode);
+		return;
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result))
+		return;
+
+	printf("\n");
+	while (bt_gatt_iter_next_read_by_type(&iter, &handle, &length,
+						&value)) {
+		printf("Found handle: 0x%04x value: ", handle);
+		for (i = 0; i < length; i++)
+			printf("%02x ", value[i]);
+		printf("\n");
+	}
+	PRLOG("\n");
+}
+
+static void cmd_search_characteristics(struct client *cli, char *cmd_str)
+{
+	char *argv[4];
+	int argc = 0;
+	uint16_t start_handle, end_handle;
+	char *endptr = NULL;
+	bt_uuid_t uuid;
+
+	if (!bt_gatt_client_is_ready(cli->gatt)) {
+		printf("GATT client not initialized\n");
+		return;
+	}
+
+	if (!parse_args(cmd_str, 3, argv, &argc) || argc != 3) {
+		search_characteristics_usage();
+		return;
+	}
+
+	start_handle = strtol(argv[0], &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		printf("Invalid start handle: %s\n", argv[0]);
+		return;
+	}
+
+	end_handle = strtol(argv[1], &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		printf("Invalid end handle: %s\n", argv[1]);
+		return;
+	}
+
+	if (bt_string_to_uuid(&uuid, argv[2]) < 0) {
+		printf("Invalid UUID: %s\n", argv[2]);
+		return;
+	}
+
+	bt_gatt_read_by_type(bt_gatt_client_get_att(cli->gatt), start_handle,
+						end_handle,
+						&uuid,
+						search_characteristics_cb,
+						NULL,
+						NULL);
+}
+
 static void cmd_help(struct client *cli, char *cmd_str);
 
 typedef void (*command_func_t)(struct client *cli, char *cmd_str);
@@ -1327,8 +1546,16 @@ static struct {
 				"\tSet security level on le connection"},
 	{ "get-security", cmd_get_security,
 				"\tGet security level on le connection"},
+	{ "set-security-retry", cmd_set_security_retry,
+			"\tSet retry on security error by elevating security"},
 	{ "set-sign-key", cmd_set_sign_key,
 				"\tSet signing key for signed write command"},
+	{ "search-all-primary-services", cmd_search_all_primary_services,
+				"\tSearch all primary services"},
+	{ "search-service", cmd_search_service,
+				"\tSearch service"},
+	{ "search-characteristics", cmd_search_characteristics,
+				"\tSearch characteristics"},
 	{ }
 };
 
diff --git a/tools/btiotest.c b/tools/btiotest.c
index 193e139..75af905 100644
--- a/tools/btiotest.c
+++ b/tools/btiotest.c
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -39,13 +40,15 @@ static int opt_update_sec = 0;
 }
 
 struct bt_iso_qos qos = {
-	.cig = BT_ISO_QOS_CIG_UNSET,
-	.cis = BT_ISO_QOS_CIG_UNSET,
-	.sca = 0x07,
-	.packing = 0x00,
-	.framing = 0x00,
-	.in = DEFAULT_IO_QOS,
-	.out = DEFAULT_IO_QOS,
+	.ucast = {
+		.cig = BT_ISO_QOS_CIG_UNSET,
+		.cis = BT_ISO_QOS_CIG_UNSET,
+		.sca = 0x07,
+		.packing = 0x00,
+		.framing = 0x00,
+		.in = DEFAULT_IO_QOS,
+		.out = DEFAULT_IO_QOS,
+	},
 };
 
 struct io_data {
diff --git a/tools/btmgmt.1 b/tools/btmgmt.1
new file mode 100644
index 0000000..c80478d
--- /dev/null
+++ b/tools/btmgmt.1
@@ -0,0 +1,114 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BTMGMT" "1" "July 2023" "BlueZ" "Linux System Administration"
+.SH NAME
+btmgmt \- interactive bluetooth management tool
+.SH SYNOPSIS
+.sp
+\fBbtmgmt\fP [\-\-options] [commands]
+.SH DESCRIPTION
+.sp
+\fBbtmgmt(1)\fP interactive bluetooth management tool. The tool issues commands
+to the Kernel using the Bluetooth Management socket, some commands may require
+net\-admin capability in order to work since the Bluetooth Management interface
+is considered a low\-level interface meant for the likes of \fBbluetoothd(8)\fP,
+it is not recommended for applications to use it directly as it may result in
+unexpected behavior.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-i/\-\-index
+Specify adapter index
+.TP
+.B \-m\-/\-monitor
+Enable monitor output
+.TP
+.B \-t/\-\-timeout
+Timeout in seconds for non\-interactive mode
+.TP
+.B \-v/\-\-version
+Display version
+.TP
+.B \-i/\-\-init\-script
+Init script file
+.TP
+.B \-h/\-\-help
+Display help
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B main
+See \fBbluetoothctl\-mgmt(1)\fP
+.TP
+.B monitor
+See \fBbluetoothctl\-monitor(1)\fP
+.UNINDENT
+.SH AUTOMATION
+.sp
+Two common ways to automate the tool are to pass the commands directly like in
+the follow example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+btmgmt <<EOF
+list
+show
+EOF
+.EE
+.UNINDENT
+.UNINDENT
+.sp
+Or create a script and pass it as init\-script:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ vi test\-script.bt
+list
+show
+quit
+:wq
+$ btmgmt \-\-init\-script=test\-script
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 29f8609..436c2bb 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -11,6026 +11,11 @@
 #endif
 
 #define _GNU_SOURCE
-#include <stdio.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <wordexp.h>
-#include <ctype.h>
-
-#include "lib/bluetooth.h"
-#include "lib/hci.h"
-#include "lib/hci_lib.h"
-#include "lib/sdp.h"
-#include "lib/sdp_lib.h"
-
-#include "src/uuid-helper.h"
-#include "lib/mgmt.h"
-
-#include "src/shared/mainloop.h"
-#include "src/shared/io.h"
-#include "src/shared/util.h"
-#include "src/shared/mgmt.h"
-#include "src/shared/shell.h"
-
-#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
-#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
-#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
-
-static struct mgmt *mgmt = NULL;
-static uint16_t mgmt_index = MGMT_INDEX_NONE;
-
-static bool discovery = false;
-static bool resolve_names = true;
-
-static struct {
-	uint16_t index;
-	uint16_t req;
-	struct mgmt_addr_info addr;
-} prompt = {
-	.index = MGMT_INDEX_NONE,
-};
-
-
-static int pending_index = 0;
-
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
-#define PROMPT_ON	COLOR_BLUE "[mgmt]" COLOR_OFF "# "
-
-static void set_index(const char *arg)
-{
-	if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
-						!strcmp(arg, "all"))
-		mgmt_index = MGMT_INDEX_NONE;
-	else if(strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
-		mgmt_index = atoi(&arg[3]);
-	else
-		mgmt_index = atoi(arg);
-}
-
-static bool parse_setting(int argc, char **argv, uint8_t *val)
-{
-	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
-		*val = 1;
-	else if (strcasecmp(argv[1], "off") == 0)
-		*val = 0;
-	else
-		*val = atoi(argv[1]);
-	return true;
-}
-
-static void update_prompt(uint16_t index)
-{
-	char str[32];
-
-	if (index == MGMT_INDEX_NONE)
-		snprintf(str, sizeof(str), "%s# ",
-					COLOR_BLUE "[mgmt]" COLOR_OFF);
-	else
-		snprintf(str, sizeof(str),
-				COLOR_BLUE "[hci%u]" COLOR_OFF "# ", index);
-
-	bt_shell_set_prompt(str);
-}
-
-#define print(fmt, arg...) do { \
-		bt_shell_printf(fmt "\n", ## arg); \
-} while (0)
-
-#define error(fmt, arg...) do { \
-		bt_shell_printf(COLOR_RED fmt "\n" COLOR_OFF, ## arg); \
-} while (0)
-
-static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
-{
-	size_t i, len;
-
-	len = MIN((strlen(hexstr) / 2), buflen);
-	memset(buf, 0, len);
-
-	for (i = 0; i < len; i++)
-		sscanf(hexstr + (i * 2), "%02hhX", &buf[i]);
-
-	return len;
-}
-
-static size_t bin2hex(const uint8_t *buf, size_t buflen, char *str,
-								size_t strlen)
-{
-	size_t i;
-
-	for (i = 0; i < buflen && i < (strlen / 2); i++)
-		sprintf(str + (i * 2), "%02x", buf[i]);
-
-	return i;
-}
-
-static void print_eir(const uint8_t *eir, uint16_t eir_len)
-{
-	uint16_t parsed = 0;
-	char str[33];
-
-	while (parsed < eir_len - 1) {
-		uint8_t field_len = eir[0];
-
-		if (field_len == 0)
-			break;
-
-		parsed += field_len + 1;
-
-		if (parsed > eir_len)
-			break;
-
-		switch (eir[1]) {
-		case 0x01:
-			print("Flags: 0x%02x", eir[2]);
-			break;
-		case 0x0d:
-			print("Class of Device: 0x%02x%02x%02x",
-						eir[4], eir[3], eir[2]);
-			break;
-		case 0x0e:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("SSP Hash C-192: %s", str);
-			break;
-		case 0x0f:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("SSP Rand R-192: %s", str);
-			break;
-		case 0x1b:
-			ba2str((bdaddr_t *) (eir + 2), str);
-			print("LE Device Address: %s (%s)", str,
-					eir[8] ? "random" : "public");
-			break;
-		case 0x1c:
-			print("LE Role: 0x%02x", eir[2]);
-			break;
-		case 0x1d:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("SSP Hash C-256: %s", str);
-			break;
-		case 0x1e:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("SSP Rand R-256: %s", str);
-			break;
-		case 0x22:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("LE SC Confirmation Value: %s", str);
-			break;
-		case 0x23:
-			bin2hex(eir + 2, 16, str, sizeof(str));
-			print("LE SC Random Value: %s", str);
-			break;
-		default:
-			print("Type %u: %u byte%s", eir[1], field_len - 1,
-					(field_len - 1) == 1 ? "" : "s");
-			break;
-		}
-
-		eir += field_len + 1;
-	}
-}
-
-static bool load_identity(const char *path, struct mgmt_irk_info *irk)
-{
-	char *addr, *key;
-	unsigned int type;
-	int n;
-	FILE *fp;
-
-	fp = fopen(path, "r");
-	if (!fp) {
-		error("Failed to open identity file: %s", strerror(errno));
-		return false;
-	}
-
-	n = fscanf(fp, "%m[0-9a-f:] (type %u) %m[0-9a-f]", &addr, &type, &key);
-
-	fclose(fp);
-
-	if (n != 3)
-		return false;
-
-	str2ba(addr, &irk->addr.bdaddr);
-	hex2bin(key, irk->val, sizeof(irk->val));
-
-	free(addr);
-	free(key);
-
-	switch (type) {
-	case 0:
-		irk->addr.type = BDADDR_LE_PUBLIC;
-		break;
-	case 1:
-		irk->addr.type = BDADDR_LE_RANDOM;
-		break;
-	default:
-		error("Invalid address type %u", type);
-		return false;
-	}
-
-	return true;
-}
-
-static void controller_error(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	const struct mgmt_ev_controller_error *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too short (%u bytes) controller error event", len);
-		return;
-	}
-
-	print("hci%u error 0x%02x", index, ev->error_code);
-}
-
-static void index_added(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	print("hci%u added", index);
-}
-
-static void index_removed(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	print("hci%u removed", index);
-}
-
-static void unconf_index_added(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	print("hci%u added (unconfigured)", index);
-}
-
-static void unconf_index_removed(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	print("hci%u removed (unconfigured)", index);
-}
-
-static void ext_index_added(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	const struct mgmt_ev_ext_index_added *ev = param;
-
-	print("hci%u added (type %u bus %u)", index, ev->type, ev->bus);
-}
-
-static void ext_index_removed(uint16_t index, uint16_t len,
-				const void *param, void *user_data)
-{
-	const struct mgmt_ev_ext_index_removed *ev = param;
-
-	print("hci%u removed (type %u bus %u)", index, ev->type, ev->bus);
-}
-
-static const char *options_str[] = {
-				"external",
-				"public-address",
-};
-
-static const char *options2str(uint32_t options)
-{
-	static char str[256];
-	unsigned i;
-	int off;
-
-	off = 0;
-	str[0] = '\0';
-
-	for (i = 0; i < NELEM(options_str); i++) {
-		if ((options & (1 << i)) != 0)
-			off += snprintf(str + off, sizeof(str) - off, "%s ",
-							options_str[i]);
-	}
-
-	return str;
-}
-
-static void new_config_options(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const uint32_t *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too short new_config_options event (%u)", len);
-		return;
-	}
-
-	print("hci%u new_config_options: %s", index, options2str(get_le32(ev)));
-}
-
-static const char *settings_str[] = {
-				"powered",
-				"connectable",
-				"fast-connectable",
-				"discoverable",
-				"bondable",
-				"link-security",
-				"ssp",
-				"br/edr",
-				"hs",
-				"le",
-				"advertising",
-				"secure-conn",
-				"debug-keys",
-				"privacy",
-				"configuration",
-				"static-addr",
-				"phy-configuration",
-				"wide-band-speech",
-};
-
-static const char *settings2str(uint32_t settings)
-{
-	static char str[256];
-	unsigned i;
-	int off;
-
-	off = 0;
-	str[0] = '\0';
-
-	for (i = 0; i < NELEM(settings_str); i++) {
-		if ((settings & (1 << i)) != 0)
-			off += snprintf(str + off, sizeof(str) - off, "%s ",
-							settings_str[i]);
-	}
-
-	return str;
-}
-
-static void new_settings(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const uint32_t *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too short new_settings event (%u)", len);
-		return;
-	}
-
-	print("hci%u new_settings: %s", index, settings2str(get_le32(ev)));
-}
-
-static void discovering(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_discovering *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too short (%u bytes) discovering event", len);
-		return;
-	}
-
-	print("hci%u type %u discovering %s", index, ev->type,
-					ev->discovering ? "on" : "off");
-
-	if (ev->discovering == 0 && discovery)
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void new_link_key(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_new_link_key *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid new_link_key length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->key.addr.bdaddr, addr);
-	print("hci%u new_link_key %s type 0x%02x pin_len %d store_hint %u",
-		index, addr, ev->key.type, ev->key.pin_len, ev->store_hint);
-}
-
-static const char *typestr(uint8_t type)
-{
-	static const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
-
-	if (type <= BDADDR_LE_RANDOM)
-		return str[type];
-
-	return "(unknown)";
-}
-
-static void connected(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_device_connected *ev = param;
-	uint16_t eir_len;
-	char addr[18];
-
-	if (len < sizeof(*ev)) {
-		error("Invalid connected event length (%u bytes)", len);
-		return;
-	}
-
-	eir_len = get_le16(&ev->eir_len);
-	if (len != sizeof(*ev) + eir_len) {
-		error("Invalid connected event length (%u != eir_len %u)",
-								len, eir_len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s type %s connected eir_len %u", index, addr,
-					typestr(ev->addr.type), eir_len);
-}
-
-static void disconnected(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_device_disconnected *ev = param;
-	char addr[18];
-	uint8_t reason;
-
-	if (len < sizeof(struct mgmt_addr_info)) {
-		error("Invalid disconnected event length (%u bytes)", len);
-		return;
-	}
-
-	if (len < sizeof(*ev))
-		reason = MGMT_DEV_DISCONN_UNKNOWN;
-	else
-		reason = ev->reason;
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s type %s disconnected with reason %u",
-			index, addr, typestr(ev->addr.type), reason);
-}
-
-static void conn_failed(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_connect_failed *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid connect_failed event length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s type %s connect failed (status 0x%02x, %s)",
-			index, addr, typestr(ev->addr.type), ev->status,
-			mgmt_errstr(ev->status));
-}
-
-static void auth_failed(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_auth_failed *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid auth_failed event length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s auth failed with status 0x%02x (%s)",
-			index, addr, ev->status, mgmt_errstr(ev->status));
-}
-
-static void class_of_dev_changed(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_ev_class_of_dev_changed *ev = param;
-
-	if (len != sizeof(*ev)) {
-		error("Invalid class_of_dev_changed length (%u bytes)", len);
-		return;
-	}
-
-	print("hci%u class of device changed: 0x%02x%02x%02x", index,
-			ev->dev_class[2], ev->dev_class[1], ev->dev_class[0]);
-}
-
-static void local_name_changed(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_local_name_changed *ev = param;
-
-	if (len != sizeof(*ev)) {
-		error("Invalid local_name_changed length (%u bytes)", len);
-		return;
-	}
-
-	print("hci%u name changed: %s", index, ev->name);
-}
-
-static void confirm_name_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_confirm_name *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("confirm_name failed with status 0x%02x (%s)", status,
-							mgmt_errstr(status));
-		return;
-	}
-
-	if (len != sizeof(*rp)) {
-		error("confirm_name rsp length %u instead of %zu",
-							len, sizeof(*rp));
-		return;
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status != 0)
-		error("confirm_name for %s failed: 0x%02x (%s)",
-			addr, status, mgmt_errstr(status));
-	else
-		print("confirm_name succeeded for %s", addr);
-}
-
-static char *eir_get_name(const uint8_t *eir, uint16_t eir_len)
-{
-	uint8_t parsed = 0;
-
-	if (eir_len < 2)
-		return NULL;
-
-	while (parsed < eir_len - 1) {
-		uint8_t field_len = eir[0];
-
-		if (field_len == 0)
-			break;
-
-		parsed += field_len + 1;
-
-		if (parsed > eir_len)
-			break;
-
-		/* Check for short of complete name */
-		if (eir[1] == 0x09 || eir[1] == 0x08)
-			return strndup((char *) &eir[2], field_len - 1);
-
-		eir += field_len + 1;
-	}
-
-	return NULL;
-}
-
-static unsigned int eir_get_flags(const uint8_t *eir, uint16_t eir_len)
-{
-	uint8_t parsed = 0;
-
-	if (eir_len < 2)
-		return 0;
-
-	while (parsed < eir_len - 1) {
-		uint8_t field_len = eir[0];
-
-		if (field_len == 0)
-			break;
-
-		parsed += field_len + 1;
-
-		if (parsed > eir_len)
-			break;
-
-		/* Check for flags */
-		if (eir[1] == 0x01)
-			return eir[2];
-
-		eir += field_len + 1;
-	}
-
-	return 0;
-}
-
-static void device_found(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_device_found *ev = param;
-	struct mgmt *mgmt = user_data;
-	uint16_t eir_len;
-	uint32_t flags;
-
-	if (len < sizeof(*ev)) {
-		error("Too short device_found length (%u bytes)", len);
-		return;
-	}
-
-	flags = btohl(ev->flags);
-
-	eir_len = get_le16(&ev->eir_len);
-	if (len != sizeof(*ev) + eir_len) {
-		error("dev_found: expected %zu bytes, got %u bytes",
-						sizeof(*ev) + eir_len, len);
-		return;
-	}
-
-	if (discovery) {
-		char addr[18], *name;
-
-		ba2str(&ev->addr.bdaddr, addr);
-		print("hci%u dev_found: %s type %s rssi %d "
-			"flags 0x%04x ", index, addr,
-			typestr(ev->addr.type), ev->rssi, flags);
-
-		if (ev->addr.type != BDADDR_BREDR)
-			print("AD flags 0x%02x ",
-					eir_get_flags(ev->eir, eir_len));
-
-		name = eir_get_name(ev->eir, eir_len);
-		if (name)
-			print("name %s", name);
-		else
-			print("eir_len %u", eir_len);
-
-		free(name);
-	}
-
-	if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
-		struct mgmt_cp_confirm_name cp;
-
-		memset(&cp, 0, sizeof(cp));
-		memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
-		if (resolve_names)
-			cp.name_known = 0;
-		else
-			cp.name_known = 1;
-
-		mgmt_reply(mgmt, MGMT_OP_CONFIRM_NAME, index, sizeof(cp), &cp,
-						confirm_name_rsp, NULL, NULL);
-	}
-}
-
-static void pin_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("PIN Code reply failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("PIN Reply successful");
-}
-
-static int mgmt_pin_reply(uint16_t index, const struct mgmt_addr_info *addr,
-					const char *pin, size_t len)
-{
-	struct mgmt_cp_pin_code_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(cp.addr));
-	cp.pin_len = len;
-	memcpy(cp.pin_code, pin, len);
-
-	return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_REPLY, index,
-				sizeof(cp), &cp, pin_rsp, NULL, NULL);
-}
-
-static void pin_neg_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("PIN Neg reply failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("PIN Negative Reply successful");
-}
-
-static int mgmt_pin_neg_reply(uint16_t index, const struct mgmt_addr_info *addr)
-{
-	struct mgmt_cp_pin_code_neg_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(cp.addr));
-
-	return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_NEG_REPLY, index,
-				sizeof(cp), &cp, pin_neg_rsp, NULL, NULL);
-}
-
-static void confirm_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("User Confirm reply failed. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("User Confirm Reply successful");
-}
-
-static int mgmt_confirm_reply(uint16_t index, const struct mgmt_addr_info *addr)
-{
-	struct mgmt_cp_user_confirm_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(*addr));
-
-	return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_REPLY, index,
-				sizeof(cp), &cp, confirm_rsp, NULL, NULL);
-}
-
-static void confirm_neg_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Confirm Neg reply failed. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("User Confirm Negative Reply successful");
-}
-
-static int mgmt_confirm_neg_reply(uint16_t index,
-					const struct mgmt_addr_info *addr)
-{
-	struct mgmt_cp_user_confirm_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(*addr));
-
-	return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
-				sizeof(cp), &cp, confirm_neg_rsp, NULL, NULL);
-}
-
-static void passkey_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("User Passkey reply failed. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("User Passkey Reply successful");
-}
-
-static int mgmt_passkey_reply(uint16_t index, const struct mgmt_addr_info *addr,
-						uint32_t passkey)
-{
-	struct mgmt_cp_user_passkey_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(*addr));
-	put_le32(passkey, &cp.passkey);
-
-	return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_REPLY, index,
-				sizeof(cp), &cp, passkey_rsp, NULL, NULL);
-}
-
-static void passkey_neg_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Passkey Neg reply failed. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("User Passkey Negative Reply successful");
-}
-
-static int mgmt_passkey_neg_reply(uint16_t index,
-					const struct mgmt_addr_info *addr)
-{
-	struct mgmt_cp_user_passkey_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(*addr));
-
-	return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_NEG_REPLY, index,
-				sizeof(cp), &cp, passkey_neg_rsp, NULL, NULL);
-}
-
-static void prompt_input(const char *input, void *user_data)
-{
-	size_t len;
-
-	len = strlen(input);
-
-	switch (prompt.req) {
-	case MGMT_EV_PIN_CODE_REQUEST:
-		if (len)
-			mgmt_pin_reply(prompt.index, &prompt.addr, input, len);
-		else
-			mgmt_pin_neg_reply(prompt.index, &prompt.addr);
-		break;
-	case MGMT_EV_USER_PASSKEY_REQUEST:
-		if (strlen(input) > 0)
-			mgmt_passkey_reply(prompt.index, &prompt.addr,
-								atoi(input));
-		else
-			mgmt_passkey_neg_reply(prompt.index,
-								&prompt.addr);
-		break;
-	case MGMT_EV_USER_CONFIRM_REQUEST:
-		if (input[0] == 'y' || input[0] == 'Y')
-			mgmt_confirm_reply(prompt.index, &prompt.addr);
-		else
-			mgmt_confirm_neg_reply(prompt.index, &prompt.addr);
-		break;
-	}
-}
-
-static void ask(uint16_t index, uint16_t req, const struct mgmt_addr_info *addr,
-						const char *fmt, ...)
-{
-	char msg[256];
-	va_list ap;
-	int off;
-
-	prompt.index = index;
-	prompt.req = req;
-	memcpy(&prompt.addr, addr, sizeof(*addr));
-
-	va_start(ap, fmt);
-	off = vsnprintf(msg, sizeof(msg), fmt, ap);
-	va_end(ap);
-
-	snprintf(msg + off, sizeof(msg) - off, " %s ",
-					COLOR_BOLDGRAY ">>" COLOR_OFF);
-
-	bt_shell_prompt_input("", msg, prompt_input, NULL);
-}
-
-static void request_pin(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_pin_code_request *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid pin_code request length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s request PIN", index, addr);
-
-	ask(index, MGMT_EV_PIN_CODE_REQUEST, &ev->addr,
-				"PIN Request (press enter to reject)");
-}
-
-static void user_confirm(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_user_confirm_request *ev = param;
-	uint32_t val;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid user_confirm request length (%u)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	val = get_le32(&ev->value);
-
-	print("hci%u %s User Confirm %06u hint %u", index, addr,
-							val, ev->confirm_hint);
-
-	if (ev->confirm_hint)
-		ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
-				"Accept pairing with %s (yes/no)", addr);
-	else
-		ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
-			"Confirm value %06u for %s (yes/no)", val, addr);
-}
-
-static void request_passkey(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_user_passkey_request *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid passkey request length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s request passkey", index, addr);
-
-	ask(index, MGMT_EV_USER_PASSKEY_REQUEST, &ev->addr,
-			"Passkey Request (press enter to reject)");
-}
-
-static void passkey_notify(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_passkey_notify *ev = param;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		error("Invalid passkey request length (%u bytes)", len);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u %s request passkey", index, addr);
-
-	print("Passkey Notify: %06u (entered %u)", get_le32(&ev->passkey),
-								ev->entered);
-}
-
-static void local_oob_data_updated(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_ev_local_oob_data_updated *ev = param;
-	uint16_t eir_len;
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) local_oob_updated event", len);
-		return;
-	}
-
-	eir_len = le16_to_cpu(ev->eir_len);
-	if (len != sizeof(*ev) + eir_len) {
-		error("local_oob_updated: expected %zu bytes, got %u bytes",
-						sizeof(*ev) + eir_len, len);
-		return;
-	}
-
-	print("hci%u oob data updated: type %u len %u", index,
-						ev->type, eir_len);
-}
-
-static void advertising_added(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_ev_advertising_added *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) advertising_added event", len);
-		return;
-	}
-
-	print("hci%u advertising_added: instance %u", index, ev->instance);
-}
-
-static void advertising_removed(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_ev_advertising_removed *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) advertising_removed event", len);
-		return;
-	}
-
-	print("hci%u advertising_removed: instance %u", index, ev->instance);
-}
-
-static void flags_changed(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_device_flags_changed *ev = param;
-	char addr[18];
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) %s event", len, __func__);
-		return;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	print("hci%u device_flags_changed: %s (%s)", index, addr,
-							typestr(ev->addr.type));
-	print("     supp: 0x%08x  curr: 0x%08x",
-					ev->supported_flags, ev->current_flags);
-}
-
-static void advmon_added(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_adv_monitor_added *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) %s event", len, __func__);
-		return;
-	}
-
-	print("hci%u %s: handle %u", index, __func__,
-					le16_to_cpu(ev->monitor_handle));
-}
-
-static void advmon_removed(uint16_t index, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_ev_adv_monitor_removed *ev = param;
-
-	if (len < sizeof(*ev)) {
-		error("Too small (%u bytes) %s event", len, __func__);
-		return;
-	}
-
-	print("hci%u %s: handle %u", index, __func__,
-					le16_to_cpu(ev->monitor_handle));
-}
-
-static void version_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_version *rp = param;
-
-	if (status != 0) {
-		error("Reading mgmt version failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small version reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("MGMT Version %u, revision %u", rp->version,
-						get_le16(&rp->revision));
-
-done:
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_revision(int argc, char **argv)
-{
-	if (mgmt_send(mgmt, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
-				0, NULL, version_rsp, NULL, NULL) == 0) {
-		error("Unable to send read_version cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void commands_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_commands *rp = param;
-	uint16_t num_commands, num_events;
-	size_t expected_len;
-	int i;
-
-	if (status != 0) {
-		error("Read Supported Commands failed: status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small commands reply (%u bytes)", len);
-		goto done;
-	}
-
-	num_commands = get_le16(&rp->num_commands);
-	num_events = get_le16(&rp->num_events);
-
-	expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
-						num_events * sizeof(uint16_t);
-
-	if (len < expected_len) {
-		error("Too small commands reply (%u != %zu)",
-							len, expected_len);
-		goto done;
-	}
-
-	print("%u commands:", num_commands);
-	for (i = 0; i < num_commands; i++) {
-		uint16_t op = get_le16(rp->opcodes + i);
-		print("\t%s (0x%04x)", mgmt_opstr(op), op);
-	}
-
-	print("%u events:", num_events);
-	for (i = 0; i < num_events; i++) {
-		uint16_t ev = get_le16(rp->opcodes + num_commands + i);
-		print("\t%s (0x%04x)", mgmt_evstr(ev), ev);
-	}
-
-done:
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_commands(int argc,
-								char **argv)
-{
-	if (mgmt_send(mgmt, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
-				0, NULL, commands_rsp, NULL, NULL) == 0) {
-		error("Unable to send read_commands cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void config_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_config_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint32_t supported_options, missing_options;
-
-	if (status != 0) {
-		error("Reading hci%u config failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("hci%u:\tUnconfigured controller", index);
-
-	print("\tmanufacturer %u", le16_to_cpu(rp->manufacturer));
-
-	supported_options = le32_to_cpu(rp->supported_options);
-	print("\tsupported options: %s", options2str(supported_options));
-
-	missing_options = le32_to_cpu(rp->missing_options);
-	print("\tmissing options: %s", options2str(missing_options));
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void unconf_index_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_unconf_index_list *rp = param;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		error("Reading index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small index list reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = le16_to_cpu(rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
-		error("Index count (%u) doesn't match reply length (%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Unconfigured index list with %u item%s",
-					count, count != 1 ? "s" : "");
-
-	for (i = 0; i < count; i++) {
-		uint16_t index = le16_to_cpu(rp->index[i]);
-
-		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, index, 0, NULL,
-				config_info_rsp, UINT_TO_PTR(index), NULL)) {
-			error("Unable to send read_config_info cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		pending_index++;
-	}
-
-	if (!count)
-		bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_config(int argc, char **argv)
-{
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_UNCONF_INDEX_LIST,
-					MGMT_INDEX_NONE, 0, NULL,
-					unconf_index_rsp, mgmt, NULL)) {
-			error("Unable to send unconf_index_list cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		return;
-	}
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, mgmt_index, 0, NULL,
-				config_info_rsp, UINT_TO_PTR(index), NULL)) {
-		error("Unable to send read_config_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void config_options_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_config_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint32_t supported_options, missing_options;
-
-	if (status != 0) {
-		error("Reading hci%u config failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("hci%u:\tConfiguration options", index);
-
-	supported_options = le32_to_cpu(rp->supported_options);
-	print("\tsupported options: %s", options2str(supported_options));
-
-	missing_options = le32_to_cpu(rp->missing_options);
-	print("\tmissing options: %s", options2str(missing_options));
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint32_t supported_settings, current_settings;
-	char addr[18];
-
-	if (status != 0) {
-		error("Reading hci%u info failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("hci%u:\tPrimary controller", index);
-
-	ba2str(&rp->bdaddr, addr);
-	print("\taddr %s version %u manufacturer %u class 0x%02x%02x%02x",
-			addr, rp->version, le16_to_cpu(rp->manufacturer),
-			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
-
-	supported_settings = le32_to_cpu(rp->supported_settings);
-	print("\tsupported settings: %s", settings2str(supported_settings));
-
-	current_settings = le32_to_cpu(rp->current_settings);
-	print("\tcurrent settings: %s", settings2str(current_settings));
-
-	print("\tname %s", rp->name);
-	print("\tshort name %s", rp->short_name);
-
-	if (supported_settings & MGMT_SETTING_CONFIGURATION) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
-					index, 0, NULL, config_options_rsp,
-					UINT_TO_PTR(index), NULL)) {
-			error("Unable to send read_config cmd");
-			goto done;
-		}
-		return;
-	}
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void ext_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_ext_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint32_t supported_settings, current_settings;
-	char addr[18];
-
-	if (status != 0) {
-		error("Reading hci%u info failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("hci%u:\tPrimary controller", index);
-
-	ba2str(&rp->bdaddr, addr);
-	print("\taddr %s version %u manufacturer %u",
-			addr, rp->version, le16_to_cpu(rp->manufacturer));
-
-	supported_settings = le32_to_cpu(rp->supported_settings);
-	print("\tsupported settings: %s", settings2str(supported_settings));
-
-	current_settings = le32_to_cpu(rp->current_settings);
-	print("\tcurrent settings: %s", settings2str(current_settings));
-
-	if (supported_settings & MGMT_SETTING_CONFIGURATION) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
-					index, 0, NULL, config_options_rsp,
-					UINT_TO_PTR(index), NULL)) {
-			error("Unable to send read_config cmd");
-			goto done;
-		}
-		return;
-	}
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void index_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_index_list *rp = param;
-	struct mgmt *mgmt = user_data;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		error("Reading index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small index list reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = le16_to_cpu(rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
-		error("Index count (%u) doesn't match reply length (%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Index list with %u item%s", count, count != 1 ? "s" : "");
-
-	for (i = 0; i < count; i++) {
-		uint16_t index = le16_to_cpu(rp->index[i]);
-
-		if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
-					info_rsp, UINT_TO_PTR(index), NULL)) {
-			error("Unable to send read_info cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		pending_index++;
-	}
-
-	if (!count)
-		bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_info(int argc, char **argv)
-{
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST,
-					MGMT_INDEX_NONE, 0, NULL,
-					index_rsp, mgmt, NULL)) {
-			error("Unable to send index_list cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		return;
-	}
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, mgmt_index, 0, NULL, info_rsp,
-					UINT_TO_PTR(mgmt_index), NULL)) {
-		error("Unable to send read_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void ext_index_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_ext_index_list *rp = param;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		error("Reading ext index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small ext index list reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = get_le16(&rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
-		error("Index count (%u) doesn't match reply length (%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Extended index list with %u item%s",
-					count, count != 1 ? "s" : "");
-
-	for (i = 0; i < count; i++) {
-		uint16_t index = le16_to_cpu(rp->entry[i].index);
-		char *busstr = hci_bustostr(rp->entry[i].bus);
-
-		switch (rp->entry[i].type) {
-		case 0x00:
-			print("Primary controller (hci%u,%s)", index, busstr);
-			if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO,
-						index, 0, NULL, ext_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-				error("Unable to send read_ext_info cmd");
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			pending_index++;
-			break;
-		case 0x01:
-			print("Unconfigured controller (hci%u,%s)",
-								index, busstr);
-			if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
-						index, 0, NULL, config_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-				error("Unable to send read_config cmd");
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			pending_index++;
-			break;
-		case 0x02:
-			print("AMP controller (hci%u,%s)", index, busstr);
-			break;
-		default:
-			print("Type %u controller (hci%u,%s)",
-					rp->entry[i].type, index, busstr);
-			break;
-		}
-	}
-
-	print("");
-
-	if (!count)
-		bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_extinfo(int argc, char **argv)
-{
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
-					MGMT_INDEX_NONE, 0, NULL,
-					ext_index_rsp, mgmt, NULL)) {
-			error("Unable to send ext_index_list cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		return;
-	}
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO, mgmt_index, 0, NULL,
-					ext_info_rsp,
-					UINT_TO_PTR(mgmt_index), NULL)) {
-		error("Unable to send ext_read_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void print_cap(const uint8_t *cap, uint16_t cap_len)
-{
-	uint16_t parsed = 0;
-
-	while (parsed < cap_len - 1) {
-		uint8_t field_len = cap[0];
-
-		if (field_len == 0)
-			break;
-
-		parsed += field_len + 1;
-
-		if (parsed > cap_len)
-			break;
-
-		switch (cap[1]) {
-		case 0x01:
-			print("\tFlags: 0x%02x", cap[2]);
-			break;
-		case 0x02:
-			print("\tMax Key Size (BR/EDR): %u", cap[2]);
-			break;
-		case 0x03:
-			print("\tMax Key Size (LE): %u", cap[2]);
-			break;
-		default:
-			print("\tType %u: %u byte%s", cap[1], field_len - 1,
-					(field_len - 1) == 1 ? "" : "s");
-			break;
-		}
-
-		cap += field_len + 1;
-	}
-}
-
-static void sec_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_controller_cap *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-
-	if (status != 0) {
-		error("Reading hci%u security failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	print("Primary controller (hci%u)", index);
-	print("\tInfo length: %u", le16_to_cpu(rp->cap_len));
-	print_cap(rp->cap, le16_to_cpu(rp->cap_len));
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void sec_index_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_ext_index_list *rp = param;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		error("Reading ext index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small ext index list reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = get_le16(&rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
-		error("Index count (%u) doesn't match reply length (%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	for (i = 0; i < count; i++) {
-		uint16_t index = le16_to_cpu(rp->entry[i].index);
-
-		if (rp->entry[i].type != 0x00)
-			continue;
-
-		if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP,
-						index, 0, NULL, sec_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-			error("Unable to send read_security_info cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-		pending_index++;
-	}
-
-	if (!count)
-		bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_secinfo(int argc, char **argv)
-{
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
-					MGMT_INDEX_NONE, 0, NULL,
-					sec_index_rsp, mgmt, NULL)) {
-			error("Unable to send ext_index_list cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		return;
-	}
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP, mgmt_index, 0, NULL,
-					sec_info_rsp,
-					UINT_TO_PTR(mgmt_index), NULL)) {
-		error("Unable to send read_security_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void exp_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_exp_features_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-
-	if (status != 0) {
-		error("Reading hci%u exp features failed with status 0x%02x (%s)",
-					index, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small info reply (%u bytes)", len);
-		goto done;
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		print("Global");
-	else
-		print("Primary controller (hci%u)", index);
-
-	print("\tNumber of experimental features: %u",
-					le16_to_cpu(rp->feature_count));
-
-done:
-	pending_index--;
-
-	if (pending_index > 0)
-		return;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void exp_index_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_ext_index_list *rp = param;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		error("Reading ext index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small ext index list reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = get_le16(&rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
-		error("Index count (%u) doesn't match reply length (%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	for (i = 0; i < count; i++) {
-		uint16_t index = le16_to_cpu(rp->entry[i].index);
-
-		if (rp->entry[i].type != 0x00)
-			continue;
-
-		if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
-						index, 0, NULL, exp_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-				error("Unable to send read_exp_features_info cmd");
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-		pending_index++;
-	}
-}
-
-static void cmd_expinfo(int argc, char **argv)
-{
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
-					MGMT_INDEX_NONE, 0, NULL,
-					exp_index_rsp, mgmt, NULL)) {
-			error("Unable to send ext_index_list cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
-					MGMT_INDEX_NONE, 0, NULL,
-					exp_info_rsp,
-					UINT_TO_PTR(MGMT_INDEX_NONE), NULL)) {
-			error("Unable to send read_exp_features_info cmd");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		pending_index++;
-		return;
-	}
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, mgmt_index,
-					0, NULL, exp_info_rsp,
-					UINT_TO_PTR(mgmt_index), NULL)) {
-		error("Unable to send read_exp_features_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void exp_debug_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set debug feature failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Debug feature successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_exp_debug(int argc, char **argv)
-{
-	/* d4992530-b9ec-469f-ab01-6c481c47da1c */
-	static const uint8_t uuid[16] = {
-				0x1c, 0xda, 0x47, 0x1c, 0x48, 0x6c, 0x01, 0xab,
-				0x9f, 0x46, 0xec, 0xb9, 0x30, 0x25, 0x99, 0xd4,
-	};
-	struct mgmt_cp_set_exp_feature cp;
-	uint8_t val;
-
-	if (parse_setting(argc, argv, &val) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(cp.uuid, uuid, 16);
-	cp.action = val;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
-			sizeof(cp), &cp, exp_debug_rsp, NULL, NULL) == 0) {
-		error("Unable to send debug feature cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void exp_privacy_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set LL privacy feature failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("LL privacy feature successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_exp_privacy(int argc, char **argv)
-{
-	/* 15c0a148-c273-11ea-b3de-0242ac130004 */
-	static const uint8_t uuid[16] = {
-				0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
-				0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
-	};
-	struct mgmt_cp_set_exp_feature cp;
-	uint8_t val;
-
-	if (parse_setting(argc, argv, &val) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(cp.uuid, uuid, 16);
-	cp.action = val;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
-			sizeof(cp), &cp, exp_privacy_rsp, NULL, NULL) == 0) {
-		error("Unable to send LL privacy feature cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void exp_quality_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set Quality Report feature failed: 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Quality Report feature successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_exp_quality(int argc, char **argv)
-{
-	/* 330859bc-7506-492d-9370-9a6f0614037f */
-	static const uint8_t uuid[16] = {
-				0x7f, 0x03, 0x14, 0x06, 0x6f, 0x9a, 0x70, 0x93,
-				0x2d, 0x49, 0x06, 0x75, 0xbc, 0x59, 0x08, 0x33,
-	};
-	struct mgmt_cp_set_exp_feature cp;
-	uint8_t val;
-
-	if (mgmt_index == MGMT_INDEX_NONE) {
-		error("BQR feature requires a valid controller index");
-		return;
-	}
-
-	if (parse_setting(argc, argv, &val) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	if (val != 0 && val != 1) {
-		error("Invalid value %u", val);
-		return;
-	}
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(cp.uuid, uuid, 16);
-	cp.action = val;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
-			sizeof(cp), &cp, exp_quality_rsp, NULL, NULL) == 0) {
-		error("Unable to send quality report feature cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void print_mgmt_tlv(void *data, void *user_data)
-{
-	const struct mgmt_tlv *entry = data;
-	char buf[256];
-
-	bin2hex(entry->value, entry->length, buf, sizeof(buf));
-	print("Type: 0x%04x\tLength: %02hhu\tValue: %s", entry->type,
-							entry->length, buf);
-}
-
-static void read_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	struct mgmt_tlv_list *tlv_list;
-
-	if (status != 0) {
-		error("Read system configuration failed with status "
-				"0x%02x (%s)", status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	tlv_list = mgmt_tlv_list_load_from_buf(param, len);
-	if (!tlv_list) {
-		error("Unable to parse response of read system configuration");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	mgmt_tlv_list_foreach(tlv_list, print_mgmt_tlv, NULL);
-	mgmt_tlv_list_free(tlv_list);
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_read_sysconfig(int argc, char **argv)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_DEF_SYSTEM_CONFIG, index,
-			0, NULL, read_sysconfig_rsp, NULL, NULL)) {
-		error("Unable to send read system configuration cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static bool parse_mgmt_tlv(const char *input, uint16_t *type, uint8_t *length,
-								uint8_t *value)
-{
-	int i, value_starting_pos;
-
-	if (sscanf(input, "%4hx:%1hhu:%n", type, length,
-						&value_starting_pos) < 2) {
-		return false;
-	}
-
-	input += value_starting_pos;
-
-	if (*length * 2 != strlen(input))
-		return false;
-
-	for (i = 0; i < *length; i++) {
-		if (sscanf(input + i * 2, "%2hhx", &value[i]) < 1)
-			return false;
-	}
-
-	return true;
-}
-
-static void set_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
-								void *user_data)
-{
-	if (status != MGMT_STATUS_SUCCESS) {
-		error("Could not set default system configuration with status "
-				"0x%02x (%s)", status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Set default system configuration success");
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static bool set_sysconfig(int argc, char **argv)
-{
-	struct mgmt_tlv_list *tlv_list = NULL;
-	int i;
-	uint16_t index, type;
-	uint8_t length;
-	uint8_t value[256] = {};
-	bool success = false;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	tlv_list = mgmt_tlv_list_new();
-	if (!tlv_list) {
-		error("tlv_list failed to init");
-		goto failed;
-	}
-
-	for (i = 0; i < argc; i++) {
-		if (!parse_mgmt_tlv(argv[i], &type, &length, value)) {
-			error("failed to parse");
-			goto failed;
-		}
-
-		if (!mgmt_tlv_add(tlv_list, type, length, value)) {
-			error("failed to add");
-			goto failed;
-		}
-	}
-
-	if (!mgmt_send_tlv(mgmt, MGMT_OP_SET_DEF_SYSTEM_CONFIG, index,
-				tlv_list, set_sysconfig_rsp, NULL, NULL)) {
-		error("Failed to send \"Set Default System Configuration\""
-								" command");
-		goto failed;
-	}
-
-	success = true;
-
-failed:
-	if (tlv_list)
-		mgmt_tlv_list_free(tlv_list);
-
-	return success;
-}
-
-static void set_sysconfig_usage(void)
-{
-	bt_shell_usage();
-	print("Parameters:\n\t-v <type:length:value>...\n"
-		"e.g.:\n\tset-sysconfig -v 001a:2:1234 001f:1:00");
-}
-
-static void cmd_set_sysconfig(int argc, char **argv)
-{
-	bool success = false;
-
-	if (strcasecmp(argv[1], "-v") == 0 && argc > 2) {
-		argc -= 2;
-		argv += 2;
-		success = set_sysconfig(argc, argv);
-	}
-
-	if (!success) {
-		set_sysconfig_usage();
-		bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void auto_power_enable_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	uint16_t index = PTR_TO_UINT(user_data);
-
-	print("Successfully enabled controller with index %u", index);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void auto_power_info_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_read_info *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint32_t supported_settings, current_settings, missing_settings;
-	uint8_t val = 0x01;
-
-	if (status) {
-		error("Reading info failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	supported_settings = le32_to_cpu(rp->supported_settings);
-	current_settings = le32_to_cpu(rp->current_settings);
-	missing_settings = current_settings ^ supported_settings;
-
-	if (missing_settings & MGMT_SETTING_BREDR)
-		mgmt_send(mgmt, MGMT_OP_SET_BREDR, index, sizeof(val), &val,
-							NULL, NULL, NULL);
-
-	if (missing_settings & MGMT_SETTING_SSP)
-		mgmt_send(mgmt, MGMT_OP_SET_SSP, index, sizeof(val), &val,
-							NULL, NULL, NULL);
-
-	if (missing_settings & MGMT_SETTING_LE)
-		mgmt_send(mgmt, MGMT_OP_SET_LE, index, sizeof(val), &val,
-							NULL, NULL, NULL);
-
-	if (missing_settings & MGMT_SETTING_SECURE_CONN)
-		mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index,
-							sizeof(val), &val,
-							NULL, NULL, NULL);
-
-	if (missing_settings & MGMT_SETTING_BONDABLE)
-		mgmt_send(mgmt, MGMT_OP_SET_BONDABLE, index, sizeof(val), &val,
-							NULL, NULL, NULL);
-
-	if (current_settings & MGMT_SETTING_POWERED)
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-
-	if (!mgmt_send(mgmt, MGMT_OP_SET_POWERED, index, sizeof(val), &val,
-						auto_power_enable_rsp,
-						UINT_TO_PTR(index), NULL)) {
-		error("Unable to send set powerd cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void auto_power_index_evt(uint16_t index, uint16_t len,
-					const void *param, void *user_data)
-{
-	uint16_t index_filter = PTR_TO_UINT(user_data);
-
-	if (index != index_filter)
-		return;
-
-	print("New controller with index %u", index);
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
-						auto_power_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-		error("Unable to send read info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void auto_power_index_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_read_index_list *rp = param;
-	uint16_t index = PTR_TO_UINT(user_data);
-	uint16_t i, count;
-	bool found = false;
-
-	if (status) {
-		error("Reading index list failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = le16_to_cpu(rp->num_controllers);
-	for (i = 0; i < count; i++) {
-		if (le16_to_cpu(rp->index[i]) == index)
-			found = true;
-	}
-
-	if (!found) {
-		print("Waiting for index %u to appear", index);
-
-		mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index,
-						auto_power_index_evt,
-						UINT_TO_PTR(index), NULL);
-		return;
-	}
-
-	print("Found controller with index %u", index);
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
-						auto_power_info_rsp,
-						UINT_TO_PTR(index), NULL)) {
-		error("Unable to send read info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_auto_power(int argc, char **argv)
-{
-	int index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
-						auto_power_index_rsp,
-						UINT_TO_PTR(index), NULL)) {
-		error("Unable to send read index list cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void get_flags_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_device_flags *rp = param;
-
-	if (status != 0) {
-		error("Get device flags failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Supported Flags: 0x%08x", rp->supported_flags);
-	print("Current Flags:   0x%08x", rp->current_flags);
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option get_flags_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_get_flags(int argc, char **argv)
-{
-	struct mgmt_cp_get_device_flags cp;
-	uint8_t type = BDADDR_BREDR;
-	char addr[18];
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", get_flags_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	ba2str(&cp.addr.bdaddr, addr);
-	print("Get device flag of %s (%s)", addr, typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_GET_DEVICE_FLAGS, index, sizeof(cp), &cp,
-					get_flags_rsp, NULL, NULL) == 0) {
-		error("Unable to send Get Device Flags command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void set_flags_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Set device flags failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option set_flags_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ "flags",	1, 0, 'f' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_set_flags(int argc, char **argv)
-{
-	struct mgmt_cp_set_device_flags cp;
-	uint8_t type = BDADDR_BREDR;
-	uint32_t flags = 0;
-	char addr[18];
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+f:t:h", set_flags_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'f':
-			flags = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-	cp.current_flags = flags;
-
-	ba2str(&cp.addr.bdaddr, addr);
-	print("Set device flag of %s (%s)", addr, typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_FLAGS, index, sizeof(cp), &cp,
-					set_flags_rsp, NULL, NULL) == 0) {
-		error("Unable to send Set Device Flags command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-}
-
-/* Wrapper to get the index and opcode to the response callback */
-struct command_data {
-	uint16_t id;
-	uint16_t op;
-	void (*callback) (uint16_t id, uint16_t op, uint8_t status,
-					uint16_t len, const void *param);
-};
-
-static void cmd_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	struct command_data *data = user_data;
-
-	data->callback(data->op, data->id, status, len, param);
-}
-
-static unsigned int send_cmd(struct mgmt *mgmt, uint16_t op, uint16_t id,
-				uint16_t len, const void *param,
-				void (*cb)(uint16_t id, uint16_t op,
-						uint8_t status, uint16_t len,
-						const void *param))
-{
-	struct command_data *data;
-	unsigned int send_id;
-
-	data = new0(struct command_data, 1);
-	if (!data)
-		return 0;
-
-	data->id = id;
-	data->op = op;
-	data->callback = cb;
-
-	send_id = mgmt_send(mgmt, op, id, len, param, cmd_rsp, data, free);
-	if (send_id == 0)
-		free(data);
-
-	return send_id;
-}
-
-static void setting_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
-							const void *param)
-{
-	const uint32_t *rp = param;
-
-	if (status != 0) {
-		error("%s for hci%u failed with status 0x%02x (%s)",
-			mgmt_opstr(op), id, status, mgmt_errstr(status));
-		goto done;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small %s response (%u bytes)",
-							mgmt_opstr(op), len);
-		goto done;
-	}
-
-	print("hci%u %s complete, settings: %s", id, mgmt_opstr(op),
-						settings2str(get_le32(rp)));
-
-done:
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_setting(uint16_t op, int argc, char **argv)
-{
-	int index;
-	uint8_t val;
-
-	if (parse_setting(argc, argv, &val) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (send_cmd(mgmt, op, index, sizeof(val), &val, setting_rsp) == 0) {
-		error("Unable to send %s cmd", mgmt_opstr(op));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_power(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_POWERED, argc, argv);
-}
-
-static void cmd_discov(int argc, char **argv)
-{
-	struct mgmt_cp_set_discoverable cp;
-	uint16_t index;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
-		cp.val = 1;
-	else if (strcasecmp(argv[1], "off") == 0)
-		cp.val = 0;
-	else if (strcasecmp(argv[1], "limited") == 0)
-		cp.val = 2;
-	else
-		cp.val = atoi(argv[1]);
-
-	if (argc > 2)
-		cp.timeout = htobs(atoi(argv[2]));
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (send_cmd(mgmt, MGMT_OP_SET_DISCOVERABLE, index, sizeof(cp), &cp,
-							setting_rsp) == 0) {
-		error("Unable to send set_discoverable cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_connectable(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_CONNECTABLE, argc, argv);
-}
-
-static void cmd_fast_conn(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_FAST_CONNECTABLE, argc, argv);
-}
-
-static void cmd_bondable(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_BONDABLE, argc, argv);
-}
-
-static void cmd_linksec(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_LINK_SECURITY, argc, argv);
-}
-
-static void cmd_ssp(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_SSP, argc, argv);
-}
-
-static void cmd_sc(int argc, char **argv)
-{
-	uint8_t val;
-	uint16_t index;
-
-	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
-		val = 1;
-	else if (strcasecmp(argv[1], "off") == 0)
-		val = 0;
-	else if (strcasecmp(argv[1], "only") == 0)
-		val = 2;
-	else
-		val = atoi(argv[1]);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (send_cmd(mgmt, MGMT_OP_SET_SECURE_CONN, index,
-					sizeof(val), &val, setting_rsp) == 0) {
-		error("Unable to send set_secure_conn cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_hs(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_HS, argc, argv);
-}
-
-static void cmd_le(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_LE, argc, argv);
-}
-
-static void cmd_advertising(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_ADVERTISING, argc, argv);
-}
-
-static void cmd_bredr(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_BREDR, argc, argv);
-}
-
-static void cmd_privacy(int argc, char **argv)
-{
-	struct mgmt_cp_set_privacy cp;
-	uint16_t index;
-
-	if (parse_setting(argc, argv, &cp.privacy) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (argc > 2) {
-		if (hex2bin(argv[2], cp.irk,
-					sizeof(cp.irk)) != sizeof(cp.irk)) {
-			error("Invalid key format");
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	} else {
-		int fd;
-
-		fd = open("/dev/urandom", O_RDONLY);
-		if (fd < 0) {
-			error("open(/dev/urandom): %s", strerror(errno));
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		if (read(fd, cp.irk, sizeof(cp.irk)) != sizeof(cp.irk)) {
-			error("Reading from urandom failed");
-			close(fd);
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-
-		close(fd);
-	}
-
-	if (send_cmd(mgmt, MGMT_OP_SET_PRIVACY, index, sizeof(cp), &cp,
-							setting_rsp) == 0) {
-		error("Unable to send Set Privacy command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void exp_offload_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set offload codec failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Offload codec feature successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_exp_offload_codecs(int argc, char **argv)
-{
-	/* a6695ace-ee7f-4fb9-881a-5fac66c629af */
-	static const uint8_t uuid[16] = {
-				0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
-				0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
-	};
-
-	struct mgmt_cp_set_exp_feature cp;
-	uint8_t val;
-	uint16_t index;
-
-	if (parse_setting(argc, argv, &val) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(cp.uuid, uuid, 16);
-	cp.action = val;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, index,
-			sizeof(cp), &cp, exp_offload_rsp, NULL, NULL) == 0) {
-		error("Unable to send offload codecs feature cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void class_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
-							const void *param)
-{
-	const struct mgmt_ev_class_of_dev_changed *rp = param;
-
-	if (len == 0 && status != 0) {
-		error("%s failed, status 0x%02x (%s)",
-				mgmt_opstr(op), status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Unexpected %s len %u", mgmt_opstr(op), len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("%s succeeded. Class 0x%02x%02x%02x", mgmt_opstr(op),
-		rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_class(int argc, char **argv)
-{
-	uint8_t class[2];
-	uint16_t index;
-
-	class[0] = atoi(argv[1]);
-	class[1] = atoi(argv[2]);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (send_cmd(mgmt, MGMT_OP_SET_DEV_CLASS, index, sizeof(class), class,
-							class_rsp) == 0) {
-		error("Unable to send set_dev_class cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void disconnect_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_disconnect *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("Disconnect failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Invalid disconnect response length (%u)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status == 0)
-		print("%s disconnected", addr);
-	else
-		error("Disconnecting %s failed with status 0x%02x (%s)",
-				addr, status, mgmt_errstr(status));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option disconnect_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_disconnect(int argc, char **argv)
-{
-	struct mgmt_cp_disconnect cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", disconnect_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argv += optind;
-	optind = 0;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (mgmt_send(mgmt, MGMT_OP_DISCONNECT, index, sizeof(cp), &cp,
-					disconnect_rsp, NULL, NULL) == 0) {
-		error("Unable to send disconnect cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void con_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_connections *rp = param;
-	uint16_t count, i;
-
-	if (len < sizeof(*rp)) {
-		error("Too small (%u bytes) get_connections rsp", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	count = get_le16(&rp->conn_count);
-	if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
-		error("Invalid get_connections length (count=%u, len=%u)",
-								count, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	for (i = 0; i < count; i++) {
-		char addr[18];
-
-		ba2str(&rp->addr[i].bdaddr, addr);
-
-		print("%s type %s", addr, typestr(rp->addr[i].type));
-	}
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_con(int argc, char **argv)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send(mgmt, MGMT_OP_GET_CONNECTIONS, index, 0, NULL,
-						con_rsp, NULL, NULL) == 0) {
-		error("Unable to send get_connections cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void find_service_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Start Service Discovery failed: status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Service discovery started");
-	discovery = true;
-}
-
-static struct option find_service_options[] = {
-	{ "help",	no_argument, 0, 'h' },
-	{ "le-only",	no_argument, 0, 'l' },
-	{ "bredr-only",	no_argument, 0, 'b' },
-	{ "uuid",	required_argument, 0, 'u' },
-	{ "rssi",	required_argument, 0, 'r' },
-	{ 0, 0, 0, 0 }
-};
-
-static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
-{
-	if (uuid->type == SDP_UUID16)
-		sdp_uuid16_to_uuid128(uuid128, uuid);
-	else if (uuid->type == SDP_UUID32)
-		sdp_uuid32_to_uuid128(uuid128, uuid);
-	else
-		memcpy(uuid128, uuid, sizeof(*uuid));
-}
-
-#define MAX_UUIDS 4
-
-static void cmd_find_service(int argc, char **argv)
-{
-	struct mgmt_cp_start_service_discovery *cp;
-	uint8_t buf[sizeof(*cp) + 16 * MAX_UUIDS];
-	uuid_t uuid;
-	uint128_t uint128;
-	uuid_t uuid128;
-	uint8_t type = SCAN_TYPE_DUAL;
-	int8_t rssi;
-	uint16_t count;
-	int opt;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	rssi = 127;
-	count = 0;
-
-	while ((opt = getopt_long(argc, argv, "+lbu:r:h",
-					find_service_options, NULL)) != -1) {
-		switch (opt) {
-		case 'l':
-			type &= ~SCAN_TYPE_BREDR;
-			type |= SCAN_TYPE_LE;
-			break;
-		case 'b':
-			type |= SCAN_TYPE_BREDR;
-			type &= ~SCAN_TYPE_LE;
-			break;
-		case 'u':
-			if (count == MAX_UUIDS) {
-				print("Max %u UUIDs supported", MAX_UUIDS);
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-
-			if (bt_string2uuid(&uuid, optarg) < 0) {
-				print("Invalid UUID: %s", optarg);
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			cp = (void *) buf;
-			uuid_to_uuid128(&uuid128, &uuid);
-			ntoh128((uint128_t *) uuid128.value.uuid128.data,
-				&uint128);
-			htob128(&uint128, (uint128_t *) cp->uuids[count++]);
-			break;
-		case 'r':
-			rssi = atoi(optarg);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	optind = 0;
-
-	cp = (void *) buf;
-	cp->type = type;
-	cp->rssi = rssi;
-	cp->uuid_count = cpu_to_le16(count);
-
-	if (mgmt_send(mgmt, MGMT_OP_START_SERVICE_DISCOVERY, index,
-				sizeof(*cp) + count * 16, cp,
-				find_service_rsp, NULL, NULL) == 0) {
-		error("Unable to send start_service_discovery cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void find_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Unable to start discovery. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Discovery started");
-	discovery = true;
-}
-
-static struct option find_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "le-only",	1, 0, 'l' },
-	{ "bredr-only",	1, 0, 'b' },
-	{ "limited",	1, 0, 'L' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_find(int argc, char **argv)
-{
-	struct mgmt_cp_start_discovery cp;
-	uint8_t op = MGMT_OP_START_DISCOVERY;
-	uint8_t type = SCAN_TYPE_DUAL;
-	int opt;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	while ((opt = getopt_long(argc, argv, "+lbLh", find_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'l':
-			type &= ~SCAN_TYPE_BREDR;
-			type |= SCAN_TYPE_LE;
-			break;
-		case 'b':
-			type |= SCAN_TYPE_BREDR;
-			type &= ~SCAN_TYPE_LE;
-			break;
-		case 'L':
-			op = MGMT_OP_START_LIMITED_DISCOVERY;
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	optind = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	cp.type = type;
-
-	if (mgmt_send(mgmt, op, index, sizeof(cp), &cp, find_rsp,
-							NULL, NULL) == 0) {
-		error("Unable to send start_discovery cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void stop_find_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Stop Discovery failed: status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-	}
-
-	print("Discovery stopped");
-	discovery = false;
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option stop_find_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "le-only",	1, 0, 'l' },
-	{ "bredr-only",	1, 0, 'b' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_stop_find(int argc, char **argv)
-{
-	struct mgmt_cp_stop_discovery cp;
-	uint8_t type = SCAN_TYPE_DUAL;
-	int opt;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	while ((opt = getopt_long(argc, argv, "+lbh", stop_find_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'l':
-			type &= ~SCAN_TYPE_BREDR;
-			type |= SCAN_TYPE_LE;
-			break;
-		case 'b':
-			type |= SCAN_TYPE_BREDR;
-			type &= ~SCAN_TYPE_LE;
-			break;
-		case 'h':
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		}
-	}
-
-	optind = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	cp.type = type;
-
-	if (mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, index, sizeof(cp), &cp,
-					     stop_find_rsp, NULL, NULL) == 0) {
-		error("Unable to send stop_discovery cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void name_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Unable to set local name with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_name(int argc, char **argv)
-{
-	struct mgmt_cp_set_local_name cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
-	if (argc > 2)
-		strncpy((char *) cp.short_name, argv[2],
-					MGMT_MAX_SHORT_NAME_LENGTH - 1);
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_LOCAL_NAME, index, sizeof(cp), &cp,
-						name_rsp, NULL, NULL) == 0) {
-		error("Unable to send set_name cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void pair_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_pair_device *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("Pairing failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Unexpected pair_rsp len %u", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status)
-		error("Pairing with %s (%s) failed. status 0x%02x (%s)",
-			addr, typestr(rp->addr.type), status,
-			mgmt_errstr(status));
-	else
-		print("Paired with %s (%s)", addr, typestr(rp->addr.type));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option pair_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "capability",	1, 0, 'c' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_pair(int argc, char **argv)
-{
-	struct mgmt_cp_pair_device cp;
-	uint8_t cap = 0x01;
-	uint8_t type = BDADDR_BREDR;
-	char addr[18];
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'c':
-			cap = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-	cp.io_cap = cap;
-
-	ba2str(&cp.addr.bdaddr, addr);
-	print("Pairing with %s (%s)", addr, typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_PAIR_DEVICE, index, sizeof(cp), &cp,
-						pair_rsp, NULL, NULL) == 0) {
-		error("Unable to send pair_device cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cancel_pair_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_addr_info *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("Cancel Pairing failed with 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Unexpected cancel_pair_rsp len %u", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->bdaddr, addr);
-
-	if (status)
-		error("Cancel Pairing with %s (%s) failed. 0x%02x (%s)",
-			addr, typestr(rp->type), status,
-			mgmt_errstr(status));
-	else
-		print("Pairing Cancelled with %s", addr);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option cancel_pair_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_cancel_pair(int argc, char **argv)
-{
-	struct mgmt_addr_info cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", cancel_pair_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.bdaddr);
-	cp.type = type;
-
-	if (mgmt_reply(mgmt, MGMT_OP_CANCEL_PAIR_DEVICE, index, sizeof(cp), &cp,
-					cancel_pair_rsp, NULL, NULL) == 0) {
-		error("Unable to send cancel_pair_device cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void unpair_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_unpair_device *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("Unpair device failed. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Unexpected unpair_device_rsp len %u", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status)
-		error("Unpairing %s failed. status 0x%02x (%s)",
-				addr, status, mgmt_errstr(status));
-	else
-		print("%s unpaired", addr);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option unpair_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_unpair(int argc, char **argv)
-{
-	struct mgmt_cp_unpair_device cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", unpair_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-	cp.disconnect = 1;
-
-	if (mgmt_send(mgmt, MGMT_OP_UNPAIR_DEVICE, index, sizeof(cp), &cp,
-						unpair_rsp, NULL, NULL) == 0) {
-		error("Unable to send unpair_device cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void keys_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Load keys failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Keys successfully loaded");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_keys(int argc, char **argv)
-{
-	struct mgmt_cp_load_link_keys cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (mgmt_send(mgmt, MGMT_OP_LOAD_LINK_KEYS, index, sizeof(cp), &cp,
-						keys_rsp, NULL, NULL) == 0) {
-		error("Unable to send load_keys cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void ltks_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Load keys failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Long term keys successfully loaded");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_ltks(int argc, char **argv)
-{
-	struct mgmt_cp_load_long_term_keys cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index, sizeof(cp), &cp,
-						ltks_rsp, NULL, NULL) == 0) {
-		error("Unable to send load_ltks cmd");
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-	}
-}
-
-static void irks_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Load IRKs failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Identity Resolving Keys successfully loaded");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option irks_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "local",	1, 0, 'l' },
-	{ "file",	1, 0, 'f' },
-	{ 0, 0, 0, 0 }
-};
-
-#define MAX_IRKS 4
-
-static void cmd_irks(int argc, char **argv)
-{
-	struct mgmt_cp_load_irks *cp;
-	uint8_t buf[sizeof(*cp) + 23 * MAX_IRKS];
-	uint16_t count, local_index;
-	char path[PATH_MAX];
-	int opt;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp = (void *) buf;
-	count = 0;
-
-	while ((opt = getopt_long(argc, argv, "+l:f:h",
-					irks_options, NULL)) != -1) {
-		switch (opt) {
-		case 'l':
-			if (count >= MAX_IRKS) {
-				error("Number of IRKs exceeded");
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			if (strlen(optarg) > 3 &&
-					strncasecmp(optarg, "hci", 3) == 0)
-				local_index = atoi(optarg + 3);
-			else
-				local_index = atoi(optarg);
-			snprintf(path, sizeof(path),
-				"/sys/kernel/debug/bluetooth/hci%u/identity",
-				local_index);
-			if (!load_identity(path, &cp->irks[count])) {
-				error("Unable to load identity");
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			count++;
-			break;
-		case 'f':
-			if (count >= MAX_IRKS) {
-				error("Number of IRKs exceeded");
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			if (!load_identity(optarg, &cp->irks[count])) {
-				error("Unable to load identities");
-				optind = 0;
-				return bt_shell_noninteractive_quit(EXIT_FAILURE);
-			}
-			count++;
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	optind = 0;
-
-	cp->irk_count = cpu_to_le16(count);
-
-	if (mgmt_send(mgmt, MGMT_OP_LOAD_IRKS, index,
-					sizeof(*cp) + count * 23, cp,
-					irks_rsp, NULL, NULL) == 0) {
-		error("Unable to send load_irks cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void block_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
-							const void *param)
-{
-	const struct mgmt_addr_info *rp = param;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("%s failed, status 0x%02x (%s)",
-				mgmt_opstr(op), status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Unexpected %s len %u", mgmt_opstr(op), len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->bdaddr, addr);
-
-	if (status)
-		error("%s %s (%s) failed. status 0x%02x (%s)",
-				mgmt_opstr(op), addr, typestr(rp->type),
-				status, mgmt_errstr(status));
-	else
-		print("%s %s succeeded", mgmt_opstr(op), addr);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option block_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_block(int argc, char **argv)
-{
-	struct mgmt_cp_block_device cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
-							NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (send_cmd(mgmt, MGMT_OP_BLOCK_DEVICE, index, sizeof(cp), &cp,
-							block_rsp) == 0) {
-		error("Unable to send block_device cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_unblock(int argc, char **argv)
-{
-	struct mgmt_cp_unblock_device cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
-							NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (send_cmd(mgmt, MGMT_OP_UNBLOCK_DEVICE, index, sizeof(cp), &cp,
-							block_rsp) == 0) {
-		error("Unable to send unblock_device cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_add_uuid(int argc, char **argv)
-{
-	struct mgmt_cp_add_uuid cp;
-	uint128_t uint128;
-	uuid_t uuid, uuid128;
-	uint16_t index;
-
-	if (argc < 3) {
-		print("UUID and service hint needed");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (bt_string2uuid(&uuid, argv[1]) < 0) {
-		print("Invalid UUID: %s", argv[1]);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	memset(&cp, 0, sizeof(cp));
-
-	uuid_to_uuid128(&uuid128, &uuid);
-	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
-	htob128(&uint128, (uint128_t *) cp.uuid);
-
-	cp.svc_hint = atoi(argv[2]);
-
-	if (send_cmd(mgmt, MGMT_OP_ADD_UUID, index, sizeof(cp), &cp,
-							class_rsp) == 0) {
-		error("Unable to send add_uuid cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_remove_uuid(int argc, char **argv)
-{
-	struct mgmt_cp_remove_uuid cp;
-	uint128_t uint128;
-	uuid_t uuid, uuid128;
-	uint16_t index;
-
-	if (argc < 2) {
-		print("UUID needed");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (bt_string2uuid(&uuid, argv[1]) < 0) {
-		print("Invalid UUID: %s", argv[1]);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	memset(&cp, 0, sizeof(cp));
-
-	uuid_to_uuid128(&uuid128, &uuid);
-	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
-	htob128(&uint128, (uint128_t *) cp.uuid);
-
-	if (send_cmd(mgmt, MGMT_OP_REMOVE_UUID, index, sizeof(cp), &cp,
-							class_rsp) == 0) {
-		error("Unable to send remove_uuid cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_clr_uuids(int argc, char **argv)
-{
-	char *uuid_any = "00000000-0000-0000-0000-000000000000";
-	char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
-
-	cmd_remove_uuid(2, rm_argv);
-}
-
-static void local_oob_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_local_oob_data *rp = param;
-	char str[33];
-
-	if (status != 0) {
-		error("Read Local OOB Data failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small (%u bytes) read_local_oob rsp", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	bin2hex(rp->hash192, 16, str, sizeof(str));
-	print("Hash C from P-192: %s", str);
-
-	bin2hex(rp->rand192, 16, str, sizeof(str));
-	print("Randomizer R with P-192: %s", str);
-
-	if (len < sizeof(*rp))
-		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-
-	bin2hex(rp->hash256, 16, str, sizeof(str));
-	print("Hash C from P-256: %s", str);
-
-	bin2hex(rp->rand256, 16, str, sizeof(str));
-	print("Randomizer R with P-256: %s", str);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_local_oob(int argc, char **argv)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_DATA, index, 0, NULL,
-					local_oob_rsp, NULL, NULL) == 0) {
-		error("Unable to send read_local_oob cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void remote_oob_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_addr_info *rp = param;
-	char addr[18];
-
-	if (status != 0) {
-		error("Add Remote OOB Data failed: 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return;
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small (%u bytes) add_remote_oob rsp", len);
-		return;
-	}
-
-	ba2str(&rp->bdaddr, addr);
-	print("Remote OOB data added for %s (%u)", addr, rp->type);
-}
-
-static struct option remote_oob_opt[] = {
-	{ "help",	0, 0, '?' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_remote_oob(int argc, char **argv)
-{
-	struct mgmt_cp_add_remote_oob_data cp;
-	int opt;
-	uint16_t index;
-
-	memset(&cp, 0, sizeof(cp));
-	cp.addr.type = BDADDR_BREDR;
-
-	while ((opt = getopt_long(argc, argv, "+t:r:R:h:H:",
-					remote_oob_opt, NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			cp.addr.type = strtol(optarg, NULL, 0);
-			break;
-		case 'r':
-			hex2bin(optarg, cp.rand192, 16);
-			break;
-		case 'h':
-			hex2bin(optarg, cp.hash192, 16);
-			break;
-		case 'R':
-			hex2bin(optarg, cp.rand256, 16);
-			break;
-		case 'H':
-			hex2bin(optarg, cp.hash256, 16);
-			break;
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	str2ba(argv[0], &cp.addr.bdaddr);
-
-	print("Adding OOB data for %s (%s)", argv[0], typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_ADD_REMOTE_OOB_DATA, index,
-				sizeof(cp), &cp, remote_oob_rsp,
-				NULL, NULL) == 0) {
-		error("Unable to send add_remote_oob cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void did_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set Device ID failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Device ID successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_did(int argc, char **argv)
-{
-	struct mgmt_cp_set_device_id cp;
-	uint16_t vendor, product, version , source;
-	int result;
-	uint16_t index;
-
-	result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
-								&version);
-	if (result == 3) {
-		source = 0x0001;
-		goto done;
-	}
-
-	result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
-								&version);
-	if (result == 3) {
-		source = 0x0002;
-		goto done;
-	}
-
-	return;
-done:
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.source = htobs(source);
-	cp.vendor = htobs(vendor);
-	cp.product = htobs(product);
-	cp.version = htobs(version);
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_ID, index, sizeof(cp), &cp,
-						did_rsp, NULL, NULL) == 0) {
-		error("Unable to send set_device_id cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void static_addr_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set static address failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Static address successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_static_addr(int argc, char **argv)
-{
-	struct mgmt_cp_set_static_address cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	str2ba(argv[1], &cp.bdaddr);
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_STATIC_ADDRESS, index, sizeof(cp), &cp,
-					static_addr_rsp, NULL, NULL) == 0) {
-		error("Unable to send set_static_address cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void options_rsp(uint16_t op, uint16_t id, uint8_t status,
-					uint16_t len, const void *param)
-{
-	const uint32_t *rp = param;
-
-	if (status != 0) {
-		error("%s for hci%u failed with status 0x%02x (%s)",
-			mgmt_opstr(op), id, status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small %s response (%u bytes)",
-							mgmt_opstr(op), len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("hci%u %s complete, options: %s", id, mgmt_opstr(op),
-						options2str(get_le32(rp)));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_public_addr(int argc, char **argv)
-{
-	struct mgmt_cp_set_public_address cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	str2ba(argv[1], &cp.bdaddr);
-
-	if (send_cmd(mgmt, MGMT_OP_SET_PUBLIC_ADDRESS, index, sizeof(cp), &cp,
-							options_rsp) == 0) {
-		error("Unable to send Set Public Address cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_ext_config(int argc, char **argv)
-{
-	struct mgmt_cp_set_external_config cp;
-	uint16_t index;
-
-	if (parse_setting(argc, argv, &cp.config) == false)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (send_cmd(mgmt, MGMT_OP_SET_EXTERNAL_CONFIG, index, sizeof(cp), &cp,
-							options_rsp) == 0) {
-		error("Unable to send Set External Config cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_debug_keys(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_DEBUG_KEYS, argc, argv);
-}
-
-static void conn_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_conn_info *rp = param;	char addr[18];
-
-	if (len == 0 && status != 0) {
-		error("Get Conn Info failed, status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Unexpected Get Conn Info len %u", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status) {
-		error("Get Conn Info for %s (%s) failed. status 0x%02x (%s)",
-						addr, typestr(rp->addr.type),
-						status, mgmt_errstr(status));
-	} else {
-		print("Connection Information for %s (%s)",
-						addr, typestr(rp->addr.type));
-		print("\tRSSI %d\tTX power %d\tmaximum TX power %d",
-				rp->rssi, rp->tx_power, rp->max_tx_power);
-	}
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option conn_info_options[] = {
-	{ "help",       0, 0, 'h' },
-	{ "type",       1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_conn_info(int argc, char **argv)
-{
-	struct mgmt_cp_get_conn_info cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", conn_info_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (mgmt_send(mgmt, MGMT_OP_GET_CONN_INFO, index, sizeof(cp), &cp,
-					conn_info_rsp, NULL, NULL) == 0) {
-		error("Unable to send get_conn_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void io_cap_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Could not set IO Capability with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("IO Capabilities successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_io_cap(int argc, char **argv)
-{
-	struct mgmt_cp_set_io_capability cp;
-	uint8_t cap;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cap = strtol(argv[1], NULL, 0);
-	memset(&cp, 0, sizeof(cp));
-	cp.io_capability = cap;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_IO_CAPABILITY, index, sizeof(cp), &cp,
-					io_cap_rsp, NULL, NULL) == 0) {
-		error("Unable to send set-io-cap cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void scan_params_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Set scan parameters failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Scan parameters successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_scan_params(int argc, char **argv)
-{
-	struct mgmt_cp_set_scan_params cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.interval = strtol(argv[1], NULL, 0);
-	cp.window = strtol(argv[2], NULL, 0);
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_SCAN_PARAMS, index, sizeof(cp), &cp,
-					scan_params_rsp, NULL, NULL) == 0) {
-		error("Unable to send set_scan_params cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void clock_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_clock_info *rp = param;
-
-	if (len < sizeof(*rp)) {
-		error("Unexpected Get Clock Info len %u", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (status) {
-		error("Get Clock Info failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Local Clock:   %u", le32_to_cpu(rp->local_clock));
-	print("Piconet Clock: %u", le32_to_cpu(rp->piconet_clock));
-	print("Accurary:      %u", le16_to_cpu(rp->accuracy));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_clock_info(int argc, char **argv)
-{
-	struct mgmt_cp_get_clock_info cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (argc > 1)
-		str2ba(argv[1], &cp.addr.bdaddr);
-
-	if (mgmt_send(mgmt, MGMT_OP_GET_CLOCK_INFO, index, sizeof(cp), &cp,
-					clock_info_rsp, NULL, NULL) == 0) {
-		error("Unable to send get_clock_info cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void add_device_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Add device failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option add_device_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "action",	1, 0, 'a' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_add_device(int argc, char **argv)
-{
-	struct mgmt_cp_add_device cp;
-	uint8_t action = 0x00;
-	uint8_t type = BDADDR_BREDR;
-	char addr[18];
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+a:t:h", add_device_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'a':
-			action = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-	cp.action = action;
-
-	ba2str(&cp.addr.bdaddr, addr);
-	print("Adding device with %s (%s)", addr, typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_ADD_DEVICE, index, sizeof(cp), &cp,
-					add_device_rsp, NULL, NULL) == 0) {
-		error("Unable to send add device command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void remove_device_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Remove device failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static struct option del_device_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_del_device(int argc, char **argv)
-{
-	struct mgmt_cp_remove_device cp;
-	uint8_t type = BDADDR_BREDR;
-	char addr[18];
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", del_device_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-		default:
-			bt_shell_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		bt_shell_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	ba2str(&cp.addr.bdaddr, addr);
-	print("Removing device with %s (%s)", addr, typestr(cp.addr.type));
-
-	if (mgmt_send(mgmt, MGMT_OP_REMOVE_DEVICE, index, sizeof(cp), &cp,
-					remove_device_rsp, NULL, NULL) == 0) {
-		error("Unable to send remove device command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_clr_devices(int argc, char **argv)
-{
-	char *bdaddr_any = "00:00:00:00:00:00";
-	char *rm_argv[] = { "del-device", bdaddr_any, NULL };
-
-	cmd_del_device(2, rm_argv);
-}
-
-static void local_oob_ext_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_local_oob_ext_data *rp = param;
-	uint16_t eir_len;
-
-	if (status != 0) {
-		error("Read Local OOB Ext Data failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small (%u bytes) read_local_oob_ext rsp", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	eir_len = le16_to_cpu(rp->eir_len);
-	if (len != sizeof(*rp) + eir_len) {
-		error("local_oob_ext: expected %zu bytes, got %u bytes",
-						sizeof(*rp) + eir_len, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print_eir(rp->eir, eir_len);
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_bredr_oob(int argc, char **argv)
-{
-	struct mgmt_cp_read_local_oob_ext_data cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.type = SCAN_TYPE_BREDR;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
-					index, sizeof(cp), &cp,
-					local_oob_ext_rsp, NULL, NULL)) {
-		error("Unable to send read_local_oob_ext cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_le_oob(int argc, char **argv)
-{
-	struct mgmt_cp_read_local_oob_ext_data cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.type = SCAN_TYPE_LE;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
-					index, sizeof(cp), &cp,
-					local_oob_ext_rsp, NULL, NULL)) {
-		error("Unable to send read_local_oob_ext cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static const char *adv_flags_str[] = {
-				"connectable",
-				"general-discoverable",
-				"limited-discoverable",
-				"managed-flags",
-				"tx-power",
-				"scan-rsp-appearance",
-				"scan-rsp-local-name",
-				"Secondary-channel-1M",
-				"Secondary-channel-2M",
-				"Secondary-channel-CODED",
-};
-
-static const char *adv_flags2str(uint32_t flags)
-{
-	static char str[256];
-	unsigned i;
-	int off;
-
-	off = 0;
-	str[0] = '\0';
-
-	for (i = 0; i < NELEM(adv_flags_str); i++) {
-		if ((flags & (1 << i)) != 0)
-			off += snprintf(str + off, sizeof(str) - off, "%s ",
-							adv_flags_str[i]);
-	}
-
-	return str;
-}
-
-static void adv_features_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_adv_features *rp = param;
-	uint32_t supported_flags;
-
-	if (status != 0) {
-		error("Reading adv features failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small adv features reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp) + rp->num_instances * sizeof(uint8_t)) {
-		error("Instances count (%u) doesn't match reply length (%u)",
-							rp->num_instances, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	supported_flags = le32_to_cpu(rp->supported_flags);
-	print("Supported flags: %s", adv_flags2str(supported_flags));
-	print("Max advertising data len: %u", rp->max_adv_data_len);
-	print("Max scan response data len: %u", rp->max_scan_rsp_len);
-	print("Max instances: %u", rp->max_instances);
-
-	print("Instances list with %u item%s", rp->num_instances,
-					rp->num_instances != 1 ? "s" : "");
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_advinfo(int argc, char **argv)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_FEATURES, index, 0, NULL,
-					adv_features_rsp, NULL, NULL)) {
-		error("Unable to send advertising features command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void adv_size_info_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_adv_size_info *rp = param;
-	uint32_t flags;
-
-	if (status != 0) {
-		error("Reading adv size info failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small adv size info reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	flags = le32_to_cpu(rp->flags);
-	print("Instance: %u", rp->instance);
-	print("Flags: %s", adv_flags2str(flags));
-	print("Max advertising data len: %u", rp->max_adv_data_len);
-	print("Max scan response data len: %u", rp->max_scan_rsp_len);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void advsize_usage(void)
-{
-	bt_shell_usage();
-	print("Options:\n"
-		"\t -c, --connectable         \"connectable\" flag\n"
-		"\t -g, --general-discov      \"general-discoverable\" flag\n"
-		"\t -l, --limited-discov      \"limited-discoverable\" flag\n"
-		"\t -m, --managed-flags       \"managed-flags\" flag\n"
-		"\t -p, --tx-power            \"tx-power\" flag\n"
-		"\t -a, --appearance          \"appearance\" flag\n"
-		"\t -n, --local-name          \"local-name\" flag");
-}
-
-static struct option advsize_options[] = {
-	{ "help",		0, 0, 'h' },
-	{ "connectable",	0, 0, 'c' },
-	{ "general-discov",	0, 0, 'g' },
-	{ "limited-discov",	0, 0, 'l' },
-	{ "managed-flags",	0, 0, 'm' },
-	{ "tx-power",		0, 0, 'p' },
-	{ "appearance",		0, 0, 'a' },
-	{ "local-name",		0, 0, 'n' },
-	{ 0, 0, 0, 0}
-};
-
-static void cmd_advsize(int argc, char **argv)
-{
-	struct mgmt_cp_get_adv_size_info cp;
-	uint8_t instance;
-	uint32_t flags = 0;
-	int opt;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+cglmphna",
-						advsize_options, NULL)) != -1) {
-		switch (opt) {
-		case 'c':
-			flags |= MGMT_ADV_FLAG_CONNECTABLE;
-			break;
-		case 'g':
-			flags |= MGMT_ADV_FLAG_DISCOV;
-			break;
-		case 'l':
-			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
-			break;
-		case 'm':
-			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
-			break;
-		case 'p':
-			flags |= MGMT_ADV_FLAG_TX_POWER;
-			break;
-		case 'a':
-			flags |= MGMT_ADV_FLAG_APPEARANCE;
-			break;
-		case 'n':
-			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
-			break;
-		default:
-			advsize_usage();
-			optind = 0;
-			return bt_shell_noninteractive_quit(EXIT_FAILURE);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc != 1) {
-		advsize_usage();
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	instance = strtol(argv[0], NULL, 0);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	cp.instance = instance;
-	cp.flags = cpu_to_le32(flags);
-
-	if (!mgmt_send(mgmt, MGMT_OP_GET_ADV_SIZE_INFO, index, sizeof(cp), &cp,
-					adv_size_info_rsp, NULL, NULL)) {
-		error("Unable to send advertising size info command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void add_adv_rsp(uint8_t status, uint16_t len, const void *param,
-								void *user_data)
-{
-	const struct mgmt_rp_add_advertising *rp = param;
-
-	if (status != 0) {
-		error("Add Advertising failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Invalid Add Advertising response length (%u)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Instance added: %u", rp->instance);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void add_adv_usage(void)
-{
-	bt_shell_usage();
-	print("Options:\n"
-		"\t -u, --uuid <uuid>         Service UUID\n"
-		"\t -d, --adv-data <data>     Advertising Data bytes\n"
-		"\t -s, --scan-rsp <data>     Scan Response Data bytes\n"
-		"\t -t, --timeout <timeout>   Timeout in seconds\n"
-		"\t -D, --duration <duration> Duration in seconds\n"
-		"\t -P, --phy <phy>           Phy type, Specify 1M/2M/CODED\n"
-		"\t -c, --connectable         \"connectable\" flag\n"
-		"\t -g, --general-discov      \"general-discoverable\" flag\n"
-		"\t -l, --limited-discov      \"limited-discoverable\" flag\n"
-		"\t -n, --scan-rsp-local-name \"local-name\" flag\n"
-		"\t -a, --scan-rsp-appearance \"appearance\" flag\n"
-		"\t -m, --managed-flags       \"managed-flags\" flag\n"
-		"\t -p, --tx-power            \"tx-power\" flag\n"
-		"e.g.:\n"
-		"\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
-}
-
-static struct option add_adv_options[] = {
-	{ "help",		0, 0, 'h' },
-	{ "uuid",		1, 0, 'u' },
-	{ "adv-data",		1, 0, 'd' },
-	{ "scan-rsp",		1, 0, 's' },
-	{ "timeout",		1, 0, 't' },
-	{ "duration",		1, 0, 'D' },
-	{ "phy",		1, 0, 'P' },
-	{ "connectable",	0, 0, 'c' },
-	{ "general-discov",	0, 0, 'g' },
-	{ "limited-discov",	0, 0, 'l' },
-	{ "managed-flags",	0, 0, 'm' },
-	{ "tx-power",		0, 0, 'p' },
-	{ 0, 0, 0, 0}
-};
-
-static bool parse_bytes(char *optarg, uint8_t **bytes, size_t *len)
-{
-	unsigned i;
-
-	if (!optarg) {
-		add_adv_usage();
-		return false;
-	}
-
-	*len = strlen(optarg);
-
-	if (*len % 2) {
-		error("Malformed data");
-		return false;
-	}
-
-	*len /= 2;
-	if (*len > UINT8_MAX) {
-		error("Data too long");
-		return false;
-	}
-
-	*bytes = malloc(*len);
-	if (!*bytes) {
-		error("Failed to allocate memory");
-		return false;
-	}
-
-	for (i = 0; i < *len; i++) {
-		if (sscanf(optarg + (i * 2), "%2hhx", *bytes + i) != 1) {
-			error("Invalid data");
-			free(*bytes);
-			*bytes = NULL;
-			return false;
-		}
-	}
-
-	return true;
-}
-
-#define MAX_AD_UUID_BYTES 32
-
-static void cmd_add_adv(int argc, char **argv)
-{
-	struct mgmt_cp_add_advertising *cp = NULL;
-	int opt;
-	uint8_t *adv_data = NULL, *scan_rsp = NULL;
-	size_t adv_len = 0, scan_rsp_len = 0;
-	size_t cp_len;
-	uint8_t uuids[MAX_AD_UUID_BYTES];
-	size_t uuid_bytes = 0;
-	uint8_t uuid_type = 0;
-	uint16_t timeout = 0, duration = 0;
-	uint8_t instance;
-	uuid_t uuid;
-	bool success = false;
-	bool quit = true;
-	uint32_t flags = 0;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+u:d:s:t:D:P:cglmphna",
-						add_adv_options, NULL)) != -1) {
-		switch (opt) {
-		case 'u':
-			if (bt_string2uuid(&uuid, optarg) < 0) {
-				print("Invalid UUID: %s", optarg);
-				goto done;
-			}
-
-			if (uuid_type && uuid_type != uuid.type) {
-				print("UUID types must be consistent");
-				goto done;
-			}
-
-			if (uuid.type == SDP_UUID16) {
-				if (uuid_bytes + 2 >= MAX_AD_UUID_BYTES) {
-					print("Too many UUIDs");
-					goto done;
-				}
-
-				put_le16(uuid.value.uuid16, uuids + uuid_bytes);
-				uuid_bytes += 2;
-			} else if (uuid.type == SDP_UUID128) {
-				if (uuid_bytes + 16 >= MAX_AD_UUID_BYTES) {
-					print("Too many UUIDs");
-					goto done;
-				}
-
-				bswap_128(uuid.value.uuid128.data,
-							uuids + uuid_bytes);
-				uuid_bytes += 16;
-			} else {
-				printf("Unsupported UUID type");
-				goto done;
-			}
-
-			if (!uuid_type)
-				uuid_type = uuid.type;
-
-			break;
-		case 'd':
-			if (adv_len) {
-				print("Only one adv-data option allowed");
-				goto done;
-			}
-
-			if (!parse_bytes(optarg, &adv_data, &adv_len))
-				goto done;
-			break;
-		case 's':
-			if (scan_rsp_len) {
-				print("Only one scan-rsp option allowed");
-				goto done;
-			}
-
-			if (!parse_bytes(optarg, &scan_rsp, &scan_rsp_len))
-				goto done;
-			break;
-		case 't':
-			timeout = strtol(optarg, NULL, 0);
-			break;
-		case 'D':
-			duration = strtol(optarg, NULL, 0);
-			break;
-		case 'c':
-			flags |= MGMT_ADV_FLAG_CONNECTABLE;
-			break;
-		case 'g':
-			flags |= MGMT_ADV_FLAG_DISCOV;
-			break;
-		case 'l':
-			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
-			break;
-		case 'm':
-			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
-			break;
-		case 'p':
-			flags |= MGMT_ADV_FLAG_TX_POWER;
-			break;
-		case 'n':
-			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
-			break;
-		case 'a':
-			flags |= MGMT_ADV_FLAG_APPEARANCE;
-			break;
-		case 'P':
-			if (strcasecmp(optarg, "1M") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_1M;
-			else if (strcasecmp(optarg, "2M") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_2M;
-			else if (strcasecmp(optarg, "CODED") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_CODED;
-			else
-				goto done;
-			break;
-		case 'h':
-			success = true;
-			/* fall through */
-		default:
-			add_adv_usage();
-			optind = 0;
-			goto done;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc != 1) {
-		add_adv_usage();
-		goto done;
-	}
-
-	if (uuid_bytes)
-		uuid_bytes += 2;
-
-	instance = strtol(argv[0], NULL, 0);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp_len = sizeof(*cp) + uuid_bytes + adv_len + scan_rsp_len;
-	cp = malloc0(cp_len);
-	if (!cp)
-		goto done;
-
-	cp->instance = instance;
-	put_le32(flags, &cp->flags);
-	put_le16(timeout, &cp->timeout);
-	put_le16(duration, &cp->duration);
-	cp->adv_data_len = adv_len + uuid_bytes;
-	cp->scan_rsp_len = scan_rsp_len;
-
-	if (uuid_bytes) {
-		cp->data[0] = uuid_bytes - 1;
-		cp->data[1] = uuid_type == SDP_UUID16 ? 0x03 : 0x07;
-		memcpy(cp->data + 2, uuids, uuid_bytes - 2);
-	}
-
-	if (adv_len)
-		memcpy(cp->data + uuid_bytes, adv_data, adv_len);
-
-	if (scan_rsp_len)
-		memcpy(cp->data + uuid_bytes + adv_len, scan_rsp, scan_rsp_len);
-
-	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADVERTISING, index, cp_len, cp,
-						add_adv_rsp, NULL, NULL)) {
-		error("Unable to send \"Add Advertising\" command");
-		goto done;
-	}
-
-	quit = false;
-
-done:
-	free(adv_data);
-	free(scan_rsp);
-	free(cp);
-
-	if (quit)
-		bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static void rm_adv_rsp(uint8_t status, uint16_t len, const void *param,
-								void *user_data)
-{
-	const struct mgmt_rp_remove_advertising *rp = param;
-
-	if (status != 0) {
-		error("Remove Advertising failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Invalid Remove Advertising response length (%u)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Instance removed: %u", rp->instance);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_rm_adv(int argc, char **argv)
-{
-	struct mgmt_cp_remove_advertising cp;
-	uint8_t instance;
-	uint16_t index;
-
-	instance = strtol(argv[1], NULL, 0);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	cp.instance = instance;
-
-	if (!mgmt_send(mgmt, MGMT_OP_REMOVE_ADVERTISING, index, sizeof(cp), &cp,
-						rm_adv_rsp, NULL, NULL)) {
-		error("Unable to send \"Remove Advertising\" command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_clr_adv(int argc, char **argv)
-{
-	char *all_instances = "0";
-	char *rm_argv[] = { "rm-adv", all_instances, NULL };
-
-	cmd_rm_adv(2, rm_argv);
-}
-
-static void add_ext_adv_params_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_add_ext_adv_params *rp = param;
-
-	if (status != 0) {
-		error("Add Ext Adv Params failed status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Invalid Add Ext Adv Params response length (%u)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Instance added: %u", rp->instance);
-	print("Tx Power: %u", rp->tx_power);
-	print("Max adv data len: %u", rp->max_adv_data_len);
-	print("Max scan resp len: %u", rp->max_scan_rsp_len);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void add_ext_adv_params_usage(void)
-{
-	bt_shell_usage();
-	print("Options:\n"
-		"\t -d, --duration <duration>  Duration in seconds\n"
-		"\t -t, --timeout <timeout>    Timeout in seconds\n"
-		"\t -r, --min-interval <valr>  Minimum interval\n"
-		"\t -x, --max-interval <valr>  Maximum interval\n"
-		"\t -w, --tx-power <power>     Tx power\n"
-		"\t -P, --phy <phy>            Phy type, Specify 1M/2M/CODED\n"
-		"\t -c, --connectable          \"connectable\" flag\n"
-		"\t -g, --general-discov       \"general-discoverable\" flag\n"
-		"\t -l, --limited-discov       \"limited-discoverable\" flag\n"
-		"\t -m, --managed-flags        \"managed-flags\" flag\n"
-		"\t -p, --add-tx-power         \"tx-power\" flag\n"
-		"\t -a, --scan-rsp-appearance  \"appearance\" flag\n"
-		"\t -n, --scan-rsp-local-name  \"local-name\" flag\n"
-		"\t -s, --adv-scan-rsp         \"scan resp in adv\" flag\n"
-		"\t -h, --help                 Show help\n"
-		"e.g.:\n"
-		"\tadd-ext-adv-params -r 0x801 -x 0x802 -P 2M -g 1");
-}
-
-static struct option add_ext_adv_params_options[] = {
-	{ "help",		0, 0, 'h' },
-	{ "duration",		1, 0, 'd' },
-	{ "timeout",		1, 0, 't' },
-	{ "min-internal",	1, 0, 'r' },
-	{ "max-interval",	1, 0, 'x' },
-	{ "tx-power",		1, 0, 'w' },
-	{ "phy",		1, 0, 'P' },
-	{ "connectable",	0, 0, 'c' },
-	{ "general-discov",	0, 0, 'g' },
-	{ "limited-discov",	0, 0, 'l' },
-	{ "scan-rsp-local-name", 0, 0, 'n' },
-	{ "scan-rsp-appearance", 0, 0, 'a' },
-	{ "managed-flags",	0, 0, 'm' },
-	{ "add-tx-power",	0, 0, 'p' },
-	{ "adv-scan-rsp",	0, 0, 's' },
-	{ 0, 0, 0, 0}
-};
-
-static void cmd_add_ext_adv_params(int argc, char **argv)
-{
-	struct mgmt_cp_add_ext_adv_params *cp = NULL;
-	int opt;
-	uint16_t timeout = 0, duration = 0;
-	uint8_t instance;
-	bool success = false;
-	bool quit = true;
-	uint32_t flags = 0;
-	uint32_t min_interval = 0;
-	uint32_t max_interval = 0;
-	uint8_t tx_power = 0;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "d:t:r:x:w:P:cglmpansh",
-				add_ext_adv_params_options, NULL)) != -1) {
-		switch (opt) {
-		case 'd':
-			duration = strtol(optarg, NULL, 0);
-			flags |= MGMT_ADV_PARAM_DURATION;
-			break;
-		case 't':
-			timeout = strtol(optarg, NULL, 0);
-			flags |= MGMT_ADV_PARAM_TIMEOUT;
-			break;
-		case 'r':
-			min_interval = strtol(optarg, NULL, 0);
-			break;
-		case 'x':
-			max_interval = strtol(optarg, NULL, 0);
-			break;
-		case 'w':
-			tx_power = strtol(optarg, NULL, 0);
-			flags |= MGMT_ADV_PARAM_TX_POWER;
-			break;
-		case 'P':
-			if (strcasecmp(optarg, "1M") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_1M;
-			else if (strcasecmp(optarg, "2M") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_2M;
-			else if (strcasecmp(optarg, "CODED") == 0)
-				flags |= MGMT_ADV_FLAG_SEC_CODED;
-			else
-				goto done;
-			break;
-		case 'c':
-			flags |= MGMT_ADV_FLAG_CONNECTABLE;
-			break;
-		case 'g':
-			flags |= MGMT_ADV_FLAG_DISCOV;
-			break;
-		case 'l':
-			flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
-			break;
-		case 'n':
-			flags |= MGMT_ADV_FLAG_LOCAL_NAME;
-			break;
-		case 'a':
-			flags |= MGMT_ADV_FLAG_APPEARANCE;
-			break;
-		case 'm':
-			flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
-			break;
-		case 'p':
-			flags |= MGMT_ADV_FLAG_TX_POWER;
-			break;
-		case 's':
-			flags |= MGMT_ADV_PARAM_SCAN_RSP;
-			break;
-		case 'h':
-			success = true;
-			/* fall through */
-		default:
-			add_ext_adv_params_usage();
-			optind = 0;
-			goto done;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc != 1) {
-		add_ext_adv_params_usage();
-		goto done;
-	}
-
-	/* Only if both min_interval and max_interval are defined */
-	if (min_interval && max_interval)
-		flags |= MGMT_ADV_PARAM_INTERVALS;
-
-	instance = strtol(argv[0], NULL, 0);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp = malloc0(sizeof(*cp));
-	if (!cp)
-		goto done;
-
-	cp->instance = instance;
-	put_le32(flags, &cp->flags);
-	put_le16(timeout, &cp->timeout);
-	put_le16(duration, &cp->duration);
-	put_le32(min_interval, &cp->min_interval);
-	put_le32(max_interval, &cp->max_interval);
-	cp->tx_power = tx_power;
-
-	if (!mgmt_send(mgmt, MGMT_OP_ADD_EXT_ADV_PARAMS, index, sizeof(*cp), cp,
-					add_ext_adv_params_rsp, NULL, NULL)) {
-		error("Unable to send \"Add Ext Advertising Params\" command");
-		goto done;
-	}
-
-	quit = false;
-
-done:
-	free(cp);
-
-	if (quit)
-		bt_shell_noninteractive_quit(success ?
-						EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static void add_ext_adv_data_rsp(uint8_t status, uint16_t len,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_add_ext_adv_data *rp = param;
-
-	if (status != 0) {
-		error("Add Ext Advertising Data failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		error("Invalid Add Ext Advertising Data response length (%u)",
-									len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Instance added: %u", rp->instance);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void add_ext_adv_data_usage(void)
-{
-	bt_shell_usage();
-	print("Options:\n"
-		"\t -u, --uuid <uuid>         Service UUID\n"
-		"\t -d, --adv-data <data>     Advertising Data bytes\n"
-		"\t -s, --scan-rsp <data>     Scan Response Data bytes\n"
-		"e.g.:\n"
-		"\tadd-ext-adv-data -u 180d -u 180f -d 080954657374204C45 1");
-}
-
-static struct option add_ext_adv_data_options[] = {
-	{ "help",		0, 0, 'h' },
-	{ "uuid",		1, 0, 'u' },
-	{ "adv-data",		1, 0, 'd' },
-	{ "scan-rsp",		1, 0, 's' },
-	{ 0, 0, 0, 0}
-};
-
-static void cmd_add_ext_adv_data(int argc, char **argv)
-{
-	struct mgmt_cp_add_ext_adv_data *cp = NULL;
-	int opt;
-	uint8_t *adv_data = NULL, *scan_rsp = NULL;
-	size_t adv_len = 0, scan_rsp_len = 0;
-	size_t cp_len;
-	uint8_t uuids[MAX_AD_UUID_BYTES];
-	size_t uuid_bytes = 0;
-	uint8_t uuid_type = 0;
-	uint8_t instance;
-	uuid_t uuid;
-	bool success = false;
-	bool quit = true;
-	uint16_t index;
-
-	while ((opt = getopt_long(argc, argv, "+u:d:s:h",
-				add_ext_adv_data_options, NULL)) != -1) {
-		switch (opt) {
-		case 'u':
-			if (bt_string2uuid(&uuid, optarg) < 0) {
-				print("Invalid UUID: %s", optarg);
-				goto done;
-			}
-
-			if (uuid_type && uuid_type != uuid.type) {
-				print("UUID types must be consistent");
-				goto done;
-			}
-
-			if (uuid.type == SDP_UUID16) {
-				if (uuid_bytes + 2 >= MAX_AD_UUID_BYTES) {
-					print("Too many UUIDs");
-					goto done;
-				}
-
-				put_le16(uuid.value.uuid16, uuids + uuid_bytes);
-				uuid_bytes += 2;
-			} else if (uuid.type == SDP_UUID128) {
-				if (uuid_bytes + 16 >= MAX_AD_UUID_BYTES) {
-					print("Too many UUIDs");
-					goto done;
-				}
-
-				bswap_128(uuid.value.uuid128.data,
-							uuids + uuid_bytes);
-				uuid_bytes += 16;
-			} else {
-				printf("Unsupported UUID type");
-				goto done;
-			}
-
-			if (!uuid_type)
-				uuid_type = uuid.type;
-
-			break;
-		case 'd':
-			if (adv_len) {
-				print("Only one adv-data option allowed");
-				goto done;
-			}
-
-			if (!parse_bytes(optarg, &adv_data, &adv_len))
-				goto done;
-			break;
-		case 's':
-			if (scan_rsp_len) {
-				print("Only one scan-rsp option allowed");
-				goto done;
-			}
-
-			if (!parse_bytes(optarg, &scan_rsp, &scan_rsp_len))
-				goto done;
-			break;
-		case 'h':
-			success = true;
-			/* fall through */
-		default:
-			add_ext_adv_data_usage();
-			optind = 0;
-			goto done;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc != 1) {
-		add_ext_adv_data_usage();
-		goto done;
-	}
-
-	if (uuid_bytes)
-		uuid_bytes += 2;
-
-	instance = strtol(argv[0], NULL, 0);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp_len = sizeof(*cp) + uuid_bytes + adv_len + scan_rsp_len;
-	cp = malloc0(cp_len);
-	if (!cp)
-		goto done;
-
-	cp->instance = instance;
-	cp->adv_data_len = adv_len + uuid_bytes;
-	cp->scan_rsp_len = scan_rsp_len;
-
-	if (uuid_bytes) {
-		cp->data[0] = uuid_bytes - 1;
-		cp->data[1] = uuid_type == SDP_UUID16 ? 0x03 : 0x07;
-		memcpy(cp->data + 2, uuids, uuid_bytes - 2);
-	}
-
-	if (adv_len)
-		memcpy(cp->data + uuid_bytes, adv_data, adv_len);
-
-	if (scan_rsp_len)
-		memcpy(cp->data + uuid_bytes + adv_len, scan_rsp, scan_rsp_len);
-
-	if (!mgmt_send(mgmt, MGMT_OP_ADD_EXT_ADV_DATA, index, cp_len, cp,
-					add_ext_adv_data_rsp, NULL, NULL)) {
-		error("Unable to send \"Add Ext Advertising Data\" command");
-		goto done;
-	}
-
-	quit = false;
-
-done:
-	free(adv_data);
-	free(scan_rsp);
-	free(cp);
-
-	if (quit)
-		bt_shell_noninteractive_quit(success ?
-						EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static void appearance_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0)
-		error("Could not set Appearance with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-	else
-		print("Appearance successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_appearance(int argc, char **argv)
-{
-	struct mgmt_cp_set_appearance cp;
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.appearance = cpu_to_le16(strtol(argv[1], NULL, 0));
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_APPEARANCE, index, sizeof(cp), &cp,
-					appearance_rsp, NULL, NULL) == 0) {
-		error("Unable to send appearance cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static const char *phys_str[] = {
-	"BR1M1SLOT",
-	"BR1M3SLOT",
-	"BR1M5SLOT",
-	"EDR2M1SLOT",
-	"EDR2M3SLOT",
-	"EDR2M5SLOT",
-	"EDR3M1SLOT",
-	"EDR3M3SLOT",
-	"EDR3M5SLOT",
-	"LE1MTX",
-	"LE1MRX",
-	"LE2MTX",
-	"LE2MRX",
-	"LECODEDTX",
-	"LECODEDRX",
-};
-
-static const char *phys2str(uint32_t phys)
-{
-	static char str[256];
-	unsigned int i;
-	int off;
-
-	off = 0;
-	str[0] = '\0';
-
-	for (i = 0; i < NELEM(phys_str); i++) {
-		if ((phys & (1 << i)) != 0)
-			off += snprintf(str + off, sizeof(str) - off, "%s ",
-							phys_str[i]);
-	}
-
-	return str;
-}
-
-static bool str2phy(const char *phy_str, uint32_t *phy_val)
-{
-	unsigned int i;
-
-	for (i = 0; i < NELEM(phys_str); i++) {
-		if (strcasecmp(phys_str[i], phy_str) == 0) {
-			*phy_val = (1 << i);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-static void get_phy_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_get_phy_confguration *rp = param;
-	uint32_t supported_phys, selected_phys, configurable_phys;
-
-	if (status != 0) {
-		error("Get PHY Configuration failed with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small get-phy reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	supported_phys = get_le32(&rp->supported_phys);
-	configurable_phys = get_le32(&rp->configurable_phys);
-	selected_phys = get_le32(&rp->selected_phys);
-
-	print("Supported phys: %s", phys2str(supported_phys));
-	print("Configurable phys: %s", phys2str(configurable_phys));
-	print("Selected phys: %s", phys2str(selected_phys));
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void get_phy(void)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send(mgmt, MGMT_OP_GET_PHY_CONFIGURATION, index, 0, NULL,
-					get_phy_rsp, NULL, NULL) == 0) {
-		error("Unable to send Get PHY cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void set_phy_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	if (status != 0) {
-		error("Could not set PHY Configuration with status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("PHY Configuration successfully set");
-
-	bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_phy(int argc, char **argv)
-{
-	struct mgmt_cp_set_phy_confguration cp;
-	int i;
-	uint32_t phys = 0;
-	uint16_t index;
-
-	if (argc < 2)
-		return get_phy();
-
-	for (i = 1; i < argc; i++) {
-		uint32_t phy_val;
-
-		if (str2phy(argv[i], &phy_val))
-			phys |= phy_val;
-	}
-
-	cp.selected_phys = cpu_to_le32(phys);
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send(mgmt, MGMT_OP_SET_PHY_CONFIGURATION, index, sizeof(cp),
-					&cp, set_phy_rsp, NULL, NULL) == 0) {
-		error("Unable to send %s cmd",
-				mgmt_opstr(MGMT_OP_SET_PHY_CONFIGURATION));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_wbs(int argc, char **argv)
-{
-	cmd_setting(MGMT_OP_SET_WIDEBAND_SPEECH, argc, argv);
-}
-
-static const char * const advmon_features_str[] = {
-	"Pattern monitor with logic OR.",
-};
-
-static const char *advmon_features2str(uint32_t features)
-{
-	static char str[512];
-	unsigned int off, i;
-
-	off = 0;
-	snprintf(str, sizeof(str), "\n\tNone");
-
-	for (i = 0; i < NELEM(advmon_features_str); i++) {
-		if ((features & (1 << i)) != 0 && off < sizeof(str))
-			off += snprintf(str + off, sizeof(str) - off, "\n\t%s",
-						advmon_features_str[i]);
-	}
-
-	return str;
-}
-
-static void advmon_features_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_read_adv_monitor_features *rp = param;
-	uint32_t supported_features, enabled_features;
-	uint16_t num_handles;
-	int i;
-
-	if (status != MGMT_STATUS_SUCCESS) {
-		error("Reading adv monitor features failed with status 0x%02x "
-					"(%s)", status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		error("Too small adv monitor features reply (%u bytes)", len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	supported_features = le32_to_cpu(rp->supported_features);
-	enabled_features = le32_to_cpu(rp->enabled_features);
-	num_handles = le16_to_cpu(rp->num_handles);
-
-	if (len < sizeof(*rp) + num_handles * sizeof(uint16_t)) {
-		error("Handles count (%u) doesn't match reply length (%u)",
-							num_handles, len);
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Supported features:%s", advmon_features2str(supported_features));
-	print("Enabled features:%s", advmon_features2str(enabled_features));
-	print("Max number of handles: %u", le16_to_cpu(rp->max_num_handles));
-	print("Max number of patterns: %u", rp->max_num_patterns);
-	print("Handles list with %u item%s", num_handles,
-			num_handles == 0 ? "" : num_handles == 1 ? ":" : "s:");
-	for (i = 0; i < num_handles; i++)
-		print("\t0x%04x ", le16_to_cpu(rp->handles[i]));
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_advmon_features(int argc, char **argv)
-{
-	uint16_t index;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_MONITOR_FEATURES, index, 0, NULL,
-					advmon_features_rsp, NULL, NULL)) {
-		error("Unable to send advertising monitor features command");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void advmon_add_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_add_adv_patterns_monitor *rp = param;
-
-	if (status != MGMT_STATUS_SUCCESS) {
-		error("Could not add advertisement monitor with status "
-				"0x%02x (%s)", status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Advertisement monitor with handle:0x%04x added",
-					le16_to_cpu(rp->monitor_handle));
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static bool str2pattern(struct mgmt_adv_pattern *pattern, const char *str)
-{
-	int type_len, offset_len, offset_end_pos, str_len;
-	int i, j;
-	char pattern_str[62] = { 0 };
-	char tmp;
-
-	if (sscanf(str, "%2hhx%n:%2hhx%n:%61s", &pattern->ad_type, &type_len,
-			&pattern->offset, &offset_end_pos, pattern_str) != 3)
-		return false;
-
-	offset_len = offset_end_pos - type_len - 1;
-	str_len = strlen(pattern_str);
-	pattern->length = str_len / 2 + str_len % 2;
-
-	if (type_len > 2 || offset_len > 2 ||
-					pattern->offset + pattern->length > 31)
-		return false;
-
-	for (i = 0, j = 0; i < str_len; i++, j++) {
-		if (sscanf(&pattern_str[i++], "%2hhx", &pattern->value[j])
-									!= 1)
-			return false;
-		if (i < str_len && sscanf(&pattern_str[i], "%1hhx", &tmp) != 1)
-			return false;
-	}
-
-	return true;
-}
-
-static struct option add_monitor_rssi_options[] = {
-	{ "help",		0, 0, 'h' },
-	{ "high-threshold",	1, 0, 'R' },
-	{ "low-threshold",	1, 0, 'r' },
-	{ "high-timeout",	1, 0, 'T' },
-	{ "low-timeout",	1, 0, 't' },
-	{ "sampling",		1, 0, 's' },
-	{ 0, 0, 0, 0 }
-};
-
-static void advmon_add_pattern_usage(void)
-{
-	bt_shell_usage();
-	print("patterns format:\n"
-		"\t<ad_type:offset:pattern> [patterns]\n"
-		"e.g.:\n"
-		"\tadd-pattern 0:1:c504 ff:a:9a55beef");
-}
-
-static void advmon_add_pattern_rssi_usage(void)
-{
-	bt_shell_usage();
-	print("RSSI options:\n"
-		"\t -R, --high-threshold <dBm>  "
-			"RSSI high threshold. Default: -70\n"
-		"\t -r, --low-threshold <dBm>   "
-			"RSSI low threshold. Default: -50\n"
-		"\t -T, --high-timeout <s>      "
-			"RSSI high threshold duration. Default: 0\n"
-		"\t -t, --low-timeout <s>       "
-			"RSSI low threshold duration. Default: 5\n"
-		"\t -s, --sampling <N * 100ms>  "
-			"RSSI sampling period. Default: 0\n"
-		"patterns format:\n"
-		"\t<ad_type:offset:pattern> [patterns]\n"
-		"e.g.:\n"
-		"\tadd-pattern-rssi -R 0xb2 -r -102 0:1:c504 ff:a:9a55beef");
-}
-
-static void cmd_advmon_add_pattern(int argc, char **argv)
-{
-	bool success = true;
-	uint16_t index;
-	int i, cp_len;
-	struct mgmt_cp_add_adv_monitor *cp = NULL;
-
-	if (!strcmp(argv[1], "-h"))
-		goto done;
-
-	argc -= 1;
-	argv += 1;
-
-	cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
-	cp = malloc0(cp_len);
-	if (!cp) {
-		error("Failed to alloc patterns.");
-		success = false;
-		goto done;
-	}
-
-	cp->pattern_count = argc;
-
-	for (i = 0; i < argc; i++) {
-		if (!str2pattern(&cp->patterns[i], argv[i])) {
-			error("Failed to parse monitor patterns.");
-			success = false;
-			goto done;
-		}
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR, index,
-				cp_len, cp, advmon_add_rsp, NULL, NULL)) {
-		error("Unable to send Add Advertising Monitor command");
-		success = false;
-		goto done;
-	}
-
-	free(cp);
-	return;
-
-done:
-	free(cp);
-	advmon_add_pattern_usage();
-	bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static void cmd_advmon_add_pattern_rssi(int argc, char **argv)
-{
-	bool success = true;
-	int opt;
-	int8_t rssi_low = -70;
-	int8_t rssi_high = -50;
-	uint16_t rssi_low_timeout = 5;
-	uint16_t rssi_high_timeout = 0;
-	uint8_t rssi_sampling_period = 0;
-	uint16_t index;
-	int i, cp_len;
-	struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = NULL;
-
-	while ((opt = getopt_long(argc, argv, "+hr:R:t:T:s:",
-				add_monitor_rssi_options, NULL)) != -1) {
-		switch (opt) {
-		case 'h':
-			goto done;
-		case 'r':
-			rssi_low = strtol(optarg, NULL, 0);
-			break;
-		case 'R':
-			rssi_high = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			rssi_low_timeout = strtol(optarg, NULL, 0);
-			break;
-		case 'T':
-			rssi_high_timeout = strtol(optarg, NULL, 0);
-			break;
-		case 's':
-			rssi_sampling_period = strtol(optarg, NULL, 0);
-			break;
-		default:
-			success = false;
-			goto done;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
-	cp = malloc0(cp_len);
-	if (!cp) {
-		error("Failed to alloc patterns.");
-		success = false;
-		goto done;
-	}
-
-	cp->pattern_count = argc;
-	cp->rssi.high_threshold = rssi_high;
-	cp->rssi.low_threshold = rssi_low;
-	cp->rssi.high_threshold_timeout = htobs(rssi_high_timeout);
-	cp->rssi.low_threshold_timeout = htobs(rssi_low_timeout);
-	cp->rssi.sampling_period = rssi_sampling_period;
-
-	for (i = 0; i < argc; i++) {
-		if (!str2pattern(&cp->patterns[i], argv[i])) {
-			error("Failed to parse monitor patterns.");
-			success = false;
-			goto done;
-		}
-	}
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, index,
-				cp_len, cp, advmon_add_rsp, NULL, NULL)) {
-		error("Unable to send Add Advertising Monitor RSSI command");
-		success = false;
-		goto done;
-	}
-
-	free(cp);
-	return;
-
-done:
-	free(cp);
-	optind = 0;
-	advmon_add_pattern_rssi_usage();
-	bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static void advmon_remove_rsp(uint8_t status, uint16_t len, const void *param,
-							void *user_data)
-{
-	const struct mgmt_rp_remove_adv_monitor *rp = param;
-
-	if (status != MGMT_STATUS_SUCCESS) {
-		error("Could not remove advertisement monitor with status "
-				"0x%02x (%s)", status, mgmt_errstr(status));
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	print("Advertisement monitor with handle: 0x%04x removed",
-					le16_to_cpu(rp->monitor_handle));
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-}
-
-static void cmd_advmon_remove(int argc, char **argv)
-{
-	struct mgmt_cp_remove_adv_monitor cp;
-	uint16_t index, monitor_handle;
-
-	index = mgmt_index;
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (sscanf(argv[1], "%hx", &monitor_handle) != 1) {
-		error("Wrong formatted handle argument");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	cp.monitor_handle = cpu_to_le16(monitor_handle);
-	if (mgmt_send(mgmt, MGMT_OP_REMOVE_ADV_MONITOR, index, sizeof(cp), &cp,
-					advmon_remove_rsp, NULL, NULL) == 0) {
-		error("Unable to send appearance cmd");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-}
-
-static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
-{
-	mgmt_register(mgmt, MGMT_EV_CONTROLLER_ERROR, index, controller_error,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index, index_added,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_INDEX_REMOVED, index, index_removed,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_NEW_SETTINGS, index, new_settings,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_DISCOVERING, index, discovering,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_NEW_LINK_KEY, index, new_link_key,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_DEVICE_CONNECTED, index, connected,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_DEVICE_DISCONNECTED, index, disconnected,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_CONNECT_FAILED, index, conn_failed,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_AUTH_FAILED, index, auth_failed,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED, index,
-					class_of_dev_changed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_LOCAL_NAME_CHANGED, index,
-					local_name_changed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_DEVICE_FOUND, index, device_found,
-								mgmt, NULL);
-	mgmt_register(mgmt, MGMT_EV_PIN_CODE_REQUEST, index, request_pin,
-								mgmt, NULL);
-	mgmt_register(mgmt, MGMT_EV_USER_CONFIRM_REQUEST, index, user_confirm,
-								mgmt, NULL);
-	mgmt_register(mgmt, MGMT_EV_USER_PASSKEY_REQUEST, index,
-						request_passkey, mgmt, NULL);
-	mgmt_register(mgmt, MGMT_EV_PASSKEY_NOTIFY, index,
-						passkey_notify, mgmt, NULL);
-	mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_ADDED, index,
-					unconf_index_added, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_REMOVED, index,
-					unconf_index_removed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_NEW_CONFIG_OPTIONS, index,
-					new_config_options, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_EXT_INDEX_ADDED, index,
-					ext_index_added, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_EXT_INDEX_REMOVED, index,
-					ext_index_removed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_LOCAL_OOB_DATA_UPDATED, index,
-					local_oob_data_updated, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_ADVERTISING_ADDED, index,
-						advertising_added, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_ADVERTISING_REMOVED, index,
-					advertising_removed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_DEVICE_FLAGS_CHANGED, index,
-					flags_changed, NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_ADDED, index, advmon_added,
-								NULL, NULL);
-	mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_REMOVED, index, advmon_removed,
-								NULL, NULL);
-}
-
-static void cmd_select(int argc, char **argv)
-{
-	mgmt_cancel_all(mgmt);
-	mgmt_unregister_all(mgmt);
-
-	set_index(argv[1]);
-
-	register_mgmt_callbacks(mgmt, mgmt_index);
-
-	print("Selected index %u", mgmt_index);
-
-	update_prompt(mgmt_index);
-}
-
-static const struct bt_shell_menu monitor_menu = {
-	.name = "monitor",
-	.desc = "Advertisement Monitor Submenu",
-	.entries = {
-	{ "features",		NULL,
-		cmd_advmon_features,	"Show advertisement monitor "
-					"features"			},
-	{ "remove",		"<handle>",
-		cmd_advmon_remove,	"Remove advertisement monitor "	},
-	{ "add-pattern",	"[-h] <patterns>",
-		cmd_advmon_add_pattern,	"Add advertisement monitor pattern" },
-	{ "add-pattern-rssi",	"[options] <patterns>",
-		cmd_advmon_add_pattern_rssi,
-		"Add advertisement monitor pattern with RSSI options"    },
-	{ } },
-};
-
-static const struct bt_shell_menu main_menu = {
-	.name = "main",
-	.entries = {
-	{ "select",		"<index>",
-		cmd_select,		"Select a different index"	},
-	{ "revision",		NULL,
-		cmd_revision,		"Get the MGMT Revision"		},
-	{ "commands",		NULL,
-		cmd_commands,		"List supported commands"	},
-	{ "config",		NULL,
-		cmd_config,		"Show configuration info"	},
-	{ "info",		NULL,
-		cmd_info,		"Show controller info"		},
-	{ "extinfo",		NULL,
-		cmd_extinfo,		"Show extended controller info"	},
-	{ "auto-power",		NULL,
-		cmd_auto_power,		"Power all available features"	},
-	{ "power",		"<on/off>",
-		cmd_power,		"Toggle powered state"		},
-	{ "discov",		"<yes/no/limited> [timeout]",
-		cmd_discov,		"Toggle discoverable state"	},
-	{ "connectable",	"<on/off>",
-	cmd_connectable,		"Toggle connectable state"	},
-	{ "fast-conn",		"<on/off>",
-		cmd_fast_conn,		"Toggle fast connectable state"	},
-	{ "bondable",		"<on/off>",
-		cmd_bondable,		"Toggle bondable state"		},
-	{ "pairable",		"<on/off>",
-		cmd_bondable,		"Toggle bondable state"		},
-	{ "linksec",		"<on/off>",
-		cmd_linksec,		"Toggle link level security"	},
-	{ "ssp",		"<on/off>",
-		cmd_ssp,		"Toggle SSP mode"		},
-	{ "sc",			"<on/off/only>",
-		cmd_sc,			"Toogle SC support"		},
-	{ "hs",			"<on/off>",
-		cmd_hs,			"Toggle HS support"		},
-	{ "le",			"<on/off>",
-		cmd_le,			"Toggle LE support"		},
-	{ "advertising",	"<on/off>",
-	cmd_advertising,		"Toggle LE advertising",	},
-	{ "bredr",		"<on/off>",
-		cmd_bredr,		"Toggle BR/EDR support",	},
-	{ "privacy",		"<on/off> [irk]",
-		cmd_privacy,		"Toggle privacy support"	},
-	{ "class",		"<major> <minor>",
-		cmd_class,		"Set device major/minor class"	},
-	{ "disconnect", 	"[-t type] <remote address>",
-		cmd_disconnect,		"Disconnect device"		},
-	{ "con",		NULL,
-		cmd_con,		"List connections"		},
-	{ "find",		"[-l|-b] [-L]",
-		cmd_find,		"Discover nearby devices"	},
-	{ "find-service",	"[-u UUID] [-r RSSI_Threshold] [-l|-b]",
-		cmd_find_service,	"Discover nearby service"	},
-	{ "stop-find",		"[-l|-b]",
-		cmd_stop_find,		"Stop discovery"		},
-	{ "name",		"<name> [shortname]",
-		cmd_name,		"Set local name"		},
-	{ "pair",		"[-c cap] [-t type] <remote address>",
-		cmd_pair,		"Pair with a remote device"	},
-	{ "cancelpair",		"[-t type] <remote address>",
-		cmd_cancel_pair,	"Cancel pairing"		},
-	{ "unpair",		"[-t type] <remote address>",
-		cmd_unpair,		"Unpair device"			},
-	{ "keys",		NULL,
-		cmd_keys,		"Load Link Keys"		},
-	{ "ltks",		NULL,
-		cmd_ltks,		"Load Long Term Keys"		},
-	{ "irks",		"[--local index] [--file file path]",
-		cmd_irks,		"Load Identity Resolving Keys"	},
-	{ "block",		"[-t type] <remote address>",
-		cmd_block,		"Block Device"			},
-	{ "unblock",		"[-t type] <remote address>",
-		cmd_unblock,		"Unblock Device"		},
-	{ "add-uuid",		"<UUID> <service class hint>",
-		cmd_add_uuid,		"Add UUID"			},
-	{ "rm-uuid",		"<UUID>",
-		cmd_remove_uuid,	"Remove UUID"			},
-	{ "clr-uuids",		NULL,
-		cmd_clr_uuids,		"Clear UUIDs"			},
-	{ "local-oob",		NULL,
-		cmd_local_oob,		"Local OOB data"		},
-	{ "remote-oob",		"[-t <addr_type>] [-r <rand192>] "
-				"[-h <hash192>] [-R <rand256>] "
-				"[-H <hash256>] <addr>",
-		cmd_remote_oob,		"Remote OOB data"		},
-	{ "did",		"<source>:<vendor>:<product>:<version>",
-		cmd_did,		"Set Device ID"			},
-	{ "static-addr",	"<address>",
-		cmd_static_addr,	"Set static address"		},
-	{ "public-addr",	"<address>",
-		cmd_public_addr,	"Set public address"		},
-	{ "ext-config",		"<on/off>",
-		cmd_ext_config,		"External configuration"	},
-	{ "debug-keys",		"<on/off>",
-		cmd_debug_keys,		"Toogle debug keys"		},
-	{ "conn-info",		"[-t type] <remote address>",
-		cmd_conn_info,		"Get connection information"	},
-	{ "io-cap",		"<cap>",
-		cmd_io_cap,		"Set IO Capability"		},
-	{ "scan-params",	"<interval> <window>",
-		cmd_scan_params,	"Set Scan Parameters"		},
-	{ "get-clock",		"[address]",
-		cmd_clock_info,		"Get Clock Information"		},
-	{ "add-device", 	"[-a action] [-t type] <address>",
-		cmd_add_device,		"Add Device"			},
-	{ "del-device", 	"[-t type] <address>",
-		cmd_del_device,		"Remove Device"			},
-	{ "clr-devices",	NULL,
-		cmd_clr_devices,	"Clear Devices"			},
-	{ "bredr-oob",		NULL,
-		cmd_bredr_oob,		"Local OOB data (BR/EDR)"	},
-	{ "le-oob",		NULL,
-		cmd_le_oob,		"Local OOB data (LE)"		},
-	{ "advinfo",		NULL,
-		cmd_advinfo,		"Show advertising features"	},
-	{ "advsize",		"[options] <instance_id>",
-		cmd_advsize,		"Show advertising size info"	},
-	{ "add-adv",		"[options] <instance_id>",
-		cmd_add_adv,		"Add advertising instance"	},
-	{ "rm-adv",		"<instance_id>",
-		cmd_rm_adv,		"Remove advertising instance"	},
-	{ "clr-adv",		NULL,
-		cmd_clr_adv,		"Clear advertising instances"	},
-	{ "add-ext-adv-params",	"[options] <instance_id>",
-		cmd_add_ext_adv_params,
-				"Add extended advertising params"	},
-	{ "add-ext-adv-data",	"[options] <instance_id>",
-		cmd_add_ext_adv_data,
-				"Add extended advertising data"		},
-	{ "appearance",		"<appearance>",
-		cmd_appearance,		"Set appearance"		},
-	{ "phy",		"[LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] "
-				"[LECODEDTX] [LECODEDRX] "
-				"[BR1M1SLOT] [BR1M3SLOT] [BR1M5SLOT]"
-				"[EDR2M1SLOT] [EDR2M3SLOT] [EDR2M5SLOT]"
-				"[EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]",
-		cmd_phy,		"Get/Set PHY Configuration"	},
-	{ "wbs",		"<on/off>",
-		cmd_wbs,		"Toggle Wideband-Speech support"},
-	{ "secinfo",		NULL,
-		cmd_secinfo,		"Show security information"	},
-	{ "expinfo",		NULL,
-		cmd_expinfo,		"Show experimental features"	},
-	{ "exp-debug",		"<on/off>",
-		cmd_exp_debug,		"Set debug feature"		},
-	{ "exp-privacy",	"<on/off>",
-		cmd_exp_privacy,	"Set LL privacy feature"	},
-	{ "exp-quality",	"<on/off>", cmd_exp_quality,
-		"Set bluetooth quality report feature"			},
-	{ "exp-offload",		"<on/off>",
-		cmd_exp_offload_codecs,	"Toggle codec support"		},
-	{ "read-sysconfig",	NULL,
-		cmd_read_sysconfig,	"Read System Configuration"	},
-	{ "set-sysconfig",	"<-v|-h> [options...]",
-		cmd_set_sysconfig,	"Set System Configuration"	},
-	{ "get-flags",		"[-t type] <address>",
-		cmd_get_flags,		"Get device flags"		},
-	{ "set-flags",		"[-f flags] [-t type] <address>",
-		cmd_set_flags,		"Set device flags"		},
-	{} },
-};
-
-static void mgmt_debug(const char *str, void *user_data)
-{
-	const char *prefix = user_data;
+#include <stdlib.h>
+#include <stdio.h>
 
-	print("%s%s", prefix, str);
-}
+#include "src/shared/shell.h"
+#include "client/mgmt.h"
 
 static const char *index_option;
 
@@ -6060,30 +45,17 @@ int main(int argc, char *argv[])
 	int status;
 
 	bt_shell_init(argc, argv, &opt);
-	bt_shell_set_menu(&main_menu);
-	bt_shell_add_submenu(&monitor_menu);
 
-	mgmt = mgmt_new_default();
-	if (!mgmt) {
+	if (!mgmt_add_submenu()) {
 		fprintf(stderr, "Unable to open mgmt_socket\n");
 		return EXIT_FAILURE;
 	}
 
-	if (getenv("MGMT_DEBUG"))
-		mgmt_set_debug(mgmt, mgmt_debug, "mgmt: ", NULL);
-
-	if (index_option)
-		set_index(index_option);
-
-	register_mgmt_callbacks(mgmt, mgmt_index);
-
+	mgmt_set_index(index_option);
 	bt_shell_attach(fileno(stdin));
-	update_prompt(mgmt_index);
 	status = bt_shell_run();
 
-	mgmt_cancel_all(mgmt);
-	mgmt_unregister_all(mgmt);
-	mgmt_unref(mgmt);
+	mgmt_remove_submenu();
 
 	return status;
 }
diff --git a/tools/btmgmt.rst b/tools/btmgmt.rst
new file mode 100644
index 0000000..0159ee1
--- /dev/null
+++ b/tools/btmgmt.rst
@@ -0,0 +1,79 @@
+======
+btmgmt
+======
+
+-------------------------------------
+interactive bluetooth management tool
+-------------------------------------
+
+:Version: BlueZ
+:Copyright: Free use of this software is granted under ther terms of the GNU
+            Lesser General Public Licenses (LGPL).
+:Date: July 2023
+:Manual section: 1
+:Manual group: Linux System Administration
+
+SYNOPSIS
+========
+
+**btmgmt** [--options] [commands]
+
+DESCRIPTION
+===========
+
+**btmgmt(1)** interactive bluetooth management tool. The tool issues commands
+to the Kernel using the Bluetooth Management socket, some commands may require
+net-admin capability in order to work since the Bluetooth Management interface
+is considered a low-level interface meant for the likes of **bluetoothd(8)**,
+it is not recommended for applications to use it directly as it may result in
+unexpected behavior.
+
+OPTIONS
+=======
+
+:-i/--index: Specify adapter index
+:-m-/-monitor: Enable monitor output
+:-t/--timeout: Timeout in seconds for non-interactive mode
+:-v/--version: Display version
+:-i/--init-script: Init script file
+:-h/--help: Display help
+
+COMMANDS
+========
+
+:main: See **bluetoothctl-mgmt(1)**
+:monitor: See **bluetoothctl-monitor(1)**
+
+AUTOMATION
+==========
+
+Two common ways to automate the tool are to pass the commands directly like in
+the follow example:
+
+.. code-block::
+
+    btmgmt <<EOF
+    list
+    show
+    EOF
+
+Or create a script and pass it as init-script:
+
+.. code-block::
+
+    $ vi test-script.bt
+    list
+    show
+    quit
+    :wq
+    $ btmgmt --init-script=test-script
+
+RESOURCES
+=========
+
+http://www.bluez.org
+
+REPORTING BUGS
+==============
+
+linux-bluetooth@vger.kernel.org
diff --git a/tools/btpclientctl.c b/tools/btpclientctl.c
index c30d5bd..eb97463 100644
--- a/tools/btpclientctl.c
+++ b/tools/btpclientctl.c
@@ -2340,7 +2340,7 @@ int main(int argc, char *argv[])
 	mainloop_add_fd(btpclientctl->server_fd, EPOLLIN, server_callback,
 			btpclientctl, NULL);
 
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT_ON, COLOR_BLUE);
 
 	status = bt_shell_run();
 
diff --git a/tools/btsnoop.c b/tools/btsnoop.c
index a0d6cf3..0bd28b6 100644
--- a/tools/btsnoop.c
+++ b/tools/btsnoop.c
@@ -283,7 +283,7 @@ next_packet:
 	if (len < 0 || len != BTSNOOP_PKT_SIZE)
 		goto close_input;
 
-	toread = be32toh(pkt.size);
+	toread = be32toh(pkt.len);
 	flags = be32toh(pkt.flags);
 
 	opcode = flags & 0x00ff;
@@ -356,7 +356,7 @@ next_packet:
 	if (len < 0 || len != BTSNOOP_PKT_SIZE)
 		goto close_input;
 
-	toread = be32toh(pkt.size);
+	toread = be32toh(pkt.len);
 	flags = be32toh(pkt.flags);
 
 	opcode = flags & 0x00ff;
@@ -433,7 +433,7 @@ next_packet:
 	if (len < 0 || len != BTSNOOP_PKT_SIZE)
 		goto close_input;
 
-	toread = be32toh(pkt.size);
+	toread = be32toh(pkt.len);
 
 	len = read(fd, buf, toread);
 	if (len < 0 || len != (ssize_t) toread) {
@@ -448,7 +448,7 @@ next_packet:
 		acl_flags = buf[2] >> 4;
 
 		/* use only packet with ACL start flag */
-		if (acl_flags & 0x02) {
+		if ((acl_flags & 0x02) && len > 9) {
 			if (current_cid == 0x0040 && pdu_len > 0) {
 				int i;
 				if (!pdu_first)
@@ -472,7 +472,7 @@ next_packet:
 			current_cid = buf[8] << 8 | buf[7];
 			memcpy(pdu_buf, buf + 9, len - 9);
 			pdu_len = len - 9;
-		} else if (acl_flags & 0x01) {
+		} else if ((acl_flags & 0x01) && len > 5) {
 			memcpy(pdu_buf + pdu_len, buf + 5, len - 5);
 			pdu_len += len - 5;
 		}
diff --git a/tools/ciptool.1 b/tools/ciptool.1
new file mode 100644
index 0000000..7dfb68a
--- /dev/null
+++ b/tools/ciptool.1
@@ -0,0 +1,89 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "CIPTOOL" "1" "June 3, 2003" "BlueZ" "Linux System Administration"
+.SH NAME
+ciptool \- Bluetooth Common ISDN Access Profile (CIP)
+.SH SYNOPSIS
+.sp
+\fBciptool\fP [\fIOPTIONS\fP] \fICOMMANDS\fP
+.SH DESCRIPTION
+.sp
+\fBciptool(1)\fP is used to set up, maintain, and inspect the CIP configuration
+of the Bluetooth subsystem in the Linux kernel.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-i \ <hciX|BDADDR>
+The command is applied to device \fIhciX\fP , which must be the
+name or the address of an installed Bluetooth device.
+.sp
+If not specified, the command will be use the first
+available Bluetooth device.
+.TP
+.B  \-h\fP,\fB  \-\-help
+Show help options
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B show
+Display information about the connected devices.
+.TP
+.B search
+Search for Bluetooth devices and connect to first one that offers CIP
+support.
+.TP
+.B connect <\fIBDADDR\fP> [\fIPSM\fP]
+Connect the local device to the remote Bluetooth device on the specified
+\fIPSM\fP number. If no \fIPSM\fP is specified,  it will use the SDP to retrieve
+it from the remote device.
+.TP
+.B release [\fIBDADDR\fP]
+Release a connection to the specific device. If no \fIBDADDR\fP is given and
+only one device is connected this will be released.
+.TP
+.B loopback <\fIBDADDR\fP> [\fIPSM\fP]
+Create a connection to the remote device for Bluetooth testing. This
+command will not provide a CAPI controller, because it is only for
+testing the CAPI Message Transport Protocol.
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann <marcel@holtmann.org>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/example.psr b/tools/example.psr
deleted file mode 100644
index bbbec73..0000000
--- a/tools/example.psr
+++ /dev/null
@@ -1,12 +0,0 @@
-// PSKEY_BDADDR
-&0001 = 0001 2821 005b 6789
-// PSKEY_ANA_FTRIM
-&01f6 = 0025
-// PSKEY_HOST_INTERFACE
-&01f9 = 0001
-// PSKEY_UART_BAUD_RATE
-&0204 = 01d8
-// PSKEY_ANA_FREQ
-&01fe = 0004
-// PSKEY_UART_CONFIG
-&0205 = 0006
diff --git a/tools/hciattach.1 b/tools/hciattach.1
new file mode 100644
index 0000000..f1c0d4a
--- /dev/null
+++ b/tools/hciattach.1
@@ -0,0 +1,258 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HCIATTACH" "1" "Jan 22, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+hciattach \- attach serial devices via UART HCI to BlueZ stack
+.SH SYNOPSIS
+.sp
+\fBhciattach\fP [\fIOPTIONS\fP] <\fItty\fP> <\fItype|id\fP> [\fIspeed\fP] [\fIflow\fP] [\fIsleep\fP] [\fIbdaddr\fP]
+.sp
+\fBhciattach\fP \-1
+.SH DESCRIPTION
+.sp
+\fBhciattach(1)\fP is used to attach a serial UART to the Bluetooth stack as HCI
+transport interface.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-i
+Send break
+.TP
+.B  \-n
+Don\(aqt detach from controlling terminal.
+.TP
+.B  \-p
+Print the PID when detaching.
+.TP
+.BI \-t \ timeout
+Specify an initialization timeout. Default is 5 seconds.
+.TP
+.BI \-s \ speed
+Specify an initial speed instead of the hardware default.
+.TP
+.B  \-l
+List all available configurations.
+.TP
+.B  \-r
+Set the HCI device into raw mode. The kernel and bluetooth daemon
+will ignore it.
+.TP
+.B  \-h\fP,\fB  \-\-help
+Show help options
+.UNINDENT
+.SH ARGUMENTS
+.INDENT 0.0
+.TP
+.B \fIshow\fP
+This specifies the serial device to attach. A leading /dev can be omitted.
+.sp
+Examples: \fB/dev/ttyS1 ttyS2\fP
+.TP
+.B \fItype|id\fP
+The \fItype\fP or \fIid\fP of the Bluetooth device that is to be attached,
+i.e. vendor or other device specific identifier.
+Currently supported types are
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fItype\fP
+T}	T{
+Description
+T}
+_
+T{
+any
+T}	T{
+Unspecified HCI_UART interface, no vendor specific options
+T}
+_
+T{
+ericsson
+T}	T{
+Ericsson based modules
+T}
+_
+T{
+digi
+T}	T{
+Digianswer based cards
+T}
+_
+T{
+xircom
+T}	T{
+Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter
+T}
+_
+T{
+csr
+T}	T{
+CSR Casira serial adapter or BrainBoxes serial dongle (BL642)
+T}
+_
+T{
+bboxes
+T}	T{
+BrainBoxes PCMCIA card (BL620)
+T}
+_
+T{
+swave
+T}	T{
+Silicon Wave kits
+T}
+_
+T{
+bcsp
+T}	T{
+Serial adapters using CSR chips with BCSP serial protocol
+T}
+_
+T{
+ath3k
+T}	T{
+Atheros AR300x based serial Bluetooth device
+T}
+_
+T{
+intel
+T}	T{
+Intel Bluetooth device
+T}
+.TE
+.TS
+box center;
+l|l.
+T{
+.nf
+Supported ID
+(manufacturer id, product id)
+.fi
+T}	T{
+Description
+T}
+_
+T{
+0x0105, 0x080a
+T}	T{
+Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter
+T}
+_
+T{
+0x0160, 0x0002
+T}	T{
+BrainBoxes PCMCIA card (BL620)
+T}
+.TE
+.INDENT 0.0
+.TP
+.B \fIspeed\fP
+The \fIspeed\fP specifies the UART speed to use. Baudrates higher than 115200bps
+require vendor specific  initializations that are not implemented for all
+types of devices. In general the following speeds are supported:
+.sp
+Supported vendor devices are automatically initialised to their respective
+best settings.
+.UNINDENT
+.TS
+box center;
+l.
+T{
+9600
+T}
+_
+T{
+19200
+T}
+_
+T{
+38400
+T}
+_
+T{
+57600
+T}
+_
+T{
+115200
+T}
+_
+T{
+230400
+T}
+_
+T{
+460800
+T}
+_
+T{
+921600
+T}
+.TE
+.INDENT 0.0
+.TP
+.B \fIflow\fP
+If the \fIflow\fP is appended to the list of options then hardware flow control
+is forced on the serial link (\fBCRTSCTS\fP). All above mentioned device
+types have flow set by default. To force no flow control use \fInoflow\fP
+instead.
+.TP
+.B \fIsleep|nosleep\fP
+Enables hardware specific power management feature. If \fIsleep\fP is appended
+to the list of options then this feature is enabled. To disable this
+feature use \fInosleep\fP instead. All above mentioned device types have
+\fInosleep\fP set by default.
+.sp
+Note: This option will only be valid for hardware which support hardware
+specific power management enable option from host.
+.TP
+.B \fIbdaddr\fP
+The bdaddr specifies the Bluetooth Address to use. Some devices (like
+the STLC2500) do not store the Bluetooth address in hardware memory.
+Instead it must be uploaded during the initialization process. If this
+argument is specified, then the address will be used to initialize the
+device. Otherwise, a default address will be used.
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Nils Faerber <nils@kernelconcepts.de>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/hciattach.c b/tools/hciattach.c
index 276a4e5..adf79ba 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -26,6 +26,7 @@
 #include <termios.h>
 #include <time.h>
 #include <poll.h>
+#include <limits.h>
 #include <sys/time.h>
 #include <sys/param.h>
 #include <sys/ioctl.h>
diff --git a/tools/hciattach_ath3k.c b/tools/hciattach_ath3k.c
index d119155..8922b48 100644
--- a/tools/hciattach_ath3k.c
+++ b/tools/hciattach_ath3k.c
@@ -16,6 +16,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <time.h>
+#include <limits.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
diff --git a/tools/hciattach_intel.c b/tools/hciattach_intel.c
index e243b3d..b686789 100644
--- a/tools/hciattach_intel.c
+++ b/tools/hciattach_intel.c
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <time.h>
diff --git a/tools/hciattach_st.c b/tools/hciattach_st.c
index 4a7186a..def7613 100644
--- a/tools/hciattach_st.c
+++ b/tools/hciattach_st.c
@@ -12,6 +12,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
diff --git a/tools/hciattach_ti.c b/tools/hciattach_ti.c
index 24efcea..c0a0025 100644
--- a/tools/hciattach_ti.c
+++ b/tools/hciattach_ti.c
@@ -14,6 +14,7 @@
 #endif
 
 #define _GNU_SOURCE
+#include <limits.h>
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
diff --git a/tools/hciconfig.1 b/tools/hciconfig.1
new file mode 100644
index 0000000..5bd2f97
--- /dev/null
+++ b/tools/hciconfig.1
@@ -0,0 +1,334 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HCICONFIG" "1" "Nov 11, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+hciconfig \- Configure Bluetooth devices
+.SH SYNOPSIS
+.sp
+\fBhciconfig\fP \-h
+.sp
+\fBhciconfig\fP [\-a]
+.sp
+\fBhciconfig\fP [\-a] \fIhciX\fP [\fICOMMAND\fP [\fIPARAMETERS\fP]]
+.SH DESCRIPTION
+.sp
+\fBhciconfig(1)\fP is used to configure Bluetooth devices. \fIhciX\fP is the name of a
+Bluetooth device installed in the system. If hciX is not given, hciconfig
+prints name and basic information about all the Bluetooth devices installed
+in the system.
+.sp
+If \fIhciX\fP is given but no command is given, it prints basic information on
+device \fIhciX\fP only. Basic information is interface type, BD address, ACL MTU,
+SCO MTU, flags (up, init, running, raw, page scan enabled, inquiry scan
+enabled, inquiry, authentication enabled, encryption enabled).
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-a\fP,\fB  \-\-all
+Print features, packet type, link policy, link mode, class, Version
+other than the basic info.
+.TP
+.B  \-h\fP,\fB  \-\-help
+Show help options
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B up
+Open and initialize HCI device.
+.TP
+.B down
+Close HCI device.
+.TP
+.B reset
+Reset HCI device.
+.TP
+.B rstat
+Reset statistic counters.
+.TP
+.B auth
+Enable authentication (sets device to security mode 3).
+.TP
+.B noauth
+Disable authentication.
+.TP
+.B encrypt
+Enable encryption (sets device to security mode 3).
+.TP
+.B noencrypt
+Disable encryption.
+.TP
+.B secmgr
+Enable security manager (current kernel support is limited).
+.TP
+.B nosecmgr
+Disable security manager.
+.TP
+.B piscan
+Enable page and inquiry scan.
+.TP
+.B noscan
+Disable page and inquiry scan.
+.TP
+.B iscan
+Enable inquiry scan, disable page scan.
+.TP
+.B pscan
+Enable page scan, disable inquiry scan.
+.TP
+.B ptype [\fItype\fP]
+With  no \fItype\fP , displays the current packet types. Otherwise, all the
+packet types specified by \fItype\fP are set. \fItype\fP is a comma\-separated list
+of packet types, where the possible packet types are \fBDM1\fP, \fBDM3\fP,
+\fBDM5\fP, \fBDH1\fP, \fBDH3\fP, \fBDH5\fP, \fBHV1\fP, \fBHV2\fP, \fBHV3\fP\&.
+.TP
+.B name [\fIname\fP]
+With no \fIname\fP, prints local name. Otherwise, sets local name to \fIname\fP\&.
+.TP
+.B class [\fIclass\fP]
+With  no \fIclass\fP, prints class of device. Otherwise, sets class of device
+to \fIclass\fP\&. \fIclass\fP is a 24\-bit hex number describing the class of device,
+as specified in section 1.2 of the Bluetooth Assigned Numers document.
+.TP
+.B voice [\fIvoice\fP]
+With no \fIvoice\fP, prints voice setting. Otherwise, sets voice setting to
+\fIvoice\fP\&. \fIvoice\fP is a 16\-bit hex number describing the voice setting.
+.TP
+.B iac [\fIiac\fP]
+With no \fIiac\fP, prints the current IAC setting. Otherwise, sets the IAC to
+\fIiac\fP\&.
+.TP
+.B inqtpl [\fIlevel\fP]
+With no \fIlevel\fP, prints out the current inquiry transmit power level.
+Otherwise, sets inquiry transmit power level to \fIlevel\fP\&.
+.TP
+.B inqmode [\fImode\fP]
+.INDENT 7.0
+.INDENT 3.5
+With no \fImode\fP, prints out the current inquiry mode. Otherwise, sets
+inquiry mode to \fImode\fP\&.
+.UNINDENT
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fImode\fP
+T}	T{
+Description
+T}
+_
+T{
+0
+T}	T{
+Standard Inquiry
+T}
+_
+T{
+1
+T}	T{
+Inquiry with RSSI
+T}
+_
+T{
+2
+T}	T{
+Inquiry with RSSI or Extended Inquiry
+T}
+.TE
+.TP
+.B inqdata [\fIdata\fP]
+With no \fIdata\fP, prints out the current inquiry data. Otherwise, sets
+inquiry data to \fIdata\fP\&.
+.TP
+.B inqtype [\fItype\fP]
+With no \fItype\fP, prints out the current inquiry scan type. Otherwise, sets
+inquiry scan type to \fItype\fP\&.
+.TP
+.B inqparams [\fIwin:int\fP]
+With no \fIwin:int\fP, prints inquiry scan window and interval. Otherwise,
+sets inquiry scan window  to \fIwin\fP slots and inquiry scan interval to
+\fIint\fP slots.
+.TP
+.B pageparms [\fIwin:int\fP]
+With no \fIwin:int\fP, prints page scan window and interval. Otherwise,
+sets page scan window to \fIwin\fP slots and page scan interval to \fIint\fP slots.
+.TP
+.B pageto [\fIto\fP]
+With no \fIto\fP, prints page timeout. Otherwise, sets page timeout \fIto\fP to
+slots.
+.TP
+.B afhmode [\fImode\fP]
+With no \fImode\fP, prints out the current AFH mode. Otherwise, sets AFH mode
+to \fImode\fP\&.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fImode\fP
+T}	T{
+Description
+T}
+_
+T{
+0
+T}	T{
+Enable
+T}
+_
+T{
+1
+T}	T{
+Disable
+T}
+.TE
+.INDENT 0.0
+.TP
+.B sspmode [\fImode\fP]
+With no \fImode\fP, prints out the current Simple Pairing mode. Otherwise,
+sets Simple Pairing mode to \fImode\fP\&.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fImode\fP
+T}	T{
+Description
+T}
+_
+T{
+0
+T}	T{
+Enable
+T}
+_
+T{
+1
+T}	T{
+Disable
+T}
+.TE
+.INDENT 0.0
+.TP
+.B aclmtu \fImtu:pkt\fP
+Sets ACL MTU to \fImtu\fP bytes and ACL buffer size to \fIpkt\fP packets.
+.TP
+.B scomtu \fImtu:pkt\fP
+Sets SCO MTU to \fImtu\fP bytes and SCO buffer size to \fIpkt\fP packets.
+.TP
+.B delkey <\fIbdaddr\fP>
+This command deletes the stored link key for \fIbdaddr\fP from the device.
+.TP
+.B oobdata
+Get local OOB data (invalidates previously read data).
+.TP
+.B commands
+Display supported commands.
+.TP
+.B features
+Display device features.
+.TP
+.B version
+Display version information.
+.TP
+.B revision
+Display revision information.
+.TP
+.B lm [\fImode\fP]
+With no \fImode\fP, prints link mode. \fBCENTRAL\fP or \fBPERIPHERAL\fP mean,
+respectively, to ask to become central or to remain peripheral when a
+connection request comes in. The additional keyword \fBACCEPT\fP means that
+baseband connections will be accepted even if there are no listening
+\fIAF_BLUETOOTH\fP sockets. \fImode\fP is \fBNONE\fP or a comma\-separated list of
+keywords, where possible keywords are \fBCENTRAL\fP and \fBACCEPT\fP\&. \fBNONE\fP
+sets link policy to the default behaviour of remaining peripheral and not
+accepting baseband connections when there are no listening \fIAF_BLUETOOTH\fP
+sockets.  If \fBCENTRAL\fP is  present, the device will ask to become central
+if a connection request comes in. If \fBACCEPT\fP is present, the device will
+accept baseband connections even when there are no listening \fIAF_BLUETOOTH\fP
+sockets.
+.TP
+.B block <\fIbdaddr\fP>
+Add a device to the reject list
+.TP
+.B unblock <\fIbdaddr\fP>
+Remove a device from the reject list
+.TP
+.B lerandaddr <\fIbdaddr\fP>
+Set LE Random Address
+.TP
+.B leadv [\fItype\fP]
+Enable LE Advertising.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fItype\fP
+T}	T{
+Description
+T}
+_
+T{
+0
+T}	T{
+Connectable undirected advertising (default)
+T}
+_
+T{
+3
+T}	T{
+Non connectable undirected advertising
+T}
+.TE
+.INDENT 0.0
+.TP
+.B noleadv
+Disable LE Advertising
+.TP
+.B lestates
+Display the supported LE states
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>, Fabrizio Gennari <fabrizio.gennari@philips.com>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/hcidump.1 b/tools/hcidump.1
new file mode 100644
index 0000000..57b0c00
--- /dev/null
+++ b/tools/hcidump.1
@@ -0,0 +1,131 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HCIDUMP" "1" "Nov 12, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+hcidump \- Parse HCI data
+.SH SYNOPSIS
+.sp
+\fBhcidump\fP \-h
+.sp
+\fBhcidump\fP [OPTIONS ...] [FILTERS]
+.SH DESCRIPTION
+.sp
+\fBhcidump(1)\fP reads raw HCI data coming from and going to a Bluetooth device
+(which can be specified with the option \fB\-i\fP, default is the first available
+one) and prints to screen commands, events and data in a human\-readable form.
+Optionally, the dump can be written to a file rather than parsed, and the dump
+file can be parsed in a subsequent moment.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-i \ <hciX>
+Data is read from \fIhciX\fP, which must be the name of an installed Bluetooth
+device. If not specified, and if \fB\-r\fP option is not set, data is read from
+the first available Bluetooth device.
+.TP
+.BI \-l \ <len>\fR,\fB \ \-\-snap\-len\fB= <len>
+Sets max length of processed packets to \fIlen\fP\&.
+.TP
+.BI \-p \ <psm>\fR,\fB \ \-\-psm\fB= <psm>
+Sets default Protocol Service Multiplexer to \fIpsm\fP\&.
+.TP
+.BI \-m \ <compid>\fR,\fB \ \-\-manufacturer\fB= <compid>
+Sets default company id for manufacturer to \fIcompid\fP\&.
+.TP
+.BI \-w \ <file>\fR,\fB \ \-\-save\-dump\fB= <file>
+Parse output is not printed to screen, instead data read from device is
+saved in \fIfile\fP\&. The saved dump file can be subsequently parsed with
+option \fB\-r\fP\&.
+.TP
+.BI \-r \ <file>\fR,\fB \ \-\-read\-dump\fB= <file>
+Data is not read from a Bluetooth device, but from \fIfile\fP\&. \fIfile\fP is
+created with option \fB\-t\fP, \fB\-\-timestamp\fP prepend a time stamp to every
+packet.
+.TP
+.B  \-a\fP,\fB  \-\-ascii
+For every packet, not only is the packet type displayed, but also all data
+in ASCII.
+.TP
+.B  \-x\fP,\fB  \-\-hex
+For every packet, not only is the packet type displayed, but also all data
+in hex.
+.TP
+.B  \-X\fP,\fB  \-\-ext
+For every packet, not only is the packet type displayed, but also all data
+in hex and ASCII.
+.TP
+.B  \-R\fP,\fB  \-\-raw
+For every packet, only the raw data is displayed.
+.TP
+.BI \-C \ <psm>\fR,\fB \ \-\-cmtp\fB= <psm>
+Sets the PSM value for the CAPI Message Transport Protocol.
+.TP
+.BI \-H \ <psm>\fR,\fB \ \-\-hcrp\fB= <psm>
+Sets the PSM value for the Hardcopy Control Channel.
+.TP
+.BI \-O \ <channel>\fR,\fB \ \-\-obex\fB= <channel>
+Sets the RFCOMM channel value for the Object Exchange Protocol.
+.TP
+.BI \-P \ <channel>\fR,\fB \ \-\-ppp\fB= <channel>
+Sets the RFCOMM channel value for the Point\-to\-Point Protocol.
+.TP
+.BI \-D \ <file>\fR,\fB \ \-\-pppdump\fB= <file>
+Extract PPP traffic with pppdump format.
+.TP
+.BI \-A \ <file>\fR,\fB \ \-\-audio\fB= <file>
+Extract SCO audio data.
+.TP
+.B  \-Y\fP,\fB  \-\-novendor
+Don\(aqt display any vendor commands or events and don\(aqt show any pin code or
+link key in plain text.
+.TP
+.B  \-h
+Prints usage info and exits
+.UNINDENT
+.SH FILTERS
+.sp
+filter is a space\-separated list of packet categories: available categories are
+\fIlmp\fP, \fIhci\fP, \fIsco\fP, \fIl2cap\fP, \fIrfcomm\fP, \fIsdp\fP, \fIbnep\fP, \fIcmtp\fP, \fIhidp\fP, \fIhcrp\fP,
+\fIavdtp\fP, \fIavctp\fP, \fIobex\fP, \fIcapi\fP and \fIppp\fP\&. If filters are used, only packets
+belonging to the specified categories are dumped. By default, all packets are
+dumped.
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>, Fabrizio Gennari <fabrizio.gennari@philips.com>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/hcidump.c b/tools/hcidump.c
index 011864b..d517031 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
@@ -610,7 +610,7 @@ static void usage(void)
 	"  -m, --manufacturer=compid  Default manufacturer\n"
 	"  -w, --save-dump=file       Save dump to a file\n"
 	"  -r, --read-dump=file       Read dump from a file\n"
-	"  -t, --ts                   Display time stamps\n"
+	"  -t, --timestamp            Display time stamps\n"
 	"  -a, --ascii                Dump data in ascii\n"
 	"  -x, --hex                  Dump data in hex\n"
 	"  -X, --ext                  Dump data in hex and ascii\n"
diff --git a/tools/hcitool.1 b/tools/hcitool.1
new file mode 100644
index 0000000..9b0d4ee
--- /dev/null
+++ b/tools/hcitool.1
@@ -0,0 +1,229 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HCITOOL" "1" "Nov 12, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+hcitool \- Configure Bluetooth connections
+.SH SYNOPSIS
+.sp
+\fBhcitool\fP \-h
+.sp
+\fBhcitool\fP \fICOMMAND\fP \-\-help
+.sp
+\fBhcitool\fP [\-i \fIhciX\fP] [\fICOMMAND\fP [\fIPARAMETERS\fP]]
+.SH DESCRIPTION
+.sp
+\fBhcitool(1)\fP is used to configure Bluetooth connections and send some special
+command to Bluetooth devices. If no \fBcommand\fP is given, or if the option
+\fB\-h\fP is used, \fIhcitool\fP prints some usage information and exits.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-i \ <hciX>
+The command is applied to device \fIhciX\fP, which must be the name of
+an installed Bluetooth device. If not specified, the command will
+be sent to the first available Bluetooth device.
+.TP
+.B  \-h
+Gives a list of possible commands
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B dev
+Display local devices
+.TP
+.B inq
+Inquire remote devices. For each discovered device, Bluetooth device
+address, clock offset and class are printed.
+.TP
+.B scan
+Inquire remote devices. For each discovered device, device name are printed.
+.TP
+.B name <\fIbdaddr\fP>
+Print device name of remote device with Bluetooth address \fIbdaddr\fP\&.
+.TP
+.B info <\fIbdaddr\fP>
+Print device name, version and supported features of remote device with
+Bluetooth address \fIbdaddr\fP\&.
+.TP
+.B spinq
+Start periodic inquiry process. No inquiry results are printed.
+.TP
+.B epinq
+Exit periodic inquiry process.
+.TP
+.B cmd <\fIogf\fP> <\fIocf\fP> [\fIparameters\fP]
+Submit an arbitrary HCI command to local device. \fIogf\fP, \fIocf\fP and
+parameters are hexadecimal bytes.
+.TP
+.B con
+Display active baseband connections
+.TP
+.B cc [\-\-\fIrole\fP=c|p] [\-\-\fIpkt\-type\fP=<\fIptype\fP>] <\fIbdaddr\fP>
+Create baseband connection to remote device with Bluetooth address \fIbdaddr\fP\&.
+.sp
+Option \fB\-\-pkt\-type\fP specifies a list  of  allowed packet types.
+<\fIptype\fP> is a comma\-separated list of packet types, where the possible
+packet types are \fBDM1\fP, \fBDM3\fP, \fBDM5\fP, \fBDH1\fP, \fBDH3\fP, \fBDH5\fP,
+\fBHV1\fP, \fBHV2\fP, \fBHV3\fP\&. Default is to allow all packet types.
+.sp
+Option  \fB\-\-role\fP can have value \fBc\fP (do not allow role switch, stay
+central) or \fBp\fP (allow role switch, become peripheral if the peer asks to
+become central). Default is \fBc\fP\&.
+.TP
+.B dc <\fIbdaddr\fP> [\fIreason\fP]
+Delete baseband connection from remote device with Bluetooth address
+\fIbdaddr\fP\&.
+.sp
+The reason can be one of the Bluetooth HCI error codes.
+Default is \fB19\fP for user ended connections. The value must be given in
+decimal.
+.TP
+.B sr <\fIbdaddr\fP> <\fIrole\fP>
+Switch role for the baseband connection from the remote device to
+\fBcentral\fP or \fBperipheral\fP\&.
+.TP
+.B cpt <\fIbdaddr\fP> <\fIptypes\fP>
+Change packet types for baseband connection to device with Bluetooth
+address \fIbdaddr\fP\&. \fIptypes\fP is a comma\-separated list of packet types,
+where the possible packet types are \fBDM1\fP, \fBDM3\fP, \fBDM5\fP, \fBDH1\fP,
+\fBDH3\fP, \fBDH5\fP, \fBHV1\fP, \fBHV2\fP, \fBHV3\fP\&.
+.TP
+.B rssi <\fIbdaddr\fP>
+Display received signal strength information for the connection to the
+device with Bluetooth address \fIbdaddr\fP\&.
+.TP
+.B lq <\fIbdaddr\fP>
+Display link quality for the connection to the device with Bluetooth
+address \fIbdaddr\fP\&.
+.TP
+.B tpl <\fIbdaddr\fP> [\fItype\fP]
+Display transmit power level for the connection to the device with
+Bluetooth address \fIbdaddr\fP\&.
+.sp
+The \fItype\fP can be \fB0\fP for the current transmit power level (which is
+default) or \fB1\fP for the maximum transmit power level.
+.TP
+.B afh <\fIbdaddr\fP>
+Display AFH channel map for the connection to the device with Bluetooth
+address \fIbdaddr\fP\&.
+.TP
+.B lp <\fIbdaddr\fP> [\fIvalue\fP]
+With no value, displays link policy settings for the connection to the
+device with Bluetooth address \fIbdaddr\fP\&.
+.sp
+If \fIvalue\fP is given, sets the link policy settings for that connection to
+\fIvalue\fP\&. Possible values are \fBRSWITCH\fP, \fBHOLD\fP, \fBSNIFF\fP and \fBPARK\fP\&.
+.TP
+.B lst <\fIbdaddr\fP> [\fIvalue\fP]
+With no value, displays link supervision timeout for the connection to
+the device with Bluetooth address \fIbdaddr\fP\&.
+.sp
+If \fIvalue\fP is given, sets the link supervision timeout for that connection
+to \fIvalue\fP slots, or to infinite if value is 0.
+.TP
+.B auth <\fIbdaddr\fP>
+Request authentication for the device with Bluetooth address \fIbdaddr\fP\&.
+.TP
+.B enc <\fIbdaddr\fP> [\fIencrypt\fP]
+\fBenable\fP or \fBdisable\fP the encryption for the device with Bluetooth
+address \fIbdaddr\fP\&.
+.TP
+.B key <\fIbdaddr\fP>
+Change the connection link key for the device with Bluetooth address
+\fIbdaddr\fP\&.
+.TP
+.B clkoff <\fIbdaddr\fP>
+Read the clock offset for the device with Bluetooth address \fIbdaddr\fP\&.
+.TP
+.B clock [\fIbdaddr\fP] [\fIclock\fP]
+Read the clock for the device with Bluetooth address \fIbdaddr\fP\&.
+.sp
+The \fIclock\fP can be \fB0\fP for the local clock or \fB1\fP for the piconet
+clock (which is default).
+.TP
+.B lescan [\-\-\fIprivacy\fP] [\-\-\fIpassive\fP] [\-\-\fIacceptlist\fP] [\-\-\fIdiscovery\fP=g|l] [\-\-\fIduplicates\fP]
+Start LE scan
+.TP
+.B leinfo [\-\-\fIstatic\fP] [\-\-\fIrandom\fP] <\fIbdaddr\fP>
+Get LE remote information
+.TP
+.B lealadd [\-\-\fIrandom\fP] <\fIbdaddr\fP>
+Add device to LE Accept List
+.TP
+.B lealrm <\fIbdaddr\fP>
+Remove device from LE Accept List
+.TP
+.B lealsz
+Read size of LE Accept List
+.TP
+.B lealclr
+Clear LE Accept List
+.TP
+.B lerladd [\-\-\fIlocal_irk\fP] [\-\-\fIpeer_irk\fP] [\-\-\fIrandom\fP] <\fIbdaddr\fP>
+Add device to LE Resolving List
+.TP
+.B lerlrm <\fIbdaddr\fP>
+Remove device from LE Resolving List
+.TP
+.B lerlclr
+Clear LE Resolving List
+.TP
+.B lerlsz
+Read size of LE Resolving List
+.TP
+.B lerlon
+Enable LE Address Resolution
+.TP
+.B lerloff
+Disable LE Address Resolution
+.TP
+.B lecc [\-\-\fIstatic\fP] [\-\-\fIrandom\fP] <\fIbdaddr\fP> | [\-\-\fIacceptlist\fP]
+Create a LE Connection
+.TP
+.B ledc <\fIhandle\fP> [\fIreason\fP]
+Disconnect a LE Connection
+.TP
+.B lecup <\fIhandle\fP> <\fImin\fP> <\fImax\fP> <\fIlatency\fP> <\fItimeout\fP>
+LE Connection Update
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>, Fabrizio Gennari <fabrizio.gennari@philips.com>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/hex2hcd.c b/tools/hex2hcd.c
index e6dca5a..452ab2b 100644
--- a/tools/hex2hcd.c
+++ b/tools/hex2hcd.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <sys/stat.h>
+#include "tools/missing.h"
 
 static ssize_t process_record(int fd, const char *line, uint16_t *upper_addr)
 {
diff --git a/tools/hid2hci.1 b/tools/hid2hci.1
new file mode 100644
index 0000000..fbbef02
--- /dev/null
+++ b/tools/hid2hci.1
@@ -0,0 +1,70 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "HID2HCI" "1" "May 15, 2009" "BlueZ" "Linux System Administration"
+.SH NAME
+hid2hci \- Bluetooth HID to HCI mode switching utility
+.SH SYNOPSIS
+.sp
+\fBhid2hci\fP [\fIOPTIONS\fP]
+.SH DESCRIPTION
+.sp
+\fBhid2hci(1)\fP is used to set up switch supported Bluetooth devices into the
+HCI mode and back.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-mode=[\fImode\fP]         Sets the mode to the device into. The possible values
+for \fImode\fP are \fBhid\fP, \fBhci\fP\&.
+.TP
+.B \-\-method=[\fImethod\fP]     Which vendor method to use for switching the device.
+The possible values for \fImethod\fP are \fBcsr\fP, \fBcsr2\fP,
+\fBlogitech\-hdi\fP, \fBdell\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B  \-\-devpath
+Specifies the device path in /sys
+.TP
+.B  \-\-help
+Gives a list of possible options.
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann <marcel@holtmann.org>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/iso-tester.c b/tools/iso-tester.c
index 269fbe2..e80c215 100644
--- a/tools/iso-tester.c
+++ b/tools/iso-tester.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation.
+ *  Copyright 2023-2024 NXP
  *
  */
 
@@ -17,19 +18,29 @@
 #include <poll.h>
 #include <stdbool.h>
 
+#include <linux/errqueue.h>
+#include <linux/net_tstamp.h>
+
 #include <glib.h>
 
 #include "lib/bluetooth.h"
 #include "lib/iso.h"
 #include "lib/mgmt.h"
+#include "lib/uuid.h"
 
 #include "monitor/bt.h"
+#include "emulator/vhci.h"
 #include "emulator/bthost.h"
 #include "emulator/hciemu.h"
 
 #include "src/shared/tester.h"
 #include "src/shared/mgmt.h"
 #include "src/shared/util.h"
+#include "src/shared/queue.h"
+
+#include "tester.h"
+
+#define EIR_SERVICE_DATA_16	0x16
 
 #define QOS_IO(_interval, _latency, _sdu, _phy, _rtn) \
 { \
@@ -42,13 +53,15 @@
 
 #define QOS_FULL(_cig, _cis, _in, _out) \
 { \
-	.cig = _cig, \
-	.cis = _cis, \
-	.sca = 0x07, \
-	.packing = 0x00, \
-	.framing = 0x00, \
-	.in = _in, \
-	.out = _out, \
+	.ucast = { \
+		.cig = _cig, \
+		.cis = _cis, \
+		.sca = 0x07, \
+		.packing = 0x00, \
+		.framing = 0x00, \
+		.in = _in, \
+		.out = _out, \
+	},\
 }
 
 #define QOS(_interval, _latency, _sdu, _phy, _rtn) \
@@ -61,11 +74,21 @@
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
 
+#define QOS_2(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x02, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
 #define QOS_1_1(_interval, _latency, _sdu, _phy, _rtn) \
 	QOS_FULL(0x01, 0x01, \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
 
+#define QOS_1_2(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, 0x02, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
 #define QOS_OUT(_interval, _latency, _sdu, _phy, _rtn) \
 	QOS_FULL(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
 		{}, QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
@@ -78,9 +101,29 @@
 	QOS_FULL(0x01, 0x01, \
 		{}, QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
 
+#define QOS_OUT_1_2(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, 0x02, \
+		{}, QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define QOS_OUT_1_EF(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, 0xEF, \
+		{}, QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
 #define QOS_IN(_interval, _latency, _sdu, _phy, _rtn) \
 	QOS_FULL(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+#define QOS_IN_1(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+#define QOS_IN_2(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x02, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+#define QOS_IN_1_1(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, 0x01, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+#define QOS_IN_1_2(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_FULL(0x01, 0x02, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
 
 /* QoS Configuration settings for low latency audio data */
 #define QOS_8_1_1 QOS(7500, 8, 26, 0x02, 2)
@@ -88,6 +131,7 @@
 #define QOS_16_1_1 QOS(7500, 8, 30, 0x02, 2)
 #define QOS_16_2_1 QOS(10000, 10, 40, 0x02, 2)
 #define QOS_1_16_2_1 QOS_1(10000, 10, 40, 0x02, 2)
+#define QOS_2_16_2_1 QOS_2(10000, 10, 40, 0x02, 2)
 #define QOS_1_1_16_2_1 QOS_1_1(10000, 10, 40, 0x02, 2)
 #define QOS_24_1_1 QOS(7500, 8, 45, 0x02, 2)
 #define QOS_24_2_1 QOS(10000, 10, 60, 0x02, 2)
@@ -102,27 +146,319 @@
 #define QOS_48_5_1 QOS_OUT(7500, 15, 117, 0x02, 5)
 #define QOS_48_6_1 QOS_OUT(10000, 20, 155, 0x02, 5)
 /* QoS Configuration settings for high reliability audio data */
-#define QOS_8_1_2 QOS(7500, 45, 26, 0x02, 41)
-#define QOS_8_2_2 QOS(10000, 60, 30, 0x02, 53)
-#define QOS_16_1_2 QOS(7500, 45, 30, 0x02, 41)
-#define QOS_16_2_2 QOS(10000, 60, 40, 0x02, 47)
-#define QOS_24_1_2 QOS(7500, 45, 45, 0x02, 35)
-#define QOS_24_2_2 QOS(10000, 60, 60, 0x02, 41)
-#define QOS_32_1_2 QOS(7500, 45, 60, 0x02, 29)
-#define QOS_32_2_2 QOS(10000, 60, 80, 0x02, 35)
-#define QOS_44_1_2 QOS_OUT(8163, 54, 98, 0x02, 23)
-#define QOS_44_2_2 QOS_OUT(10884, 71, 130, 0x02, 23)
-#define QOS_48_1_2 QOS_OUT(7500, 45, 75, 0x02, 23)
-#define QOS_48_2_2 QOS_OUT(10000, 60, 100, 0x02, 23)
-#define QOS_48_3_2 QOS_OUT(7500, 45, 90, 0x02, 23)
-#define QOS_48_4_2 QOS_OUT(10000, 60, 120, 0x02, 23)
-#define QOS_48_5_2 QOS_OUT(7500, 45, 117, 0x02, 23)
-#define QOS_48_6_2 QOS_OUT(10000, 60, 155, 0x02, 23)
-
-#define QOS_OUT_16_2_1 QOS_OUT(10000, 10, 40, 0x02, 2)
-#define QOS_OUT_1_16_2_1 QOS_OUT_1(10000, 10, 40, 0x02, 2)
-#define QOS_OUT_1_1_16_2_1 QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
-#define QOS_IN_16_2_1 QOS_IN(10000, 10, 40, 0x02, 2)
+#define QOS_8_1_2 QOS(7500, 75, 26, 0x02, 13)
+#define QOS_8_2_2 QOS(10000, 95, 30, 0x02, 13)
+#define QOS_16_1_2 QOS(7500, 75, 30, 0x02, 13)
+#define QOS_16_2_2 QOS(10000, 95, 40, 0x02, 13)
+#define QOS_24_1_2 QOS(7500, 75, 45, 0x02, 13)
+#define QOS_24_2_2 QOS(10000, 95, 60, 0x02, 13)
+#define QOS_32_1_2 QOS(7500, 65, 60, 0x02, 13)
+#define QOS_32_2_2 QOS(10000, 95, 80, 0x02, 13)
+#define QOS_44_1_2 QOS_OUT(8163, 80, 98, 0x02, 13)
+#define QOS_44_2_2 QOS_OUT(10884, 85, 130, 0x02, 13)
+#define QOS_48_1_2 QOS_OUT(7500, 75, 75, 0x02, 13)
+#define QOS_48_2_2 QOS_OUT(10000, 95, 100, 0x02, 13)
+#define QOS_48_3_2 QOS_OUT(7500, 75, 90, 0x02, 13)
+#define QOS_48_4_2 QOS_OUT(10000, 100, 120, 0x02, 13)
+#define QOS_48_5_2 QOS_OUT(7500, 75, 117, 0x02, 13)
+#define QOS_48_6_2 QOS_OUT(10000, 100, 155, 0x02, 13)
+/* QoS configuration support setting requirements for the UGG and UGT */
+#define QOS_16_1_gs QOS(7500, 15, 30, 0x02, 1)
+#define QOS_16_2_gs QOS(10000, 20, 40, 0x02, 1)
+#define QOS_32_1_gs QOS(7500, 15, 60, 0x02, 1)
+#define QOS_32_2_gs QOS(10000, 20, 80, 0x02, 1)
+#define QOS_48_1_gs QOS(7500, 15, 75, 0x02, 1)
+#define QOS_48_2_gs QOS(10000, 20, 100, 0x02, 1)
+#define QOS_32_1_gr QOS(7500, 15, 60, 0x02, 1)
+#define QOS_32_2_gr QOS(10000, 20, 80, 0x02, 1)
+#define QOS_48_1_gr QOS(7500, 15, 75, 0x02, 1)
+#define QOS_48_2_gr QOS(10000, 20, 100, 0x02, 1)
+#define QOS_48_3_gr QOS(7500, 15, 90, 0x02, 1)
+#define QOS_48_4_gr QOS(10000, 20, 120, 0x02, 1)
+
+/* One unidirectional CIS. Unicast Server is Audio Sink */
+#define AC_1_4 QOS_OUT(10000, 10, 40, 0x02, 2)
+/* One unidirectional CIS. Unicast Server is Audio Sink CIG 0x01 */
+#define AC_1_4_1 QOS_OUT_1(10000, 10, 40, 0x02, 2)
+/* One unidirectional CIS. Unicast Server is Audio Source. */
+#define AC_2_10 QOS_IN(10000, 10, 40, 0x02, 2)
+/* One unidirectional CIS. Unicast Server is Audio Source CIG 0x02 */
+#define AC_2_10_2 QOS_IN_2(10000, 10, 40, 0x02, 2)
+/* One bidirectional CIS. Unicast Server is Audio Sink and Audio Source. */
+#define AC_3_5 QOS(10000, 10, 40, 0x02, 2)
+/* Two unidirectional CISes. Unicast Server is Audio Sink.
+ * #1 - CIG 1 CIS 1 (output)
+ * #2 - CIG 1 CIS 2 (output)
+ */
+#define AC_6i_1 QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define AC_6i_2 QOS_OUT_1_2(10000, 10, 40, 0x02, 2)
+/* Two Unicast Servers. Unicast Server 1 is Audio Sink. Unicast Server 2 is
+ * Audio Sink.
+ * #1 - CIG 1 CIS auto (output)
+ * #2 - CIG 1 CIS auto (output)
+ */
+#define AC_6ii_1 QOS_OUT_1(10000, 10, 40, 0x02, 2)
+#define AC_6ii_2 QOS_OUT_1(10000, 10, 40, 0x02, 2)
+#define AC_6ii_1_EF QOS_OUT_1_EF(10000, 10, 40, 0x02, 2)  /* different CIS ID */
+/* Two unidirectional CISes. Unicast Server is Audio Sink and Audio Source.
+ * #1 - CIG 1 CIS 1 (input)
+ * #2 - CIG 1 CIS 2 (output)
+ */
+#define AC_7i_1 QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define AC_7i_2 QOS_IN_1_2(10000, 10, 40, 0x02, 2)
+/* Two Unidirectional CISes. Two Unicast Servers. Unicast Server 1 is Audio
+ * Sink. Unicast Server 2 is Audio Source.
+ * #1 - CIG 1 CIS auto (output)
+ * #2 - CIG 1 CIS auto (output)
+ */
+#define AC_7ii_1 QOS_OUT_1(10000, 10, 40, 0x02, 2)
+#define AC_7ii_2 QOS_IN_1(10000, 10, 40, 0x02, 2)
+/* One bidirectional CIS and one unidirectional CIS. Unicast Server is Audio
+ * Sink and Audio Source.
+ * #1 - CIG 1 CIS 1 (output)
+ * #2 - CIG 1 CIS 2 (input/output)
+ */
+#define AC_8i_1 QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define AC_8i_2 QOS_1_2(10000, 10, 40, 0x02, 2)
+/* One bidirectional CIS and one unidirectional CIS. Two Unicast Servers.
+ * Unicast Server 1 is Audio Sink and Audio Source. Unicast Server 2 is
+ * Audio Sink.
+ * #1 - CIG 1 CIS auto (input/output)
+ * #2 - CIG 1 CIS auto (output)
+ */
+#define AC_8ii_1 QOS_1(10000, 10, 40, 0x02, 2)
+#define AC_8ii_2 QOS_OUT_1(10000, 10, 40, 0x02, 2)
+/* Two unidirectional CISes. Unicast Server is Audio Source.
+ * #1 - CIG 1 CIS 1 (input)
+ * #2 - CIG 1 CIS 2 (input)
+ */
+#define AC_9i_1 QOS_IN_1_1(10000, 10, 40, 0x02, 2)
+#define AC_9i_2 QOS_IN_1_2(10000, 10, 40, 0x02, 2)
+/* Two unidirectional CISes. Two Unicast Servers. Unicast Server 1 is Audio
+ * Source. Unicast Server 2 is Audio Source.
+ * #1 - CIG 1 CIS auto (input)
+ * #2 - CIG 1 CIS auto (input)
+ */
+#define AC_9ii_1 QOS_IN_1(10000, 10, 40, 0x02, 2)
+#define AC_9ii_2 QOS_IN_1(10000, 10, 40, 0x02, 2)
+/* Two bidirectional CISes. Unicast Server is Audio Sink and Audio Source.
+ * #1 - CIG 1 CIS 1 (input/output)
+ * #2 - CIG 1 CIS 2 (input/output)
+ */
+#define AC_11i_1 QOS_1_1(10000, 10, 40, 0x02, 2)
+#define AC_11i_2 QOS_1_2(10000, 10, 40, 0x02, 2)
+/* Two bidirectional CISes. Two Unicast Servers. Unicast Server 1 is Audio Sink
+ * and Audio Source. Unicast Server 2 is Audio Sink and Audio Source.
+ * #1 - CIG 1 CIS auto (input/output)
+ * #2 - CIG 1 CIS auto (input/output)
+ */
+#define AC_11ii_1 QOS_1(10000, 10, 40, 0x02, 2)
+#define AC_11ii_2 QOS_1(10000, 10, 40, 0x02, 2)
+
+#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
+				0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
+
+#define QOS_BCAST_FULL(_big, _bis, _encryption, _bcode, _in, _out) \
+{ \
+	.bcast = { \
+		.big = _big, \
+		.bis = _bis, \
+		.sync_factor = 0x07, \
+		.packing = 0x00, \
+		.framing = 0x00, \
+		.in = _in, \
+		.out = _out, \
+		.encryption = _encryption, \
+		.bcode = _bcode, \
+		.options = 0x00, \
+		.skip = 0x0000, \
+		.sync_timeout = BT_ISO_SYNC_TIMEOUT, \
+		.sync_cte_type = 0x00, \
+		.mse = 0x00, \
+		.timeout = BT_ISO_SYNC_TIMEOUT, \
+	}, \
+}
+
+#define BCAST_QOS_OUT(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x00, {0x00}, {}, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_OUT_ENC(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x01, BCODE, {}, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_OUT_1(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(0x01, BT_ISO_QOS_BIS_UNSET, \
+		0x00, {0x00}, {}, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_OUT_1_1(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(0x01, 0x01, \
+		0x00, {0x00}, {}, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_IN(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x00, {0x00}, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+
+#define BCAST_QOS_IN_ENC(_interval, _latency, _sdu, _phy, _rtn) \
+	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x01, BCODE, \
+		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
+
+#define QOS_OUT_16_2_1 BCAST_QOS_OUT(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_ENC_16_2_1 BCAST_QOS_OUT_ENC(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_1_16_2_1 BCAST_QOS_OUT_1(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_1_1_16_2_1 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define QOS_IN_16_2_1 BCAST_QOS_IN(10000, 10, 40, 0x02, 2)
+#define QOS_IN_ENC_16_2_1 BCAST_QOS_IN_ENC(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_48_1_g BCAST_QOS_OUT(7500, 8, 75, 0x02, 1)
+#define QOS_OUT_48_2_g BCAST_QOS_OUT(10000, 10, 100, 0x02, 1)
+#define QOS_OUT_48_3_g BCAST_QOS_OUT(7500, 8, 90, 0x02, 1)
+#define QOS_OUT_48_4_g BCAST_QOS_OUT(10000, 10, 120, 0x02, 1)
+
+#define BASE(_pd, _sgrp, _nbis, _cfg...) \
+{ \
+	_pd & 0xff, _pd >> 8, _pd >> 16, \
+	_sgrp, \
+	_nbis, \
+	_cfg \
+}
+
+#define LC3_BASE(_pd, _sgrp, _nbis, _cc...) \
+	BASE(_pd, _sgrp, _nbis, 0x06, 0x00, 0x00, 0x00, 0x00, _cc)
+
+/* 16 KHZ - 10 ms - Front Left - Frame Length 40 bytes */
+#define LC3_CONFIG_16_2_1 \
+	0x10, \
+	0x02, 0x01, 0x03, \
+	0x02, 0x02, 0x01, \
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00, \
+	0x03, 0x04, 0x28, 0x00
+
+/* Audio Context: Convertional */
+#define CTXT_CONVERSIONAL \
+	0x04, \
+	0x03, 0x02, 0x02, 0x00
+
+static const uint8_t base_lc3_16_2_1[] =
+	LC3_BASE(40000, 1, 1, LC3_CONFIG_16_2_1, CTXT_CONVERSIONAL,
+		0x01, /* BIS */
+		0x00  /* Codec Specific Configuration */);
+
+#define LC3_CONFIG_G(_freq, _dur, _len) \
+	0x0a, \
+	0x02, 0x01, _freq, \
+	0x02, 0x02, _dur, \
+	0x03, 0x04, _len, _len >> 8
+
+#define LC3_CONFIG_FRONT_LEFT \
+	0x06, \
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00
+
+/* 48 KHZ - 7.5 ms - Frame Length 75 bytes */
+#define LC3_CONFIG_48_1_G \
+	LC3_CONFIG_G(0x08, 0x00, 75)
+
+static const uint8_t base_lc3_48_1_g[] =
+	LC3_BASE(10000, 1, 1, LC3_CONFIG_48_1_G, CTXT_CONVERSIONAL,
+			0x01, LC3_CONFIG_FRONT_LEFT);
+
+/* 48 KHZ - 10 ms Frame Length 100 bytes */
+#define LC3_CONFIG_48_2_G \
+	LC3_CONFIG_G(0x08, 0x01, 100)
+
+static const uint8_t base_lc3_48_2_g[] =
+	LC3_BASE(10000, 1, 1, LC3_CONFIG_48_2_G, CTXT_CONVERSIONAL,
+			0x01, LC3_CONFIG_FRONT_LEFT);
+
+/* 48 KHZ - 7.5 ms Frame Length 90 bytes */
+#define LC3_CONFIG_48_3_G \
+	LC3_CONFIG_G(0x08, 0x00, 90)
+
+static const uint8_t base_lc3_48_3_g[] =
+	LC3_BASE(10000, 1, 1, LC3_CONFIG_48_3_G, CTXT_CONVERSIONAL,
+			0x01, LC3_CONFIG_FRONT_LEFT);
+
+/* 48 KHZ - 7.5 ms Frame Length 90 bytes */
+#define LC3_CONFIG_48_4_G \
+	LC3_CONFIG_G(0x08, 0x00, 120)
+
+static const uint8_t base_lc3_48_4_g[] =
+	LC3_BASE(10000, 1, 1, LC3_CONFIG_48_3_G, CTXT_CONVERSIONAL,
+			0x01, LC3_CONFIG_FRONT_LEFT);
+
+/* Single Audio Channel. One BIS. */
+#define BCAST_AC_12 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+
+static const uint8_t base_lc3_ac_12[] = {
+	0x28, 0x00, 0x00, /* Presentation Delay */
+	0x01, /* Number of Subgroups */
+	0x01, /* Number of BIS */
+	0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
+	0x10, /* Codec Specific Configuration */
+	0x02, 0x01, 0x03, /* 16 KHZ */
+	0x02, 0x02, 0x01, /* 10 ms */
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
+	0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
+	0x04, /* Metadata */
+	0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
+	0x01, /* BIS */
+	0x00, /* Codec Specific Configuration */
+};
+
+/* Multiple Audio Channels. Two BISes. */
+#define BCAST_AC_13_1_1 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define BCAST_AC_13_1 BCAST_QOS_OUT_1(10000, 10, 40, 0x02, 2)
+
+static const uint8_t base_lc3_ac_13[] = {
+	0x28, 0x00, 0x00, /* Presentation Delay */
+	0x01, /* Number of Subgroups */
+	0x02, /* Number of BIS */
+	0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
+	0x10, /* Codec Specific Configuration */
+	0x02, 0x01, 0x03, /* 16 KHZ */
+	0x02, 0x02, 0x01, /* 10 ms */
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
+	0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
+	0x04, /* Metadata */
+	0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
+	0x01, /* BIS 1 */
+	0x06, /* Codec Specific Configuration */
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* Audio_Channel_Allocation:
+					     * Front left
+					     */
+	0x01, /* BIS 2 */
+	0x06, /* Codec Specific Configuration */
+	0x05, 0x03, 0x02, 0x00, 0x00, 0x00, /* Audio_Channel_Allocation:
+					     * Front right
+					     */
+};
+
+/* Multiple Audio Channels. One BIS. */
+#define BCAST_AC_14 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+
+static const uint8_t base_lc3_ac_14[] = {
+	0x28, 0x00, 0x00, /* Presentation Delay */
+	0x01, /* Number of Subgroups */
+	0x01, /* Number of BIS */
+	0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
+	0x10, /* Codec Specific Configuration */
+	0x02, 0x01, 0x03, /* 16 KHZ */
+	0x02, 0x02, 0x01, /* 10 ms */
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
+	0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
+	0x04, /* Metadata */
+	0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
+	0x01, /* BIS */
+	0x06, /* Codec Specific Configuration */
+	0x05, 0x03, 0x03, 0x00, 0x00, 0x00, /* Audio_Channel_Allocation:
+					     * Front left, Front right
+					     */
+};
 
 struct test_data {
 	const void *test_data;
@@ -130,17 +466,21 @@ struct test_data {
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
+	uint8_t accept_reason;
 	uint16_t handle;
 	uint16_t acl_handle;
-	GIOChannel *io;
-	unsigned int io_id[2];
+	struct queue *io_queue;
+	unsigned int io_id[4];
 	uint8_t client_num;
 	int step;
 	bool reconnect;
+	bool suspending;
+	struct tx_tstamp_data tx_ts;
 };
 
 struct iso_client_data {
 	struct bt_iso_qos qos;
+	struct bt_iso_qos qos_2;
 	int expect_err;
 	const struct iovec *send;
 	const struct iovec *recv;
@@ -148,8 +488,38 @@ struct iso_client_data {
 	bool bcast;
 	bool defer;
 	bool disconnect;
+	bool ts;
+	bool mconn;
+	bool suspend;
+	uint8_t pkt_status;
+	const uint8_t *base;
+	size_t base_len;
+	bool listen_bind;
+	bool pa_bind;
+	bool big;
+
+	/* Enable SO_TIMESTAMPING with these flags */
+	uint32_t so_timestamping;
+
+	/* Enable SO_TIMESTAMPING using CMSG instead of setsockopt() */
+	bool cmsg_timestamping;
+
+	/* Number of additional packets to send, before SO_TIMESTAMPING.
+	 * Used to test kernel timestamp TX queue logic.
+	 */
+	unsigned int repeat_send_pre_ts;
+
+	/* Number of additional packets to send, after SO_TIMESTAMPING.
+	 * Used for testing TX timestamping OPT_ID.
+	 */
+	unsigned int repeat_send;
+
+	/* Disable BT_POLL_ERRQUEUE before enabling TX timestamping */
+	bool no_poll_errqueue;
 };
 
+typedef bool (*iso_defer_accept_t)(struct test_data *data, GIOChannel *io);
+
 static void mgmt_debug(const char *str, void *user_data)
 {
 	const char *prefix = user_data;
@@ -281,6 +651,18 @@ static const uint8_t reset_iso_socket_param[] = {
 	0x00,						/* Action - disable */
 };
 
+static const uint8_t set_poll_errqueue_param[] = {
+	0x33, 0x57, 0x7b, 0xb4, 0x21, 0xc0, 0xc1, 0x8b, /* UUID */
+	0x79, 0x46, 0x9f, 0xb6, 0x4c, 0x8c, 0x51, 0x69,
+	0x01,						/* Action - enable */
+};
+
+static const uint8_t reset_poll_errqueue_param[] = {
+	0x33, 0x57, 0x7b, 0xb4, 0x21, 0xc0, 0xc1, 0x8b, /* UUID */
+	0x79, 0x46, 0x9f, 0xb6, 0x4c, 0x8c, 0x51, 0x69,
+	0x00,						/* Action - disable */
+};
+
 static void set_iso_socket_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -292,9 +674,26 @@ static void set_iso_socket_callback(uint8_t status, uint16_t length,
 	tester_print("ISO socket feature is enabled");
 }
 
+static void set_poll_errqueue_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	if (status != MGMT_STATUS_SUCCESS) {
+		tester_print("Poll Errqueue feature could not be enabled");
+		return;
+	}
+
+	tester_print("Poll Errqueue feature is enabled");
+}
+
 static void test_pre_setup(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct iso_client_data *isodata = test_data;
+
+	if (isodata && isodata->so_timestamping) {
+		if (tester_pre_setup_skip_by_default())
+			return;
+	}
 
 	data->mgmt = mgmt_new_default();
 	if (!data->mgmt) {
@@ -310,6 +709,13 @@ static void test_pre_setup(const void *test_data)
 		  sizeof(set_iso_socket_param), set_iso_socket_param,
 		  set_iso_socket_callback, NULL, NULL);
 
+	if (isodata && isodata->no_poll_errqueue) {
+		mgmt_send(data->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE,
+			  sizeof(set_poll_errqueue_param),
+			  set_poll_errqueue_param,
+			  set_poll_errqueue_callback, NULL, NULL);
+	}
+
 	mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
 					read_index_list_callback, NULL, NULL);
 }
@@ -317,32 +723,46 @@ static void test_pre_setup(const void *test_data)
 static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct iso_client_data *isodata = test_data;
 
 	mgmt_send(data->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE,
 		  sizeof(reset_iso_socket_param), reset_iso_socket_param,
 		  NULL, NULL, NULL);
 
+	if (isodata && isodata->no_poll_errqueue) {
+		mgmt_send(data->mgmt, MGMT_OP_SET_EXP_FEATURE, MGMT_INDEX_NONE,
+			  sizeof(reset_poll_errqueue_param),
+			  reset_poll_errqueue_param,
+			  NULL, NULL, NULL);
+	}
+
 	hciemu_unref(data->hciemu);
 	data->hciemu = NULL;
 }
 
+static void io_free(void *data)
+{
+	GIOChannel *io = data;
+
+	g_io_channel_unref(io);
+}
+
 static void test_data_free(void *test_data)
 {
 	struct test_data *data = test_data;
+	unsigned int i;
 
-	if (data->io)
-		g_io_channel_unref(data->io);
+	if (data->io_queue)
+		queue_destroy(data->io_queue, io_free);
 
-	if (data->io_id[0] > 0)
-		g_source_remove(data->io_id[0]);
-
-	if (data->io_id[1] > 0)
-		g_source_remove(data->io_id[1]);
+	for (i = 0; i < ARRAY_SIZE(data->io_id); ++i)
+		if (data->io_id[i] > 0)
+			g_source_remove(data->io_id[i]);
 
 	free(data);
 }
 
-#define test_iso_full(name, data, setup, func, num) \
+#define test_iso_full(name, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
@@ -351,16 +771,20 @@ static void test_data_free(void *test_data)
 		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
 		user->test_data = data; \
 		user->client_num = num; \
+		user->accept_reason = reason; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
 				test_post_teardown, 2, user, test_data_free); \
 	} while (0)
 
 #define test_iso(name, data, setup, func) \
-	test_iso_full(name, data, setup, func, 1)
+	test_iso_full(name, data, setup, func, 1, 0x00)
 
 #define test_iso2(name, data, setup, func) \
-	test_iso_full(name, data, setup, func, 2)
+	test_iso_full(name, data, setup, func, 2, 0x00)
+
+#define test_iso_rej(name, data, setup, func, reason) \
+	test_iso_full(name, data, setup, func, 1, reason)
 
 static const struct iso_client_data connect_8_1_1 = {
 	.qos = QOS_8_1_1,
@@ -532,11 +956,91 @@ static const struct iso_client_data connect_48_6_2 = {
 	.expect_err = 0
 };
 
+static const struct iso_client_data connect_16_1_gs = {
+	.qos = QOS_16_1_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_16_2_gs = {
+	.qos = QOS_16_2_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_32_1_gs = {
+	.qos = QOS_32_1_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_32_2_gs = {
+	.qos = QOS_32_2_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_1_gs = {
+	.qos = QOS_48_1_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_2_gs = {
+	.qos = QOS_48_2_gs,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_32_1_gr = {
+	.qos = QOS_32_1_gr,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_32_2_gr = {
+	.qos = QOS_32_2_gr,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_1_gr = {
+	.qos = QOS_48_1_gr,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_2_gr = {
+	.qos = QOS_48_2_gr,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_3_gr = {
+	.qos = QOS_48_3_gr,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_48_4_gr = {
+	.qos = QOS_48_4_gr,
+	.expect_err = 0
+};
+
 static const struct iso_client_data connect_invalid = {
 	.qos = QOS(0, 0, 0, 0, 0),
 	.expect_err = -EINVAL
 };
 
+static const struct iso_client_data connect_reject = {
+	.qos = QOS_16_1_2,
+	.expect_err = -ENOSYS
+};
+
+static const struct iso_client_data connect_suspend = {
+	.qos = QOS_16_2_1,
+	.expect_err = -ECONNRESET
+};
+
+static const struct iso_client_data connect_cig_f0_invalid = {
+	.qos = QOS_FULL(0xF0, 0x00, {}, QOS_IO(10000, 10, 40, 0x02, 2)),
+	.expect_err = -EINVAL
+};
+
+static const struct iso_client_data connect_cis_f0_invalid = {
+	.qos = QOS_FULL(0x00, 0xF0, {}, QOS_IO(10000, 10, 40, 0x02, 2)),
+	.expect_err = -EINVAL
+};
+
 static const uint8_t data_16_2_1[40] = { [0 ... 39] = 0xff };
 static const struct iovec send_16_2_1 = {
 	.iov_base = (void *)data_16_2_1,
@@ -555,6 +1059,48 @@ static const struct iso_client_data connect_16_2_1_send = {
 	.send = &send_16_2_1,
 };
 
+static const struct iso_client_data connect_send_tx_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_OPT_ID |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+	.repeat_send = 1,
+	.repeat_send_pre_ts = 2,
+};
+
+static const struct iso_client_data connect_send_tx_sched_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_TX_SOFTWARE |
+					SOF_TIMESTAMPING_OPT_TSONLY |
+					SOF_TIMESTAMPING_TX_SCHED),
+	.repeat_send = 1,
+};
+
+static const struct iso_client_data connect_send_tx_cmsg_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+	.repeat_send = 1,
+	.cmsg_timestamping = true,
+};
+
+static const struct iso_client_data connect_send_tx_no_poll_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+	.repeat_send = 1,
+	.no_poll_errqueue = true,
+};
+
 static const struct iso_client_data listen_16_2_1_recv = {
 	.qos = QOS_16_2_1,
 	.expect_err = 0,
@@ -562,12 +1108,34 @@ static const struct iso_client_data listen_16_2_1_recv = {
 	.server = true,
 };
 
+static const struct iso_client_data listen_16_2_1_recv_ts = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.ts = true,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_pkt_status = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.pkt_status = 0x02,
+};
+
 static const struct iso_client_data defer_16_2_1 = {
 	.qos = QOS_16_2_1,
 	.expect_err = 0,
 	.defer = true,
 };
 
+static const struct iso_client_data defer_1_16_2_1 = {
+	.qos = QOS_1_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+};
+
 static const struct iso_client_data connect_16_2_1_defer_send = {
 	.qos = QOS_16_2_1,
 	.expect_err = 0,
@@ -619,51 +1187,341 @@ static const struct iso_client_data disconnect_16_2_1 = {
 	.disconnect = true,
 };
 
+static const struct iso_client_data suspend_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.suspend = true,
+};
+
 static const struct iso_client_data reconnect_16_2_1 = {
 	.qos = QOS_16_2_1,
 	.expect_err = 0,
 	.disconnect = true,
 };
 
-static const struct iso_client_data bcast_16_2_1_send = {
-	.qos = QOS_OUT_16_2_1,
+static const struct iso_client_data connect_ac_1_4 = {
+	.qos = AC_1_4,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_2_10 = {
+	.qos = AC_2_10,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_3_5 = {
+	.qos = AC_3_5,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_6i = {
+	.qos = AC_6i_1,
+	.qos_2 = AC_6i_2,
 	.expect_err = 0,
-	.send = &send_16_2_1,
-	.bcast = true,
+	.mconn = true,
+	.defer = true,
 };
 
-static const struct iso_client_data bcast_1_16_2_1_send = {
-	.qos = QOS_OUT_1_16_2_1,
+static const struct iso_client_data reconnect_ac_6i = {
+	.qos = AC_6i_1,
+	.qos_2 = AC_6i_2,
 	.expect_err = 0,
-	.send = &send_16_2_1,
-	.bcast = true,
+	.mconn = true,
+	.defer = true,
+	.disconnect = true,
 };
 
-static const struct iso_client_data bcast_1_1_16_2_1_send = {
-	.qos = QOS_OUT_1_1_16_2_1,
+static const struct iso_client_data connect_ac_6ii = {
+	.qos = AC_6ii_1,
+	.qos_2 = AC_6ii_2,
 	.expect_err = 0,
-	.send = &send_16_2_1,
-	.bcast = true,
+	.mconn = true,
+	.defer = true,
 };
 
-static const struct iso_client_data bcast_16_2_1_recv = {
-	.qos = QOS_IN_16_2_1,
+static const struct iso_client_data reconnect_ac_6ii = {
+	.qos = AC_6ii_1,
+	.qos_2 = AC_6ii_2,
 	.expect_err = 0,
-	.recv = &send_16_2_1,
-	.bcast = true,
+	.mconn = true,
+	.defer = true,
+	.disconnect = true,
 };
 
-static void client_connectable_complete(uint16_t opcode, uint8_t status,
-					const void *param, uint8_t len,
-					void *user_data)
-{
-	struct test_data *data = user_data;
-	static uint8_t client_num;
+static const struct iso_client_data connect_ac_6ii_cis_ef_auto = {
+	.qos = AC_6ii_1_EF,
+	.qos_2 = AC_6ii_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
 
-	if (opcode != BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE)
-		return;
+static const struct iso_client_data connect_ac_6ii_cis_ef_ef = {
+	.qos = AC_6ii_1_EF,
+	.qos_2 = AC_6ii_1_EF,
+	.expect_err = -EINVAL,
+	.mconn = true,
+	.defer = true,
+};
 
-	tester_print("Client %u set connectable status 0x%02x", client_num,
+static const struct iso_client_data connect_ac_7i = {
+	.qos = AC_7i_1,
+	.qos_2 = AC_7i_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_7ii = {
+	.qos = AC_7ii_1,
+	.qos_2 = AC_7ii_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_8i = {
+	.qos = AC_8i_1,
+	.qos_2 = AC_8i_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_8ii = {
+	.qos = AC_8ii_1,
+	.qos_2 = AC_8ii_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_9i = {
+	.qos = AC_9i_1,
+	.qos_2 = AC_9i_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_9ii = {
+	.qos = AC_9ii_1,
+	.qos_2 = AC_9ii_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_11i = {
+	.qos = AC_11i_1,
+	.qos_2 = AC_11i_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_11ii = {
+	.qos = AC_11ii_1,
+	.qos_2 = AC_11ii_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_ac_1_2 = {
+	.qos = AC_1_4,
+	.qos_2 = AC_2_10,
+	.expect_err = 0,
+	.mconn = true,
+};
+
+static const struct iso_client_data connect_ac_1_2_cig_1_2 = {
+	.qos = AC_1_4_1,
+	.qos_2 = AC_2_10_2,
+	.expect_err = 0,
+	.mconn = true,
+};
+
+static const struct iso_client_data bcast_48_1_g = {
+	.qos = QOS_OUT_48_1_g,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_48_1_g,
+	.base_len = sizeof(base_lc3_48_1_g),
+};
+
+static const struct iso_client_data bcast_48_2_g = {
+	.qos = QOS_OUT_48_2_g,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_48_2_g,
+	.base_len = sizeof(base_lc3_48_2_g),
+};
+
+static const struct iso_client_data bcast_48_3_g = {
+	.qos = QOS_OUT_48_3_g,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_48_3_g,
+	.base_len = sizeof(base_lc3_48_3_g),
+};
+
+static const struct iso_client_data bcast_48_4_g = {
+	.qos = QOS_OUT_48_4_g,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_48_4_g,
+	.base_len = sizeof(base_lc3_48_4_g),
+};
+
+static const struct iso_client_data bcast_16_2_1_send = {
+	.qos = QOS_OUT_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_enc_16_2_1_send = {
+	.qos = QOS_OUT_ENC_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_1_16_2_1_send = {
+	.qos = QOS_OUT_1_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_1_1_16_2_1_send = {
+	.qos = QOS_OUT_1_1_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_16_2_1_recv = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_enc_16_2_1_recv = {
+	.qos = QOS_IN_ENC_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_16_2_1_recv_defer = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.listen_bind = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_16_2_1_recv_defer_no_bis = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_16_2_1_recv_defer_pa_bind = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+	.bcast = true,
+	.server = true,
+	.pa_bind = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_16_2_1_recv_defer_get_base = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+	.bcast = true,
+	.server = true,
+	.base = base_lc3_ac_12,
+	.base_len = sizeof(base_lc3_ac_12),
+};
+
+static const struct iso_client_data bcast_ac_12 = {
+	.qos = BCAST_AC_12,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_ac_12,
+	.base_len = sizeof(base_lc3_ac_12),
+};
+
+static const struct iso_client_data bcast_ac_13_1_1 = {
+	.qos = BCAST_AC_13_1_1,
+	.expect_err = 0,
+	.bcast = true,
+	.mconn = true,
+	.base = base_lc3_ac_13,
+	.base_len = sizeof(base_lc3_ac_13),
+};
+
+static const struct iso_client_data bcast_ac_13_1_1_reconn = {
+	.qos = BCAST_AC_13_1_1,
+	.expect_err = 0,
+	.bcast = true,
+	.mconn = true,
+	.base = base_lc3_ac_13,
+	.base_len = sizeof(base_lc3_ac_13),
+	.disconnect = true,
+};
+
+static const struct iso_client_data bcast_ac_13_1 = {
+	.qos = BCAST_AC_13_1,
+	.expect_err = 0,
+	.bcast = true,
+	.mconn = true,
+	.base = base_lc3_ac_13,
+	.base_len = sizeof(base_lc3_ac_13),
+};
+
+static const struct iso_client_data bcast_ac_14 = {
+	.qos = BCAST_AC_14,
+	.expect_err = 0,
+	.bcast = true,
+	.base = base_lc3_ac_14,
+	.base_len = sizeof(base_lc3_ac_14),
+};
+
+static void client_connectable_complete(uint16_t opcode, uint8_t status,
+					const void *param, uint8_t len,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	static uint8_t client_num;
+
+	if (opcode != BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE)
+		return;
+
+	tester_print("Client %u set connectable status 0x%02x", client_num,
 								status);
 
 	client_num++;
@@ -681,14 +1539,17 @@ static void bthost_recv_data(const void *buf, uint16_t len, void *user_data)
 	struct test_data *data = user_data;
 	const struct iso_client_data *isodata = data->test_data;
 
+	--data->step;
+
 	tester_print("Client received %u bytes of data", len);
 
 	if (isodata->send && (isodata->send->iov_len != len ||
 			memcmp(isodata->send->iov_base, buf, len))) {
 		if (!isodata->recv->iov_base)
 			tester_test_failed();
-	} else
+	} else if (!data->step) {
 		tester_test_passed();
+	}
 }
 
 static void bthost_iso_disconnected(void *user_data)
@@ -714,6 +1575,16 @@ static void iso_new_conn(uint16_t handle, void *user_data)
 				bthost_iso_disconnected);
 }
 
+static uint8_t iso_accept_conn(uint16_t handle, void *user_data)
+{
+	struct test_data *data = user_data;
+
+	tester_print("Accept client connection with handle 0x%04x: 0x%02x",
+		     handle, data->accept_reason);
+
+	return data->accept_reason;
+}
+
 static void acl_new_conn(uint16_t handle, void *user_data)
 {
 	struct test_data *data = user_data;
@@ -751,13 +1622,24 @@ static void setup_powered_callback(uint8_t status, uint16_t length,
 		if (!isodata)
 			continue;
 
-		if (isodata->send || isodata->recv || isodata->disconnect)
-			bthost_set_iso_cb(host, iso_new_conn, data);
+		if (isodata->send || isodata->recv || isodata->disconnect ||
+				isodata->suspend || data->accept_reason)
+			bthost_set_iso_cb(host, iso_accept_conn, iso_new_conn,
+									data);
 
 		if (isodata->bcast) {
 			bthost_set_pa_params(host);
 			bthost_set_pa_enable(host, 0x01);
-			bthost_create_big(host, 1);
+
+			if (isodata->base)
+				bthost_set_base(host, isodata->base,
+							isodata->base_len);
+
+			if (isodata->big)
+				bthost_create_big(host, 1,
+						isodata->qos.bcast.encryption,
+						isodata->qos.bcast.bcode);
+
 		} else if (!isodata->send && isodata->recv) {
 			const uint8_t *bdaddr;
 
@@ -855,6 +1737,7 @@ static void test_setsockopt(const void *test_data)
 	int sk, err;
 	socklen_t len;
 	struct bt_iso_qos qos = QOS_16_1_2;
+	int pkt_status = 1;
 
 	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
 	if (sk < 0) {
@@ -883,6 +1766,26 @@ static void test_setsockopt(const void *test_data)
 		goto end;
 	}
 
+	err = setsockopt(sk, SOL_BLUETOOTH, BT_PKT_STATUS, &pkt_status,
+			 sizeof(pkt_status));
+	if (err < 0) {
+		tester_warn("Can't set socket BT_PKT_STATUS option: "
+				"%s (%d)", strerror(errno), errno);
+		tester_test_failed();
+		goto end;
+	}
+
+	len = sizeof(pkt_status);
+	memset(&pkt_status, 0, len);
+
+	err = getsockopt(sk, SOL_BLUETOOTH, BT_PKT_STATUS, &pkt_status, &len);
+	if (err < 0) {
+		tester_warn("Can't get socket option : %s (%d)",
+							strerror(errno), errno);
+		tester_test_failed();
+		goto end;
+	}
+
 	tester_test_passed();
 
 end:
@@ -906,6 +1809,7 @@ static int create_iso_sock(struct test_data *data)
 	master_bdaddr = hciemu_get_central_bdaddr(data->hciemu);
 	if (!master_bdaddr) {
 		tester_warn("No master bdaddr");
+		close(sk);
 		return -ENODEV;
 	}
 
@@ -925,46 +1829,42 @@ static int create_iso_sock(struct test_data *data)
 	return sk;
 }
 
-static const uint8_t base_lc3_16_2_1[] = {
-	0x28, 0x00, 0x00, /* Presentation Delay */
-	0x01, /* Number of Subgroups */
-	0x01, /* Number of BIS */
-	0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
-	0x11, /* Codec Specific Configuration */
-	0x02, 0x01, 0x03, /* 16 KHZ */
-	0x02, 0x02, 0x01, /* 10 ms */
-	0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
-	0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
-	0x04, /* Metadata */
-	0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
-	0x01, /* BIS */
-	0x00, /* Codec Specific Configuration */
-};
-
 static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 {
 	const struct iso_client_data *isodata = data->test_data;
 	struct hciemu_client *client;
 	const uint8_t *client_bdaddr = NULL;
+	const struct bt_iso_qos *qos = &isodata->qos;
 	struct sockaddr_iso addr;
 	char str[18];
 	int err;
 
 	client = hciemu_get_client(data->hciemu, num);
 	if (!client) {
-		tester_warn("No client");
-		return -ENODEV;
+		if (!isodata->mconn) {
+			tester_warn("No client");
+			return -ENODEV;
+		}
+
+		client = hciemu_get_client(data->hciemu, 0);
+		if (!client) {
+			tester_warn("No client");
+			return -ENODEV;
+		}
 	}
 
+	if (!isodata->bcast && num && isodata->mconn)
+		qos = &isodata->qos_2;
+
 	if (!isodata->bcast) {
 		client_bdaddr = hciemu_client_bdaddr(client);
 		if (!client_bdaddr) {
 			tester_warn("No client bdaddr");
 			return -ENODEV;
 		}
-	} else {
+	} else if (!isodata->server) {
 		err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_BASE,
-				base_lc3_16_2_1, sizeof(base_lc3_16_2_1));
+				isodata->base, isodata->base_len);
 		if (err < 0) {
 			tester_warn("Can't set socket BT_ISO_BASE option: "
 					"%s (%d)", strerror(errno), errno);
@@ -973,8 +1873,7 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 		}
 	}
 
-	err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &isodata->qos,
-						sizeof(isodata->qos));
+	err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, qos, sizeof(*qos));
 	if (err < 0) {
 		tester_warn("Can't set socket BT_ISO_QOS option : %s (%d)",
 							strerror(errno), errno);
@@ -982,7 +1881,7 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 		return -EINVAL;
 	}
 
-	if (isodata->defer) {
+	if (isodata->defer || (isodata->bcast && isodata->mconn && !num)) {
 		int opt = 1;
 
 		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
@@ -1018,14 +1917,14 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 static bool check_io_qos(const struct bt_iso_io_qos *io1,
 				const struct bt_iso_io_qos *io2)
 {
-	if (io1->interval && io2->interval && io1->interval != io2->interval) {
-		tester_warn("Unexpected IO interval: %u != %u",
+	if (io1->interval && io2->interval && io1->interval > io2->interval) {
+		tester_warn("Unexpected IO interval: %u > %u",
 				io1->interval, io2->interval);
 		return false;
 	}
 
-	if (io1->latency && io2->latency && io1->latency != io2->latency) {
-		tester_warn("Unexpected IO latency: %u != %u",
+	if (io1->latency && io2->latency && io1->latency > io2->latency) {
+		tester_warn("Unexpected IO latency: %u > %u",
 				io1->latency, io2->latency);
 		return false;
 	}
@@ -1049,43 +1948,62 @@ static bool check_io_qos(const struct bt_iso_io_qos *io1,
 	return true;
 }
 
-static bool check_qos(const struct bt_iso_qos *qos1,
-				const struct bt_iso_qos *qos2)
+static bool check_ucast_qos(const struct bt_iso_qos *qos1,
+				const struct bt_iso_qos *qos2,
+				const struct bt_iso_qos *qos2_2)
 {
-	if (qos1->cig != BT_ISO_QOS_CIG_UNSET &&
-			qos2->cig != BT_ISO_QOS_CIG_UNSET &&
-			qos1->cig != qos2->cig) {
+	if (qos1->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+			qos2->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+			qos1->ucast.cig != qos2->ucast.cig) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected CIG ID: 0x%02x != 0x%02x",
-				qos1->cig, qos2->cig);
+				qos1->ucast.cig, qos2->ucast.cig);
 		return false;
 	}
 
-	if (qos1->cis != BT_ISO_QOS_CIS_UNSET &&
-			qos2->cis != BT_ISO_QOS_CIS_UNSET &&
-			qos1->cis != qos2->cis) {
+	if (qos1->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+			qos2->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+			qos1->ucast.cis != qos2->ucast.cis) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected CIS ID: 0x%02x != 0x%02x",
-				qos1->cis, qos2->cis);
+				qos1->ucast.cis, qos2->ucast.cis);
 		return false;
 	}
 
-	if (qos1->packing != qos2->packing) {
+	if (qos1->ucast.packing != qos2->ucast.packing) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
-				qos1->packing, qos2->packing);
+				qos1->ucast.packing, qos2->ucast.packing);
 		return false;
 	}
 
-	if (qos1->framing != qos2->framing) {
+	if (qos1->ucast.framing != qos2->ucast.framing) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
-				qos1->framing, qos2->framing);
+				qos1->ucast.framing, qos2->ucast.framing);
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->in, &qos2->in)) {
+	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected Input QoS");
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->out, &qos2->out)) {
+	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
 		tester_warn("Unexpected Output QoS");
 		return false;
 	}
@@ -1093,63 +2011,343 @@ static bool check_qos(const struct bt_iso_qos *qos1,
 	return true;
 }
 
-static gboolean iso_recv_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool check_bcast_qos(const struct bt_iso_qos *qos1,
+				const struct bt_iso_qos *qos2)
 {
-	struct test_data *data = user_data;
-	const struct iso_client_data *isodata = data->test_data;
-	int sk = g_io_channel_unix_get_fd(io);
-	ssize_t ret;
-	char buf[1024];
+	if (qos1->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+			qos2->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+			qos1->bcast.big != qos2->bcast.big) {
+		tester_warn("Unexpected BIG ID: 0x%02x != 0x%02x",
+				qos1->bcast.big, qos2->bcast.big);
+		return false;
+	}
 
-	data->io_id[0] = 0;
+	if (qos1->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+			qos2->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+			qos1->bcast.bis != qos2->bcast.bis) {
+		tester_warn("Unexpected BIS ID: 0x%02x != 0x%02x",
+				qos1->bcast.bis, qos2->bcast.bis);
+		return false;
+	}
 
-	ret = read(sk, buf, isodata->recv->iov_len);
-	if (ret < 0 || isodata->recv->iov_len != (size_t) ret) {
-		tester_warn("Failed to read %zu bytes: %s (%d)",
-				isodata->recv->iov_len, strerror(errno), errno);
-		tester_test_failed();
-		return FALSE;
+	if (qos1->bcast.sync_factor != qos2->bcast.sync_factor) {
+		tester_warn("Unexpected QoS sync interval: 0x%02x != 0x%02x",
+			qos1->bcast.sync_factor, qos2->bcast.sync_factor);
+		return false;
 	}
 
-	if (memcmp(buf, isodata->recv->iov_base, ret))
-		tester_test_failed();
-	else
-		tester_test_passed();
+	if (qos1->bcast.packing != qos2->bcast.packing) {
+		tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
+				qos1->bcast.packing, qos2->bcast.packing);
+		return false;
+	}
 
-	return FALSE;
-}
+	if (qos1->bcast.framing != qos2->bcast.framing) {
+		tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
+				qos1->bcast.framing, qos2->bcast.framing);
+		return false;
+	}
 
-static void iso_recv(struct test_data *data, GIOChannel *io)
-{
-	const struct iso_client_data *isodata = data->test_data;
-	struct bthost *host;
+	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+		tester_warn("Unexpected Input QoS");
+		return false;
+	}
 
-	tester_print("Receive %zu bytes of data", isodata->recv->iov_len);
+	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+		tester_warn("Unexpected Output QoS");
+		return false;
+	}
 
-	if (!data->handle) {
+	if (qos1->bcast.encryption != qos2->bcast.encryption) {
+		tester_warn("Unexpected QoS encryption: 0x%02x != 0x%02x",
+				qos1->bcast.encryption, qos2->bcast.encryption);
+		return false;
+	}
+
+	if (memcmp(qos1->bcast.bcode, qos2->bcast.bcode,
+				sizeof(qos1->bcast.bcode))) {
+		tester_warn("Unexpected QoS Broadcast Code");
+		return false;
+	}
+
+	if (qos1->bcast.options != qos2->bcast.options) {
+		tester_warn("Unexpected QoS options: 0x%02x != 0x%02x",
+				qos1->bcast.options, qos2->bcast.options);
+		return false;
+	}
+
+	if (qos1->bcast.skip != qos2->bcast.skip) {
+		tester_warn("Unexpected QoS skip: 0x%04x != 0x%04x",
+				qos1->bcast.skip, qos2->bcast.skip);
+		return false;
+	}
+
+	if (qos1->bcast.sync_timeout != qos2->bcast.sync_timeout) {
+		tester_warn("Unexpected QoS sync timeout: 0x%04x != 0x%04x",
+			qos1->bcast.sync_timeout, qos2->bcast.sync_timeout);
+		return false;
+	}
+
+	if (qos1->bcast.sync_cte_type != qos2->bcast.sync_cte_type) {
+		tester_warn("Unexpected QoS sync cte type: 0x%02x != 0x%02x",
+			qos1->bcast.sync_cte_type, qos2->bcast.sync_cte_type);
+		return false;
+	}
+
+	if (qos1->bcast.mse != qos2->bcast.mse) {
+		tester_warn("Unexpected QoS MSE: 0x%02x != 0x%02x",
+				qos1->bcast.mse, qos2->bcast.mse);
+		return false;
+	}
+
+	if (qos1->bcast.timeout != qos2->bcast.timeout) {
+		tester_warn("Unexpected QoS MSE: 0x%04x != 0x%04x",
+				qos1->bcast.timeout, qos2->bcast.timeout);
+		return false;
+	}
+
+	return true;
+}
+
+static gboolean iso_recv_data(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = user_data;
+	const struct iso_client_data *isodata = data->test_data;
+	int sk = g_io_channel_unix_get_fd(io);
+	unsigned char control[64];
+	ssize_t ret;
+	char buf[1024];
+	struct msghdr msg;
+	struct iovec iov;
+
+	data->io_id[0] = 0;
+
+	iov.iov_base = buf;
+	iov.iov_len = isodata->recv->iov_len;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = control;
+	msg.msg_controllen = sizeof(control);
+
+	ret = recvmsg(sk, &msg, MSG_DONTWAIT);
+	if (ret < 0 || isodata->recv->iov_len != (size_t) ret) {
+		tester_warn("Failed to read %zu bytes: %s (%d)",
+				isodata->recv->iov_len, strerror(errno), errno);
+		tester_test_failed();
+		return FALSE;
+	}
+
+	if (isodata->pkt_status) {
+		struct cmsghdr *cmsg;
+		uint8_t pkt_status = 0;
+
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level != SOL_BLUETOOTH)
+				continue;
+
+			if (cmsg->cmsg_type == BT_SCM_PKT_STATUS) {
+				memcpy(&pkt_status, CMSG_DATA(cmsg),
+						sizeof(pkt_status));
+				tester_debug("BT_SCM_PKT_STATUS = 0x%2.2x",
+							pkt_status);
+				break;
+			}
+		}
+
+		if (isodata->pkt_status != pkt_status) {
+			tester_warn("isodata->pkt_status 0x%2.2x != 0x%2.2x "
+					"pkt_status", isodata->pkt_status,
+					pkt_status);
+			tester_test_failed();
+		} else
+			tester_test_passed();
+
+		return FALSE;
+	}
+
+	if (memcmp(buf, isodata->recv->iov_base, ret))
+		tester_test_failed();
+	else
+		tester_test_passed();
+
+	return FALSE;
+}
+
+static void iso_recv(struct test_data *data, GIOChannel *io)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	struct bthost *host;
+	static uint16_t sn;
+
+	tester_print("Receive %zu bytes of data", isodata->recv->iov_len);
+
+	if (!data->handle) {
 		tester_warn("ISO handle not set");
 		tester_test_failed();
 		return;
 	}
 
 	host = hciemu_client_get_host(data->hciemu);
-	bthost_send_iso(host, data->handle, isodata->recv, 1);
+	bthost_send_iso(host, data->handle, isodata->ts, sn++, 0,
+				isodata->pkt_status, isodata->recv, 1);
 
 	data->io_id[0] = g_io_add_watch(io, G_IO_IN, iso_recv_data, data);
 }
 
-static void iso_send(struct test_data *data, GIOChannel *io)
+static gboolean iso_recv_errqueue(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
 {
+	struct test_data *data = user_data;
 	const struct iso_client_data *isodata = data->test_data;
-	ssize_t ret;
+	int sk = g_io_channel_unix_get_fd(io);
+	int err;
+
+	data->step--;
+
+	err = tx_tstamp_recv(&data->tx_ts, sk, isodata->send->iov_len);
+	if (err > 0)
+		return TRUE;
+	else if (!err && !data->step)
+		tester_test_passed();
+	else
+		tester_test_failed();
+
+	data->io_id[2] = 0;
+	return FALSE;
+}
+
+static gboolean iso_fail_errqueue(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = user_data;
+
+	tester_warn("Unexpected POLLERR");
+	tester_test_failed();
+
+	data->io_id[3] = 0;
+	return FALSE;
+}
+
+static gboolean iso_timer_errqueue(gpointer user_data)
+{
+	struct test_data *data = user_data;
+	GIOChannel *io;
+	gboolean ret;
+
+	io = queue_peek_head(data->io_queue);
+	g_assert(io);
+
+	ret = iso_recv_errqueue(io, G_IO_IN, data);
+	if (!ret) {
+		if (data->io_id[3])
+			g_source_remove(data->io_id[3]);
+		data->io_id[3] = 0;
+	}
+
+	return ret;
+}
+
+static void iso_tx_timestamping(struct test_data *data, GIOChannel *io)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	int so = isodata->so_timestamping;
 	int sk;
+	int err;
+	unsigned int count;
+
+	if (!(isodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+		return;
+
+	tester_print("Enabling TX timestamping");
+
+	tx_tstamp_init(&data->tx_ts, isodata->so_timestamping);
+
+	for (count = 0; count < isodata->repeat_send + 1; ++count)
+		data->step += tx_tstamp_expect(&data->tx_ts);
 
 	sk = g_io_channel_unix_get_fd(io);
 
+	if (isodata->no_poll_errqueue) {
+		uint32_t flag = 0;
+
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_POLL_ERRQUEUE,
+							&flag, sizeof(flag));
+		if (err < 0) {
+			tester_warn("setsockopt BT_POLL_ERRQUEUE: %s (%d)",
+						strerror(errno), errno);
+			tester_test_failed();
+			return;
+		}
+
+		if (!data->io_queue)
+			data->io_queue = queue_new();
+		queue_push_head(data->io_queue, g_io_channel_ref(io));
+
+		data->io_id[2] = g_timeout_add(100, iso_timer_errqueue, data);
+		data->io_id[3] = g_io_add_watch(io, G_IO_ERR, iso_fail_errqueue,
+									data);
+	} else {
+		uint32_t flag = 1;
+
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_POLL_ERRQUEUE,
+							&flag, sizeof(flag));
+		if (err >= 0) {
+			tester_warn("BT_POLL_ERRQUEUE available");
+			tester_test_failed();
+			return;
+		}
+
+		data->io_id[2] = g_io_add_watch(io, G_IO_ERR, iso_recv_errqueue,
+									data);
+	}
+
+	if (isodata->cmsg_timestamping)
+		so &= ~SOF_TIMESTAMPING_TX_RECORD_MASK;
+
+	err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so));
+	if (err < 0) {
+		tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)",
+						strerror(errno), errno);
+		tester_test_failed();
+		return;
+	}
+}
+
+static void iso_send_data(struct test_data *data, GIOChannel *io)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	char control[CMSG_SPACE(sizeof(uint32_t))];
+	struct msghdr msg = {
+		.msg_iov = (struct iovec *)isodata->send,
+		.msg_iovlen = 1,
+	};
+	struct cmsghdr *cmsg;
+	ssize_t ret;
+	int sk;
+
 	tester_print("Writing %zu bytes of data", isodata->send->iov_len);
 
-	ret = writev(sk, isodata->send, 1);
+	sk = g_io_channel_unix_get_fd(io);
+
+	if (isodata->cmsg_timestamping) {
+		memset(control, 0, sizeof(control));
+		msg.msg_control = control;
+		msg.msg_controllen = sizeof(control);
+
+		cmsg = CMSG_FIRSTHDR(&msg);
+		cmsg->cmsg_level = SOL_SOCKET;
+		cmsg->cmsg_type = SO_TIMESTAMPING;
+		cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
+
+		*((uint32_t *)CMSG_DATA(cmsg)) = (isodata->so_timestamping &
+					SOF_TIMESTAMPING_TX_RECORD_MASK);
+	}
+
+	ret = sendmsg(sk, &msg, 0);
 	if (ret < 0 || isodata->send->iov_len != (size_t) ret) {
 		tester_warn("Failed to write %zu bytes: %s (%d)",
 				isodata->send->iov_len, strerror(errno), errno);
@@ -1157,6 +2355,22 @@ static void iso_send(struct test_data *data, GIOChannel *io)
 		return;
 	}
 
+	data->step++;
+}
+
+static void iso_send(struct test_data *data, GIOChannel *io)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	unsigned int count;
+
+	for (count = 0; count < isodata->repeat_send_pre_ts; ++count)
+		iso_send_data(data, io);
+
+	iso_tx_timestamping(data, io);
+
+	for (count = 0; count < isodata->repeat_send + 1; ++count)
+		iso_send_data(data, io);
+
 	if (isodata->bcast) {
 		tester_test_passed();
 		return;
@@ -1166,23 +2380,29 @@ static void iso_send(struct test_data *data, GIOChannel *io)
 		iso_recv(data, io);
 }
 
-static void setup_connect(struct test_data *data, uint8_t num, GIOFunc func);
+static void test_connect(const void *test_data);
 static gboolean iso_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data);
+static gboolean iso_accept_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data);
 
 static gboolean iso_disconnected(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = user_data;
+	const struct iso_client_data *isodata = data->test_data;
 
 	data->io_id[0] = 0;
 
-	if ((cond & G_IO_HUP) && !data->handle) {
+	if (cond & G_IO_HUP) {
+		if (!isodata->bcast && data->handle)
+			tester_test_failed();
+
 		tester_print("Successfully disconnected");
 
 		if (data->reconnect) {
 			data->reconnect = false;
-			setup_connect(data, 0, iso_connect_cb);
+			test_connect(data->test_data);
 			return FALSE;
 		}
 
@@ -1209,6 +2429,46 @@ static void iso_shutdown(struct test_data *data, GIOChannel *io)
 	tester_print("Disconnecting...");
 }
 
+static bool hook_set_event_mask(const void *msg, uint16_t len, void *user_data)
+{
+	struct test_data *data = user_data;
+
+	tester_print("Set Event Mask");
+
+	--data->step;
+	if (!data->step)
+		tester_test_passed();
+
+	return true;
+}
+
+static void trigger_force_suspend(void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	struct vhci *vhci = hciemu_get_vhci(data->hciemu);
+	int err;
+
+	/* Make sure suspend is only triggered once */
+	if (data->suspending)
+		return;
+
+	data->suspending = true;
+
+	/* Triggers the suspend */
+	tester_print("Set the system into Suspend via force_suspend");
+	err = vhci_set_force_suspend(vhci, true);
+	if (err) {
+		tester_warn("Unable to enable the force_suspend");
+		return;
+	}
+
+	data->step++;
+
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+					BT_HCI_CMD_SET_EVENT_MASK,
+					hook_set_event_mask, data);
+}
+
 static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -1217,6 +2477,8 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
 	int err, sk_err, sk;
 	socklen_t len;
 	struct bt_iso_qos qos;
+	bool ret = true;
+	uint8_t base[BASE_MAX_LENGTH] = {0};
 
 	sk = g_io_channel_unix_get_fd(io);
 
@@ -1227,16 +2489,45 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
 	if (err < 0) {
 		tester_warn("Can't get socket option : %s (%d)",
 							strerror(errno), errno);
+		data->step = 0;
 		tester_test_failed();
 		return FALSE;
 	}
 
-	if (!check_qos(&qos, &isodata->qos)) {
+	if (!isodata->bcast) {
+		ret = check_ucast_qos(&qos, &isodata->qos,
+				      isodata->mconn ? &isodata->qos_2 : NULL);
+	} else if (!isodata->server)
+		ret = check_bcast_qos(&qos, &isodata->qos);
+
+	if (!ret) {
 		tester_warn("Unexpected QoS parameter");
+		data->step = 0;
 		tester_test_failed();
 		return FALSE;
 	}
 
+	if (isodata->bcast && isodata->server && isodata->base) {
+		len = BASE_MAX_LENGTH;
+
+		if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_BASE,
+				base, &len) < 0) {
+			tester_warn("Can't get socket option : %s (%d)",
+						strerror(errno), errno);
+			data->step = 0;
+			tester_test_failed();
+			return FALSE;
+		}
+
+		if (len != isodata->base_len ||
+				memcmp(base, isodata->base, len)) {
+			tester_warn("Unexpected BASE");
+			data->step = 0;
+			tester_test_failed();
+			return FALSE;
+		}
+	}
+
 	len = sizeof(sk_err);
 
 	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
@@ -1249,10 +2540,11 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
 	else
 		tester_print("Successfully connected");
 
-	if (-err != isodata->expect_err) {
+	if (err != isodata->expect_err) {
 		tester_warn("Expect error: %s (%d) != %s (%d)",
 				strerror(-isodata->expect_err),
 				-isodata->expect_err, strerror(-err), -err);
+		data->step = 0;
 		tester_test_failed();
 	} else {
 		data->step--;
@@ -1264,6 +2556,8 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
 			iso_recv(data, io);
 		else if (isodata->disconnect)
 			iso_shutdown(data, io);
+		else if (isodata->suspend)
+			trigger_force_suspend(data);
 		else
 			tester_test_passed();
 	}
@@ -1291,13 +2585,9 @@ static gboolean iso_connect2_cb(GIOChannel *io, GIOCondition cond,
 	return iso_connect(io, cond, user_data);
 }
 
-static void setup_connect(struct test_data *data, uint8_t num, GIOFunc func)
+static int setup_sock(struct test_data *data, uint8_t num)
 {
-	const struct iso_client_data *isodata = data->test_data;
-	GIOChannel *io;
 	int sk, err;
-	char c;
-	struct pollfd pfd;
 
 	sk = create_iso_sock(data);
 	if (sk < 0) {
@@ -1305,7 +2595,8 @@ static void setup_connect(struct test_data *data, uint8_t num, GIOFunc func)
 			tester_test_abort();
 		else
 			tester_test_failed();
-		return;
+
+		return sk;
 	}
 
 	err = connect_iso_sock(data, num, sk);
@@ -1319,73 +2610,122 @@ static void setup_connect(struct test_data *data, uint8_t num, GIOFunc func)
 		else
 			tester_test_failed();
 
-		return;
+		return err;
 	}
 
-	if (isodata->defer) {
-		int defer;
-		socklen_t len;
-
-		/* Check if socket has DEFER_SETUP set */
-		len = sizeof(defer);
-		if (getsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &defer,
-				&len) < 0) {
-			tester_warn("getsockopt: %s (%d)", strerror(errno),
-								errno);
+	return sk;
+}
+
+static int connect_deferred(int sk)
+{
+	int defer;
+	socklen_t len;
+	struct pollfd pfd;
+	char c;
+
+	/* Check if socket has DEFER_SETUP set */
+	len = sizeof(defer);
+	if (getsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &defer,
+					&len) < 0) {
+		tester_warn("getsockopt: %s (%d)", strerror(errno),
+				errno);
+		tester_test_failed();
+		return 0;
+	}
+
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = sk;
+	pfd.events = POLLOUT;
+
+	if (poll(&pfd, 1, 0) < 0) {
+		tester_warn("poll: %s (%d)", strerror(errno), errno);
+		tester_test_failed();
+		return -EIO;
+	}
+
+	if (!(pfd.revents & POLLOUT)) {
+		if (read(sk, &c, 1) < 0) {
+			tester_warn("read: %s (%d)", strerror(errno),
+					errno);
 			tester_test_failed();
-			return;
+			return -EIO;
 		}
+	}
 
-		memset(&pfd, 0, sizeof(pfd));
-		pfd.fd = sk;
-		pfd.events = POLLOUT;
+	return 0;
+}
 
-		if (poll(&pfd, 1, 0) < 0) {
-			tester_warn("poll: %s (%d)", strerror(errno), errno);
-			tester_test_failed();
+static void setup_connect_many(struct test_data *data, uint8_t n, uint8_t *num,
+								GIOFunc *func)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	int sk[256];
+	GIOChannel *io;
+	unsigned int i;
+
+	for (i = 0; i < n; ++i) {
+		sk[i] = setup_sock(data, num[i]);
+		if (sk[i] < 0)
 			return;
-		}
+	}
 
-		if (!(pfd.revents & POLLOUT)) {
-			if (read(sk, &c, 1) < 0) {
-				tester_warn("read: %s (%d)", strerror(errno),
-								errno);
-				tester_test_failed();
+	if (isodata->defer) {
+		for (i = 0; i < n; ++i)
+			if (connect_deferred(sk[i]) < 0)
 				return;
-			}
-		}
 	}
 
-	io = g_io_channel_unix_new(sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
+	for (i = 0; i < n; ++i) {
+		io = g_io_channel_unix_new(sk[i]);
+		g_io_channel_set_close_on_unref(io, TRUE);
 
-	data->io_id[num] = g_io_add_watch(io, G_IO_OUT, func, NULL);
+		data->io_id[num[i]] = g_io_add_watch(io, G_IO_OUT, func[i],
+									NULL);
 
-	g_io_channel_unref(io);
+		if (!isodata->bcast || !data->reconnect)
+			g_io_channel_unref(io);
+		else if (data->io_queue)
+			/* For the broadcast reconnect scenario, do not
+			 * unref channel here, to avoid closing the
+			 * socket. All queued channels will be closed
+			 * by test_data_free.
+			 */
+			queue_push_tail(data->io_queue, io);
 
-	tester_print("Connect in progress");
+		tester_print("Connect %d in progress", num[i]);
 
-	data->step++;
+		data->step++;
+	}
+}
+
+static void setup_connect(struct test_data *data, uint8_t num, GIOFunc func)
+{
+	return setup_connect_many(data, 1, &num, &func);
 }
 
 static void test_connect(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct iso_client_data *isodata = test_data;
+	uint8_t n = 0;
+	GIOFunc func[2];
+	uint8_t num[2] = {0, 1};
 
-	setup_connect(data, 0, iso_connect_cb);
-}
+	func[n++] = iso_connect_cb;
 
-static void setup_reconnect(struct test_data *data, uint8_t num, GIOFunc func)
-{
-	data->reconnect = true;
-	setup_connect(data, num, func);
+	/* Check if configuration requires multiple CIS setup */
+	if (!isodata->bcast && isodata->mconn)
+		func[n++] = iso_connect2_cb;
+
+	setup_connect_many(data, n, num, func);
 }
 
 static void test_reconnect(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	setup_reconnect(data, 0, iso_connect_cb);
+	data->reconnect = true;
+	test_connect(test_data);
 }
 
 static void test_defer(const void *test_data)
@@ -1463,8 +2803,11 @@ static int listen_iso_sock(struct test_data *data)
 
 		bacpy(&addr->iso_bc->bc_bdaddr, (void *) dst);
 		addr->iso_bc->bc_bdaddr_type = BDADDR_LE_PUBLIC;
-		addr->iso_bc->bc_num_bis = 1;
-		addr->iso_bc->bc_bis[0] = 1;
+
+		if (!isodata->defer || isodata->listen_bind) {
+			addr->iso_bc->bc_num_bis = 1;
+			addr->iso_bc->bc_bis[0] = 1;
+		}
 
 		err = bind(sk, (struct sockaddr *) addr, sizeof(*addr) +
 						   sizeof(*addr->iso_bc));
@@ -1482,173 +2825,511 @@ static int listen_iso_sock(struct test_data *data)
 	if (isodata->defer) {
 		int opt = 1;
 
-		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
-							sizeof(opt)) < 0) {
-			tester_print("Can't enable deferred setup: %s (%d)",
-						strerror(errno), errno);
-			goto fail;
-		}
-	}
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
+							sizeof(opt)) < 0) {
+			tester_print("Can't enable deferred setup: %s (%d)",
+						strerror(errno), errno);
+			goto fail;
+		}
+	}
+
+	if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &isodata->qos,
+						sizeof(isodata->qos)) < 0) {
+		tester_print("Can't set socket BT_ISO_QOS option: %s (%d)",
+					strerror(errno), errno);
+		goto fail;
+	}
+
+	if (listen(sk, 10)) {
+		err = -errno;
+		tester_warn("Can't listen socket: %s (%d)", strerror(errno),
+									errno);
+		goto fail;
+	}
+
+	free(addr);
+
+	return sk;
+
+fail:
+	free(addr);
+	close(sk);
+	return err;
+}
+
+static void setup_listen(struct test_data *data, uint8_t num, GIOFunc func)
+{
+	const struct iso_client_data *isodata = data->test_data;
+	GIOChannel *io;
+	int sk;
+
+	sk = listen_iso_sock(data);
+	if (sk < 0) {
+		if (sk == -EPROTONOSUPPORT)
+			tester_test_abort();
+		else
+			tester_test_failed();
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	data->io_id[num] = g_io_add_watch(io, G_IO_IN, func, NULL);
+
+	g_io_channel_unref(io);
+
+	tester_print("Listen in progress");
+
+	data->step++;
+
+	if (!isodata->bcast) {
+		struct hciemu_client *client;
+		struct bthost *host;
+
+		if (!data->acl_handle) {
+			tester_print("ACL handle not set");
+			tester_test_failed();
+			return;
+		}
+
+		client = hciemu_get_client(data->hciemu, 0);
+		host = hciemu_client_host(client);
+
+		bthost_set_cig_params(host, 0x01, 0x01, &isodata->qos);
+		bthost_create_cis(host, 257, data->acl_handle);
+	}
+}
+
+static bool iso_defer_accept_bcast(struct test_data *data, GIOChannel *io)
+{
+	int sk;
+	char c;
+	const struct iso_client_data *isodata = data->test_data;
+	struct sockaddr_iso *addr = NULL;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	if (isodata->pa_bind) {
+		addr = malloc(sizeof(*addr) + sizeof(*addr->iso_bc));
+		memset(addr, 0, sizeof(*addr) + sizeof(*addr->iso_bc));
+		addr->iso_family = AF_BLUETOOTH;
+
+		addr->iso_bc->bc_num_bis = 1;
+		addr->iso_bc->bc_bis[0] = 1;
+
+		if (bind(sk, (struct sockaddr *) addr, sizeof(*addr) +
+						sizeof(*addr->iso_bc)) < 0) {
+			tester_warn("bind: %s (%d)", strerror(errno), errno);
+			free(addr);
+			return false;
+		}
+
+		free(addr);
+	}
+
+	if (read(sk, &c, 1) < 0) {
+		tester_warn("read: %s (%d)", strerror(errno), errno);
+		return false;
+	}
+
+	tester_print("Accept deferred setup");
+
+	data->io_queue = queue_new();
+	if (data->io_queue)
+		queue_push_tail(data->io_queue, io);
+
+	data->io_id[0] = g_io_add_watch(io, G_IO_IN,
+				iso_accept_cb, NULL);
+
+	return true;
+}
+
+static bool iso_defer_accept_ucast(struct test_data *data, GIOChannel *io)
+{
+	int sk;
+	char c;
+	struct pollfd pfd;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = sk;
+	pfd.events = POLLOUT;
+
+	if (poll(&pfd, 1, 0) < 0) {
+		tester_warn("poll: %s (%d)", strerror(errno), errno);
+		return false;
+	}
+
+	if (!(pfd.revents & POLLOUT)) {
+		if (read(sk, &c, 1) < 0) {
+			tester_warn("read: %s (%d)", strerror(errno), errno);
+			return false;
+		}
+	}
+
+	tester_print("Accept deferred setup");
+
+	data->io_queue = queue_new();
+	if (data->io_queue)
+		queue_push_tail(data->io_queue, io);
+
+	data->io_id[0] = g_io_add_watch(io, G_IO_OUT,
+				iso_connect_cb, NULL);
+
+	return true;
+}
+
+static gboolean iso_accept_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct iso_client_data *isodata = data->test_data;
+	int sk, new_sk;
+	iso_defer_accept_t iso_accept = isodata->bcast ?
+						iso_defer_accept_bcast :
+						iso_defer_accept_ucast;
+
+	data->io_id[0] = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	new_sk = accept(sk, NULL, NULL);
+	if (new_sk < 0) {
+		tester_test_failed();
+		return false;
+	}
+
+	io = g_io_channel_unix_new(new_sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	if (isodata->defer) {
+		if (isodata->expect_err < 0) {
+			g_io_channel_unref(io);
+			tester_test_passed();
+			return false;
+		}
+
+		if (isodata->bcast) {
+			iso_connect(io, cond, user_data);
+
+			if (!data->step)
+				return false;
+		}
+
+		if (!iso_accept(data, io)) {
+			tester_warn("Unable to accept deferred setup");
+			tester_test_failed();
+		}
+		return false;
+	}
+
+	if (isodata->pkt_status) {
+		int opt = 1;
+
+		if (setsockopt(new_sk, SOL_BLUETOOTH, BT_PKT_STATUS, &opt,
+							sizeof(opt)) < 0) {
+			tester_print("Can't set socket BT_PKT_STATUS option: "
+					"%s (%d)", strerror(errno), errno);
+			tester_test_failed();
+			return false;
+		}
+	}
+
+	return iso_connect(io, cond, user_data);
+}
+
+static void test_listen(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	setup_listen(data, 0, iso_accept_cb);
+}
+
+static void test_connect2(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	uint8_t num[2] = {0, 1};
+	GIOFunc funcs[2] = {iso_connect_cb, iso_connect2_cb};
+
+	setup_connect_many(data, 2, num, funcs);
+}
+
+static gboolean iso_connect2_seq_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	data->io_id[0] = 0;
+
+	setup_connect(data, 1, iso_connect2_cb);
+
+	return iso_connect(io, cond, user_data);
+}
+
+static void test_connect2_seq(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	setup_connect(data, 0, iso_connect2_seq_cb);
+}
+
+static gboolean test_connect2_busy_done(gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	if (data->io_id[0] > 0) {
+		/* First connection still exists */
+		g_source_remove(data->io_id[0]);
+		data->io_id[0] = 0;
+		tester_test_passed();
+	} else {
+		tester_test_failed();
+	}
+
+	return FALSE;
+}
+
+static gboolean iso_connect_cb_busy_disc(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	data->io_id[0] = 0;
+
+	tester_print("Disconnected 1");
+	tester_test_failed();
+	return FALSE;
+}
+
+static gboolean iso_connect_cb_busy_2(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	int err, sk_err, sk;
+	socklen_t len;
+
+	data->io_id[1] = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	len = sizeof(sk_err);
+
+	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+		err = -errno;
+	else
+		err = -sk_err;
+
+	tester_print("Connected 2: %d", err);
+
+	if (err == -EBUSY && data->io_id[0] > 0) {
+		/* Wait in case first connection still gets disconnected */
+		data->io_id[1] = g_timeout_add(250, test_connect2_busy_done,
+									data);
+	} else {
+		tester_test_failed();
+	}
+
+	return FALSE;
+}
+
+static gboolean iso_connect_cb_busy(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	/* First connection shall not be disconnected */
+	data->io_id[0] = g_io_add_watch(io, G_IO_ERR | G_IO_HUP,
+						iso_connect_cb_busy_disc, data);
+
+	/* Second connect shall fail since CIG is now busy */
+	setup_connect(data, 1, iso_connect_cb_busy_2);
+
+	return iso_connect(io, cond, user_data);
+}
+
+static void test_connect2_busy(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	setup_connect(data, 0, iso_connect_cb_busy);
+}
+
+static gboolean iso_connect_close_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = user_data;
+
+	data->io_id[0] = 0;
+
+	tester_print("Disconnected");
+
+	--data->step;
+	if (!data->step)
+		tester_test_passed();
+
+	return FALSE;
+}
 
-	if (listen(sk, 10)) {
-		err = -errno;
-		tester_warn("Can't listen socket: %s (%d)", strerror(errno),
-									errno);
-		goto fail;
-	}
+static bool hook_remove_cig(const void *msg, uint16_t len, void *user_data)
+{
+	struct test_data *data = user_data;
 
-	free(addr);
+	tester_print("Remove CIG");
 
-	return sk;
+	--data->step;
+	if (!data->step)
+		tester_test_passed();
 
-fail:
-	free(addr);
-	close(sk);
-	return err;
+	return true;
 }
 
-static void setup_listen(struct test_data *data, uint8_t num, GIOFunc func)
+static void test_connect_close(const void *test_data)
 {
-	const struct iso_client_data *isodata = data->test_data;
-	GIOChannel *io;
+	struct test_data *data = tester_get_data();
 	int sk;
+	GIOChannel *io;
 
-	sk = listen_iso_sock(data);
-	if (sk < 0) {
-		if (sk == -EPROTONOSUPPORT)
-			tester_test_abort();
-		else
-			tester_test_failed();
+	data->step = 2;
+
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+					BT_HCI_CMD_LE_REMOVE_CIG,
+					hook_remove_cig, data);
+
+	sk = setup_sock(data, 0);
+	if (sk < 0)
 		return;
-	}
 
 	io = g_io_channel_unix_new(sk);
 	g_io_channel_set_close_on_unref(io, TRUE);
+	data->io_id[0] = g_io_add_watch(io, G_IO_HUP, iso_connect_close_cb,
+									data);
 
-	data->io_id[num] = g_io_add_watch(io, G_IO_IN, func, NULL);
+	shutdown(sk, SHUT_RDWR);
+}
 
-	g_io_channel_unref(io);
+static gboolean iso_connect_wait_close_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	int sk;
 
-	tester_print("Listen in progress");
+	tester_print("Connected");
 
-	data->step++;
+	sk = g_io_channel_unix_get_fd(io);
 
-	if (!isodata->bcast) {
-		struct hciemu_client *client;
-		struct bthost *host;
+	data->io_id[0] = g_io_add_watch(io, G_IO_HUP, iso_connect_close_cb,
+									data);
 
-		if (!data->acl_handle) {
-			tester_print("ACL handle not set");
-			tester_test_failed();
-			return;
-		}
+	shutdown(sk, SHUT_RDWR);
 
-		client = hciemu_get_client(data->hciemu, 0);
-		host = hciemu_client_host(client);
+	return FALSE;
+}
 
-		bthost_set_cig_params(host, 0x01, 0x01, &isodata->qos);
-		bthost_create_cis(host, 257, data->acl_handle);
-	}
+static void test_connect_wait_close(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	data->step = 1;
+
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+					BT_HCI_CMD_LE_REMOVE_CIG,
+					hook_remove_cig, data);
+
+	setup_connect(data, 0, iso_connect_wait_close_cb);
 }
 
-static bool iso_defer_accept(struct test_data *data, GIOChannel *io)
+static void test_connect_suspend(const void *test_data)
 {
-	int sk;
-	char c;
-	struct pollfd pfd;
+	test_connect(test_data);
+	trigger_force_suspend((void *)test_data);
+}
 
-	sk = g_io_channel_unix_get_fd(io);
+static bool hook_acl_disc(const void *msg, uint16_t len, void *user_data)
+{
+	const uint8_t *msg_data = msg;
+	const struct bt_hci_evt_le_enhanced_conn_complete *ev;
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
 
-	memset(&pfd, 0, sizeof(pfd));
-	pfd.fd = sk;
-	pfd.events = POLLOUT;
+	if (msg_data[0] != BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE)
+		return true;
 
-	if (poll(&pfd, 1, 0) < 0) {
-		tester_warn("poll: %s (%d)", strerror(errno), errno);
-		return false;
-	}
+	ev = (void *) &msg_data[1];
 
-	if (!(pfd.revents & POLLOUT)) {
-		if (read(sk, &c, 1) < 0) {
-			tester_warn("read: %s (%d)", strerror(errno), errno);
-			return false;
-		}
-	}
+	tester_print("Disconnect ACL");
 
-	tester_print("Accept deferred setup");
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_hci_disconnect(bthost, le16_to_cpu(ev->handle), 0x13);
 
-	data->io = io;
-	data->io_id[0] = g_io_add_watch(io, G_IO_OUT, iso_connect_cb, NULL);
+	hciemu_flush_client_events(data->hciemu);
 
 	return true;
 }
 
-static gboolean iso_accept_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static void test_connect_acl_disc(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct iso_client_data *isodata = data->test_data;
-	int sk, new_sk;
 
-	data->io_id[0] = 0;
-
-	sk = g_io_channel_unix_get_fd(io);
-
-	new_sk = accept(sk, NULL, NULL);
-	if (new_sk < 0) {
-		tester_test_failed();
-		return false;
-	}
-
-	io = g_io_channel_unix_new(new_sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
+	/* ACL disconnected before ISO is created */
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_EVT,
+					BT_HCI_EVT_LE_META_EVENT,
+					hook_acl_disc, NULL);
 
-	if (isodata->defer) {
-		if (isodata->expect_err < 0) {
-			g_io_channel_unref(io);
-			tester_test_passed();
-			return false;
-		}
+	test_connect(test_data);
+}
 
-		if (!iso_defer_accept(data, io)) {
-			tester_warn("Unable to accept deferred setup");
-			tester_test_failed();
-		}
-		return false;
-	}
+static void test_bcast(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
 
-	return iso_connect(io, cond, user_data);
+	setup_connect(data, 0, iso_connect_cb);
 }
 
-static void test_listen(const void *test_data)
+static void test_bcast2(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	uint8_t num[2] = {0, 1};
+	GIOFunc funcs[2] = {iso_connect_cb, iso_connect2_cb};
 
-	setup_listen(data, 0, iso_accept_cb);
+	setup_connect_many(data, 2, num, funcs);
 }
 
-static void test_connect2(const void *test_data)
+static void test_bcast2_reconn(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	uint8_t num[2] = {0, 1};
+	GIOFunc funcs[2] = {iso_connect_cb, iso_connect2_cb};
 
-	setup_connect(data, 0, iso_connect_cb);
-	setup_connect(data, 1, iso_connect2_cb);
+	data->io_queue = queue_new();
+
+	data->reconnect = true;
+	setup_connect_many(data, 2, num, funcs);
 }
 
-static void test_bcast(const void *test_data)
+static void test_bcast_recv(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	setup_connect(data, 0, iso_connect_cb);
+	setup_listen(data, 0, iso_accept_cb);
 }
 
-static void test_bcast_recv(const void *test_data)
+static void test_bcast_recv_defer(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
+	data->step = 1;
+
 	setup_listen(data, 0, iso_accept_cb);
 }
 
+static void test_connect2_suspend(const void *test_data)
+{
+	test_connect2(test_data);
+	trigger_force_suspend((void *)test_data);
+}
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -1770,22 +3451,149 @@ int main(int argc, char *argv[])
 	test_iso("ISO QoS 48_6_2 - Success", &connect_48_6_2, setup_powered,
 							test_connect);
 
+	test_iso("ISO QoS 16_1_gs - Success", &connect_16_1_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 16_2_gs - Success", &connect_16_2_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 32_1_gs - Success", &connect_32_1_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 32_2_gs - Success", &connect_32_2_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_1_gs - Success", &connect_48_1_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_2_gs - Success", &connect_48_2_gs, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 32_1_gr - Success", &connect_32_1_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 32_2_gr - Success", &connect_32_2_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_1_gr - Success", &connect_48_1_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_2_gr - Success", &connect_48_2_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_3_gr - Success", &connect_48_3_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_4_gr - Success", &connect_48_4_gr, setup_powered,
+							test_connect);
+
+	test_iso("ISO QoS 48_1_g - Success", &bcast_48_1_g,
+						setup_powered, test_bcast);
+
+	test_iso("ISO QoS 48_2_g - Success", &bcast_48_2_g,
+						setup_powered, test_bcast);
+
+	test_iso("ISO QoS 48_3_g - Success", &bcast_48_3_g,
+						setup_powered, test_bcast);
+
+	test_iso("ISO QoS 48_4_g - Success", &bcast_48_4_g,
+						setup_powered, test_bcast);
+
 	test_iso("ISO QoS - Invalid", &connect_invalid, setup_powered,
 							test_connect);
 
-	test_iso2("ISO Connect2 CIG 0x01 - Success", &connect_1_16_2_1,
-							setup_powered,
-							test_connect2);
+	test_iso("ISO QoS CIG 0xF0 - Invalid", &connect_cig_f0_invalid,
+			setup_powered, test_connect);
+
+	test_iso("ISO QoS CIS 0xF0 - Invalid", &connect_cis_f0_invalid,
+			setup_powered, test_connect);
+
+	test_iso_rej("ISO Connect - Reject", &connect_reject, setup_powered,
+			test_connect, BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
 
 	test_iso("ISO Send - Success", &connect_16_2_1_send, setup_powered,
 							test_connect);
 
+	/* Test basic TX timestamping */
+	test_iso("ISO Send - TX Timestamping", &connect_send_tx_timestamping,
+						setup_powered, test_connect);
+
+	/* Test schedule-time TX timestamps are emitted */
+	test_iso("ISO Send - TX Sched Timestamping",
+			&connect_send_tx_sched_timestamping, setup_powered,
+			test_connect);
+
+	/* Test TX timestamping with flags set via per-packet CMSG */
+	test_iso("ISO Send - TX CMSG Timestamping",
+			&connect_send_tx_cmsg_timestamping, setup_powered,
+			test_connect);
+
+	/* Test TX timestamping and disabling POLLERR wakeup */
+	test_iso("ISO Send - TX No Poll Timestamping",
+			&connect_send_tx_no_poll_timestamping, setup_powered,
+			test_connect);
+
 	test_iso("ISO Receive - Success", &listen_16_2_1_recv, setup_powered,
 							test_listen);
 
+	test_iso("ISO Receive Timestamped - Success", &listen_16_2_1_recv_ts,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive Packet Status - Success",
+						&listen_16_2_1_recv_pkt_status,
+						setup_powered, test_listen);
+
 	test_iso("ISO Defer - Success", &defer_16_2_1, setup_powered,
 							test_defer);
 
+	test_iso("ISO Defer Connect - Success", &defer_16_2_1, setup_powered,
+							test_connect);
+
+	test_iso("ISO Defer Close - Success", &defer_16_2_1, setup_powered,
+							test_connect_close);
+
+	test_iso("ISO Connect Close - Success", &connect_16_2_1, setup_powered,
+							test_connect_close);
+
+	test_iso("ISO Defer Wait Close - Success", &defer_16_2_1,
+					setup_powered, test_connect_wait_close);
+
+	test_iso("ISO Connect Wait Close - Success", &connect_16_2_1,
+					setup_powered, test_connect_wait_close);
+
+	test_iso("ISO Connect Suspend - Success", &connect_suspend,
+							setup_powered,
+							test_connect_suspend);
+
+	test_iso("ISO Connected Suspend - Success", &suspend_16_2_1,
+							setup_powered,
+							test_connect);
+
+	test_iso2("ISO Connect2 CIG 0x01 - Success", &connect_1_16_2_1,
+							setup_powered,
+							test_connect2);
+
+	test_iso2("ISO Connect2 Busy CIG 0x01 - Success/Invalid",
+					&connect_1_16_2_1, setup_powered,
+					test_connect2_busy);
+
+	test_iso2("ISO Defer Connect2 CIG 0x01 - Success", &defer_1_16_2_1,
+							setup_powered,
+							test_connect2);
+
+	test_iso2("ISO Connect2 Suspend - Success", &connect_suspend,
+							setup_powered,
+							test_connect2_suspend);
+
+	test_iso2("ISO Connected2 Suspend - Success", &suspend_16_2_1,
+							setup_powered,
+							test_connect2);
+
+	test_iso("ISO Connect ACL Disconnect - Failure", &connect_suspend,
+							setup_powered,
+							test_connect_acl_disc);
+
 	test_iso("ISO Defer Send - Success", &connect_16_2_1_defer_send,
 							setup_powered,
 							test_connect);
@@ -1816,8 +3624,74 @@ int main(int argc, char *argv[])
 							setup_powered,
 							test_reconnect);
 
+	test_iso("ISO AC 1 & 4 - Success", &connect_ac_1_4, setup_powered,
+							test_connect);
+
+	test_iso("ISO AC 2 & 10 - Success", &connect_ac_2_10, setup_powered,
+							test_connect);
+
+	test_iso("ISO AC 3 & 5 - Success", &connect_ac_3_5, setup_powered,
+							test_connect);
+
+	test_iso("ISO AC 6(i) - Success", &connect_ac_6i, setup_powered,
+							test_connect);
+
+	test_iso2("ISO AC 6(ii) - Success", &connect_ac_6ii, setup_powered,
+							test_connect2);
+
+	test_iso("ISO AC 7(i) - Success", &connect_ac_7i, setup_powered,
+							test_connect);
+
+	test_iso2("ISO AC 7(ii) - Success", &connect_ac_7ii, setup_powered,
+							test_connect2);
+
+	test_iso("ISO AC 8(i) - Success", &connect_ac_8i, setup_powered,
+							test_connect);
+
+	test_iso2("ISO AC 8(ii) - Success", &connect_ac_8ii, setup_powered,
+							test_connect2);
+
+	test_iso("ISO AC 9(i) - Success", &connect_ac_9i, setup_powered,
+							test_connect);
+
+	test_iso2("ISO AC 9(ii) - Success", &connect_ac_9ii, setup_powered,
+							test_connect2);
+
+	test_iso("ISO AC 11(i) - Success", &connect_ac_11i, setup_powered,
+							test_connect);
+
+	test_iso2("ISO AC 11(ii) - Success", &connect_ac_11ii, setup_powered,
+							test_connect2);
+
+	test_iso2("ISO AC 1 + 2 - Success", &connect_ac_1_2, setup_powered,
+							test_connect2_seq);
+
+	test_iso2("ISO AC 1 + 2 CIG 0x01/0x02 - Success",
+							&connect_ac_1_2_cig_1_2,
+							setup_powered,
+							test_connect2_seq);
+
+	test_iso2("ISO Reconnect AC 6(i) - Success", &reconnect_ac_6i,
+							setup_powered,
+							test_reconnect);
+
+	test_iso2("ISO Reconnect AC 6(ii) - Success", &reconnect_ac_6ii,
+							setup_powered,
+							test_reconnect);
+
+	test_iso2("ISO AC 6(ii) CIS 0xEF/auto - Success",
+						&connect_ac_6ii_cis_ef_auto,
+						setup_powered, test_connect);
+
+	test_iso2("ISO AC 6(ii) CIS 0xEF/0xEF - Invalid",
+						&connect_ac_6ii_cis_ef_ef,
+						setup_powered, test_connect);
+
 	test_iso("ISO Broadcaster - Success", &bcast_16_2_1_send, setup_powered,
 							test_bcast);
+	test_iso("ISO Broadcaster Encrypted - Success", &bcast_enc_16_2_1_send,
+							setup_powered,
+							test_bcast);
 	test_iso("ISO Broadcaster BIG 0x01 - Success", &bcast_1_16_2_1_send,
 							setup_powered,
 							test_bcast);
@@ -1829,6 +3703,44 @@ int main(int argc, char *argv[])
 	test_iso("ISO Broadcaster Receiver - Success", &bcast_16_2_1_recv,
 							setup_powered,
 							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver Encrypted - Success",
+							&bcast_enc_16_2_1_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver Defer - Success",
+						&bcast_16_2_1_recv_defer,
+						setup_powered,
+						test_bcast_recv_defer);
+	test_iso("ISO Broadcaster Receiver Defer No BIS - Success",
+						&bcast_16_2_1_recv_defer_no_bis,
+						setup_powered,
+						test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver Defer PA Bind - Success",
+					&bcast_16_2_1_recv_defer_pa_bind,
+					setup_powered,
+					test_bcast_recv_defer);
+	test_iso("ISO Broadcaster Receiver Defer Get BASE - Success",
+					&bcast_16_2_1_recv_defer_get_base,
+					setup_powered,
+					test_bcast_recv);
+
+	test_iso("ISO Broadcaster AC 12 - Success", &bcast_ac_12, setup_powered,
+							test_bcast);
+
+	test_iso("ISO Broadcaster AC 13 BIG 0x01 BIS 0x01 - Success",
+						&bcast_ac_13_1_1,
+						setup_powered,
+						test_bcast2);
+
+	test_iso("ISO Broadcaster AC 13 BIG 0x01 - Success", &bcast_ac_13_1,
+						setup_powered, test_bcast2);
+
+	test_iso("ISO Broadcaster AC 13 Reconnect - Success",
+					&bcast_ac_13_1_1_reconn, setup_powered,
+					test_bcast2_reconn);
+
+	test_iso("ISO Broadcaster AC 14 - Success", &bcast_ac_14, setup_powered,
+							test_bcast);
 
 	return tester_run();
 }
diff --git a/tools/isotest.1 b/tools/isotest.1
new file mode 100644
index 0000000..1628581
--- /dev/null
+++ b/tools/isotest.1
@@ -0,0 +1,329 @@
+'\" t
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "ISOTEST" "1" "May 4, 2022" "BlueZ" "Linux System Administration"
+.SH NAME
+isotest \- ISO testing
+.SH SYNOPSIS
+.sp
+\fBisotest\fP <\fIMODE\fP> [\fIOPTIONS\fP] [\fIbdaddr\fP] [\fIbdaddr1\fP]...
+.SH DESCRIPTION
+.sp
+\fBisotest(1)\fP is used to test Isochronous (CIS/BIS) communications on the
+BlueZ stack
+.SH MODES
+.INDENT 0.0
+.TP
+.B \-d, \-\-dump=[FILE]        Listen and dump incoming data
+(CIS server/BIS broadcaster) and optionally save the
+contents to \fIFILE\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B  \-c\fP,\fB  \-\-reconnect
+Reconnect (CIS client).
+.TP
+.B  \-m\fP,\fB  \-\-multiple
+Multiple connects (CIS client).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-r, \-\-receive=[FILE]     Receive (CIS server/BIS broadcast receiver) and
+optionally save the contents to \fIFILE\fP\&.
+.TP
+.B \-s, \-\-send=[FILE]        Connect and send (CIS client/BIS broadcaster), can
+optionally use contents from \fIFILE\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B  \-n\fP,\fB  \-\-silent
+Connect and be silent (CIS client/BIS broadcaster).
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-b\fP,\fB  \-\-bytes\fB= <SIZE>
+Send or Receive packet size
+.TP
+.BI \-i\fP,\fB  \-\-index\fB= <NUM>
+Select the specified HCI device index. \fIhciNUM\fP is
+also acceptable.
+.TP
+.BI \-j\fP,\fB  \-\-jitter\fB= <JITTER>
+Socket jitter buffer.
+.UNINDENT
+.sp
+\-h, \-\-help
+.INDENT 0.0
+.TP
+.B  \-q\fP,\fB  \-\-quiet
+Disables packet logging.
+.TP
+.BI \-t\fP,\fB  \-\-timeout\fB= <USEC>
+Socket send timeout.
+.TP
+.B  \-C\fP,\fB  \-\-continue
+Continuously send packets starting over in case of a
+file.
+.TP
+.BI \-W\fP,\fB  \-\-defer\fB= <SEC>
+Enable deferred setup.
+.TP
+.BI \-M\fP,\fB  \-\-mtu\fB= <SDU>
+Socket QoS SDU.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S, \-\-sca/adv\-interval=<SCA/INTERVAL>
+Socket QoS CIS SCA/BIS advertising interval.
+.UNINDENT
+.INDENT 0.0
+.TP
+.BI \-P\fP,\fB  \-\-packing\fB= <PACKING>
+Socket QoS Packing.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIPACKING\fP
+T}	T{
+Description
+T}
+_
+T{
+\fB0x00\fP
+T}	T{
+Sequential
+T}
+_
+T{
+\fB0x01\fP
+T}	T{
+Interleaved
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-F\fP,\fB  \-\-framing\fB= <FRAMING>
+Socket QoS Framing.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIFRAMING\fP
+T}	T{
+Description
+T}
+_
+T{
+\fB0x00\fP
+T}	T{
+Unframed
+T}
+_
+T{
+\fB0x01\fP
+T}	T{
+Framed
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-I\fP,\fB  \-\-interval\fB= <USEC>
+Socket QoS Interval.
+.TP
+.BI \-L\fP,\fB  \-\-latency\fB= <MSEC>
+Socket QoS Latency.
+.TP
+.BI \-Y\fP,\fB  \-\-phy\fB= <PHY>
+Socket QoS PHY.
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIPHY\fP
+T}	T{
+Description
+T}
+_
+T{
+\fB0x01\fP
+T}	T{
+LE 1M
+T}
+_
+T{
+\fB0x02\fP
+T}	T{
+LE 2M
+T}
+_
+T{
+\fB0x03\fP
+T}	T{
+LE Coded
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-R\fP,\fB  \-\-rtn\fB= <NUM>
+Socket QoS retransmissions.
+.TP
+.BI \-B\fP,\fB  \-\-preset\fB= <PRESET>
+Socket QoS preset.
+.UNINDENT
+.sp
+\-G, \-\-CIG/BIG=<ID>       Socket QoS CIG/BIG ID.
+.sp
+\-T, \-\-CIS/BIS=<ID>       Socket QoS CIS/BIS ID.
+.INDENT 0.0
+.TP
+.BI \-V\fP,\fB  \-\-type\fB= <TYPE>
+Socket destination address type:
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fITYPE\fP
+T}	T{
+Description
+T}
+_
+T{
+\fBle_public\fP
+T}	T{
+LE Public Address
+T}
+_
+T{
+\fBle_random\fP
+T}	T{
+LE Random Address
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-e\fP,\fB  \-\-enc\fB= <ENCRYPTION>
+Socket QoS BIG Encryption
+.UNINDENT
+.TS
+box center;
+l|l.
+T{
+\fIENCRYPTION\fP
+T}	T{
+Description
+T}
+_
+T{
+\fB0x00\fP
+T}	T{
+BIG unencrypted
+T}
+_
+T{
+\fB0x01\fP
+T}	T{
+BIG encrypted
+T}
+.TE
+.INDENT 0.0
+.TP
+.BI \-k\fP,\fB  \-\-bcode\fB= <BCODE>
+Socket QoS Broadcast Code
+.TP
+.BI \-N\fP,\fB  \-\-nbis\fB= <NBIS>
+Number of BISes to create as part of a
+BIG (BIS broadcaster) or to synchronize
+to (BIS broadcast receiver)
+.UNINDENT
+.SH EXAMPLES
+.SS Unicast Central
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ tools/isotest \-s XX:XX:XX:XX:XX:XX
+.EE
+.UNINDENT
+.UNINDENT
+.SS Unicast Central connecting to 2 peers using CIG 0x01
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ tools/isotest \-G 0x01 \-s XX:XX:XX:XX:XX:XX YY:YY:YY:YY:YY:YY
+.EE
+.UNINDENT
+.UNINDENT
+.SS Unicast Peripheral
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ tools/isotest \-d
+.EE
+.UNINDENT
+.UNINDENT
+.SS Broadcaster
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ tools/isotest \-s 00:00:00:00:00:00
+.EE
+.UNINDENT
+.UNINDENT
+.SS Broadcast Receiver using hci1
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ tools/isotest \-i hci1 \-d XX:XX:XX:XX:XX:XX
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Luiz Augusto Von Dentz <luiz.von.dentz@intel.com>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/isotest.c b/tools/isotest.c
index 8a50bfe..2cac0e4 100644
--- a/tools/isotest.c
+++ b/tools/isotest.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation.
+ *  Copyright 2023 NXP
  *
  */
 
@@ -30,6 +31,9 @@
 #include <sys/uio.h>
 #include <linux/sockios.h>
 #include <time.h>
+#include <inttypes.h>
+#include <sys/wait.h>
+#include <poll.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
@@ -42,6 +46,12 @@
 #define NSEC_USEC(_t) (_t / 1000L)
 #define SEC_USEC(_t)  (_t  * 1000000L)
 #define TS_USEC(_ts)  (SEC_USEC((_ts)->tv_sec) + NSEC_USEC((_ts)->tv_nsec))
+#define ROUND_CLOSEST(_x, _y) (((_x) + (_y / 2)) / (_y))
+
+#define DEFAULT_BIG_ID 0x01
+#define DEFAULT_BIS_ID 0x01
+
+#define MAX_DATA_SIZE 0x40000000
 
 /* Test modes */
 enum {
@@ -70,6 +80,8 @@ static bool quiet;
 struct bt_iso_qos *iso_qos;
 static bool inout;
 
+static uint8_t num_bis = 1;
+
 struct lookup_table {
 	const char *name;
 	int flag;
@@ -238,7 +250,7 @@ fail:
 	return err < 0 ? err : 0;
 }
 
-static void print_qos(int sk, struct sockaddr_iso *addr)
+static void print_ucast_qos(int sk)
 {
 	struct bt_iso_qos qos;
 	socklen_t len;
@@ -253,21 +265,60 @@ static void print_qos(int sk, struct sockaddr_iso *addr)
 		return;
 	}
 
-	if (!bacmp(&addr->iso_bdaddr, BDADDR_ANY)) {
-		syslog(LOG_INFO, "QoS BIG 0x%02x BIS 0x%02x Packing 0x%02x "
-			"Framing 0x%02x]", qos.big, qos.bis, qos.packing,
-			qos.framing);
-	} else {
-		syslog(LOG_INFO, "QoS CIG 0x%02x CIS 0x%02x Packing 0x%02x "
-			"Framing 0x%02x]", qos.cig, qos.cis, qos.packing,
-			qos.framing);
-		syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
-			"ms SDU %u PHY 0x%02x RTN %u]", qos.in.interval,
-			qos.in.latency, qos.in.sdu, qos.in.phy, qos.in.rtn);
+	syslog(LOG_INFO, "QoS CIG 0x%02x CIS 0x%02x Packing 0x%02x "
+		"Framing 0x%02x]", qos.ucast.cig, qos.ucast.cis,
+		qos.ucast.packing, qos.ucast.framing);
+
+	syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
+		"ms SDU %u PHY 0x%02x RTN %u]", qos.ucast.in.interval,
+		qos.ucast.in.latency, qos.ucast.in.sdu, qos.ucast.in.phy,
+		qos.ucast.in.rtn);
+
+	syslog(LOG_INFO, "Output QoS [Interval %u us Latency %u "
+		"ms SDU %u PHY 0x%02x RTN %u]", qos.ucast.out.interval,
+		qos.ucast.out.latency, qos.ucast.out.sdu, qos.ucast.out.phy,
+		qos.ucast.out.rtn);
+}
+
+static void print_bcast_qos(int sk)
+{
+	struct bt_iso_qos qos;
+	socklen_t len;
+
+	/* Read Out QOS */
+	memset(&qos, 0, sizeof(qos));
+	len = sizeof(qos);
+
+	if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
+		syslog(LOG_ERR, "Can't get QoS socket option: %s (%d)",
+				strerror(errno), errno);
+		return;
 	}
+
+	syslog(LOG_INFO, "QoS [BIG 0x%02x BIS 0x%02x Packing 0x%02x "
+		"Framing 0x%02x Encryption 0x%02x]", qos.bcast.big,
+		qos.bcast.bis, qos.bcast.packing, qos.bcast.framing,
+		qos.bcast.encryption);
+
+	if (qos.bcast.encryption == 0x01)
+		syslog(LOG_INFO, "Broadcast Code 0x%02x 0x%02x 0x%02x 0x%02x "
+		"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "
+		"0x%02x 0x%02x 0x%02x 0x%02x", qos.bcast.bcode[0],
+		qos.bcast.bcode[1], qos.bcast.bcode[2], qos.bcast.bcode[3],
+		qos.bcast.bcode[4], qos.bcast.bcode[5], qos.bcast.bcode[6],
+		qos.bcast.bcode[7], qos.bcast.bcode[8], qos.bcast.bcode[9],
+		qos.bcast.bcode[10], qos.bcast.bcode[11], qos.bcast.bcode[12],
+		qos.bcast.bcode[13], qos.bcast.bcode[14], qos.bcast.bcode[15]);
+
+	syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
+		"ms SDU %u PHY 0x%02x RTN %u]", qos.bcast.in.interval,
+		qos.bcast.in.latency, qos.bcast.in.sdu,
+		qos.bcast.in.phy, qos.bcast.in.rtn);
+
 	syslog(LOG_INFO, "Output QoS [Interval %u us Latency %u "
-		"ms SDU %u PHY 0x%02x RTN %u]", qos.out.interval,
-		qos.out.latency, qos.out.sdu, qos.out.phy, qos.out.rtn);
+		"ms SDU %u PHY 0x%02x RTN %u]", qos.bcast.out.interval,
+		qos.bcast.out.latency, qos.bcast.out.sdu,
+		qos.bcast.out.phy, qos.bcast.out.rtn);
 }
 
 static int do_connect(char *peer)
@@ -275,8 +326,6 @@ static int do_connect(char *peer)
 	struct sockaddr_iso addr;
 	int sk;
 
-	mgmt_set_experimental();
-
 	/* Create socket */
 	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
 	if (sk < 0) {
@@ -301,8 +350,8 @@ static int do_connect(char *peer)
 	/* Set QoS if available */
 	if (iso_qos) {
 		if (!inout || !strcmp(peer, "00:00:00:00:00:00")) {
-			iso_qos->in.phy = 0x00;
-			iso_qos->in.sdu = 0;
+			iso_qos->ucast.in.phy = 0x00;
+			iso_qos->ucast.in.sdu = 0;
 		}
 
 		if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, iso_qos,
@@ -337,7 +386,10 @@ static int do_connect(char *peer)
 
 	syslog(LOG_INFO, "Connected [%s]", peer);
 
-	print_qos(sk, &addr);
+	if (!strcmp(peer, "00:00:00:00:00:00"))
+		print_bcast_qos(sk);
+	else
+		print_ucast_qos(sk);
 
 	return sk;
 
@@ -346,13 +398,99 @@ error:
 	return -1;
 }
 
-static void do_listen(char *filename, void (*handler)(int fd, int sk),
-							char *peer)
+static int *bcast_do_connect_mbis(uint8_t count, char *peer)
+{
+	int *sk;
+	uint8_t sk_cnt = 0;
+
+	sk = malloc(count * sizeof(*sk));
+	if (!sk) {
+		syslog(LOG_ERR, "Can't allocate socket array");
+		return NULL;
+	}
+
+	defer_setup = 1;
+
+	for (int i = 0; i < count; i++) {
+		if (i == count - 1)
+			defer_setup = 0;
+
+		sk[i] = do_connect(peer);
+		if (sk[i] < 0) {
+			syslog(LOG_ERR, "Can't create socket: %s (%d)",
+					strerror(errno), errno);
+
+			goto error;
+		}
+
+		sk_cnt++;
+	}
+
+	return sk;
+
+error:
+	for (int i = 0; i < sk_cnt; i++)
+		close(sk[i]);
+
+	free(sk);
+	return NULL;
+
+}
+
+static int accept_conn(int sk, struct sockaddr_iso *addr, char *peer)
+{
+	socklen_t optlen;
+	int nsk, err, sk_err;
+	struct pollfd fds;
+	socklen_t len;
+
+	memset(addr, 0, sizeof(*addr) + sizeof(*addr->iso_bc));
+	optlen = sizeof(*addr);
+
+	if (peer)
+		optlen += sizeof(*addr->iso_bc);
+
+	nsk = accept(sk, (struct sockaddr *) addr, &optlen);
+	if (nsk < 0) {
+		syslog(LOG_ERR, "Accept failed: %s (%d)",
+						strerror(errno), errno);
+		return -1;
+	}
+
+	/* Check if connection was successful */
+	memset(&fds, 0, sizeof(fds));
+	fds.fd = nsk;
+	fds.events = POLLERR;
+
+	if (poll(&fds, 1, 0) > 0 && (fds.revents & POLLERR)) {
+		len = sizeof(sk_err);
+
+		if (getsockopt(nsk, SOL_SOCKET, SO_ERROR,
+					&sk_err, &len) < 0)
+			err = -errno;
+		else
+			err = -sk_err;
+
+		if (err < 0)
+			syslog(LOG_ERR, "Connection failed: %s (%d)",
+					strerror(-err), -err);
+
+		close(nsk);
+		return -1;
+	}
+
+	return nsk;
+}
+
+static void do_listen(char *filename,
+		void (*handler)(int fd, int sk, char *peer),
+		char *peer)
 {
 	struct sockaddr_iso *addr = NULL;
 	socklen_t optlen;
 	int sk, nsk, fd = -1;
 	char ba[18];
+	int read_len;
 
 	if (filename) {
 		fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
@@ -387,8 +525,11 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
 	if (peer) {
 		str2ba(peer, &addr->iso_bc->bc_bdaddr);
 		addr->iso_bc->bc_bdaddr_type = bdaddr_type;
-		addr->iso_bc->bc_num_bis = 1;
-		addr->iso_bc->bc_bis[0] = 1;
+		addr->iso_bc->bc_num_bis = num_bis;
+
+		for (int i = 0; i < num_bis; i++)
+			addr->iso_bc->bc_bis[i] = i + 1;
+
 		optlen += sizeof(*addr->iso_bc);
 	}
 
@@ -406,6 +547,16 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
 		goto error;
 	}
 
+	/* Set QoS if available */
+	if (iso_qos) {
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, iso_qos,
+					sizeof(*iso_qos)) < 0) {
+			syslog(LOG_ERR, "Can't set QoS socket option: "
+					"%s (%d)", strerror(errno), errno);
+			goto error;
+		}
+	}
+
 	/* Listen for connections */
 	if (listen(sk, 10)) {
 		syslog(LOG_ERR, "Can not listen on the socket: %s (%d)",
@@ -415,19 +566,27 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
 
 	syslog(LOG_INFO, "Waiting for connection %s...", peer ? peer : "");
 
-	while (1) {
-		memset(addr, 0, sizeof(*addr) + sizeof(*addr->iso_bc));
-		optlen = sizeof(*addr);
+	/* Handle deferred setup */
+	if (defer_setup && peer) {
+		nsk = accept_conn(sk, addr, peer);
+		if (nsk < 0)
+			goto error;
 
-		if (peer)
-			optlen += sizeof(*addr->iso_bc);
+		close(sk);
+		sk = nsk;
 
-		nsk = accept(sk, (struct sockaddr *) addr, &optlen);
-		if (nsk < 0) {
-			syslog(LOG_ERR, "Accept failed: %s (%d)",
-							strerror(errno), errno);
-			goto error;
-		}
+		read_len = read(sk, buf, data_size);
+		if (read_len < 0)
+			syslog(LOG_ERR, "Initial read error: %s (%d)",
+						strerror(errno), errno);
+		else
+			syslog(LOG_INFO, "Initial bytes %d", read_len);
+	}
+
+	while (1) {
+		nsk = accept_conn(sk, addr, peer);
+		if (nsk < 0)
+			continue;
 
 		if (fork()) {
 			/* Parent */
@@ -440,7 +599,10 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
 		ba2str(&addr->iso_bdaddr, ba);
 		syslog(LOG_INFO, "Connected [%s]", ba);
 
-		print_qos(nsk, addr);
+		if (peer)
+			print_bcast_qos(nsk);
+		else
+			print_ucast_qos(nsk);
 
 		/* Handle deferred setup */
 		if (defer_setup) {
@@ -454,7 +616,7 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
 			}
 		}
 
-		handler(fd, nsk);
+		handler(fd, nsk, peer);
 
 		syslog(LOG_INFO, "Disconnect");
 		exit(0);
@@ -469,11 +631,11 @@ error:
 	exit(1);
 }
 
-static void dump_mode(int fd, int sk)
+static void dump_mode(int fd, int sk, char *peer)
 {
 	int len;
 
-	if (defer_setup) {
+	if (defer_setup && !peer) {
 		len = read(sk, buf, data_size);
 		if (len < 0)
 			syslog(LOG_ERR, "Initial read error: %s (%d)",
@@ -483,7 +645,7 @@ static void dump_mode(int fd, int sk)
 	}
 
 	syslog(LOG_INFO, "Receiving ...");
-	while ((len = read(sk, buf, data_size)) > 0) {
+	while ((len = read(sk, buf, data_size)) >= 0) {
 		if (fd >= 0) {
 			len = write(fd, buf, len);
 			if (len < 0) {
@@ -496,14 +658,14 @@ static void dump_mode(int fd, int sk)
 	}
 }
 
-static void recv_mode(int fd, int sk)
+static void recv_mode(int fd, int sk, char *peer)
 {
 	struct timeval tv_beg, tv_end, tv_diff;
 	long total;
 	int len;
 	uint32_t seq;
 
-	if (defer_setup) {
+	if (defer_setup && !peer) {
 		len = read(sk, buf, data_size);
 		if (len < 0)
 			syslog(LOG_ERR, "Initial read error: %s (%d)",
@@ -521,12 +683,13 @@ static void recv_mode(int fd, int sk)
 			int r;
 
 			r = recv(sk, buf, data_size, 0);
-			if (r <= 0) {
+			if (r < 0) {
 				if (r < 0)
 					syslog(LOG_ERR, "Read failed: %s (%d)",
 							strerror(errno), errno);
 				if (errno != ENOTCONN)
 					return;
+
 				r = 0;
 			}
 
@@ -560,7 +723,7 @@ static int open_file(const char *filename)
 	syslog(LOG_INFO, "Opening %s ...", filename);
 
 	fd = open(filename, O_RDONLY);
-	if (fd <= 0) {
+	if (fd < 0) {
 		syslog(LOG_ERR, "Can't open file %s: %s\n",
 						filename, strerror(errno));
 	}
@@ -584,17 +747,21 @@ static void send_wait(struct timespec *t_start, uint32_t us)
 	}
 
 	t_diff.tv_sec = t_now.tv_sec - t_start->tv_sec;
+	if (t_start->tv_nsec > t_now.tv_nsec) {
+		t_diff.tv_sec--;
+		t_now.tv_nsec += 1000000000L;
+	}
 	t_diff.tv_nsec = t_now.tv_nsec - t_start->tv_nsec;
 
 	delta_us = us - TS_USEC(&t_diff);
 
 	if (delta_us < 0) {
-		syslog(LOG_INFO, "Send is behind: %zd us", delta_us);
+		syslog(LOG_INFO, "Send is behind: %" PRId64 " us", delta_us);
 		delta_us = 1000;
 	}
 
 	if (!quiet)
-		syslog(LOG_INFO, "Waiting (%zd us)...", delta_us);
+		syslog(LOG_INFO, "Waiting (%" PRId64 " us)...", delta_us);
 
 	usleep(delta_us);
 
@@ -643,12 +810,67 @@ static int read_file(int fd, ssize_t count, bool rewind)
 	return len;
 }
 
-static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,
-		    bool repeat)
+static void do_send(int sk, int fd, char *peer, bool repeat)
 {
 	uint32_t seq;
 	struct timespec t_start;
-	int len, used;
+	int send_len, used;
+	socklen_t len;
+	struct bt_iso_qos qos;
+	uint32_t num;
+	struct bt_iso_io_qos *out;
+
+	syslog(LOG_INFO, "Sending ...");
+
+	/* Read QoS */
+	if (!strcmp(peer, "00:00:00:00:00:00"))
+		out = &qos.bcast.out;
+	else
+		out = &qos.ucast.out;
+
+	memset(&qos, 0, sizeof(qos));
+	len = sizeof(qos);
+	if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
+		syslog(LOG_ERR, "Can't get Output QoS socket option: %s (%d)",
+				strerror(errno), errno);
+		out->sdu = ISO_DEFAULT_MTU;
+	}
+
+	/* num of packets = latency (ms) / interval (us) */
+	num = ROUND_CLOSEST(out->latency * 1000, out->interval);
+	if (!num)
+		num = 1;
+
+	syslog(LOG_INFO, "Number of packets: %d", num);
+
+	if (!sndbuf)
+		/* Use socket buffer as a jitter buffer for the entire buffer
+		 * latency:
+		 * jitter buffer = 2 * (SDU * subevents)
+		 */
+		sndbuf = 2 * (num * out->sdu);
+
+	len = sizeof(sndbuf);
+	if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &sndbuf, len) < 0) {
+		syslog(LOG_ERR, "Can't set socket SO_SNDBUF option: %s (%d)",
+				strerror(errno), errno);
+	}
+
+	syslog(LOG_INFO, "Socket jitter buffer: %d buffer", sndbuf);
+
+	if (sndto.tv_usec) {
+		len = sizeof(sndto);
+		if (setsockopt(sk, SOL_SOCKET, SO_SNDTIMEO, &sndto, len) < 0) {
+			syslog(LOG_ERR, "Can't set socket SO_SNDTIMEO option: "
+				"%s (%d)", strerror(errno), errno);
+		} else {
+			syslog(LOG_INFO, "Socket send timeout: %ld usec",
+							sndto.tv_usec);
+		}
+	}
+
+	for (int i = 6; i < out->sdu; i++)
+		buf[i] = 0x7f;
 
 	if (clock_gettime(CLOCK_MONOTONIC, &t_start) < 0) {
 		perror("clock_gettime");
@@ -657,17 +879,17 @@ static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,
 
 	for (seq = 0; ; seq++) {
 		if (fd >= 0) {
-			len = read_file(fd, qos->out.sdu, repeat);
-			if (len < 0) {
+			send_len = read_file(fd, out->sdu, repeat);
+			if (send_len < 0) {
 				syslog(LOG_ERR, "read failed: %s (%d)",
-						strerror(-len), -len);
+						strerror(-send_len), -send_len);
 				exit(1);
 			}
 		} else
-			len = qos->out.sdu;
+			send_len = out->sdu;
 
-		len = send(sk, buf, len, 0);
-		if (len <= 0) {
+		send_len = send(sk, buf, send_len, 0);
+		if (send_len <= 0) {
 			syslog(LOG_ERR, "send failed: %s (%d)",
 						strerror(errno), errno);
 			exit(1);
@@ -678,19 +900,20 @@ static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,
 		if (!quiet)
 			syslog(LOG_INFO,
 				"[seq %d] %d bytes buffered %d (%d bytes)",
-				seq, len, used / len, used);
+				seq, send_len, used / send_len, used);
 
 		if (seq && !((seq + 1) % num))
-			send_wait(&t_start, num * qos->out.interval);
+			send_wait(&t_start, num * out->interval);
 	}
 }
 
 static void send_mode(char *filename, char *peer, int i, bool repeat)
 {
-	struct bt_iso_qos qos;
-	socklen_t len;
 	int sk, fd = -1;
-	uint32_t num;
+	int *sk_arr;
+	uint8_t nconn = strcmp(peer, "00:00:00:00:00:00") ? 1 : num_bis;
+
+	mgmt_set_experimental();
 
 	if (filename) {
 		char altername[PATH_MAX];
@@ -703,10 +926,39 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
 		if (!err)
 			fd = open_file(altername);
 
-		if (fd <= 0)
+		if (fd < 0)
 			fd = open_file(filename);
 	}
 
+	if (nconn > 1) {
+		sk_arr = bcast_do_connect_mbis(nconn, peer);
+		if (!sk_arr)
+			exit(1);
+
+		for (int i = 0; i < nconn; i++) {
+			if (fork()) {
+				/* Parent */
+				continue;
+			}
+
+			/* Child */
+			do_send(sk_arr[i], fd, peer, repeat);
+			exit(0);
+		}
+
+		/* Wait for children to exit */
+		while (wait(NULL) > 0)
+			;
+
+		for (int i = 0; i < nconn; i++)
+			close(sk_arr[i]);
+
+		free(sk_arr);
+		if (fd >= 0)
+			close(fd);
+		return;
+	}
+
 	sk = do_connect(peer);
 	if (sk < 0) {
 		syslog(LOG_ERR, "Can't connect to the server: %s (%d)",
@@ -720,57 +972,13 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
 		sleep(abs(defer_setup) - 1);
 	}
 
-	syslog(LOG_INFO, "Sending ...");
-
-	/* Read QoS */
-	memset(&qos, 0, sizeof(qos));
-	len = sizeof(qos);
-	if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
-		syslog(LOG_ERR, "Can't get Output QoS socket option: %s (%d)",
-				strerror(errno), errno);
-		qos.out.sdu = ISO_DEFAULT_MTU;
-	}
-
-	/* num of packets = latency (ms) / interval (us) */
-	num = (qos.out.latency * 1000 / qos.out.interval);
-
-	syslog(LOG_INFO, "Number of packets: %d", num);
-
-	if (!sndbuf)
-		/* Use socket buffer as a jitter buffer for the entire buffer
-		 * latency:
-		 * jitter buffer = 2 * (SDU * subevents)
-		 */
-		sndbuf = 2 * ((qos.out.latency * 1000 / qos.out.interval) *
-							qos.out.sdu);
-
-	len = sizeof(sndbuf);
-	if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &sndbuf, len) < 0) {
-		syslog(LOG_ERR, "Can't set socket SO_SNDBUF option: %s (%d)",
-				strerror(errno), errno);
-	}
-
-	syslog(LOG_INFO, "Socket jitter buffer: %d buffer", sndbuf);
-
-	if (sndto.tv_usec) {
-		len = sizeof(sndto);
-		if (setsockopt(sk, SOL_SOCKET, SO_SNDTIMEO, &sndto, len) < 0) {
-			syslog(LOG_ERR, "Can't set socket SO_SNDTIMEO option: "
-				"%s (%d)", strerror(errno), errno);
-		} else {
-			syslog(LOG_INFO, "Socket send timeout: %ld usec",
-							sndto.tv_usec);
-		}
-	}
-
-	for (i = 6; i < qos.out.sdu; i++)
-		buf[i] = 0x7f;
-
-	do_send(sk, fd, &qos, num, repeat);
+	do_send(sk, fd, peer, repeat);
 }
 
 static void reconnect_mode(char *peer)
 {
+	mgmt_set_experimental();
+
 	while (1) {
 		int sk;
 
@@ -789,6 +997,8 @@ static void reconnect_mode(char *peer)
 
 static void multy_connect_mode(char *peer)
 {
+	mgmt_set_experimental();
+
 	while (1) {
 		int i, sk;
 
@@ -821,12 +1031,22 @@ static void multy_connect_mode(char *peer)
 
 #define QOS(_interval, _latency, _sdu, _phy, _rtn) \
 { \
-	.cig = BT_ISO_QOS_CIG_UNSET, \
-	.cis = BT_ISO_QOS_CIS_UNSET, \
-	.sca = 0x07, \
-	.packing = 0x00, \
-	.framing = 0x00, \
-	.out = QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+	.bcast = { \
+		.big = BT_ISO_QOS_BIG_UNSET, \
+		.bis = BT_ISO_QOS_BIS_UNSET, \
+		.sync_factor = 0x07, \
+		.packing = 0x00, \
+		.framing = 0x00, \
+		.out = QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+		.encryption = 0x00, \
+		.bcode = {0}, \
+		.options = 0x00, \
+		.skip = 0x0000, \
+		.sync_timeout = 0x4000, \
+		.sync_cte_type = 0x00, \
+		.mse = 0x00, \
+		.timeout = 0x4000, \
+	}, \
 }
 
 #define QOS_PRESET(_name, _inout, _interval, _latency, _sdu, _phy, _rtn) \
@@ -859,22 +1079,35 @@ static struct qos_preset {
 	QOS_PRESET("48_5_1", false, 7500, 15, 117, 0x02, 5),
 	QOS_PRESET("44_6_1", false, 10000, 20, 155, 0x02, 5),
 	/* QoS Configuration settings for high reliability audio data */
-	QOS_PRESET("8_1_2", true, 7500, 45, 26, 0x02, 41),
-	QOS_PRESET("8_2_2", true, 10000, 60, 30, 0x02, 53),
-	QOS_PRESET("16_1_2", true, 7500, 45, 30, 0x02, 41),
-	QOS_PRESET("16_2_2", true, 10000, 60, 40, 0x02, 47),
-	QOS_PRESET("24_1_2", true, 7500, 45, 45, 0x02, 35),
-	QOS_PRESET("24_2_2", true, 10000, 60, 60, 0x02, 41),
-	QOS_PRESET("32_1_2", true, 7500, 45, 60, 0x02, 29),
-	QOS_PRESET("32_2_1", true, 10000, 60, 80, 0x02, 35),
-	QOS_PRESET("44_1_2", false, 8163, 54, 98, 0x02, 23),
-	QOS_PRESET("44_2_2", false, 10884, 71, 130, 0x02, 23),
-	QOS_PRESET("48_1_2", false, 7500, 45, 75, 0x02, 23),
-	QOS_PRESET("48_2_2", false, 10000, 60, 100, 0x02, 23),
-	QOS_PRESET("48_3_2", false, 7500, 45, 90, 0x02, 23),
-	QOS_PRESET("48_4_2", false, 10000, 60, 120, 0x02, 23),
-	QOS_PRESET("48_5_2", false, 7500, 45, 117, 0x02, 23),
-	QOS_PRESET("44_6_2", false, 10000, 60, 155, 0x02, 23),
+	QOS_PRESET("8_1_2", true, 7500, 75, 26, 0x02, 13),
+	QOS_PRESET("8_2_2", true, 10000, 95, 30, 0x02, 13),
+	QOS_PRESET("16_1_2", true, 7500, 75, 30, 0x02, 13),
+	QOS_PRESET("16_2_2", true, 10000, 95, 40, 0x02, 13),
+	QOS_PRESET("24_1_2", true, 7500, 75, 45, 0x02, 13),
+	QOS_PRESET("24_2_2", true, 10000, 95, 60, 0x02, 13),
+	QOS_PRESET("32_1_2", true, 7500, 75, 60, 0x02, 13),
+	QOS_PRESET("32_2_2", true, 10000, 95, 80, 0x02, 13),
+	QOS_PRESET("44_1_2", false, 8163, 80, 97, 0x02, 13),
+	QOS_PRESET("44_2_2", false, 10884, 85, 130, 0x02, 13),
+	QOS_PRESET("48_1_2", false, 7500, 75, 75, 0x02, 13),
+	QOS_PRESET("48_2_2", false, 10000, 95, 100, 0x02, 13),
+	QOS_PRESET("48_3_2", false, 7500, 75, 90, 0x02, 13),
+	QOS_PRESET("48_4_2", false, 10000, 100, 120, 0x02, 13),
+	QOS_PRESET("48_5_2", false, 7500, 75, 117, 0x02, 13),
+	QOS_PRESET("44_6_2", false, 10000, 100, 155, 0x02, 13),
+	/* QoS configuration support setting requirements for the UGG and UGT */
+	QOS_PRESET("16_1_gs", true, 7500, 15, 30, 0x02, 1),
+	QOS_PRESET("16_2_gs", true, 10000, 20, 40, 0x02, 1),
+	QOS_PRESET("32_1_gs", true, 7500, 15, 60, 0x02, 1),
+	QOS_PRESET("32_2_gs", true, 10000, 20, 80, 0x02, 1),
+	QOS_PRESET("48_1_gs", true, 7500, 15, 75, 0x02, 1),
+	QOS_PRESET("48_2_gs", true, 10000, 20, 100, 0x02, 1),
+	QOS_PRESET("32_1_gr", true, 7500, 15, 60, 0x02, 1),
+	QOS_PRESET("32_2_gr", true, 10000, 20, 80, 0x02, 1),
+	QOS_PRESET("48_1_gr", true, 7500, 15, 75, 0x02, 1),
+	QOS_PRESET("48_2_gr", true, 10000, 20, 100, 0x02, 1),
+	QOS_PRESET("48_3_gr", true, 7500, 15, 90, 0x02, 1),
+	QOS_PRESET("48_4_gr", true, 10000, 20, 120, 0x02, 1),
 };
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -912,7 +1145,8 @@ static void usage(void)
 		"\t[-B, --preset <value>]\n"
 		"\t[-G, --CIG/BIG <value>]\n"
 		"\t[-T, --CIS/BIS <value>]\n"
-		"\t[-V, --type <value>] address type (help for list)\n");
+		"\t[-V, --type <value>] address type (help for list)\n"
+		"\t[-N, --nbis <value>] Number of BISes to create/synchronize to\n");
 }
 
 static const struct option main_options[] = {
@@ -942,9 +1176,29 @@ static const struct option main_options[] = {
 	{ "CIG/BIG",   required_argument, NULL, 'G'},
 	{ "CIS/BIS",   required_argument, NULL, 'T'},
 	{ "type",      required_argument, NULL, 'V'},
+	{ "nbis",      required_argument, NULL, 'N'},
 	{}
 };
 
+static bool str2hex(const char *str, uint16_t in_len, uint8_t *out,
+		uint16_t out_len)
+{
+	uint16_t i;
+
+	if (in_len < out_len * 2)
+		return false;
+
+	if (!strncasecmp(str, "0x", 2))
+		str += 2;
+
+	for (i = 0; i < out_len; i++) {
+		if (sscanf(&str[i * 2], "%02hhx", &out[i]) != 1)
+			return false;
+	}
+
+	return true;
+}
+
 int main(int argc, char *argv[])
 {
 	struct sigaction sa;
@@ -952,6 +1206,8 @@ int main(int argc, char *argv[])
 	char *filename = NULL;
 	bool repeat = false;
 	unsigned int i;
+	uint8_t nconn = 1;
+	char *peer;
 
 	iso_qos = malloc(sizeof(*iso_qos));
 	/* Default to 16_2_1 */
@@ -962,7 +1218,7 @@ int main(int argc, char *argv[])
 		int opt;
 
 		opt = getopt_long(argc, argv,
-			"d::cmr::s::nb:i:j:hqt:CV:W:M:S:P:F:I:L:Y:R:B:G:T:",
+			"d::cmr::s::nb:i:j:hqt:CV:W:M:S:P:F:I:L:Y:R:B:G:T:e:k:N:",
 			main_options, NULL);
 		if (opt < 0)
 			break;
@@ -999,7 +1255,7 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'b':
-			if (optarg)
+			if (optarg && atoi(optarg) < MAX_DATA_SIZE)
 				data_size = atoi(optarg);
 			break;
 
@@ -1052,43 +1308,43 @@ int main(int argc, char *argv[])
 
 		case 'M':
 			if (optarg)
-				iso_qos->out.sdu = atoi(optarg);
+				iso_qos->ucast.out.sdu = atoi(optarg);
 			break;
 
 		case 'S':
 			if (optarg)
-				iso_qos->sca = atoi(optarg);
+				iso_qos->ucast.sca = atoi(optarg);
 			break;
 
 
 		case 'P':
 			if (optarg)
-				iso_qos->packing = atoi(optarg);
+				iso_qos->ucast.packing = atoi(optarg);
 			break;
 
 		case 'F':
 			if (optarg)
-				iso_qos->framing = atoi(optarg);
+				iso_qos->ucast.framing = atoi(optarg);
 			break;
 
 		case 'I':
 			if (optarg)
-				iso_qos->out.interval = atoi(optarg);
+				iso_qos->ucast.out.interval = atoi(optarg);
 			break;
 
 		case 'L':
 			if (optarg)
-				iso_qos->out.latency = atoi(optarg);
+				iso_qos->ucast.out.latency = atoi(optarg);
 			break;
 
 		case 'Y':
 			if (optarg)
-				iso_qos->out.phy = atoi(optarg);
+				iso_qos->ucast.out.phy = atoi(optarg);
 			break;
 
 		case 'R':
 			if (optarg)
-				iso_qos->out.rtn = atoi(optarg);
+				iso_qos->ucast.out.rtn = atoi(optarg);
 			break;
 
 		case 'B':
@@ -1107,12 +1363,42 @@ int main(int argc, char *argv[])
 
 		case 'G':
 			if (optarg)
-				iso_qos->cig = atoi(optarg);
+				iso_qos->ucast.cig = atoi(optarg);
 			break;
 
 		case 'T':
 			if (optarg)
-				iso_qos->cis = atoi(optarg);
+				iso_qos->ucast.cis = atoi(optarg);
+			break;
+
+		case 'e':
+			if (optarg)
+				iso_qos->bcast.encryption =
+					strtol(optarg, NULL, 16);
+			break;
+
+		case 'k':
+			if (optarg)
+				if (!str2hex(optarg, strlen(optarg),
+						iso_qos->bcast.bcode, 16))
+					exit(1);
+			break;
+
+		case 'N':
+			if (optarg)
+				num_bis = atoi(optarg);
+
+			if (num_bis > 1) {
+				/* If the user requested multiple BISes,
+				 * make sure that all BISes are bound
+				 * for the same BIG and advertising set
+				 */
+				if (iso_qos->bcast.big == BT_ISO_QOS_BIG_UNSET)
+					iso_qos->bcast.big = DEFAULT_BIG_ID;
+
+				if (iso_qos->bcast.bis == BT_ISO_QOS_BIS_UNSET)
+					iso_qos->bcast.bis = DEFAULT_BIS_ID;
+			}
 			break;
 
 		/* fall through */
@@ -1123,11 +1409,11 @@ int main(int argc, char *argv[])
 	}
 
 	if (inout) {
-		iso_qos->in = iso_qos->out;
+		iso_qos->ucast.in = iso_qos->ucast.out;
 	} else {
 		/* Align interval and latency even if is unidirectional */
-		iso_qos->in.interval = iso_qos->out.interval;
-		iso_qos->in.latency = iso_qos->out.latency;
+		iso_qos->ucast.in.interval = iso_qos->ucast.out.interval;
+		iso_qos->ucast.in.latency = iso_qos->ucast.out.latency;
 	}
 
 	buf = malloc(data_size);
@@ -1174,9 +1460,18 @@ int main(int argc, char *argv[])
 
 		switch (mode) {
 		case SEND:
-			send_mode(filename, argv[optind + i], i, repeat);
-			if (filename && strchr(filename, ','))
-				filename = strchr(filename, ',') + 1;
+			peer = argv[optind + i];
+			if (bachk(peer) < 0) {
+				fprintf(stderr, "Invalid peer address '%s'\n",
+						peer);
+				exit(1);
+			}
+			send_mode(filename, peer, i, repeat);
+			if (filename && strchr(filename, ',')) {
+				char *tmp = filename;
+				filename = strdup(strchr(filename, ',') + 1);
+				free(tmp);
+			}
 			break;
 
 		case RECONNECT:
@@ -1188,10 +1483,59 @@ int main(int argc, char *argv[])
 			break;
 
 		case CONNECT:
-			sk = do_connect(argv[optind + i]);
-			if (sk < 0)
+			peer = argv[optind + i];
+			if (bachk(peer) < 0) {
+				fprintf(stderr, "Invalid peer address '%s'\n",
+						peer);
 				exit(1);
-			dump_mode(-1, sk);
+			}
+
+			mgmt_set_experimental();
+
+			if (!strcmp(peer, "00:00:00:00:00:00"))
+				nconn = num_bis;
+
+			if (nconn > 1) {
+				int *sk_arr =  bcast_do_connect_mbis(nconn,
+								peer);
+
+				if (!sk_arr)
+					exit(1);
+
+				for (int i = 0; i < nconn; i++) {
+					if (fork()) {
+						/* Parent */
+						continue;
+					}
+
+					/* Child */
+					if (!strcmp(peer, "00:00:00:00:00:00"))
+						dump_mode(-1, sk_arr[i], peer);
+					else
+						dump_mode(-1, sk_arr[i], NULL);
+
+					exit(0);
+				}
+
+				/* Wait for children to exit */
+				while (wait(NULL) > 0)
+					;
+
+				for (int i = 0; i < nconn; i++)
+					close(sk_arr[i]);
+
+				free(sk_arr);
+			} else {
+				sk = do_connect(peer);
+				if (sk < 0)
+					exit(1);
+
+				if (!strcmp(peer, "00:00:00:00:00:00"))
+					dump_mode(-1, sk, peer);
+				else
+					dump_mode(-1, sk, NULL);
+			}
+
 			break;
 
 		case RECV:
diff --git a/tools/isotest.rst b/tools/isotest.rst
index b2f4e4b..fc5b3c5 100644
--- a/tools/isotest.rst
+++ b/tools/isotest.rst
@@ -153,6 +153,29 @@ OPTIONS
    * - **le_random**
      - LE Random Address
 
+-e, --enc=<ENCRYPTION>  Socket QoS BIG Encryption
+
+.. list-table::
+   :header-rows: 1
+   :widths: auto
+   :stub-columns: 1
+   :align: left
+
+   * - *ENCRYPTION*
+     - Description
+
+   * - **0x00**
+     - BIG unencrypted
+
+   * - **0x01**
+     - BIG encrypted
+
+-k, --bcode=<BCODE>  Socket QoS Broadcast Code
+
+-N, --nbis=<NBIS>  Number of BISes to create as part of a
+                   BIG (BIS broadcaster) or to synchronize
+                   to (BIS broadcast receiver)
+
 EXAMPLES
 ========
 
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 3f04640..1780c9f 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -15,6 +15,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <poll.h>
 #include <stdbool.h>
 
 #include <glib.h>
@@ -29,6 +30,9 @@
 
 #include "src/shared/tester.h"
 #include "src/shared/mgmt.h"
+#include "src/shared/util.h"
+
+#include "tester.h"
 
 struct test_data {
 	const void *test_data;
@@ -37,12 +41,16 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	unsigned int io_id;
+	unsigned int err_io_id;
 	uint16_t handle;
 	uint16_t scid;
 	uint16_t dcid;
+	struct l2cap_options l2o;
 	int sk;
 	int sk2;
 	bool host_disconnected;
+	int step;
+	struct tx_tstamp_data tx_ts;
 };
 
 struct l2cap_data {
@@ -50,7 +58,11 @@ struct l2cap_data {
 	uint16_t server_psm;
 	uint16_t cid;
 	uint8_t mode;
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
 	int expect_err;
+	int timeout;
 
 	uint8_t send_cmd_code;
 	const void *send_cmd;
@@ -81,8 +93,15 @@ struct l2cap_data {
 	bool server_not_advertising;
 	bool direct_advertising;
 	bool close_1;
+	bool defer;
 
 	bool shut_sock_wr;
+
+	/* Enable SO_TIMESTAMPING with these flags */
+	uint32_t so_timestamping;
+
+	/* Number of additional packets to send. */
+	unsigned int repeat_send;
 };
 
 static void print_debug(const char *str, void *user_data)
@@ -199,6 +218,12 @@ static void read_index_list_callback(uint8_t status, uint16_t length,
 static void test_pre_setup(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = test_data;
+
+	if (l2data && l2data->so_timestamping) {
+		if (tester_pre_setup_skip_by_default())
+			return;
+	}
 
 	data->mgmt = mgmt_new_default();
 	if (!data->mgmt) {
@@ -223,6 +248,11 @@ static void test_post_teardown(const void *test_data)
 		data->io_id = 0;
 	}
 
+	if (data->err_io_id > 0) {
+		g_source_remove(data->err_io_id);
+		data->err_io_id = 0;
+	}
+
 	hciemu_unref(data->hciemu);
 	data->hciemu = NULL;
 }
@@ -242,6 +272,7 @@ static void test_data_free(void *test_data)
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDR; \
 		user->io_id = 0; \
+		user->err_io_id = 0; \
 		user->test_data = data; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
@@ -256,6 +287,7 @@ static void test_data_free(void *test_data)
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_LE; \
 		user->io_id = 0; \
+		user->err_io_id = 0; \
 		user->test_data = data; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
@@ -269,6 +301,15 @@ static const struct l2cap_data client_connect_success_test = {
 	.server_psm = 0x1001,
 };
 
+static const struct l2cap_data client_connect_close_test = {
+	.client_psm = 0x1001,
+};
+
+static const struct l2cap_data client_connect_timeout_test = {
+	.client_psm = 0x1001,
+	.timeout = 1
+};
+
 static const struct l2cap_data client_connect_ssp_success_test_1 = {
 	.client_psm = 0x1001,
 	.server_psm = 0x1001,
@@ -295,6 +336,16 @@ static const struct l2cap_data client_connect_pin_success_test = {
 
 static uint8_t l2_data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
 
+const uint8_t l2_data_32k[32768] = { [0 ... 4095] =  0x00,
+				[4096 ... 8191] =  0x01,
+				[8192 ... 12287] =  0x02,
+				[12288 ... 16383] =  0x03,
+				[16384 ... 20479] =  0x04,
+				[20480 ... 24575] =  0x05,
+				[24576 ... 28671] =  0x06,
+				[28672 ... 32767] =  0x07,
+};
+
 static const struct l2cap_data client_connect_read_success_test = {
 	.client_psm = 0x1001,
 	.server_psm = 0x1001,
@@ -302,6 +353,13 @@ static const struct l2cap_data client_connect_read_success_test = {
 	.data_len = sizeof(l2_data),
 };
 
+static const struct l2cap_data client_connect_read_32k_success_test = {
+	.client_psm = 0x1001,
+	.server_psm = 0x1001,
+	.read_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
 static const struct l2cap_data client_connect_write_success_test = {
 	.client_psm = 0x1001,
 	.server_psm = 0x1001,
@@ -309,6 +367,24 @@ static const struct l2cap_data client_connect_write_success_test = {
 	.data_len = sizeof(l2_data),
 };
 
+static const struct l2cap_data client_connect_write_32k_success_test = {
+	.client_psm = 0x1001,
+	.server_psm = 0x1001,
+	.write_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
+static const struct l2cap_data client_connect_tx_timestamping_test = {
+	.client_psm = 0x1001,
+	.server_psm = 0x1001,
+	.write_data = l2_data,
+	.data_len = sizeof(l2_data),
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_OPT_ID |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+	.repeat_send = 2,
+};
+
 static const struct l2cap_data client_connect_shut_wr_success_test = {
 	.client_psm = 0x1001,
 	.server_psm = 0x1001,
@@ -351,6 +427,16 @@ static const struct l2cap_data l2cap_server_read_success_test = {
 	.data_len = sizeof(l2_data),
 };
 
+static const struct l2cap_data l2cap_server_read_32k_success_test = {
+	.server_psm = 0x1001,
+	.send_cmd_code = BT_L2CAP_PDU_CONN_REQ,
+	.send_cmd = l2cap_connect_req,
+	.send_cmd_len = sizeof(l2cap_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_CONN_RSP,
+	.read_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
 static const struct l2cap_data l2cap_server_write_success_test = {
 	.server_psm = 0x1001,
 	.send_cmd_code = BT_L2CAP_PDU_CONN_REQ,
@@ -361,6 +447,16 @@ static const struct l2cap_data l2cap_server_write_success_test = {
 	.data_len = sizeof(l2_data),
 };
 
+static const struct l2cap_data l2cap_server_write_32k_success_test = {
+	.server_psm = 0x1001,
+	.send_cmd_code = BT_L2CAP_PDU_CONN_REQ,
+	.send_cmd = l2cap_connect_req,
+	.send_cmd_len = sizeof(l2cap_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_CONN_RSP,
+	.write_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
 static const uint8_t l2cap_sec_block_rsp[] = {	0x00, 0x00,	/* dcid */
 						0x41, 0x00,	/* scid */
 						0x03, 0x00,	/* Sec Block */
@@ -436,6 +532,71 @@ static const struct l2cap_data le_client_connect_success_test_1 = {
 	.server_psm = 0x0080,
 };
 
+static const struct l2cap_data le_client_connect_close_test_1 = {
+	.client_psm = 0x0080,
+};
+
+static const struct l2cap_data le_client_connect_timeout_test_1 = {
+	.client_psm = 0x0080,
+	.timeout = 1,
+};
+
+static const struct l2cap_data le_client_connect_read_success_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.read_data = l2_data,
+	.data_len = sizeof(l2_data),
+};
+
+static const struct l2cap_data le_client_connect_read_32k_success_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mtu = 672,
+	.mps = 251,
+	/* Given enough credits to complete the transfer without waiting for
+	 * more credits.
+	 * credits = round_up(data size / mtu) * round_up(mtu / mps)
+	 * credits = 49 * 3
+	 * credits = 147
+	 */
+	.credits = 147,
+	.read_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
+static const struct l2cap_data le_client_connect_write_success_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.write_data = l2_data,
+	.data_len = sizeof(l2_data),
+};
+
+static const struct l2cap_data le_client_connect_write_32k_success_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mtu = 672,
+	.mps = 251,
+	/* Given enough credits to complete the transfer without waiting for
+	 * more credits.
+	 * credits = round_up(data size / mtu) * round_up(mtu / mps)
+	 * credits = 49 * 3
+	 * credits = 147
+	 */
+	.credits = 147,
+	.write_data = l2_data_32k,
+	.data_len = sizeof(l2_data_32k),
+};
+
+static const struct l2cap_data le_client_connect_tx_timestamping_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.write_data = l2_data,
+	.data_len = sizeof(l2_data),
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_OPT_ID |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+};
+
 static const struct l2cap_data le_client_connect_adv_success_test_1 = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
@@ -540,6 +701,64 @@ static const struct l2cap_data le_server_nval_scid_test = {
 	.expect_cmd_len = sizeof(nval_le_connect_rsp),
 };
 
+static const uint8_t ecred_connect_req[] = {	0x80, 0x00, /* PSM */
+						0x40, 0x00, /* MTU */
+						0x40, 0x00, /* MPS */
+						0x05, 0x00, /* Credits */
+						0x41, 0x00, /* SCID #1 */
+						0x42, 0x00, /* SCID #2 */
+						0x43, 0x00, /* SCID #3 */
+						0x44, 0x00, /* SCID #4 */
+						0x45, 0x00, /* SCID #5 */
+};
+
+static const uint8_t ecred_connect_rsp[] = {	0xa0, 0x02, /* MTU */
+						0xbc, 0x00, /* MPS */
+						0x04, 0x00, /* Credits */
+						0x00, 0x00, /* Result */
+						0x40, 0x00, /* DCID #1 */
+						0x41, 0x00, /* DCID #2 */
+						0x42, 0x00, /* DCID #3 */
+						0x43, 0x00, /* DCID #4 */
+						0x44, 0x00, /* DCID #5 */
+};
+
+static const struct l2cap_data ext_flowctl_server_success_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+};
+
+static const uint8_t nval_ecred_connect_req[] = {
+						0x80, 0x00, /* PSM */
+						0x40, 0x00, /* MTU */
+						0x40, 0x00, /* MPS */
+						0x05, 0x00, /* Credits */
+						0x01, 0x00, /* SCID #1 */
+};
+
+static const uint8_t nval_ecred_connect_rsp[] = {
+						0x00, 0x00, /* MTU */
+						0x00, 0x00, /* MPS */
+						0x00, 0x00, /* Credits */
+						0x09, 0x00, /* Result */
+						0x00, 0x00, /* DCID #1 */
+};
+
+static const struct l2cap_data ext_flowctl_server_nval_scid_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = nval_ecred_connect_req,
+	.send_cmd_len = sizeof(nval_ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = nval_ecred_connect_rsp,
+	.expect_cmd_len = sizeof(nval_ecred_connect_rsp),
+};
+
 static const struct l2cap_data le_att_client_connect_success_test_1 = {
 	.cid = 0x0004,
 	.sec_level = BT_SECURITY_LOW,
@@ -549,12 +768,86 @@ static const struct l2cap_data le_att_server_success_test_1 = {
 	.cid = 0x0004,
 };
 
+static const struct l2cap_data le_eatt_client_connect_success_test_1 = {
+	.client_psm = 0x0027,
+	.server_psm = 0x0027,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.sec_level = BT_SECURITY_LOW,
+};
+
+static const uint8_t eatt_connect_req[] = {	0x27, 0x00, /* PSM */
+						0x40, 0x00, /* MTU */
+						0x40, 0x00, /* MPS */
+						0x05, 0x00, /* Credits */
+						0x41, 0x00, /* SCID #1 */
+};
+
+static const uint8_t eatt_connect_rsp[] = {	0xa0, 0x02, /* MTU */
+						0xbc, 0x00, /* MPS */
+						0x04, 0x00, /* Credits */
+						0x00, 0x00, /* Result */
+						0x40, 0x00, /* DCID #1 */
+};
+
+static const struct l2cap_data le_eatt_server_success_test_1 = {
+	.server_psm = 0x0027,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = eatt_connect_req,
+	.send_cmd_len = sizeof(eatt_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = eatt_connect_rsp,
+	.expect_cmd_len = sizeof(eatt_connect_rsp),
+	.defer = true,
+};
+
+static const uint8_t eatt_reject_req[] = {	0x27, 0x00, /* PSM */
+						0x40, 0x00, /* MTU */
+						0x40, 0x00, /* MPS */
+						0x05, 0x00, /* Credits */
+						0x41, 0x00, /* SCID #1 */
+						0x42, 0x00, /* SCID #2 */
+						0x43, 0x00, /* SCID #3 */
+						0x44, 0x00, /* SCID #4 */
+						0x45, 0x00, /* SCID #5 */
+};
+
+static const uint8_t eatt_reject_rsp[] = {	0xa0, 0x02, /* MTU */
+						0xbc, 0x00, /* MPS */
+						0x04, 0x00, /* Credits */
+						0x06, 0x00, /* Result */
+};
+
+static const struct l2cap_data le_eatt_server_reject_test_1 = {
+	.server_psm = 0x0027,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = eatt_reject_req,
+	.send_cmd_len = sizeof(eatt_reject_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = eatt_reject_rsp,
+	.expect_cmd_len = sizeof(eatt_reject_rsp),
+	.defer = true,
+	.expect_err = -1,
+};
+
 static const struct l2cap_data ext_flowctl_client_connect_success_test_1 = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
 	.mode = BT_MODE_EXT_FLOWCTL,
 };
 
+static const struct l2cap_data ext_flowctl_client_connect_close_test_1 = {
+	.client_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+};
+
+static const struct l2cap_data ext_flowctl_client_connect_timeout_test_1 = {
+	.client_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.timeout = 1,
+};
+
 static const struct l2cap_data ext_flowctl_client_connect_adv_success_test_1 = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
@@ -657,6 +950,11 @@ static void setup_powered_client_callback(uint8_t status, uint16_t length,
 
 	tester_print("Controller powered on");
 
+	if (l2data && l2data->timeout) {
+		tester_setup_complete();
+		return;
+	}
+
 	bthost = hciemu_client_get_host(data->hciemu);
 	bthost_set_cmd_complete_cb(bthost, client_cmd_complete, user_data);
 
@@ -886,48 +1184,54 @@ static void test_basic(const void *test_data)
 	tester_test_passed();
 }
 
-static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static void received_data(struct test_data *tdata, const void *buf,
+					uint16_t len, const void *data,
+					uint16_t data_len)
 {
-	struct test_data *data = tester_get_data();
-	const struct l2cap_data *l2data = data->test_data;
-	char buf[1024];
-	int sk;
+	static struct iovec iov;
 
-	sk = g_io_channel_unix_get_fd(io);
-	if (read(sk, buf, l2data->data_len) != l2data->data_len) {
-		tester_warn("Unable to read %u bytes", l2data->data_len);
-		tester_test_failed();
-		return FALSE;
-	}
+	util_iov_append(&iov, buf, len);
 
-	if (memcmp(buf, l2data->read_data, l2data->data_len))
+	tester_debug("read: %d/%zu", len, iov.iov_len);
+
+	/* Check if all the data has been received */
+	if (iov.iov_len < data_len)
+		return;
+
+	--tdata->step;
+
+	if (iov.iov_len != data_len || memcmp(iov.iov_base, data, data_len))
 		tester_test_failed();
-	else
+	else if (!tdata->step)
 		tester_test_passed();
 
-	return FALSE;
+	free(iov.iov_base);
+	iov.iov_base = NULL;
+	iov.iov_len = 0;
 }
 
-static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
+static gboolean sock_received_data(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	char buf[1024];
 	int sk;
+	ssize_t len;
 
 	sk = g_io_channel_unix_get_fd(io);
-	if (read(sk, buf, l2data->data_len) != l2data->data_len) {
-		tester_warn("Unable to read %u bytes", l2data->data_len);
+
+	len = read(sk, buf, sizeof(buf));
+	if (len < 0) {
+		tester_warn("Unable to read: %s (%d)", strerror(errno), errno);
 		tester_test_failed();
 		return FALSE;
 	}
 
-	if (memcmp(buf, l2data->read_data, l2data->data_len))
-		tester_test_failed();
-	else
-		tester_test_passed();
+	received_data(data, buf, len, l2data->read_data, l2data->data_len);
+
+	if (data->step)
+		return TRUE;
 
 	return FALSE;
 }
@@ -938,32 +1242,7 @@ static void bthost_received_data(const void *buf, uint16_t len,
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 
-	if (len != l2data->data_len) {
-		tester_test_failed();
-		return;
-	}
-
-	if (memcmp(buf, l2data->write_data, l2data->data_len))
-		tester_test_failed();
-	else
-		tester_test_passed();
-}
-
-static void server_bthost_received_data(const void *buf, uint16_t len,
-							void *user_data)
-{
-	struct test_data *data = tester_get_data();
-	const struct l2cap_data *l2data = data->test_data;
-
-	if (len != l2data->data_len) {
-		tester_test_failed();
-		return;
-	}
-
-	if (memcmp(buf, l2data->write_data, l2data->data_len))
-		tester_test_failed();
-	else
-		tester_test_passed();
+	received_data(data, buf, len, l2data->write_data, l2data->data_len);
 }
 
 static gboolean socket_closed_cb(GIOChannel *io, GIOCondition cond,
@@ -971,6 +1250,10 @@ static gboolean socket_closed_cb(GIOChannel *io, GIOCondition cond,
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
+	int err, sk_err, sk;
+	socklen_t len = sizeof(sk_err);
+
+	tester_print("Disconnected");
 
 	if (l2data->shut_sock_wr) {
 		/* if socket is closed using SHUT_WR, L2CAP disconnection
@@ -984,51 +1267,202 @@ static gboolean socket_closed_cb(GIOChannel *io, GIOCondition cond,
 		}
 	}
 
+	data->io_id = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+		err = -errno;
+	else
+		err = -sk_err;
+
+	if (!l2data->timeout && -err != l2data->expect_err) {
+		tester_print("err %d != %d expected_err", -err,
+						l2data->expect_err);
+		tester_test_failed();
+	} else
+		tester_test_passed();
+
 	return FALSE;
 }
 
 static bool check_mtu(struct test_data *data, int sk)
 {
 	const struct l2cap_data *l2data = data->test_data;
-	struct l2cap_options l2o;
 	socklen_t len;
 
-	memset(&l2o, 0, sizeof(l2o));
+	memset(&data->l2o, 0, sizeof(data->l2o));
 
 	if (data->hciemu_type == HCIEMU_TYPE_LE &&
 				(l2data->client_psm || l2data->server_psm)) {
 		/* LE CoC enabled kernels should support BT_RCVMTU and
 		 * BT_SNDMTU.
 		 */
-		len = sizeof(l2o.imtu);
+		len = sizeof(data->l2o.imtu);
 		if (getsockopt(sk, SOL_BLUETOOTH, BT_RCVMTU,
-							&l2o.imtu, &len) < 0) {
+						&data->l2o.imtu, &len) < 0) {
 			tester_warn("getsockopt(BT_RCVMTU): %s (%d)",
 					strerror(errno), errno);
 			return false;
 		}
 
-		len = sizeof(l2o.omtu);
+		len = sizeof(data->l2o.omtu);
 		if (getsockopt(sk, SOL_BLUETOOTH, BT_SNDMTU,
-							&l2o.omtu, &len) < 0) {
+						&data->l2o.omtu, &len) < 0) {
 			tester_warn("getsockopt(BT_SNDMTU): %s (%d)",
 					strerror(errno), errno);
 			return false;
 		}
+
+		/* Take SDU len into account */
+		data->l2o.imtu -= 2;
+		data->l2o.omtu -= 2;
 	} else {
 		/* For non-LE CoC enabled kernels we need to fall back to
 		 * L2CAP_OPTIONS, so test support for it as well */
-		len = sizeof(l2o);
-		if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
+		len = sizeof(data->l2o);
+		if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &data->l2o,
+						&len) < 0) {
 			 tester_warn("getsockopt(L2CAP_OPTIONS): %s (%d)",
 						strerror(errno), errno);
 			 return false;
-		 }
+		}
 	}
 
 	return true;
 }
 
+static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = user_data;
+	const struct l2cap_data *l2data = data->test_data;
+	int sk = g_io_channel_unix_get_fd(io);
+	int err;
+
+	data->step--;
+
+	err = tx_tstamp_recv(&data->tx_ts, sk, l2data->data_len);
+	if (err > 0)
+		return TRUE;
+	else if (!err && !data->step)
+		tester_test_passed();
+	else
+		tester_test_failed();
+
+	data->err_io_id = 0;
+	return FALSE;
+}
+
+static void l2cap_tx_timestamping(struct test_data *data, GIOChannel *io)
+{
+	const struct l2cap_data *l2data = data->test_data;
+	int so = l2data->so_timestamping;
+	int sk;
+	int err;
+	unsigned int count;
+
+	if (!(l2data->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+		return;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	tester_print("Enabling TX timestamping");
+
+	tx_tstamp_init(&data->tx_ts, l2data->so_timestamping);
+
+	for (count = 0; count < l2data->repeat_send + 1; ++count)
+		data->step += tx_tstamp_expect(&data->tx_ts);
+
+	err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so));
+	if (err < 0) {
+		tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)",
+						strerror(errno), errno);
+		tester_test_failed();
+		return;
+	}
+
+	data->err_io_id = g_io_add_watch(io, G_IO_ERR, recv_errqueue, data);
+}
+
+static int l2cap_send(int sk, const void *data, size_t len, uint16_t mtu)
+{
+	struct iovec iov = { (void *)data, len };
+	int err;
+	size_t total = 0;
+
+	len = MIN(mtu, len);
+
+	while (iov.iov_len) {
+		size_t l = MIN(iov.iov_len, len);
+
+		err = write(sk, util_iov_pull_mem(&iov, l), l);
+		if (err < 0)
+			return -errno;
+
+		total += err;
+		tester_debug("write: %d/%zu", err, total);
+	}
+
+	return total;
+}
+
+static void l2cap_read_data(struct test_data *data, GIOChannel *io,
+							uint16_t cid)
+{
+	const struct l2cap_data *l2data = data->test_data;
+	struct bthost *bthost;
+	struct iovec iov = { (void *)l2data->read_data, l2data->data_len };
+	size_t len;
+
+	data->step = 0;
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	g_io_add_watch(io, G_IO_IN, sock_received_data, NULL);
+
+	len = MIN(iov.iov_len, data->l2o.imtu);
+
+	while (iov.iov_len) {
+		size_t l = MIN(iov.iov_len, len);
+
+		bthost_send_cid(bthost, data->handle, cid,
+					util_iov_pull_mem(&iov, l), l);
+	}
+
+	++data->step;
+}
+
+static void l2cap_write_data(struct test_data *data, GIOChannel *io,
+							uint16_t cid)
+{
+	const struct l2cap_data *l2data = data->test_data;
+	struct bthost *bthost;
+	ssize_t ret;
+	int sk;
+	unsigned int count;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	data->step = 0;
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_add_cid_hook(bthost, data->handle, cid, bthost_received_data,
+							NULL);
+
+	l2cap_tx_timestamping(data, io);
+
+	for (count = 0; count < l2data->repeat_send + 1; ++count) {
+		ret = l2cap_send(sk, l2data->write_data, l2data->data_len,
+							data->l2o.omtu);
+		if (ret != l2data->data_len) {
+			tester_warn("Unable to write all data: "
+					"%zd != %u", ret, l2data->data_len);
+			tester_test_failed();
+		}
+		++data->step;
+	}
+}
+
 static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -1051,7 +1485,7 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 		goto failed;
 	}
 
-	tester_print("Successfully connected");
+	tester_print("Successfully connected to CID 0x%04x", data->dcid);
 
 	if (!check_mtu(data, sk)) {
 		tester_test_failed();
@@ -1059,29 +1493,10 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 	}
 
 	if (l2data->read_data) {
-		struct bthost *bthost;
-
-		bthost = hciemu_client_get_host(data->hciemu);
-		g_io_add_watch(io, G_IO_IN, client_received_data, NULL);
-
-		bthost_send_cid(bthost, data->handle, data->dcid,
-					l2data->read_data, l2data->data_len);
-
+		l2cap_read_data(data, io, data->dcid);
 		return FALSE;
 	} else if (l2data->write_data) {
-		struct bthost *bthost;
-		ssize_t ret;
-
-		bthost = hciemu_client_get_host(data->hciemu);
-		bthost_add_cid_hook(bthost, data->handle, data->dcid,
-					bthost_received_data, NULL);
-
-		ret = write(sk, l2data->write_data, l2data->data_len);
-		if (ret != l2data->data_len) {
-			tester_warn("Unable to write all data");
-			tester_test_failed();
-		}
-
+		l2cap_write_data(data, io, data->dcid);
 		return FALSE;
 	} else if (l2data->shut_sock_wr) {
 		g_io_add_watch(io, G_IO_HUP, socket_closed_cb, NULL);
@@ -1235,6 +1650,8 @@ static void client_l2cap_connect_cb(uint16_t handle, uint16_t cid,
 {
 	struct test_data *data = user_data;
 
+	tester_debug("Client connect CID 0x%04x handle 0x%04x", cid, handle);
+
 	data->dcid = cid;
 	data->handle = handle;
 }
@@ -1295,9 +1712,20 @@ static void test_connect(const void *test_data)
 		if (l2data->shut_sock_wr)
 			host_disconnect_cb = client_l2cap_disconnect_cb;
 
-		bthost_add_l2cap_server(bthost, l2data->server_psm,
-					host_connect_cb, host_disconnect_cb,
-					data);
+		if (l2data->mtu || l2data->mps || l2data->credits)
+			bthost_add_l2cap_server_custom(bthost,
+							l2data->server_psm,
+							l2data->mtu,
+							l2data->mps,
+							l2data->credits,
+							host_connect_cb,
+							host_disconnect_cb,
+							data);
+		else
+			bthost_add_l2cap_server(bthost, l2data->server_psm,
+							host_connect_cb,
+							host_disconnect_cb,
+							data);
 	}
 
 	if (l2data->direct_advertising)
@@ -1331,6 +1759,82 @@ static void test_connect(const void *test_data)
 	tester_print("Connect in progress");
 }
 
+static void test_connect_close(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
+	GIOChannel *io;
+	int sk;
+
+	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
+							l2data->mode);
+	if (sk < 0) {
+		if (sk == -ENOPROTOOPT)
+			tester_test_abort();
+		else
+			tester_test_failed();
+		return;
+	}
+
+	if (connect_l2cap_sock(data, sk, l2data->client_psm,
+							l2data->cid) < 0) {
+		close(sk);
+		tester_test_failed();
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+	data->io_id = g_io_add_watch(io, G_IO_HUP, socket_closed_cb, NULL);
+	g_io_channel_unref(io);
+
+	shutdown(sk, SHUT_RDWR);
+}
+
+static void test_connect_timeout(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
+	GIOChannel *io;
+	int sk;
+	struct timeval sndto;
+	socklen_t len;
+
+	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
+							l2data->mode);
+	if (sk < 0) {
+		if (sk == -ENOPROTOOPT)
+			tester_test_abort();
+		else
+			tester_test_failed();
+		return;
+	}
+
+	memset(&sndto, 0, sizeof(sndto));
+
+	sndto.tv_sec = l2data->timeout;
+	len = sizeof(sndto);
+	if (setsockopt(sk, SOL_SOCKET, SO_SNDTIMEO, &sndto, len) < 0) {
+		tester_print("Can't set SO_SNDTIMEO: %s (%d)", strerror(errno),
+								errno);
+		close(sk);
+		tester_test_failed();
+		return;
+	}
+
+	if (connect_l2cap_sock(data, sk, l2data->client_psm,
+							l2data->cid) < 0) {
+		close(sk);
+		tester_test_failed();
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+	data->io_id = g_io_add_watch(io, G_IO_HUP, socket_closed_cb, NULL);
+	g_io_channel_unref(io);
+}
+
 static void test_connect_reject(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -1689,71 +2193,103 @@ static void test_connect_2(const void *test_data)
 								defer);
 }
 
-static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
+static gboolean l2cap_accept_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
-	int sk, new_sk;
-
-	data->io_id = 0;
+	int sk;
 
 	sk = g_io_channel_unix_get_fd(io);
 
-	new_sk = accept(sk, NULL, NULL);
-	if (new_sk < 0) {
-		tester_warn("accept failed: %s (%u)", strerror(errno), errno);
+	if (!check_mtu(data, sk)) {
 		tester_test_failed();
 		return FALSE;
 	}
 
-	if (!check_mtu(data, new_sk)) {
-		tester_test_failed();
-		close(new_sk);
+	if (l2data->read_data) {
+		l2cap_read_data(data, io, data->dcid);
+		return FALSE;
+	} else if (l2data->write_data) {
+		l2cap_write_data(data, io, data->scid);
 		return FALSE;
 	}
 
-	if (l2data->read_data) {
-		struct bthost *bthost;
-		GIOChannel *new_io;
+	tester_print("Successfully connected");
 
-		new_io = g_io_channel_unix_new(new_sk);
-		g_io_channel_set_close_on_unref(new_io, TRUE);
+	tester_test_passed();
 
-		bthost = hciemu_client_get_host(data->hciemu);
-		g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL);
-		bthost_send_cid(bthost, data->handle, data->dcid,
-					l2data->read_data, l2data->data_len);
+	return FALSE;
+}
 
-		g_io_channel_unref(new_io);
+static bool defer_accept(struct test_data *data, GIOChannel *io)
+{
+	int sk;
+	char c;
+	struct pollfd pfd;
 
-		return FALSE;
-	} else if (l2data->write_data) {
-		struct bthost *bthost;
-		ssize_t ret;
+	sk = g_io_channel_unix_get_fd(io);
 
-		bthost = hciemu_client_get_host(data->hciemu);
-		bthost_add_cid_hook(bthost, data->handle, data->scid,
-					server_bthost_received_data, NULL);
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = sk;
+	pfd.events = POLLOUT;
 
-		ret = write(new_sk, l2data->write_data, l2data->data_len);
-		close(new_sk);
+	if (poll(&pfd, 1, 0) < 0) {
+		tester_warn("poll: %s (%d)", strerror(errno), errno);
+		return false;
+	}
 
-		if (ret != l2data->data_len) {
-			tester_warn("Unable to write all data");
-			tester_test_failed();
+	if (!(pfd.revents & POLLOUT)) {
+		if (read(sk, &c, 1) < 0) {
+			tester_warn("read: %s (%d)", strerror(errno), errno);
+			return false;
 		}
+	}
+
+	data->io_id = g_io_add_watch(io, G_IO_OUT, l2cap_accept_cb, NULL);
+
+	g_io_channel_unref(io);
+
+	tester_print("Accept deferred setup");
+
+	return true;
+}
+
+static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
+	int sk, new_sk;
+
+	data->io_id = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
 
+	new_sk = accept(sk, NULL, NULL);
+	if (new_sk < 0) {
+		tester_warn("accept failed: %s (%u)", strerror(errno), errno);
+		tester_test_failed();
 		return FALSE;
 	}
 
-	tester_print("Successfully connected");
+	io = g_io_channel_unix_new(new_sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
 
-	close(new_sk);
+	if (l2data->defer) {
+		if (l2data->expect_err < 0) {
+			g_io_channel_unref(io);
+			return FALSE;
+		}
 
-	tester_test_passed();
+		if (!defer_accept(data, io)) {
+			tester_warn("Unable to accept deferred setup");
+			tester_test_failed();
+		}
+		return FALSE;
+	}
 
-	return FALSE;
+	return l2cap_accept_cb(io, cond, user_data);
 }
 
 static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len,
@@ -1767,7 +2303,7 @@ static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len,
 	if (code != l2data->expect_cmd_code) {
 		tester_warn("Unexpected L2CAP response code (expected 0x%02x)",
 						l2data->expect_cmd_code);
-		return;
+		goto failed;
 	}
 
 	if (code == BT_L2CAP_PDU_CONN_RSP) {
@@ -1844,6 +2380,8 @@ static void test_server(const void *test_data)
 	int sk;
 
 	if (l2data->server_psm || l2data->cid) {
+		int opt = 1;
+
 		sk = create_l2cap_sock(data, l2data->server_psm,
 					l2data->cid, l2data->sec_level,
 					l2data->mode);
@@ -1852,6 +2390,15 @@ static void test_server(const void *test_data)
 			return;
 		}
 
+		if (l2data->defer && setsockopt(sk, SOL_BLUETOOTH,
+				BT_DEFER_SETUP, &opt, sizeof(opt)) < 0) {
+			tester_warn("Can't enable deferred setup: %s (%d)",
+						strerror(errno), errno);
+			tester_test_failed();
+			close(sk);
+			return;
+		}
+
 		if (listen(sk, 5) < 0) {
 			tester_warn("listening on socket failed: %s (%u)",
 					strerror(errno), errno);
@@ -1935,6 +2482,15 @@ int main(int argc, char *argv[])
 					&client_connect_success_test,
 					setup_powered_client, test_connect);
 
+	test_l2cap_bredr("L2CAP BR/EDR Client - Close",
+					&client_connect_close_test,
+					setup_powered_client,
+					test_connect_close);
+	test_l2cap_bredr("L2CAP BR/EDR Client - Timeout",
+					&client_connect_timeout_test,
+					setup_powered_client,
+					test_connect_timeout);
+
 	test_l2cap_bredr("L2CAP BR/EDR Client SSP - Success 1",
 					&client_connect_ssp_success_test_1,
 					setup_powered_client, test_connect);
@@ -1949,10 +2505,22 @@ int main(int argc, char *argv[])
 					&client_connect_read_success_test,
 					setup_powered_client, test_connect);
 
+	test_l2cap_bredr("L2CAP BR/EDR Client - Read 32k Success",
+					&client_connect_read_32k_success_test,
+					setup_powered_client, test_connect);
+
 	test_l2cap_bredr("L2CAP BR/EDR Client - Write Success",
 					&client_connect_write_success_test,
 					setup_powered_client, test_connect);
 
+	test_l2cap_bredr("L2CAP BR/EDR Client - Write 32k Success",
+					&client_connect_write_32k_success_test,
+					setup_powered_client, test_connect);
+
+	test_l2cap_bredr("L2CAP BR/EDR Client - TX Timestamping",
+					&client_connect_tx_timestamping_test,
+					setup_powered_client, test_connect);
+
 	test_l2cap_bredr("L2CAP BR/EDR Client - Invalid PSM 1",
 					&client_connect_nval_psm_test_1,
 					setup_powered_client, test_connect);
@@ -1977,10 +2545,18 @@ int main(int argc, char *argv[])
 					&l2cap_server_read_success_test,
 					setup_powered_server, test_server);
 
+	test_l2cap_bredr("L2CAP BR/EDR Server - Read 32k Success",
+					&l2cap_server_read_32k_success_test,
+					setup_powered_server, test_server);
+
 	test_l2cap_bredr("L2CAP BR/EDR Server - Write Success",
 					&l2cap_server_write_success_test,
 					setup_powered_server, test_server);
 
+	test_l2cap_bredr("L2CAP BR/EDR Server - Write 32k Success",
+					&l2cap_server_write_32k_success_test,
+					setup_powered_server, test_server);
+
 	test_l2cap_bredr("L2CAP BR/EDR Server - Security Block",
 					&l2cap_server_sec_block_test,
 					setup_powered_server, test_server);
@@ -2001,6 +2577,27 @@ int main(int argc, char *argv[])
 	test_l2cap_le("L2CAP LE Client - Success",
 				&le_client_connect_success_test_1,
 				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE Client - Close",
+				&le_client_connect_close_test_1,
+				setup_powered_client, test_connect_close);
+	test_l2cap_le("L2CAP LE Client - Timeout",
+				&le_client_connect_timeout_test_1,
+				setup_powered_client, test_connect_timeout);
+	test_l2cap_le("L2CAP LE Client - Read Success",
+				&le_client_connect_read_success_test,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE Client - Read 32k Success",
+				&le_client_connect_read_32k_success_test,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE Client - Write Success",
+				&le_client_connect_write_success_test,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE Client - Write 32k Success",
+				&le_client_connect_write_32k_success_test,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE Client - TX Timestamping",
+				&le_client_connect_tx_timestamping_test,
+				setup_powered_client, test_connect);
 	test_l2cap_le("L2CAP LE Client, Direct Advertising - Success",
 				&le_client_connect_adv_success_test_1,
 				setup_powered_client, test_connect);
@@ -2046,6 +2643,12 @@ int main(int argc, char *argv[])
 	test_l2cap_le("L2CAP Ext-Flowctl Client - Success",
 				&ext_flowctl_client_connect_success_test_1,
 				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Close",
+				&ext_flowctl_client_connect_close_test_1,
+				setup_powered_client, test_connect_close);
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Timeout",
+				&ext_flowctl_client_connect_timeout_test_1,
+				setup_powered_client, test_connect_timeout);
 	test_l2cap_le("L2CAP Ext-Flowctl Client, Direct Advertising - Success",
 				&ext_flowctl_client_connect_adv_success_test_1,
 				setup_powered_client, test_connect);
@@ -2066,6 +2669,13 @@ int main(int argc, char *argv[])
 				setup_powered_client,
 				test_connect_2);
 
+	test_l2cap_le("L2CAP Ext-Flowctl Server - Success",
+				&ext_flowctl_server_success_test,
+				setup_powered_server, test_server);
+	test_l2cap_le("L2CAP Ext-Flowctl Server - Nval SCID",
+				&ext_flowctl_server_nval_scid_test,
+				setup_powered_server, test_server);
+
 	test_l2cap_le("L2CAP LE ATT Client - Success",
 				&le_att_client_connect_success_test_1,
 				setup_powered_client, test_connect);
@@ -2073,5 +2683,15 @@ int main(int argc, char *argv[])
 				&le_att_server_success_test_1,
 				setup_powered_server, test_server);
 
+	test_l2cap_le("L2CAP LE EATT Client - Success",
+				&le_eatt_client_connect_success_test_1,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP LE EATT Server - Success",
+				&le_eatt_server_success_test_1,
+				setup_powered_server, test_server);
+	test_l2cap_le("L2CAP LE EATT Server - Reject",
+				&le_eatt_server_reject_test_1,
+				setup_powered_server, test_server);
+
 	return tester_run();
 }
diff --git a/tools/l2ping.1 b/tools/l2ping.1
new file mode 100644
index 0000000..9585c96
--- /dev/null
+++ b/tools/l2ping.1
@@ -0,0 +1,92 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "L2PING" "1" "Jan 22, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+l2ping \- Send L2CAP echo request and receive answer
+.SH SYNOPSIS
+.sp
+\fBl2ping\fP [\fIOPTIONS\fP] \fIbd_addr\fP
+.SH DESCRIPTION
+.sp
+\fBl2ping(1)\fP sends a L2CAP echo request to the Bluetooth MAC address bd_addr
+given in dotted hex notation.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-i \ <hciX>
+The command is applied to device \fIhciX\fP, which must be the
+name of an installed Bluetooth device (X = 0, 1, 2, ...)
+If not specified, the command will be sent to the first
+available Bluetooth device.
+.TP
+.BI \-s \ size
+The size of the data packets to be sent.
+.TP
+.BI \-c \ count
+Send count number of packets then exit.
+.TP
+.BI \-t \ timeout
+Wait timeout seconds for the response.
+.TP
+.BI \-d \ delay
+Wait delay seconds between pings.
+.TP
+.B  \-f
+Kind of flood ping. Use with care! It reduces the delay time
+between packets to 0.
+.TP
+.B  \-r
+Reverse ping (gnip?). Send echo response instead of echo
+request.
+.TP
+.B  \-v
+Verify response payload is identical to request payload.
+It is not required for remote stacks to return the request
+payload, but most stacks do (including Bluez).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B bd_addr
+The Bluetooth MAC address to be pinged in dotted hex notation
+like \fB01:02:03:ab:cd:ef\fP or \fB01:EF:cd:aB:02:03\fP
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>, Nils Faerber <nils@kernelconcepts.de>, Adam Laurie <adam@algroup.co.uk>.
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/l2test.c b/tools/l2test.c
index 5aae4b6..4c22968 100644
--- a/tools/l2test.c
+++ b/tools/l2test.c
@@ -155,6 +155,24 @@ static struct lookup_table bdaddr_types[] = {
 	{ NULL,		0			},
 };
 
+static int bt_mode_to_l2cap_mode(int mode)
+{
+	switch (mode) {
+	case BT_MODE_BASIC:
+		return L2CAP_MODE_BASIC;
+	case BT_MODE_ERTM:
+		return L2CAP_MODE_ERTM;
+	case BT_MODE_STREAMING:
+		return L2CAP_MODE_STREAMING;
+	case BT_MODE_LE_FLOWCTL:
+		return L2CAP_MODE_LE_FLOWCTL;
+	case BT_MODE_EXT_FLOWCTL:
+		return L2CAP_MODE_FLOWCTL;
+	default:
+		return mode;
+	}
+}
+
 static int get_lookup_flag(struct lookup_table *table, char *name)
 {
 	int i;
@@ -287,9 +305,11 @@ static int getopts(int sk, struct l2cap_options *opts, bool connected)
 
 static int setopts(int sk, struct l2cap_options *opts)
 {
-	if (bdaddr_type == BDADDR_BREDR)
+	if (bdaddr_type == BDADDR_BREDR) {
+		opts->mode = bt_mode_to_l2cap_mode(opts->mode);
 		return setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, opts,
 								sizeof(*opts));
+	}
 
 	if (opts->mode) {
 		if (setsockopt(sk, SOL_BLUETOOTH, BT_MODE, &opts->mode,
@@ -893,7 +913,7 @@ static void recv_mode(int sk)
 					timestamp = 0;
 					memset(ts, 0, sizeof(ts));
 				} else {
-					sprintf(ts, "[%lld.%lld] ",
+					snprintf(ts, sizeof(ts), "[%lld.%lld] ",
 							(long long)tv.tv_sec,
 							(long long)tv.tv_usec);
 				}
@@ -955,6 +975,11 @@ static void do_send(int sk)
 			buflen = (size > omtu) ? omtu : size;
 
 			len = send(sk, buf + sent, buflen, 0);
+			if (len < 0) {
+				syslog(LOG_ERR, "Send failed: %s (%d)",
+							strerror(errno), errno);
+				exit(1);
+			}
 
 			sent += len;
 			size -= len;
@@ -1416,7 +1441,7 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'P':
-			psm = atoi(optarg);
+			psm = strtoul(optarg, NULL, 0);
 			break;
 
 		case 'I':
diff --git a/tools/mesh-cfgclient.c b/tools/mesh-cfgclient.c
index 237afbb..e64950a 100644
--- a/tools/mesh-cfgclient.c
+++ b/tools/mesh-cfgclient.c
@@ -38,11 +38,15 @@
 #include "tools/mesh/model.h"
 #include "tools/mesh/remote.h"
 
-#define PROMPT_ON	COLOR_BLUE "[mesh-cfgclient]" COLOR_OFF "# "
+#define PROMPT_ON	"[mesh-cfgclient]# "
 #define PROMPT_OFF	"Waiting to connect to bluetooth-meshd..."
 
 #define CFG_SRV_MODEL	0x0000
 #define CFG_CLI_MODEL	0x0001
+#define RPR_SVR_MODEL	0x0004
+#define RPR_CLI_MODEL	0x0005
+#define PRV_BEACON_SVR	0x0008
+#define PRV_BEACON_CLI	0x0009
 
 #define UNPROV_SCAN_MAX_SECS	300
 
@@ -57,7 +61,7 @@
 struct meshcfg_el {
 	const char *path;
 	uint8_t index;
-	uint16_t mods[2];
+	uint16_t mods[4];
 };
 
 struct meshcfg_app {
@@ -83,8 +87,12 @@ struct meshcfg_node {
 
 struct unprov_device {
 	time_t last_seen;
-	int16_t rssi;
+	int id;
+	uint32_t uri_hash;
 	uint8_t uuid[16];
+	int16_t rssi;
+	uint16_t server;
+	uint16_t oob_info;
 };
 
 struct generic_request {
@@ -96,8 +104,16 @@ struct generic_request {
 	const char *str;
 };
 
+struct scan_data {
+	uint16_t dst;
+	uint16_t secs;
+};
+
+static void *finalized = L_UINT_TO_PTR(-1);
+
 static struct l_dbus *dbus;
 
+static struct l_timeout *scan_timeout;
 static struct l_queue *node_proxies;
 static struct l_dbus_proxy *net_proxy;
 static struct meshcfg_node *local;
@@ -130,7 +146,8 @@ static struct meshcfg_app app = {
 	.ele = {
 		.path = "/mesh/cfgclient/ele0",
 		.index = 0,
-		.mods = {CFG_SRV_MODEL, CFG_CLI_MODEL}
+		.mods = {CFG_SRV_MODEL, CFG_CLI_MODEL,
+					PRV_BEACON_SVR, PRV_BEACON_CLI}
 	}
 };
 
@@ -197,23 +214,57 @@ static bool parse_argument_on_off(int argc, char *argv[], bool *value)
 static bool match_device_uuid(const void *a, const void *b)
 {
 	const struct unprov_device *dev = a;
-	const uint8_t *uuid = b;
 
-	return (memcmp(dev->uuid, uuid, 16) == 0);
+	if (a == finalized)
+		return false;
+
+	return memcmp(dev->uuid, b, 16) == 0;
 }
 
-static void print_device(void *a, void *b)
+static bool match_by_id(const void *a, const void *b)
 {
 	const struct unprov_device *dev = a;
-	struct tm *tm = localtime(&dev->last_seen);
+	int id = L_PTR_TO_UINT(b);
+
+	if (a == finalized)
+		return false;
+
+	l_info("test %d %d", dev->id, id);
+	return dev->id == id;
+}
+
+static bool match_by_srv_uuid(const void *a, const void *b)
+{
+	const struct unprov_device *dev = a;
+	const struct unprov_device *new_dev = b;
+
+	if (a == finalized)
+		return false;
+
+	return (dev->server == new_dev->server) &&
+				(memcmp(dev->uuid, new_dev->uuid, 16) == 0);
+}
+
+static void print_device(void *a, void *b)
+{
+	struct unprov_device *dev = a;
+	int *cnt = b;
+	struct tm *tm;
 	char buf[80];
 	char *str;
 
+	if (a == finalized)
+		return;
+
+	tm = localtime(&dev->last_seen);
 	assert(strftime(buf, sizeof(buf), "%c", tm));
+	(*cnt)++;
 
+	dev->id = *cnt;
 	str = l_util_hexstring_upper(dev->uuid, sizeof(dev->uuid));
-	bt_shell_printf("UUID: %s, RSSI %d, Seen: %s\n",
-			str, dev->rssi, buf);
+	bt_shell_printf(COLOR_YELLOW "#%d" COLOR_OFF
+			" UUID: %s, RSSI %d, Server: %4.4x\n Seen: %s\n",
+			*cnt, str, dev->rssi, dev->server, buf);
 
 	l_free(str);
 }
@@ -725,6 +776,10 @@ static void attach_node_reply(struct l_dbus_proxy *proxy,
 		remote_clear_rejected_addresses(ivi);
 	}
 
+	/* Read own node composition */
+	if (!cfgcli_get_comp(0x0001, 128))
+		l_error("Failed to read own composition");
+
 	return;
 
 fail:
@@ -794,15 +849,56 @@ static void scan_reply(struct l_dbus_proxy *proxy, struct l_dbus_message *msg,
 
 static void scan_setup(struct l_dbus_message *msg, void *user_data)
 {
-	uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
+	struct scan_data *data = user_data;
 	struct l_dbus_message_builder *builder;
 
 	builder = l_dbus_message_builder_new(msg);
 	l_dbus_message_builder_enter_array(builder, "{sv}");
-	append_dict_entry_basic(builder, "Seconds", "q", &secs);
+	append_dict_entry_basic(builder, "Seconds", "q", &data->secs);
+	append_dict_entry_basic(builder, "Server", "q", &data->dst);
 	l_dbus_message_builder_leave_array(builder);
 	l_dbus_message_builder_finalize(builder);
 	l_dbus_message_builder_destroy(builder);
+
+	/* Destination info not needed after call */
+	l_free(data);
+}
+
+static void scan_start(void *user_data, uint16_t dst, uint32_t model)
+{
+	struct scan_data *data;
+
+	if (model != (0xffff0000 | RPR_SVR_MODEL))
+		return;
+
+	data = l_malloc(sizeof(struct scan_data));
+	data->secs = L_PTR_TO_UINT(user_data);
+	data->dst = dst;
+
+	if (!l_dbus_proxy_method_call(local->mgmt_proxy, "UnprovisionedScan",
+					scan_setup, scan_reply, data, NULL))
+		l_free(data);
+}
+
+static void scan_to(struct l_timeout *timeout, void *user_data)
+{
+	int cnt = 0;
+
+	if (l_queue_peek_head(devices) != finalized)
+		l_queue_push_head(devices, finalized);
+
+	l_timeout_remove(timeout);
+	scan_timeout = NULL;
+	bt_shell_printf(COLOR_YELLOW "Unprovisioned devices:\n" COLOR_OFF);
+	l_queue_foreach(devices, print_device, &cnt);
+}
+
+static void free_devices(void *a)
+{
+	if (a == finalized)
+		return;
+
+	l_free(a);
 }
 
 static void cmd_scan_unprov(int argc, char *argv[])
@@ -820,21 +916,28 @@ static void cmd_scan_unprov(int argc, char *argv[])
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	if (argc == 3)
+	if (argc == 3) {
 		sscanf(argv[2], "%u", &secs);
 
-	if (secs > UNPROV_SCAN_MAX_SECS)
-		secs = UNPROV_SCAN_MAX_SECS;
+		if (secs > UNPROV_SCAN_MAX_SECS)
+			secs = UNPROV_SCAN_MAX_SECS;
+	} else
+		secs = 60;
 
-	if (enable)
-		l_dbus_proxy_method_call(local->mgmt_proxy, "UnprovisionedScan",
-						scan_setup, scan_reply,
-						L_UINT_TO_PTR(secs), NULL);
-	else
+	l_timeout_remove(scan_timeout);
+	scan_timeout = NULL;
+
+	if (enable) {
+		l_queue_clear(devices, free_devices);
+		remote_foreach_model(scan_start, L_UINT_TO_PTR(secs));
+		scan_timeout = l_timeout_create(secs, scan_to, NULL, NULL);
+	} else {
+		/* Mark devices queue as finalized */
+		l_queue_push_head(devices, finalized);
 		l_dbus_proxy_method_call(local->mgmt_proxy,
 						"UnprovisionedScanCancel",
 						NULL, NULL, NULL, NULL);
-
+	}
 }
 
 static uint8_t *parse_key(struct l_dbus_message_iter *iter, uint16_t id,
@@ -1030,8 +1133,10 @@ static void cmd_export_db(int argc, char *argv[])
 
 static void cmd_list_unprov(int argc, char *argv[])
 {
+	int cnt = 0;
+
 	bt_shell_printf(COLOR_YELLOW "Unprovisioned devices:\n" COLOR_OFF);
-	l_queue_foreach(devices, print_device, NULL);
+	l_queue_foreach(devices, print_device, &cnt);
 }
 
 static void cmd_list_nodes(int argc, char *argv[])
@@ -1505,32 +1610,56 @@ static void add_node_reply(struct l_dbus_proxy *proxy,
 	bt_shell_printf("Provisioning started\n");
 }
 
-static void add_node_setup(struct l_dbus_message *msg, void *user_data)
+static void reprov_reply(struct l_dbus_proxy *proxy,
+				struct l_dbus_message *msg, void *user_data)
 {
-	char *str = user_data;
-	size_t sz;
-	unsigned char *uuid;
-	struct l_dbus_message_builder *builder;
+	if (l_dbus_message_is_error(msg)) {
+		const char *name;
 
-	uuid = l_util_from_hexstring(str, &sz);
-	if (!uuid || sz != 16 || !l_uuid_is_valid(uuid)) {
-		l_error("Failed to generate UUID array from %s", str);
+		prov_in_progress = false;
+		l_dbus_message_get_error(msg, &name, NULL);
+		l_error("Failed to start provisioning: %s", name);
 		return;
 	}
 
+	bt_shell_printf("Reprovisioning started\n");
+}
+
+static void reprovision_setup(struct l_dbus_message *msg, void *user_data)
+{
+	uint16_t target = L_PTR_TO_UINT(user_data);
+	uint8_t nppi = L_PTR_TO_UINT(user_data) >> 16;
+	struct l_dbus_message_builder *builder;
+
 	builder = l_dbus_message_builder_new(msg);
-	append_byte_array(builder, uuid, 16);
+	l_dbus_message_builder_append_basic(builder, 'q', &target);
 	l_dbus_message_builder_enter_array(builder, "{sv}");
 	/* TODO: populate with options when defined */
+	append_dict_entry_basic(builder, "NPPI", "y", &nppi);
 	l_dbus_message_builder_leave_array(builder);
 	l_dbus_message_builder_finalize(builder);
 	l_dbus_message_builder_destroy(builder);
+}
 
-	l_free(uuid);
+static void add_node_setup(struct l_dbus_message *msg, void *user_data)
+{
+	struct unprov_device *dev = user_data;
+	struct l_dbus_message_builder *builder;
+
+	builder = l_dbus_message_builder_new(msg);
+	append_byte_array(builder, dev->uuid, 16);
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+	/* TODO: populate with options when defined */
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
 }
 
 static void cmd_start_prov(int argc, char *argv[])
 {
+	struct unprov_device *dev = NULL;
+	int id;
+
 	if (!local || !local->proxy || !local->mgmt_proxy) {
 		bt_shell_printf("Node is not attached\n");
 		return;
@@ -1541,14 +1670,96 @@ static void cmd_start_prov(int argc, char *argv[])
 		return;
 	}
 
-	if (!argv[1] || (strlen(argv[1]) != 32)) {
+	if (!argv[1]) {
+		bt_shell_printf(COLOR_RED "Requires UUID\n" COLOR_RED);
+		return;
+	}
+
+	if (*(argv[1]) == '#') {
+		if (sscanf(argv[1] + 1, "%d", &id) == 1)
+			dev = l_queue_find(devices, match_by_id,
+							L_UINT_TO_PTR(id));
+
+		if (!dev) {
+			bt_shell_printf(COLOR_RED "unknown id\n" COLOR_RED);
+			return;
+		}
+	} else if (strlen(argv[1]) == 32) {
+		size_t sz;
+		uint8_t *uuid = l_util_from_hexstring(argv[1], &sz);
+
+		if (sz != 16) {
+			bt_shell_printf(COLOR_RED "Invalid UUID\n" COLOR_RED);
+			return;
+		}
+
+		dev = l_queue_find(devices, match_device_uuid, uuid);
+
+		if (!dev) {
+			dev = l_new(struct unprov_device, 1);
+			memcpy(dev->uuid, uuid, 16);
+			l_queue_push_tail(devices, dev);
+		}
+
+		l_free(uuid);
+
+	} else {
 		bt_shell_printf(COLOR_RED "Requires UUID\n" COLOR_RED);
 		return;
 	}
 
 	if (l_dbus_proxy_method_call(local->mgmt_proxy, "AddNode",
 						add_node_setup, add_node_reply,
-						argv[1], NULL))
+						dev, NULL))
+		prov_in_progress = true;
+}
+
+static void cmd_start_reprov(int argc, char *argv[])
+{
+	uint16_t target = 0;
+	uint8_t nppi = 0;
+
+	if (!local || !local->proxy || !local->mgmt_proxy) {
+		bt_shell_printf("Node is not attached\n");
+		return;
+	}
+
+	if (prov_in_progress) {
+		bt_shell_printf("Provisioning is already in progress\n");
+		return;
+	}
+
+	if (!argv[1]) {
+		bt_shell_printf(COLOR_RED "Requires Unicast\n" COLOR_RED);
+		return;
+	}
+
+	if (argv[2]) {
+		char *end;
+
+		nppi = strtol(argv[2], &end, 16);
+	}
+
+	if (strlen(argv[1]) == 4) {
+		char *end;
+
+		target = strtol(argv[1], &end, 16);
+
+		if (end != (argv[1] + 4)) {
+			bt_shell_printf(COLOR_RED "Invalid Unicast\n"
+								COLOR_RED);
+			return;
+		}
+
+	} else {
+		bt_shell_printf(COLOR_RED "Requires Unicast\n" COLOR_RED);
+		return;
+	}
+
+	if (l_dbus_proxy_method_call(local->mgmt_proxy, "Reprovision",
+					reprovision_setup, reprov_reply,
+					L_UINT_TO_PTR(target + (nppi << 16)),
+					NULL))
 		prov_in_progress = true;
 }
 
@@ -1581,6 +1792,8 @@ static const struct bt_shell_menu main_menu = {
 			"List unprovisioned devices" },
 	{ "provision", "<uuid>", cmd_start_prov,
 			"Initiate provisioning"},
+	{ "reprovision", "<unicast> [0|1|2]", cmd_start_reprov,
+			"Refresh Device Key"},
 	{ "node-import", "<uuid> <net_idx> <primary> <ele_count> <dev_key>",
 			cmd_import_node,
 			"Import an externally provisioned remote node"},
@@ -1684,6 +1897,8 @@ static bool mod_getter(struct l_dbus *dbus,
 	l_dbus_message_builder_enter_array(builder, "(qa{sv})");
 	build_model(builder, app.ele.mods[0], false, false);
 	build_model(builder, app.ele.mods[1], false, false);
+	build_model(builder, app.ele.mods[2], false, false);
+	build_model(builder, app.ele.mods[3], false, false);
 	l_dbus_message_builder_leave_array(builder);
 
 	return true;
@@ -1758,18 +1973,34 @@ static void setup_ele_iface(struct l_dbus_interface *iface)
 	/* TODO: Other methods */
 }
 
+static int sort_rssi(const void *a, const void *b, void *user_data)
+{
+	const struct unprov_device *new_dev = a;
+	const struct unprov_device *dev = b;
+
+	if (b == finalized)
+		return 1;
+
+	return dev->rssi - new_dev->rssi;
+}
+
 static struct l_dbus_message *scan_result_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
 {
-	struct l_dbus_message_iter iter, opts;
+	struct l_dbus_message_iter iter, opts, var;
+	struct unprov_device result, *dev;
 	int16_t rssi;
+	uint16_t server = 0;
 	uint32_t n;
 	uint8_t *prov_data;
-	char *str;
-	struct unprov_device *dev;
+	const char *key;
 	const char *sig = "naya{sv}";
 
+	if (finalized == l_queue_peek_head(devices))
+		goto done;
+
+
 	if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
 		l_error("Cannot parse scan results");
 		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
@@ -1781,42 +2012,71 @@ static struct l_dbus_message *scan_result_call(struct l_dbus *dbus,
 		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
 	}
 
-	bt_shell_printf("Scan result:\n");
-	bt_shell_printf("\t" COLOR_GREEN "rssi = %d\n" COLOR_OFF, rssi);
-	str = l_util_hexstring_upper(prov_data, 16);
-	bt_shell_printf("\t" COLOR_GREEN "UUID = %s\n" COLOR_OFF, str);
-	l_free(str);
-
-	if (n >= 18) {
-		str = l_util_hexstring_upper(prov_data + 16, 2);
-		bt_shell_printf("\t" COLOR_GREEN "OOB = %s\n" COLOR_OFF, str);
-		l_free(str);
+	while (l_dbus_message_iter_next_entry(&opts, &key, &var)) {
+		if (!strcmp(key, "Server"))
+			l_dbus_message_iter_get_variant(&var, "q", &server);
 	}
 
-	if (n >= 22) {
-		str = l_util_hexstring_upper(prov_data + 18, 4);
-		bt_shell_printf("\t" COLOR_GREEN "URI Hash = %s\n" COLOR_OFF,
-									str);
-		l_free(str);
-	}
+	memcpy(result.uuid, prov_data, 16);
+	result.server = server;
+	result.rssi = rssi;
+	result.id = 0;
+	result.last_seen = time(NULL);
+
+	if (n > 16 && n <= 18)
+		result.oob_info = l_get_be16(prov_data + 16);
+	else
+		result.oob_info = 0;
 
-	/* TODO: Handle the rest of provisioning data if present */
+	if (n > 18 && n <= 22)
+		result.uri_hash = l_get_be32(prov_data + 18);
+	else
+		result.uri_hash = 0;
+
+	dev = l_queue_remove_if(devices, match_by_srv_uuid, &result);
 
-	dev = l_queue_find(devices, match_device_uuid, prov_data);
 	if (!dev) {
-		dev = l_new(struct unprov_device, 1);
-		memcpy(dev->uuid, prov_data, sizeof(dev->uuid));
-		/* TODO: timed self-destructor */
-		l_queue_push_tail(devices, dev);
-	}
+		bt_shell_printf("\r" COLOR_YELLOW "Results = %d\n" COLOR_OFF,
+						l_queue_length(devices) + 1);
+		dev = l_malloc(sizeof(struct unprov_device));
+		*dev = result;
+
+	} else if (dev->rssi < result.rssi)
+		*dev = result;
 
-	/* Update with the latest rssi */
-	dev->rssi = rssi;
-	dev->last_seen = time(NULL);
+	l_queue_insert(devices, dev, sort_rssi, NULL);
 
+done:
 	return l_dbus_message_new_method_return(msg);
 }
 
+static struct l_dbus_message *req_reprov_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	uint8_t cnt;
+	uint16_t unicast, original;
+	struct l_dbus_message *reply;
+
+
+	if (!l_dbus_message_get_arguments(msg, "qy", &original, &cnt) ||
+							!IS_UNICAST(original)) {
+		l_error("Cannot parse request for reprov data");
+		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+
+	}
+
+	unicast = remote_get_next_unicast(low_addr, high_addr, cnt);
+
+	bt_shell_printf("Assign addresses for %u elements\n", cnt);
+	bt_shell_printf("Original: %4.4x New: %4.4x\n", original, unicast);
+
+	reply = l_dbus_message_new_method_return(msg);
+	l_dbus_message_set_arguments(reply, "q", unicast);
+
+	return reply;
+}
+
 static struct l_dbus_message *req_prov_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
@@ -1825,6 +2085,7 @@ static struct l_dbus_message *req_prov_call(struct l_dbus *dbus,
 	uint16_t unicast;
 	struct l_dbus_message *reply;
 
+	/* Both calls handled identicaly except for parameter list */
 	if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
 		l_error("Cannot parse request for prov data");
 		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
@@ -1833,14 +2094,14 @@ static struct l_dbus_message *req_prov_call(struct l_dbus *dbus,
 
 	unicast = remote_get_next_unicast(low_addr, high_addr, cnt);
 
-	if (unicast == 0) {
+	if (!IS_UNICAST(unicast)) {
 		l_error("Failed to allocate addresses for %u elements\n", cnt);
 		return l_dbus_message_new_error(msg,
 					"org.freedesktop.DBus.Error."
 					"Failed to allocate address", NULL);
 	}
 
-	bt_shell_printf("Assign addresses for %u elements\n", cnt);
+	bt_shell_printf("Assign addresses: %4.4x (cnt: %d)\n", unicast, cnt);
 
 	reply = l_dbus_message_new_method_return(msg);
 	l_dbus_message_set_arguments(reply, "qq", prov_net_idx, unicast);
@@ -1852,11 +2113,13 @@ static void remove_device(uint8_t *uuid)
 {
 	struct unprov_device *dev;
 
-	dev = l_queue_remove_if(devices, match_device_uuid, uuid);
-	l_free(dev);
+	do {
+		dev = l_queue_remove_if(devices, match_device_uuid, uuid);
+		l_free(dev);
+	} while (dev);
 }
 
-static struct l_dbus_message *add_node_cmplt_call(struct l_dbus *dbus,
+static struct l_dbus_message *prov_cmplt_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
 {
@@ -1866,6 +2129,7 @@ static struct l_dbus_message *add_node_cmplt_call(struct l_dbus *dbus,
 	uint32_t n;
 	uint8_t *uuid;
 
+	l_debug("ProvComplete");
 	if (!prov_in_progress)
 		return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
 
@@ -1896,7 +2160,49 @@ static struct l_dbus_message *add_node_cmplt_call(struct l_dbus *dbus,
 	return l_dbus_message_new_method_return(msg);
 }
 
-static struct l_dbus_message *add_node_fail_call(struct l_dbus *dbus,
+static struct l_dbus_message *reprov_cmplt_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	uint16_t unicast, original;
+	uint8_t old_cnt, cnt, nppi;
+
+	l_debug("ReprovComplete");
+	if (!prov_in_progress)
+		return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+
+	prov_in_progress = false;
+
+	if (!l_dbus_message_get_arguments(msg, "qyqy", &original, &nppi,
+							&unicast, &cnt)) {
+		l_error("Cannot parse reprov complete message");
+		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+
+	}
+
+	l_debug("ReprovComplete org: %4.4x, nppi: %d, new: %4.4x, cnt: %d",
+						original, nppi, unicast, cnt);
+	old_cnt = remote_ele_cnt(original);
+
+	if (nppi != 1 && (original != unicast || cnt != old_cnt)) {
+		l_error("Invalid reprov complete message (NPPI == %d)", nppi);
+		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+	}
+
+	if (nppi)
+		remote_reset_node(original, unicast, cnt,
+						mesh_db_get_iv_index());
+
+	bt_shell_printf("Reprovisioning done (nppi: %d):\n", nppi);
+	remote_print_node(unicast);
+
+	if (!mesh_db_reset_node(original, unicast, cnt))
+		l_error("Failed to reset remote node");
+
+	return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *prov_fail_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
 {
@@ -1911,24 +2217,49 @@ static struct l_dbus_message *add_node_fail_call(struct l_dbus *dbus,
 	prov_in_progress = false;
 
 	if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
-		l_error("Cannot parse add node failed message");
+		l_error("Cannot parse failed message");
 		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
-
 	}
 
-	if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
-								n != 16) {
-		l_error("Cannot parse add node failed message: uuid");
+	if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) || n != 16) {
+		l_error("Cannot parse failed message: uuid");
 		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
 	}
 
 	bt_shell_printf("Provisioning failed:\n");
+
 	str = l_util_hexstring_upper(uuid, 16);
 	bt_shell_printf("\t" COLOR_RED "UUID = %s\n" COLOR_OFF, str);
 	l_free(str);
+	remove_device(uuid);
 	bt_shell_printf("\t" COLOR_RED "%s\n" COLOR_OFF, reason);
 
-	remove_device(uuid);
+	return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *reprov_fail_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	struct l_dbus_message_iter iter;
+	uint16_t original = UNASSIGNED_ADDRESS;
+	char *reason;
+
+	if (!prov_in_progress)
+		return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
+
+	prov_in_progress = false;
+
+	if (!l_dbus_message_get_arguments(msg, "qs", &iter, &reason) ||
+							!IS_UNICAST(original)) {
+
+		l_error("Cannot parse Reprov failed message");
+		return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+	}
+
+	bt_shell_printf("Reprovisioning failed:\n");
+	bt_shell_printf("\t" COLOR_RED "UNICAST = %4.4x\n" COLOR_OFF, original);
+	bt_shell_printf("\t" COLOR_RED "%s\n" COLOR_OFF, reason);
 
 	return l_dbus_message_new_method_return(msg);
 }
@@ -1941,12 +2272,23 @@ static void setup_prov_iface(struct l_dbus_interface *iface)
 	l_dbus_interface_method(iface, "RequestProvData", 0, req_prov_call,
 				"qq", "y", "net_index", "unicast", "count");
 
+	l_dbus_interface_method(iface, "RequestReprovData", 0, req_reprov_call,
+					"q", "qy", "unicast",
+					"original", "count");
+
 	l_dbus_interface_method(iface, "AddNodeComplete", 0,
-					add_node_cmplt_call, "", "ayqy",
+					prov_cmplt_call, "", "ayqy",
 					"uuid", "unicast", "count");
 
-	l_dbus_interface_method(iface, "AddNodeFailed", 0, add_node_fail_call,
+	l_dbus_interface_method(iface, "ReprovComplete", 0,
+					reprov_cmplt_call, "", "qyqy",
+					"original", "nppi", "unicast", "count");
+
+	l_dbus_interface_method(iface, "AddNodeFailed", 0, prov_fail_call,
 					"", "ays", "uuid", "reason");
+
+	l_dbus_interface_method(iface, "ReprovFailed", 0, reprov_fail_call,
+					"", "qs", "unicast", "reason");
 }
 
 static bool cid_getter(struct l_dbus *dbus,
@@ -2140,7 +2482,7 @@ static void client_ready(struct l_dbus_client *client, void *user_data)
 static void client_connected(struct l_dbus *dbus, void *user_data)
 {
 	bt_shell_printf("D-Bus client connected\n");
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT_ON, COLOR_BLUE);
 }
 
 static void client_disconnected(struct l_dbus *dbus, void *user_data)
@@ -2300,7 +2642,7 @@ int main(int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT_OFF, NULL);
 
 	dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
 
diff --git a/tools/mesh-cfgtest.c b/tools/mesh-cfgtest.c
index 116ab7f..739d1d9 100644
--- a/tools/mesh-cfgtest.c
+++ b/tools/mesh-cfgtest.c
@@ -38,14 +38,21 @@
 #define MAX_CRPL_SIZE	0x7fff
 #define CFG_SRV_MODEL	0x0000
 #define CFG_CLI_MODEL	0x0001
+#define RMT_PROV_SRV_MODEL 0x0004
+#define RMT_PROV_CLI_MODEL 0x0005
+#define PVT_BEACON_SRV_MODEL 0x0008
 #define DEFAULT_IV_INDEX 0x0000
 
-#define IS_CONFIG_MODEL(x) ((x) == CFG_SRV_MODEL || (x) == CFG_CLI_MODEL)
+#define IS_CONFIG_MODEL(x) (((x) == (CFG_SRV_MODEL)) ||		\
+				((x) == (CFG_CLI_MODEL)) ||		\
+				((x) == (RMT_PROV_SRV_MODEL)) ||	\
+				((x) == (RMT_PROV_CLI_MODEL)))
 
 struct meshcfg_el {
 	const char *path;
 	uint8_t index;
-	uint16_t mods[2];
+	uint16_t location;
+	uint16_t mods[4];
 	uint32_t vmods[2];
 };
 
@@ -77,6 +84,11 @@ struct msg_data {
 	uint8_t data[MAX_MSG_LEN];
 };
 
+struct exp_rsp {
+	uint8_t test_id;
+	void *rsp;
+};
+
 struct key_data {
 	uint16_t idx;
 	bool update;
@@ -140,7 +152,9 @@ static struct meshcfg_app client_app = {
 		{
 			.path = cli_ele_path_00,
 			.index = PRIMARY_ELE_IDX,
-			.mods = {CFG_SRV_MODEL, CFG_CLI_MODEL},
+			.location = 0x0001,
+			.mods = {CFG_SRV_MODEL, CFG_CLI_MODEL,
+				 RMT_PROV_SRV_MODEL, PVT_BEACON_SRV_MODEL},
 			.vmods = {0xffffffff, 0xffffffff}
 		}
 	}
@@ -158,13 +172,16 @@ static struct meshcfg_app server_app = {
 		{
 			.path = srv_ele_path_00,
 			.index = PRIMARY_ELE_IDX,
-			.mods = {CFG_SRV_MODEL, 0xffff},
+			.location = 0x0001,
+			.mods = {CFG_SRV_MODEL, RMT_PROV_SRV_MODEL,
+						PVT_BEACON_SRV_MODEL, 0xffff},
 			.vmods = {0xffffffff, 0xffffffff}
 		},
 		{
 			.path = srv_ele_path_01,
 			.index = PRIMARY_ELE_IDX + 1,
-			.mods = {0x1000, 0xffff},
+			.location = 0x0002,
+			.mods = {0x1000, 0xffff, 0xffff, 0xffff},
 			.vmods = {0x5F10001, 0xffffffff}
 		}
 	}
@@ -262,6 +279,11 @@ static struct msg_data test_add_appkey_rsp = {
 	.data = {0x80, 0x03, 0x00, 0x01, 0x20, 0x00}
 };
 
+static struct exp_rsp test_add_appkey_expected = {
+	.test_id = 1,
+	.rsp = &test_add_appkey_rsp,
+};
+
 static struct key_data test_add_appkey_req = {
 	.idx = 0x002,
 	.update = false
@@ -285,6 +307,11 @@ static struct msg_data test_set_ttl_rsp = {
 	.data = { 0x80, 0x0E, 0x7}
 };
 
+static struct exp_rsp test_set_ttl_expected = {
+	.test_id = 2,
+	.rsp = &test_set_ttl_rsp
+};
+
 static struct msg_data test_set_ttl_req = {
 	.len = 3,
 	.data = { 0x80, 0x0D, 0x7}
@@ -295,27 +322,42 @@ static struct msg_data test_bind_rsp = {
 	.data = { 0x80, 0x3E, 0x00, 0xCE, 0x0B, 0x01, 0x00, 0x00, 0x10},
 };
 
+static struct exp_rsp test_bind_expected = {
+	.test_id = 3,
+	.rsp = &test_bind_rsp
+};
+
 static struct msg_data test_bind_req = {
 	.len = 8,
 	.data = { 0x80, 0x3D, 0xCE, 0x0B, 0x01, 0x00, 0x00, 0x10}
 };
 
-
 static struct msg_data test_bind_inv_mod_rsp = {
 	.len = 9,
 	.data = { 0x80, 0x3E, 0x02, 0xCE, 0x0B, 0x01, 0x00, 0x00, 0x11},
 };
 
+static struct exp_rsp test_bind_inv_mod_expected = {
+	.test_id = 4,
+	.rsp = &test_bind_inv_mod_rsp
+};
+
 static struct msg_data test_bind_inv_mod_req = {
 	.len = 8,
 	.data = { 0x80, 0x3D, 0xCE, 0x0B, 0x01, 0x00, 0x00, 0x11}
 };
 
 static struct msg_data test_dev_comp_rsp = {
-	.len = 28,
-	.data = { 0x02, 0x00, 0xf1, 0x05, 0x02, 0x00, 0x01, 0x00, 0xff, 0x7f,
-			0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x01, 0x01, 0x00, 0x10, 0xf1, 0x05, 0x01, 0x00}
+	.len = 32,
+	.data = { 0x02, 0x00, 0xf1, 0x05, 0x02, 0x00, 0x01, 0x00,
+		0xff, 0x7f, 0x05, 0x00,
+		0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
+		0x02, 0x00, 0x01, 0x01, 0x00, 0x10, 0xf1, 0x05, 0x01, 0x00}
+};
+
+static struct exp_rsp test_dev_comp_expected = {
+	.test_id = 5,
+	.rsp = &test_dev_comp_rsp
 };
 
 static struct msg_data test_dev_comp_req = {
@@ -955,11 +997,101 @@ static bool ele_idx_getter(struct l_dbus *dbus,
 	return true;
 }
 
+static bool location_getter(struct l_dbus *dbus,
+				struct l_dbus_message *message,
+				struct l_dbus_message_builder *builder,
+				void *user_data)
+{
+	struct meshcfg_el *ele = user_data;
+
+	l_dbus_message_builder_append_basic(builder, 'q', &ele->location);
+
+	return true;
+}
+
+static bool find_model(uint8_t *buf, uint32_t len, uint8_t *mod, uint8_t sz)
+{
+	bool found = false;
+
+	while (len >= sz) {
+		if (!memcmp(buf, mod, sz)) {
+			/* Disallow duplicates */
+			if (found)
+				return false;
+
+			found = true;
+		}
+
+		buf += sz;
+		len -= sz;
+	}
+
+	return found;
+}
+
+static bool check_device_composition(struct msg_data *rsp, uint32_t len,
+								uint8_t *data)
+{
+	uint32_t cnt;
+
+	if (len != rsp->len)
+		return false;
+
+	if (!memcmp(data, rsp->data, len))
+		return true;
+
+	/* Allow for a different ordering of model IDs */
+
+	/* First, check that the fixed length data matches */
+	if (memcmp(data, rsp->data, 12))
+		return false;
+
+	cnt = 12;
+	data += 12;
+
+	while (cnt < len) {
+		uint8_t s, v, i;
+
+		if ((len - cnt) < 4)
+			return false;
+
+		/* Check element index, location and model count */
+		if (memcmp(data, rsp->data + cnt, 4))
+			return false;
+
+		s = data[2];
+		v = data[3];
+
+		if ((cnt + s * 2 + v * 4) > len)
+			return false;
+
+		data += 4;
+		cnt += 4;
+
+		for (i = 0; i < s; i++) {
+			if (!find_model(&rsp->data[cnt], s * 2, data, 2))
+				return false;
+			data += 2;
+		}
+
+		cnt += s * 2;
+
+		for (i = 0; i < v; i++) {
+			if (!find_model(&rsp->data[cnt], v * 4, data, 4))
+				return false;
+			data += 4;
+		}
+
+		cnt += v * 4;
+	}
+
+	return true;
+}
+
 static struct l_dbus_message *dev_msg_recv_call(struct l_dbus *dbus,
 						struct l_dbus_message *msg,
 						void *user_data)
 {
-	struct msg_data *rsp;
 	struct l_dbus_message_iter iter;
 	uint16_t src, idx;
 	uint8_t *data;
@@ -983,7 +1115,7 @@ static struct l_dbus_message *dev_msg_recv_call(struct l_dbus *dbus,
 		uint32_t i;
 
 		for (i = 0; i < n; i++)
-			printf("%x ", data[i]);
+			printf("%02x ", data[i]);
 		printf("\n");
 	}
 
@@ -999,9 +1131,24 @@ static struct l_dbus_message *dev_msg_recv_call(struct l_dbus *dbus,
 			l_tester_pre_setup_failed(tester);
 		}
 	} else {
-		rsp = l_tester_get_data(tester);
+		struct exp_rsp *exp = l_tester_get_data(tester);
+		bool res = false;
+
+		if (exp && exp->rsp) {
+			if (exp->test_id == 5)
+				/* Check device composition */
+				res = check_device_composition(exp->rsp, n,
+									data);
+			else {
+				struct msg_data *rsp = exp->rsp;
+
+				if (n == rsp->len &&
+						!memcmp(data, rsp->data, n))
+					res = true;
+			}
+		}
 
-		if (rsp && rsp->len == n && !memcmp(data, rsp->data, n))
+		if (res)
 			l_idle_oneshot(test_success, NULL, NULL);
 		else
 			l_idle_oneshot(test_fail, NULL, NULL);
@@ -1019,7 +1166,8 @@ static void setup_ele_iface(struct l_dbus_interface *iface)
 							vmod_getter, NULL);
 	l_dbus_interface_property(iface, "Models", 0, "a(qa{sv})", mod_getter,
 									NULL);
-
+	l_dbus_interface_property(iface, "Location", 0, "q", location_getter,
+									NULL);
 	/* Methods */
 	l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
 				dev_msg_recv_call, "", "qbqay", "source",
@@ -1411,23 +1559,23 @@ int main(int argc, char *argv[])
 
 	l_tester_add_full(tester, "Config AppKey Add: Success",
 			&test_add_appkey, init_test, create_appkey, add_appkey,
-				NULL, NULL, 2, &test_add_appkey_rsp, NULL);
+				NULL, NULL, 2, &test_add_appkey_expected, NULL);
 
 	tester_add_with_response("Config Default TTL Set: Success",
 					&test_set_ttl_req, send_cfg_msg,
-							&test_set_ttl_rsp);
+						&test_set_ttl_expected);
 
 	tester_add_with_response("Config Get Device Composition: Success",
 					&test_dev_comp_req, send_cfg_msg,
-							&test_dev_comp_rsp);
+						&test_dev_comp_expected);
 
 	tester_add_with_response("Config Bind: Success",
 					&test_bind_req, send_cfg_msg,
-							&test_bind_rsp);
+						&test_bind_expected);
 
 	tester_add_with_response("Config Bind: Error Invalid Model",
 					&test_bind_inv_mod_req, send_cfg_msg,
-							&test_bind_inv_mod_rsp);
+						&test_bind_inv_mod_expected);
 
 	l_tester_start(tester, done_callback);
 
diff --git a/tools/mesh-gatt/README b/tools/mesh-gatt/README
deleted file mode 100644
index 44d6333..0000000
--- a/tools/mesh-gatt/README
+++ /dev/null
@@ -1,43 +0,0 @@
-MeshCtl - BlueZ GATT based Bluetooth Mesh Provisioner
-*****************************************************
-
-Copyright (C) 2017  Intel Corporation. All rights reserved.
-
-Compilation and installation
-============================
-
-In addition to main BlueZ requirements, MeshCtl needs the following:
-	- JSON library
-
-Configuration and options
-=========================
-
-	--enable-mesh
-
-		Build meshctl and other Bluetooth Mesh based tools and utils
-
-Example configuration files
-===========================
-
-The MeshCtl tool requires two input configuration files in JSON format:
-	- local_node.json
-		Local mesh node configuration
-	- prov_db.json
-		Provisoner's database for all the configured nodes in the mesh
-
-The default directory for MeshCtl configuration files is
-/home/<username>/.config/meshctl
-
-To use .json configuration files either copy them to the default directory
-or, to specify a custom storage directory, run meshctl tool as:
-
-	meshctl -c <config_dir_name>
-
-Information
-===========
-
-Mailing lists:
-	linux-bluetooth@vger.kernel.org
-
-For additional information about the project visit BlueZ web site:
-	http://www.bluez.org
diff --git a/tools/mesh-gatt/local_node.json b/tools/mesh-gatt/local_node.json
deleted file mode 100644
index 5ffa7ad..0000000
--- a/tools/mesh-gatt/local_node.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "$schema":"file:\/\/\/BlueZ\/Mesh\/local_schema\/mesh.jsonschema",
-  "meshName":"BT Mesh",
-  "netKeys":[
-    {
-      "index": 0,
-      "keyRefresh": 0
-    }
-  ],
-  "appKeys":[
-    {
-      "index": 0,
-      "boundNetKey": 0
-    },
-    {
-      "index": 1,
-      "boundNetKey": 0
-    }
-  ],
-"node": {
-	"IVindex":"00000005",
-	"IVupdate":"0",
-	"sequenceNumber": 0,
-    "composition": {
-        "cid": "0002",
-        "pid": "0010",
-        "vid": "0001",
-        "crpl": "000a",
-        "features": {
-            "relay": false,
-            "proxy": true,
-            "friend": false,
-            "lowPower": false
-        },
-        "elements": [
-            {
-                "elementIndex": 0,
-                "location": "0001",
-                "models": ["0000", "0001", "1001"]
-            }
-        ]
-    },
-    "configuration":{
-        "netKeys": [0],
-        "appKeys": [ 0, 1],
-        "defaultTTL": 10,
-        "elements": [
-          {
-            "elementIndex": 0,
-            "unicastAddress":"0077",
-            "models": [
-               {
-                 "modelId": "1001",
-                 "bind": [1]
-                }
-            ]
-          }
-        ]
-    }
-  }
-}
diff --git a/tools/mesh-gatt/prov_db.json b/tools/mesh-gatt/prov_db.json
deleted file mode 100644
index 74a0312..0000000
--- a/tools/mesh-gatt/prov_db.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "$schema":"file:\/\/\/BlueZ\/Mesh\/schema\/mesh.jsonschema",
-  "meshName":"BT Mesh",
-  "IVindex":5,
-  "IVupdate":0,
-  "netKeys":[
-    {
-      "index":0,
-      "keyRefresh":0,
-      "key":"18eed9c2a56add85049ffc3c59ad0e12"
-    }
-  ],
-  "appKeys":[
-    {
-      "index":0,
-      "boundNetKey":0,
-      "key":"4f68ad85d9f48ac8589df665b6b49b8a"
-    },
-    {
-      "index":1,
-      "boundNetKey":0,
-      "key":"2aa2a6ded5a0798ceab5787ca3ae39fc"
-    }
-  ],
-  "provisioners":[
-    {
-      "provisionerName":"BT Mesh Provisioner",
-      "unicastAddress":"0077",
-      "allocatedUnicastRange":[
-        {
-          "lowAddress":"0100",
-          "highAddress":"7fff"
-        }
-      ]
-    }
-  ],
-}
diff --git a/tools/mesh-gatt/util.c b/tools/mesh-gatt/util.c
index eb8b8eb..58f240a 100644
--- a/tools/mesh-gatt/util.c
+++ b/tools/mesh-gatt/util.c
@@ -29,9 +29,9 @@ void set_menu_prompt(const char *name, const char *id)
 {
 	char *prompt;
 
-	prompt = g_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", name,
+	prompt = g_strdup_printf("[%s%s%s]# ", name,
 					id ? ": Target = " : "", id ? id : "");
-	bt_shell_set_prompt(prompt);
+	bt_shell_set_prompt(prompt, COLOR_BLUE);
 	g_free(prompt);
 }
 
diff --git a/tools/mesh/README b/tools/mesh/README
deleted file mode 100644
index 3830d1b..0000000
--- a/tools/mesh/README
+++ /dev/null
@@ -1,54 +0,0 @@
-MeshCfgclient - BlueZ PB-Adv based Bluetooth Mesh Provisioner
-*************************************************************
-
-Copyright (C) 2019  Intel Corporation. All rights reserved.
-
-Compilation and installation
-============================
-
-In addition to main BlueZ requirements, MeshCfgclient needs the following:
-	- JSON library
-
-Configuration and options
-=========================
-
-	--enable-mesh
-
-		Build mesh-cfgclient and other Bluetooth Mesh based tools
-
-Storage for mesh configuration file
-===================================
-
-The mesh-cfgclient tool generates a mesh configuration file in JSON format:
-	- mesh_db.json
-that contains information about the current state of the configured mesh
-network.
-
-The default directory for mesh-cfgclient configuration file is
-$HOME/.config/meshcfg
-
-To specify a custom file, run mesh-cfgclient tool as:
-
-	mesh-cfgclient -c <config_file_name>
-
-If a configuration file is not found, it is assumed that a mesh network
-does not exist. In this case, the tool may be used to generate a new  mesh
-network by invoking "create" command from the main menu and, on a successful
-completion of this command, an initial configuration file is written.
-
-If the configuration file is present, then "create" command will fail. This
-is done so that the existing configuration is not accidentally overwritten.
-If the intention is to create a new network then, the existing mesh
-configuration file has to be either moved or dleted prior to running the
-mesh-cfgclient tool. Also, a new custom storage location may be
-specified for a new network on the start up as a command line option.
-
-
-Information
-===========
-
-Mailing lists:
-	linux-bluetooth@vger.kernel.org
-
-For additional information about the project visit BlueZ web site:
-	http://www.bluez.org
diff --git a/tools/mesh/cfgcli.c b/tools/mesh/cfgcli.c
index a48eace..1a404af 100644
--- a/tools/mesh/cfgcli.c
+++ b/tools/mesh/cfgcli.c
@@ -21,6 +21,7 @@
 #include "src/shared/util.h"
 
 #include "mesh/mesh-defs.h"
+#include "mesh/prv-beacon.h"
 #include "mesh/util.h"
 #include "mesh/crypto.h"
 
@@ -73,9 +74,12 @@ static struct cfg_cmd cmds[] = {
 	{ OP_APPKEY_UPDATE, OP_APPKEY_STATUS, "AppKeyUpdate" },
 	{ OP_DEV_COMP_GET, OP_DEV_COMP_STATUS, "DeviceCompositionGet" },
 	{ OP_DEV_COMP_STATUS, NO_RESPONSE, "DeviceCompositionStatus" },
-	{ OP_CONFIG_BEACON_GET, OP_CONFIG_BEACON_STATUS, "BeaconGet" },
-	{ OP_CONFIG_BEACON_SET, OP_CONFIG_BEACON_STATUS, "BeaconSet" },
-	{ OP_CONFIG_BEACON_STATUS, NO_RESPONSE, "BeaconStatus" },
+	{ OP_CONFIG_BEACON_GET, OP_CONFIG_BEACON_STATUS, "SNBGet" },
+	{ OP_CONFIG_BEACON_SET, OP_CONFIG_BEACON_STATUS, "SNBSet" },
+	{ OP_CONFIG_BEACON_STATUS, NO_RESPONSE, "SNBStatus" },
+	{ OP_PRIVATE_BEACON_GET, OP_PRIVATE_BEACON_STATUS, "MPBGet" },
+	{ OP_PRIVATE_BEACON_SET, OP_PRIVATE_BEACON_STATUS, "MPBSet" },
+	{ OP_PRIVATE_BEACON_STATUS, NO_RESPONSE, "MPBStatus" },
 	{ OP_CONFIG_DEFAULT_TTL_GET, OP_CONFIG_DEFAULT_TTL_STATUS,
 							"DefaultTTLGet" },
 	{ OP_CONFIG_DEFAULT_TTL_SET, OP_CONFIG_DEFAULT_TTL_STATUS,
@@ -266,14 +270,21 @@ static uint32_t print_mod_id(uint8_t *data, bool vendor, const char *offset)
 	return mod_id;
 }
 
-static void print_composition(uint8_t *data, uint16_t len)
+static uint8_t print_composition(uint8_t *data, uint16_t len)
 {
 	uint16_t features;
 	int i = 0;
+	bool nppi = false;
 
-	bt_shell_printf("Received composion:\n");
+	bt_shell_printf("Received composition:\n");
+
+	/* We only support Pages 0 && 128 */
+	if (*data == 128) {
+		bt_shell_printf("Dev Key Refresh (NPPI) required\n");
+		nppi = true;
+	} else if (*data != 0)
+		return 0;
 
-	/* skip page -- We only support Page Zero */
 	data++;
 	len--;
 
@@ -328,6 +339,11 @@ static void print_composition(uint8_t *data, uint16_t len)
 
 		i++;
 	}
+
+	if (nppi)
+		return (uint8_t) i;
+	else
+		return 0;
 }
 
 static void print_pub(uint16_t ele_addr, uint32_t mod_id,
@@ -402,6 +418,7 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 	const struct cfg_cmd *cmd;
 	uint16_t app_idx, net_idx, addr, ele_addr, features;
 	struct mesh_group *grp;
+	uint8_t page128_cnt;
 	struct model_pub pub;
 	int n;
 	struct pending_req *req;
@@ -431,7 +448,19 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 		if (len < MIN_COMPOSITION_LEN)
 			return true;
 
-		print_composition(data, len);
+		page128_cnt = print_composition(data, len);
+		if (page128_cnt) {
+			if (page128_cnt != remote_ele_cnt(src)) {
+				bt_shell_printf("Ele count was %d, now %d\n",
+					remote_ele_cnt(src), page128_cnt);
+				bt_shell_printf("Reprovision with NPPI-1\n");
+			} else {
+				bt_shell_printf("Models or Features changed\n");
+				bt_shell_printf("Reprovision with NPPI-2\n");
+			}
+
+			break;
+		}
 
 		saved = mesh_db_node_set_composition(src, data, len);
 		if (saved)
@@ -592,12 +621,20 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
 		if (len != 1)
 			return true;
 
-		bt_shell_printf("Node %4.4x: Config Beacon Status 0x%02x\n",
+		bt_shell_printf("Node %4.4x: SecBeacon Status 0x%02x\n",
 				src, data[0]);
 
 		saved = mesh_db_node_set_beacon(src, data[0] != 0);
 		break;
 
+	case OP_PRIVATE_BEACON_STATUS:
+		if (len != 2)
+			return true;
+
+		bt_shell_printf("Node %4.4x: PrivBeacon Status 0x%02x 0x%02x\n",
+				src, data[0], data[1]);
+		break;
+
 	case OP_CONFIG_RELAY_STATUS:
 		if (len != 2)
 			return true;
@@ -1044,6 +1081,21 @@ static void cmd_default(uint32_t opcode)
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
+
+bool cfgcli_get_comp(uint16_t unicast, uint8_t page)
+{
+	uint16_t n;
+	uint8_t msg[32];
+
+	n = mesh_opcode_set(OP_DEV_COMP_GET, msg);
+
+	msg[n++] = page;
+
+	target = unicast;
+
+	return config_send(msg, n, OP_DEV_COMP_GET);
+}
+
 static void cmd_composition_get(int argc, char *argv[])
 {
 	uint16_t n;
@@ -1051,8 +1103,8 @@ static void cmd_composition_get(int argc, char *argv[])
 
 	n = mesh_opcode_set(OP_DEV_COMP_GET, msg);
 
-	/* By default, use page 0 */
-	msg[n++] = (read_input_parameters(argc, argv) == 1) ? parms[0] : 0;
+	/* By default, use page 128 */
+	msg[n++] = (read_input_parameters(argc, argv) == 1) ? parms[0] : 128;
 
 	if (!config_send(msg, n, OP_DEV_COMP_GET))
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
@@ -1320,7 +1372,7 @@ static void cmd_del_binding(int argc, char *argv[])
 	cmd_bind(OP_MODEL_APP_UNBIND, argc, argv);
 }
 
-static void cmd_beacon_set(int argc, char *argv[])
+static void cmd_snb_set(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[2 + 1];
@@ -1342,11 +1394,41 @@ static void cmd_beacon_set(int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
-static void cmd_beacon_get(int argc, char *argv[])
+static void cmd_mpb_set(int argc, char *argv[])
+{
+	uint16_t n;
+	uint8_t msg[2 + 2];
+	uint32_t parm_cnt;
+
+	n = mesh_opcode_set(OP_PRIVATE_BEACON_SET, msg);
+
+	parm_cnt = read_input_parameters(argc, argv);
+	if (parm_cnt != 1  && parm_cnt != 2) {
+		bt_shell_printf("bad arguments\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	msg[n++] = parms[0];
+
+	if (parm_cnt == 2)
+		msg[n++] = parms[1];
+
+	if (!config_send(msg, n, OP_PRIVATE_BEACON_SET))
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_snb_get(int argc, char *argv[])
 {
 	cmd_default(OP_CONFIG_BEACON_GET);
 }
 
+static void cmd_mpb_get(int argc, char *argv[])
+{
+	cmd_default(OP_PRIVATE_BEACON_GET);
+}
+
 static void cmd_ident_set(int argc, char *argv[])
 {
 	uint16_t n;
@@ -2052,10 +2134,10 @@ static const struct bt_shell_menu cfg_menu = {
 				"Set node identity state"},
 	{"ident-get", "<net_idx>", cmd_ident_get,
 				"Get node identity state"},
-	{"beacon-set", "<state>", cmd_beacon_set,
-				"Set node identity state"},
-	{"beacon-get", NULL, cmd_beacon_get,
-				"Get node beacon state"},
+	{"snb-set", "<state>", cmd_snb_set, "Set node SNB state"},
+	{"snb-get", NULL, cmd_snb_get, "Get node SNB state"},
+	{"mpb-set", "<state> <period>", cmd_mpb_set, "Set node MPB state"},
+	{"mpb-get", NULL, cmd_mpb_get, "Get node MPB state"},
 	{"relay-set", "<relay> <rexmt count> <rexmt steps>", cmd_relay_set,
 				"Set relay"},
 	{"relay-get", NULL, cmd_relay_get,
diff --git a/tools/mesh/cfgcli.h b/tools/mesh/cfgcli.h
index 7281caa..621dd02 100644
--- a/tools/mesh/cfgcli.h
+++ b/tools/mesh/cfgcli.h
@@ -19,4 +19,6 @@ typedef void (*delete_remote_func_t) (uint16_t primary, uint8_t ele_cnt);
 
 struct model_info *cfgcli_init(key_send_func_t key_func,
 				delete_remote_func_t del_node, void *user_data);
+
+bool cfgcli_get_comp(uint16_t unicast, uint8_t page);
 void cfgcli_cleanup(void);
diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c
index 896ff72..fb9c436 100644
--- a/tools/mesh/mesh-db.c
+++ b/tools/mesh/mesh-db.c
@@ -503,7 +503,8 @@ static void load_remotes(json_object *jcfg)
 		uint8_t uuid[16];
 		uint16_t unicast, key_idx;
 		const char *str;
-		int ele_cnt, key_cnt;
+		uint8_t ele_cnt;
+		int key_cnt;
 		int j;
 
 		jnode = json_object_array_get_idx(jnodes, i);
@@ -528,14 +529,13 @@ static void load_remotes(json_object *jcfg)
 			continue;
 
 		json_object_object_get_ex(jnode, "elements", &jarray);
-		if (!jarray || json_object_get_type(jarray) != json_type_array)
+		if (!jarray ||
+			json_object_get_type(jarray) != json_type_array ||
+			json_object_array_length(jarray) > MAX_ELE_COUNT)
 			continue;
 
 		ele_cnt = json_object_array_length(jarray);
 
-		if (ele_cnt > MAX_ELE_COUNT)
-			continue;
-
 		json_object_object_get_ex(jnode, "netKeys", &jarray);
 		if (!jarray || json_object_get_type(jarray) != json_type_array)
 			continue;
@@ -1702,6 +1702,29 @@ static json_object *init_elements(uint8_t num_els)
 	return jelements;
 }
 
+bool mesh_db_reset_node(uint16_t original, uint16_t unicast, uint8_t num_els)
+{
+	json_object *jnode, *jelements;
+
+	if (!cfg || !cfg->jcfg)
+		return false;
+
+	jnode = get_node_by_unicast(cfg->jcfg, original);
+	if (!jnode) {
+		l_error("Node %4.4x does not exist", original);
+		return false;
+	}
+
+	if (!write_uint16_hex(jnode, "unicastAddress", unicast))
+		return false;
+
+	json_object_object_del(jnode, "elements");
+	jelements = init_elements(num_els);
+	json_object_object_add(jnode, "elements", jelements);
+
+	return save_config();
+}
+
 bool mesh_db_add_node(uint8_t uuid[16], uint8_t num_els, uint16_t unicast,
 							uint16_t net_idx)
 {
@@ -1864,13 +1887,11 @@ bool mesh_db_node_set_composition(uint16_t unicast, uint8_t *data, uint16_t len)
 	if (!jnode)
 		return false;
 
-	/* skip page -- We only support Page Zero */
-	data++;
-	len--;
+	/* This is for page-0 only */
+	if (*data++ != 0)
+		return false;
 
-	/* If "crpl" property is present, composition is already recorded */
-	if (json_object_object_get_ex(jnode, "crpl", &jobj))
-		return true;
+	len--;
 
 	if (!write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
 		return false;
@@ -1943,29 +1964,35 @@ bool mesh_db_node_set_composition(uint16_t unicast, uint8_t *data, uint16_t len)
 
 		while (len >= 2 && m--) {
 			mod_id = l_get_le16(data);
+			data += 2;
+			len -= 2;
+
+			jobj = get_model(unicast, unicast + i, mod_id, false);
+			if (jobj)
+				continue;
 
 			jobj = init_model(mod_id);
 			if (!jobj)
 				goto fail;
 
 			json_object_array_add(jmods, jobj);
-			data += 2;
-			len -= 2;
 		}
 
 		while (len >= 4 && v--) {
-			jobj = json_object_new_object();
 			mod_id = l_get_le16(data + 2);
 			mod_id = l_get_le16(data) << 16 | mod_id;
+			data += 4;
+			len -= 4;
+
+			jobj = get_model(unicast, unicast + i, mod_id, true);
+			if (jobj)
+				continue;
 
 			jobj = init_vendor_model(mod_id);
 			if (!jobj)
 				goto fail;
 
 			json_object_array_add(jmods, jobj);
-
-			data += 4;
-			len -= 4;
 		}
 
 		i++;
@@ -1984,7 +2011,8 @@ bool mesh_db_node_set_composition(uint16_t unicast, uint8_t *data, uint16_t len)
 fail:
 	/* Reset elements array */
 	json_object_object_del(jnode, "elements");
-	init_elements(sz);
+	jelements = init_elements(sz);
+	json_object_object_add(jnode, "elements", jelements);
 
 	return false;
 }
diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h
index 4b6b2ad..0e45112 100644
--- a/tools/mesh/mesh-db.h
+++ b/tools/mesh/mesh-db.h
@@ -29,6 +29,7 @@ bool mesh_db_del_app_key(uint16_t app_idx);
 bool mesh_db_get_addr_range(uint16_t *low, uint16_t *high);
 bool mesh_db_add_node(uint8_t uuid[16], uint8_t num_els, uint16_t unicast,
 							uint16_t net_idx);
+bool mesh_db_reset_node(uint16_t original, uint16_t unicast, uint8_t num_els);
 bool mesh_db_del_node(uint16_t unicast);
 bool mesh_db_node_set_composition(uint16_t unicast, uint8_t *data,
 								uint16_t len);
diff --git a/tools/mesh/remote.c b/tools/mesh/remote.c
index 6ec220a..b917ae9 100644
--- a/tools/mesh/remote.c
+++ b/tools/mesh/remote.c
@@ -30,6 +30,12 @@ struct remote_key {
 	bool updated;
 };
 
+struct foreach_data {
+	remote_foreach_t each;
+	void *user_data;
+	uint16_t dst;
+};
+
 struct remote_node {
 	uint16_t unicast;
 	struct l_queue *net_keys;
@@ -48,6 +54,11 @@ struct rejected_addr {
 static struct l_queue *nodes;
 static struct l_queue *reject_list;
 
+static bool match_mod_id(const void *a, const void *b)
+{
+	return a == b;
+}
+
 static int compare_mod_id(const void *a, const void *b, void *user_data)
 {
 	uint32_t id1 = L_PTR_TO_UINT(a);
@@ -138,6 +149,40 @@ uint8_t remote_del_node(uint16_t unicast)
 	return num_ele;
 }
 
+bool remote_reset_node(uint16_t original, uint16_t unicast, uint8_t ele_cnt,
+							uint32_t iv_index)
+{
+	struct remote_node *rmt;
+	bool reject = true;
+	int i;
+
+	rmt = l_queue_remove_if(nodes, match_node_addr,
+						L_UINT_TO_PTR(original));
+	if (!rmt)
+		return false;
+
+	if (unicast == rmt->unicast)
+		reject = false;
+
+	for (i = 0; i < rmt->num_ele; ++i) {
+		l_queue_destroy(rmt->els[i], NULL);
+		if (reject)
+			remote_add_rejected_address(rmt->unicast + i,
+								iv_index, true);
+	}
+
+	if (ele_cnt != rmt->num_ele) {
+		l_free(rmt->els);
+		rmt->els = l_new(struct l_queue *, ele_cnt);
+	} else
+		memset(rmt->els, 0, sizeof(struct l_queue *) * ele_cnt);
+
+	rmt->unicast = unicast;
+	rmt->num_ele = ele_cnt;
+	l_queue_insert(nodes, rmt, compare_unicast, NULL);
+	return true;
+}
+
 bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
 					uint8_t ele_cnt, uint16_t net_idx)
 {
@@ -187,6 +232,10 @@ bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
 	if (!vendor)
 		mod_id = VENDOR_ID_MASK | mod_id;
 
+	if (l_queue_find(rmt->els[ele_idx], match_mod_id,
+							L_UINT_TO_PTR(mod_id)))
+		return true;
+
 	l_queue_insert(rmt->els[ele_idx], L_UINT_TO_PTR(mod_id),
 							compare_mod_id, NULL);
 
@@ -526,6 +575,76 @@ void remote_print_all(void)
 	l_queue_foreach(nodes, print_node, NULL);
 }
 
+static void each_node(void *rmt, void *user_data)
+{
+	struct remote_node *node = rmt;
+	struct foreach_data *data = user_data;
+
+	data->each(data->user_data, node->unicast, (uint32_t) -1);
+}
+
+static void each_addr(void *rmt, void *user_data)
+{
+	struct remote_node *node = rmt;
+	struct foreach_data *data = user_data;
+	uint16_t cnt;
+
+	for (cnt = 0; cnt <= node->num_ele; cnt++)
+		data->each(data->user_data, node->unicast + cnt, (uint32_t) -1);
+}
+
+static void parse_model(void *model, void *user_data)
+{
+	struct foreach_data *data = user_data;
+
+	data->each(data->user_data, data->dst, L_PTR_TO_UINT(model));
+}
+
+static void each_model(void *rmt, void *user_data)
+{
+	struct remote_node *node = rmt;
+	struct foreach_data *data = user_data;
+	uint16_t cnt;
+
+	for (cnt = 0; cnt < node->num_ele; cnt++) {
+		data->dst = node->unicast + cnt;
+		l_queue_foreach(node->els[cnt], parse_model, data);
+	}
+}
+
+void remote_foreach(remote_foreach_t each, void *user_data)
+{
+	struct foreach_data data = {
+		.each = each,
+		.user_data = user_data
+	};
+
+	if (each)
+		l_queue_foreach(nodes, each_node, &data);
+}
+
+void remote_foreach_unicast(remote_foreach_t each, void *user_data)
+{
+	struct foreach_data data = {
+		.each = each,
+		.user_data = user_data
+	};
+
+	if (each)
+		l_queue_foreach(nodes, each_addr, &data);
+}
+
+void remote_foreach_model(remote_foreach_t each, void *user_data)
+{
+	struct foreach_data data = {
+		.each = each,
+		.user_data = user_data
+	};
+
+	if (each)
+		l_queue_foreach(nodes, each_model, &data);
+}
+
 uint16_t remote_get_next_unicast(uint16_t low, uint16_t high, uint8_t ele_cnt)
 {
 	struct remote_node *rmt;
@@ -598,3 +717,15 @@ void remote_clear_rejected_addresses(uint32_t iv_index)
 
 	mesh_db_clear_rejected(iv_index);
 }
+
+uint8_t remote_ele_cnt(uint16_t unicast)
+{
+	struct remote_node *rmt;
+
+	rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(unicast));
+
+	if (rmt)
+		return rmt->num_ele;
+
+	return 0;
+}
diff --git a/tools/mesh/remote.h b/tools/mesh/remote.h
index 6645723..2a3947b 100644
--- a/tools/mesh/remote.h
+++ b/tools/mesh/remote.h
@@ -8,8 +8,13 @@
  *
  */
 
+typedef void (*remote_foreach_t)(void *user_data, uint16_t dst,
+								uint32_t model);
+
 bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
 					uint8_t ele_cnt, uint16_t net_idx);
+bool remote_reset_node(uint16_t original, uint16_t unicast, uint8_t ele_cnt,
+							uint32_t iv_index);
 uint8_t remote_del_node(uint16_t unicast);
 bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
 								bool vendor);
@@ -30,3 +35,7 @@ bool remote_has_composition(uint16_t addr);
 uint16_t remote_get_subnet_idx(uint16_t addr);
 void remote_print_node(uint16_t addr);
 void remote_print_all(void);
+void remote_foreach(remote_foreach_t each, void *user_data);
+void remote_foreach_unicast(remote_foreach_t each, void *user_data);
+void remote_foreach_model(remote_foreach_t each, void *user_data);
+uint8_t remote_ele_cnt(uint16_t unicast);
diff --git a/tools/mesh/util.c b/tools/mesh/util.c
index 2964143..310aae0 100644
--- a/tools/mesh/util.c
+++ b/tools/mesh/util.c
@@ -20,6 +20,7 @@
 #include "src/shared/util.h"
 
 #include "mesh/mesh-defs.h"
+#include "mesh/prv-beacon.h"
 
 #include "tools/mesh/util.h"
 
@@ -27,9 +28,9 @@ void set_menu_prompt(const char *name, const char *id)
 {
 	char *prompt;
 
-	prompt = l_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", name,
+	prompt = l_strdup_printf("[%s%s%s]# ", name,
 					id ? ": Target = " : "", id ? id : "");
-	bt_shell_set_prompt(prompt);
+	bt_shell_set_prompt(prompt, COLOR_BLUE);
 	l_free(prompt);
 }
 
@@ -137,6 +138,10 @@ const char *sig_model_string(uint16_t sig_model_id)
 	case 0x0001: return "Configuration Client";
 	case 0x0002: return "Health Server";
 	case 0x0003: return "Health Client";
+	case 0x0004: return "Remote Provisioning Server";
+	case 0x0005: return "Remote Provisioning Client";
+	case 0x0008: return "Private Beacon Server";
+	case 0x0009: return "Private Beacon Client";
 	case 0x1000: return "Generic OnOff Server";
 	case 0x1001: return "Generic OnOff Client";
 	case 0x1002: return "Generic Level Server";
diff --git a/tools/meshctl.c b/tools/meshctl.c
index 38ffd35..00a68a3 100644
--- a/tools/meshctl.c
+++ b/tools/meshctl.c
@@ -54,7 +54,7 @@
 #define COLORED_CHG	COLOR_YELLOW "CHG" COLOR_OFF
 #define COLORED_DEL	COLOR_RED "DEL" COLOR_OFF
 
-#define PROMPT_ON	COLOR_BLUE "[meshctl]" COLOR_OFF "# "
+#define PROMPT_ON	"[meshctl]# "
 #define PROMPT_OFF	"Waiting to connect to bluetoothd..."
 
 #define MESH_PROV_DATA_IN_UUID_STR	"00002adb-0000-1000-8000-00805f9b34fb"
@@ -172,14 +172,14 @@ static void proxy_leak(gpointer data)
 
 static void connect_handler(DBusConnection *connection, void *user_data)
 {
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT_ON, COLOR_BLUE);
 }
 
 static void disconnect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_detach();
 
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT_OFF, NULL);
 
 	g_list_free_full(ctrl_list, proxy_leak);
 	ctrl_list = NULL;
@@ -608,7 +608,7 @@ static void set_connected_device(GDBusProxy *proxy)
 				mesh ? buf : "");
 
 done:
-	bt_shell_set_prompt(desc ? desc : PROMPT_ON);
+	bt_shell_set_prompt(desc ? desc : PROMPT_ON, COLOR_BLUE);
 	g_free(desc);
 
 	/* If disconnected, return to main menu */
@@ -1901,7 +1901,7 @@ int main(int argc, char *argv[])
 
 	bt_shell_init(argc, argv, &opt);
 	bt_shell_set_menu(&main_menu);
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT_OFF, NULL);
 
 	if (!config_dir) {
 		char *home;
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index a56c381..1d5c82a 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -290,6 +290,20 @@ static void index_removed_callback(uint16_t index, uint16_t length,
 	tester_post_teardown_complete();
 }
 
+#define MAX_COREDUMP_LINE_LEN	40
+
+struct devcoredump_test_data {
+	enum devcoredump_state {
+		HCI_DEVCOREDUMP_IDLE,
+		HCI_DEVCOREDUMP_ACTIVE,
+		HCI_DEVCOREDUMP_DONE,
+		HCI_DEVCOREDUMP_ABORT,
+		HCI_DEVCOREDUMP_TIMEOUT,
+	} state;
+	unsigned int timeout;
+	char data[MAX_COREDUMP_LINE_LEN];
+};
+
 struct hci_cmd_data {
 	uint16_t opcode;
 	uint8_t len;
@@ -362,6 +376,8 @@ struct generic_data {
 	bool set_adv;
 	const uint8_t *adv_data;
 	uint8_t adv_data_len;
+	const struct devcoredump_test_data *dump_data;
+	const char (*expect_dump_data)[MAX_COREDUMP_LINE_LEN];
 };
 
 static const uint8_t set_exp_feat_param_debug[] = {
@@ -1672,53 +1688,6 @@ static const struct generic_data set_sc_only_on_success_test_2 = {
 	.expect_hci_len = sizeof(set_sc_on_write_sc_support_param),
 };
 
-static const char set_hs_on_param[] = { 0x01 };
-static const char set_hs_invalid_param[] = { 0x02 };
-static const char set_hs_garbage_param[] = { 0x01, 0x00 };
-static const char set_hs_settings_param_1[] = { 0xc0, 0x01, 0x00, 0x00 };
-
-static const struct generic_data set_hs_on_success_test = {
-	.setup_settings = settings_ssp,
-	.send_opcode = MGMT_OP_SET_HS,
-	.send_param = set_hs_on_param,
-	.send_len = sizeof(set_hs_on_param),
-	.expect_status = MGMT_STATUS_SUCCESS,
-	.expect_param = set_hs_settings_param_1,
-	.expect_len = sizeof(set_hs_settings_param_1),
-	.expect_settings_set = MGMT_SETTING_HS,
-};
-
-static const struct generic_data set_hs_on_invalid_param_test_1 = {
-	.setup_settings = settings_ssp,
-	.send_opcode = MGMT_OP_SET_HS,
-	.expect_status = MGMT_STATUS_INVALID_PARAMS,
-};
-
-static const struct generic_data set_hs_on_invalid_param_test_2 = {
-	.setup_settings = settings_ssp,
-	.send_opcode = MGMT_OP_SET_HS,
-	.send_param = set_hs_invalid_param,
-	.send_len = sizeof(set_hs_invalid_param),
-	.expect_status = MGMT_STATUS_INVALID_PARAMS,
-};
-
-static const struct generic_data set_hs_on_invalid_param_test_3 = {
-	.setup_settings = settings_ssp,
-	.send_opcode = MGMT_OP_SET_HS,
-	.send_param = set_hs_garbage_param,
-	.send_len = sizeof(set_hs_garbage_param),
-	.expect_status = MGMT_STATUS_INVALID_PARAMS,
-};
-
-static const struct generic_data set_hs_on_invalid_index_test = {
-	.setup_settings = settings_ssp,
-	.send_index_none = true,
-	.send_opcode = MGMT_OP_SET_HS,
-	.send_param = set_hs_on_param,
-	.send_len = sizeof(set_hs_on_param),
-	.expect_status = MGMT_STATUS_INVALID_INDEX,
-};
-
 static uint16_t settings_le[] = { MGMT_OP_SET_LE, 0 };
 
 static const char set_le_on_param[] = { 0x01 };
@@ -1870,14 +1839,13 @@ static const char set_adv_set_local_name_param[260] = { 'T', 'e', 's', 't', ' ',
 							'n', 'a', 'm', 'e' };
 
 static const uint8_t set_adv_scan_rsp_data_name_1[] = {
-	0x0c, /* Scan rsp data len */
-	0x0b, /* Local name data len */
+	0x0b, /* Scan rsp data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
 	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, /* "Test name" */
-	0x00, /* null */
 	/* padding */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
 static const struct generic_data set_adv_on_local_name_test_1 = {
@@ -1910,17 +1878,16 @@ static const struct setup_mgmt_cmd set_advertising_mgmt_cmd_arr[] = {
 };
 
 static const uint8_t set_adv_scan_rsp_data_name_and_appearance[] = {
-	0x10, /* scan rsp data len */
+	0x0f, /* scan rsp data len */
 	0x03, /* appearance data len */
 	0x19, /* eir_appearance */
 	0x54, 0x65, /* appearance value */
-	0x0b, /* local name data len */
+	0x0a, /* local name data len */
 	0x09, /* complete name */
 	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, /* "test name" */
-	0x00, /* null */
 	/* padding */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
 
@@ -3200,7 +3167,7 @@ static const struct generic_data pair_device_power_off_test_1 = {
 	.send_opcode = MGMT_OP_PAIR_DEVICE,
 	.send_func = pair_device_send_param_func,
 	.force_power_off = true,
-	.expect_status = MGMT_STATUS_NOT_POWERED,
+	.expect_status = MGMT_STATUS_DISCONNECTED,
 	.expect_func = pair_device_expect_param_func,
 };
 
@@ -4666,6 +4633,16 @@ static const struct generic_data remove_device_success_6 = {
 	.expect_status = MGMT_STATUS_SUCCESS,
 };
 
+static const struct generic_data add_remove_device_nowait = {
+	.setup_settings = settings_powered_le,
+	.expect_param = remove_device_param_2,
+	.expect_len = sizeof(remove_device_param_2),
+	.expect_status = MGMT_STATUS_SUCCESS,
+	.expect_alt_ev = MGMT_EV_DEVICE_REMOVED,
+	.expect_alt_ev_param = remove_device_param_2,
+	.expect_alt_ev_len = sizeof(remove_device_param_2),
+};
+
 static const struct generic_data read_adv_features_invalid_param_test = {
 	.send_opcode = MGMT_OP_READ_ADV_FEATURES,
 	.send_param = dummy_data,
@@ -5642,7 +5619,7 @@ static const char ext_ctrl_info1[] = {
 	0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */
 	0x09, /* version */
 	0xf1, 0x05, /* manufacturer */
-	0xff, 0xbf, 0x01, 0x00, /* supported settings */
+	0xff, 0xbe, 0x01, 0x00, /* supported settings */
 	0x80, 0x00, 0x00, 0x00, /* current settings */
 	0x09, 0x00, /* eir length */
 	0x04, /* dev class length */
@@ -5682,7 +5659,7 @@ static const char ext_ctrl_info2[] = {
 	0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */
 	0x09, /* version */
 	0xf1, 0x05, /* manufacturer */
-	0xff, 0xbf, 0x01, 0x00, /* supported settings */
+	0xff, 0xbe, 0x01, 0x00, /* supported settings */
 	0x81, 0x02, 0x00, 0x00, /* current settings */
 	0x0D, 0x00, /* eir length */
 	0x04, /* dev class length */
@@ -5714,7 +5691,7 @@ static const char ext_ctrl_info3[] = {
 	0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */
 	0x09, /* version */
 	0xf1, 0x05, /* manufacturer */
-	0xff, 0xbf, 0x01, 0x00, /* supported settings */
+	0xff, 0xbe, 0x01, 0x00, /* supported settings */
 	0x80, 0x02, 0x00, 0x00, /* current settings */
 	0x16, 0x00, /* eir length */
 	0x04, /* dev class length */
@@ -5749,7 +5726,7 @@ static const char ext_ctrl_info4[] = {
 	0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */
 	0x09, /* version */
 	0xf1, 0x05, /* manufacturer */
-	0xff, 0xbf, 0x01, 0x00, /* supported settings */
+	0xff, 0xbe, 0x01, 0x00, /* supported settings */
 	0x80, 0x02, 0x00, 0x00, /* current settings */
 	0x1a, 0x00, /* eir length */
 	0x04, /* dev class length */
@@ -5803,7 +5780,7 @@ static const char ext_ctrl_info5[] = {
 	0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */
 	0x09, /* version */
 	0xf1, 0x05, /* manufacturer */
-	0xff, 0xbf, 0x01, 0x00, /* supported settings */
+	0xff, 0xbe, 0x01, 0x00, /* supported settings */
 	0x81, 0x02, 0x00, 0x00, /* current settings */
 	0x1a, 0x00, /* eir len */
 	0x04, /* dev class len */
@@ -5878,8 +5855,8 @@ static const char ext_adv_hci_params_valid[] = {
 static const char ext_adv_params_mgmt_rsp_valid_50[] = {
 	0x01, /* instance */
 	0x00, /* tx_power defaults to 0 on BT5 platform*/
-	0x1f, /* max_adv_data_len */
-	0x1f, /* max_scan_rsp_len */
+	0xfb, /* max_adv_data_len */
+	0xfb, /* max_scan_rsp_len */
 };
 
 static const char ext_adv_params_mgmt_rsp_valid[] = {
@@ -7699,6 +7676,23 @@ static const uint8_t add_advertising_param_scrsp_data_only_too_long[] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00,
 };
 
@@ -7752,6 +7746,29 @@ static const uint8_t add_advertising_param_scrsp_appear_data_too_long[] = {
 	/* scan rsp data: */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
@@ -7833,8 +7850,8 @@ static const uint8_t add_advertising_param_name[] = {
 };
 
 static const uint8_t set_scan_rsp_data_name_fits_in_scrsp[] = {
-	0x0c, /* Scan rsp data len */
-	0x0b, /* Local name data len */
+	0x0b, /* Scan rsp data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
 	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, /* "Test name" */
 	/* padding */
@@ -7859,8 +7876,8 @@ static const struct generic_data add_advertising_name_fits_in_scrsp = {
 };
 
 static const uint8_t set_scan_rsp_data_shortened_name_fits[] = {
-	0x0d, /* Scan rsp data len */
-	0x0c, /* Local name data len */
+	0x0c, /* Scan rsp data len */
+	0x0b, /* Local name data len */
 	0x08, /* Short name */
 	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x31,
 	/* "Test name1" */
@@ -7886,8 +7903,8 @@ static const struct generic_data add_advertising_shortened_name_in_scrsp = {
 };
 
 static const uint8_t set_scan_rsp_data_short_name_fits[] = {
-	0x07, /* Scan rsp data len */
-	0x06, /* Local name data len */
+	0x06, /* Scan rsp data len */
+	0x05, /* Local name data len */
 	0x08, /* Short name */
 	0x54, 0x65, 0x73, 0x74,
 	/* "Test*/
@@ -7927,16 +7944,16 @@ static const uint8_t add_advertising_param_name_data_ok[] = {
 };
 
 static const uint8_t set_scan_rsp_data_param_name_data_ok[] = {
-	0x1e, /* Scan rsp data len */
+	0x1d, /* Scan rsp data len */
 	/* scan rsp data */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x0b, /* Local name data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 	/* "Test name" */
 	/* padding */
-	0x00,
+	0x00, 0x00,
 };
 
 static const struct generic_data add_advertising_name_data_ok = {
@@ -7965,6 +7982,29 @@ static const uint8_t add_advertising_param_name_data_inv[] = {
 	/* adv data: */
 	/* scan rsp data: */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
@@ -8008,19 +8048,19 @@ static const struct setup_mgmt_cmd add_advertising_mgmt_cmd_arr[] = {
 };
 
 static const uint8_t set_scan_rsp_data_name_data_appear[] = {
-	0x1e, /* Scan rsp data len */
+	0x1d, /* Scan rsp data len */
 	0x03, /* appearance len */
 	0x19, /* EIR_APPEARANCE */
 	0x54, 0x65, /* appearance value */
 	/* scan rsp data */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00,
-	0x0b, /* Local name data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 	/* "Test name" */
 	/* padding */
-	0x00,
+	0x00, 0x00,
 };
 
 static const struct generic_data add_advertising_name_data_appear = {
@@ -8058,8 +8098,8 @@ static const struct generic_data set_appearance_success = {
 
 static const uint8_t read_adv_features_rsp_3[] =  {
 	0xff, 0xff, 0x01, 0x00,	/* supported flags */
-	0x1f,			/* max_adv_data_len */
-	0x1f,			/* max_scan_rsp_len */
+	0xfb,			/* max_adv_data_len */
+	0xfb,			/* max_scan_rsp_len */
 	0x03,			/* max_instances */
 	0x00,			/* num_instances */
 };
@@ -8709,6 +8749,7 @@ static const struct hci_cmd_data multi_ext_adv_add_second_hci_cmds[] = {
 		.len = sizeof(le_set_ext_adv_enable_inst_2),
 		.param = le_set_ext_adv_enable_inst_2,
 	},
+	{},
 };
 
 static const struct generic_data multi_ext_advertising_add_second_2 = {
@@ -8756,6 +8797,7 @@ static const struct hci_cmd_data multi_ext_adv_remove_adv_hci_cmds[] = {
 		.len = sizeof(advertising_instance1_param),
 		.param = advertising_instance1_param,
 	},
+	{},
 };
 
 static const struct generic_data multi_ext_advertising_remove = {
@@ -8788,6 +8830,7 @@ static const struct hci_cmd_data multi_ext_adv_remove_all_adv_hci_cmds[] = {
 	{
 		.opcode = BT_HCI_CMD_LE_CLEAR_ADV_SETS,
 	},
+	{},
 };
 
 static const struct generic_data multi_ext_advertising_remove_all = {
@@ -8824,6 +8867,7 @@ static const struct hci_cmd_data multi_ext_adv_add_2_advs_hci_cmds[] = {
 		.len = sizeof(set_ext_adv_data_test1),
 		.param = set_ext_adv_data_test1,
 	},
+	{},
 };
 
 static const struct generic_data multi_ext_advertising_add_no_power = {
@@ -8930,11 +8974,11 @@ static const uint8_t set_ext_scan_rsp_data_name_fits_in_scrsp[] = {
 	0x01,				/* handle */
 	0x03,				/* complete data */
 	0x01,				/* controller should not fragment */
-	0x0c, /* Scan rsp data len */
-	0x0b, /* Local name data len */
+	0x0b, /* Scan rsp data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
 	/* "Test name" */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 };
 
 static const struct generic_data add_ext_advertising_name_fits_in_scrsp = {
@@ -8957,11 +9001,11 @@ static const uint8_t set_ext_scan_rsp_data_shortened_name_fits[] = {
 	0x01,				/* handle */
 	0x03,				/* complete data */
 	0x01,				/* controller should not fragment */
-	0x0d, /* Scan rsp data len */
-	0x0c, /* Local name data len */
+	0x0c, /* Scan rsp data len */
+	0x0b, /* Local name data len */
 	0x08, /* Short name */
 	/* "Test name1" */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x31,
 };
 
 static const struct generic_data add_ext_advertising_shortened_name_in_scrsp = {
@@ -8984,13 +9028,13 @@ static const uint8_t set_ext_scan_rsp_data_param_name_data_ok[] = {
 	0x01,				/* handle */
 	0x03,				/* complete data */
 	0x01,				/* controller should not fragment */
-	0x1e, /* Scan rsp data len */
+	0x1d, /* Scan rsp data len */
 	/* scan rsp data */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x0b, /* Local name data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 	/* "Test name" */
 };
 
@@ -9027,16 +9071,16 @@ static const uint8_t set_ext_scan_rsp_data_name_data_appear[] = {
 	0x01,				/* handle */
 	0x03,				/* complete data */
 	0x01,				/* controller should not fragment */
-	0x1e, /* Scan rsp data len */
+	0x1d, /* Scan rsp data len */
 	0x03, /* appearance len */
 	0x19, /* EIR_APPEARANCE */
 	0x54, 0x65, /* appearance value */
 	/* scan rsp data */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00,
-	0x0b, /* Local name data len */
+	0x0a, /* Local name data len */
 	0x09, /* Complete name */
-	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+	0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 	/* "Test name" */
 };
 
@@ -9429,7 +9473,7 @@ static const struct generic_data add_ext_advertising_conn_off_1m = {
 static const uint8_t get_phy_param[] = {
 	0xff, 0x7f, 0x00, 0x00,	/* All PHYs */
 	0xfe, 0x79,	0x00, 0x00, /* All PHYs except BR 1M 1SLOT, LE 1M TX & LE 1M RX */
-	0xff, 0x07, 0x00, 0x00, /* All BREDR PHYs and LE 1M TX & LE 1M RX */
+	0xff, 0x7f, 0x00, 0x00, /* All PHYs */
 };
 
 static const struct generic_data get_phy_success = {
@@ -9492,26 +9536,6 @@ static const uint8_t set_phy_all_param[] = {
 	0xff, 0x7f,	0x00, 0x00	/* All PHYs */
 };
 
-static const uint8_t set_default_phy_all_param[] = {
-	0x00, 		/* preference is there for tx and rx */
-	0x07,		/* 1m 2m coded tx */
-	0x07,		/* 1m 2m coded rx */
-};
-
-static const struct generic_data set_phy_all_success = {
-	.setup_settings = settings_powered_le,
-	.send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
-	.send_param = set_phy_all_param,
-	.send_len = sizeof(set_phy_all_param),
-	.expect_status = MGMT_STATUS_SUCCESS,
-	.expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
-	.expect_hci_param = set_default_phy_all_param,
-	.expect_hci_len = sizeof(set_default_phy_all_param),
-	.expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
-	.expect_alt_ev_param = set_phy_all_param,
-	.expect_alt_ev_len = sizeof(set_phy_all_param),
-};
-
 static const uint8_t set_phy_2m_tx_param[] = {
 	0xff, 0x0f,	0x00, 0x00	/* 1mtxrx, 2m tx */
 };
@@ -9619,13 +9643,16 @@ static const struct generic_data start_discovery_le_ext_scan_enable = {
 	.expect_alt_ev_len = sizeof(start_discovery_le_evt),
 };
 
-static const char start_discovery_valid_ext_scan_param[] = {
+static const char start_discovery_ext_scan_param[] = {
 	0x01,			/* Own Addr type*/
 	0x00,			/* Scan filter policy*/
-	0x01,			/*Phys - 1m */
+	0x05,			/* Phys - 1m and Coded*/
 	0x01,			/* Type */
 	0x12, 0x00,		/* Interval */
 	0x12, 0x00,		/* Window */
+	0x01,			/* Type */
+	0x36, 0x00,		/* Interval */
+	0x36, 0x00,		/* Window */
 };
 
 static const struct generic_data start_discovery_le_ext_scan_param = {
@@ -9637,8 +9664,8 @@ static const struct generic_data start_discovery_le_ext_scan_param = {
 	.expect_param = start_discovery_le_param,
 	.expect_len = sizeof(start_discovery_le_param),
 	.expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
-	.expect_hci_param = start_discovery_valid_ext_scan_param,
-	.expect_hci_len = sizeof(start_discovery_valid_ext_scan_param),
+	.expect_hci_param = start_discovery_ext_scan_param,
+	.expect_hci_len = sizeof(start_discovery_ext_scan_param),
 	.expect_alt_ev = MGMT_EV_DISCOVERING,
 	.expect_alt_ev_param = start_discovery_le_evt,
 	.expect_alt_ev_len = sizeof(start_discovery_le_evt),
@@ -9670,6 +9697,15 @@ static const struct generic_data stop_discovery_le_ext_scan_disable = {
 	.expect_alt_ev_len = sizeof(stop_discovery_evt),
 };
 
+static const char start_discovery_2m_ext_scan_param[] = {
+	0x01,			/* Own Addr type*/
+	0x00,			/* Scan filter policy*/
+	0x01,			/* Phys - 1m and Coded*/
+	0x01,			/* Type */
+	0x12, 0x00,		/* Interval */
+	0x12, 0x00,		/* Window */
+};
+
 static const struct generic_data start_discovery_le_2m_scan_param = {
 	.setup_settings = settings_powered_le,
 	.setup_send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
@@ -9682,8 +9718,8 @@ static const struct generic_data start_discovery_le_2m_scan_param = {
 	.expect_param = start_discovery_bredrle_param,
 	.expect_len = sizeof(start_discovery_bredrle_param),
 	.expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
-	.expect_hci_param = start_discovery_valid_ext_scan_param,
-	.expect_hci_len = sizeof(start_discovery_valid_ext_scan_param),
+	.expect_hci_param = start_discovery_2m_ext_scan_param,
+	.expect_hci_len = sizeof(start_discovery_2m_ext_scan_param),
 	.expect_alt_ev = MGMT_EV_DISCOVERING,
 	.expect_alt_ev_param = start_discovery_evt,
 	.expect_alt_ev_len = sizeof(start_discovery_evt),
@@ -9697,8 +9733,8 @@ static const char start_discovery_valid_coded_scan_param[] = {
 	0x12, 0x00,		/* Interval */
 	0x12, 0x00,		/* Window */
 	0x01,			/* Type */
-	0x12, 0x00,		/* Interval */
-	0x12, 0x00,		/* Window */
+	0x36, 0x00,		/* Interval */
+	0x36, 0x00,		/* Window */
 };
 
 static const struct generic_data start_discovery_le_coded_scan_param = {
@@ -9728,8 +9764,8 @@ static const char start_discovery_valid_1m_2m_coded_scan_param[] = {
 	0x12, 0x00,		/* Interval */
 	0x12, 0x00,		/* Window */
 	0x01,			/* Type */
-	0x12, 0x00,		/* Interval */
-	0x12, 0x00,		/* Window */
+	0x36, 0x00,		/* Interval */
+	0x36, 0x00,		/* Window */
 };
 
 static const struct generic_data start_discovery_le_1m_coded_scan_param = {
@@ -10297,6 +10333,7 @@ static const struct hci_cmd_data ll_privacy_add_device_3_hci_list[] = {
 		.param = set_resolv_on_param,
 		.len = sizeof(set_resolv_on_param),
 	},
+	{},
 };
 
 static const struct generic_data ll_privacy_add_device_3 = {
@@ -10414,6 +10451,7 @@ static const struct hci_cmd_data ll_privacy_add_device_9_hci_list[] = {
 		.len = sizeof(le_add_to_resolv_list_param),
 		.param = le_add_to_resolv_list_param
 	},
+	{},
 };
 
 static const struct generic_data ll_privacy_add_device_9 = {
@@ -10742,6 +10780,7 @@ static const struct hci_cmd_data ll_privacy_set_device_flags_1_hci_list[] = {
 		.param = set_resolv_on_param,
 		.len = sizeof(set_resolv_on_param),
 	},
+	{},
 };
 
 static const uint8_t device_flags_changed_params_1[] = {
@@ -11452,6 +11491,41 @@ static void test_remove_device(const void *test_data)
 	test_add_condition(data);
 }
 
+static bool hook_delay_cmd(const void *data, uint16_t len, void *user_data)
+{
+	tester_print("Delaying emulator response...");
+	g_usleep(250000);
+	tester_print("Delaying emulator response... Done.");
+	return true;
+}
+
+static void test_add_remove_device_nowait(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	/* Add and remove LE device with autoconnect without waiting for reply,
+	 * while delaying emulator response to better hit a race condition.
+	 * This shall not crash the kernel (but eg Linux 6.4-rc4 crashes).
+	 */
+
+	tester_print("Adding and removing a device");
+
+	test_add_condition(data);
+
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+					BT_HCI_CMD_LE_ADD_TO_ACCEPT_LIST,
+					hook_delay_cmd, NULL);
+
+	mgmt_send_nowait(data->mgmt, MGMT_OP_ADD_DEVICE, data->mgmt_index,
+				sizeof(add_device_success_param_3),
+				add_device_success_param_3, NULL, NULL, NULL);
+
+	mgmt_send_nowait(data->mgmt, MGMT_OP_REMOVE_DEVICE, data->mgmt_index,
+				sizeof(remove_device_param_2),
+				remove_device_param_2,
+				command_generic_callback, NULL, NULL);
+}
+
 static void trigger_device_found(void *user_data)
 {
 	struct test_data *data = tester_get_data();
@@ -12511,6 +12585,143 @@ static void test_suspend_resume_success_10(const void *test_data)
 	tester_wait(2, trigger_force_resume, NULL);
 }
 
+#define MAX_COREDUMP_BUF_LEN	512
+
+static const struct devcoredump_test_data data_complete_dump = {
+	.state = HCI_DEVCOREDUMP_DONE,
+	.data = "test data",
+};
+
+static const char expected_complete_dump[][MAX_COREDUMP_LINE_LEN] = {
+	"Bluetooth devcoredump",
+	"State: 2",
+	"Controller Name: vhci_ctrl",
+	"Firmware Version: vhci_fw",
+	"Driver: vhci_drv",
+	"Vendor: vhci",
+	"--- Start dump ---",
+	"", /* end of header data */
+};
+
+static const struct generic_data dump_complete = {
+	.dump_data = &data_complete_dump,
+	.expect_dump_data = expected_complete_dump,
+};
+
+static const struct devcoredump_test_data data_abort_dump = {
+	.state = HCI_DEVCOREDUMP_ABORT,
+	.data = "test data",
+};
+
+static const char expected_abort_dump[][MAX_COREDUMP_LINE_LEN] = {
+	"Bluetooth devcoredump",
+	"State: 3",
+	"Controller Name: vhci_ctrl",
+	"Firmware Version: vhci_fw",
+	"Driver: vhci_drv",
+	"Vendor: vhci",
+	"--- Start dump ---",
+	"", /* end of header data */
+};
+
+static const struct generic_data dump_abort = {
+	.dump_data = &data_abort_dump,
+	.expect_dump_data = expected_abort_dump,
+};
+
+static const struct devcoredump_test_data data_timeout_dump = {
+	.state = HCI_DEVCOREDUMP_TIMEOUT,
+	.timeout = 1,
+	.data = "test data",
+};
+
+static const char expected_timeout_dump[][MAX_COREDUMP_LINE_LEN] = {
+	"Bluetooth devcoredump",
+	"State: 4",
+	"Controller Name: vhci_ctrl",
+	"Firmware Version: vhci_fw",
+	"Driver: vhci_drv",
+	"Vendor: vhci",
+	"--- Start dump ---",
+	"", /* end of header data */
+};
+
+static const struct generic_data dump_timeout = {
+	.dump_data = &data_timeout_dump,
+	.expect_dump_data = expected_timeout_dump,
+};
+
+static void verify_devcd(void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct generic_data *test = data->test_data;
+	struct vhci *vhci = hciemu_get_vhci(data->hciemu);
+	char buf[MAX_COREDUMP_BUF_LEN + 1] = {0};
+	int read;
+	char delim[] = "\n";
+	char *line;
+	char *saveptr;
+	int i = 0;
+
+	/* Read the generated devcoredump file */
+	read = vhci_read_devcd(vhci, buf, MAX_COREDUMP_BUF_LEN);
+	if (read <= 0) {
+		tester_warn("Unable to read devcoredump");
+		tester_test_failed();
+		return;
+	}
+	/* Make sure buf is nul-terminated */
+	buf[read] = '\0';
+
+	/* Verify if all devcoredump header fields are present */
+	line = strtok_r(buf, delim, &saveptr);
+	while (strlen(test->expect_dump_data[i])) {
+		if (!line || strcmp(line, test->expect_dump_data[i])) {
+			tester_warn("Incorrect coredump data: %s (expected %s)",
+					line, test->expect_dump_data[i]);
+			tester_test_failed();
+			return;
+		}
+
+		if (!strcmp(strtok(line, ":"), "State")) {
+			/* After updating the devcoredump state, the HCI
+			 * devcoredump API adds a `\0` at the end. Skip it
+			 * before reading the next line.
+			 */
+			saveptr++;
+		}
+
+		line = strtok_r(NULL, delim, &saveptr);
+		i++;
+	}
+
+	/* Verify the devcoredump data */
+	if (!line || strcmp(line, test->dump_data->data)) {
+		tester_warn("Incorrect coredump data: %s (expected %s)", line,
+				test->dump_data->data);
+		tester_test_failed();
+		return;
+	}
+
+	tester_test_passed();
+}
+
+static void test_hci_devcd(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct generic_data *test = data->test_data;
+	struct vhci *vhci = hciemu_get_vhci(data->hciemu);
+
+	/* Triggers the devcoredump */
+	if (vhci_force_devcd(vhci, test->dump_data, sizeof(*test->dump_data))) {
+		tester_warn("Unable to set force_devcoredump");
+		tester_test_abort();
+		return;
+	}
+
+	tester_wait(test->dump_data->timeout + 1, verify_devcd, NULL);
+}
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -12832,22 +13043,6 @@ int main(int argc, char *argv[])
 				&set_sc_only_on_success_test_2,
 				NULL, test_command_generic);
 
-	test_hs("Set High Speed on - Success",
-				&set_hs_on_success_test,
-				NULL, test_command_generic);
-	test_hs("Set High Speed on - Invalid parameters 1",
-				&set_hs_on_invalid_param_test_1,
-				NULL, test_command_generic);
-	test_hs("Set High Speed on - Invalid parameters 2",
-				&set_hs_on_invalid_param_test_2,
-				NULL, test_command_generic);
-	test_hs("Set High Speed on - Invalid parameters 3",
-				&set_hs_on_invalid_param_test_3,
-				NULL, test_command_generic);
-	test_hs("Set High Speed on - Invalid index",
-				&set_hs_on_invalid_index_test,
-				NULL, test_command_generic);
-
 	test_bredrle("Set Low Energy on - Success 1",
 				&set_le_on_success_test_1,
 				NULL, test_command_generic);
@@ -13399,6 +13594,10 @@ int main(int argc, char *argv[])
 				&remove_device_success_6,
 				setup_add_device, test_remove_device);
 
+	test_le("Add + Remove Device Nowait - Success",
+				&add_remove_device_nowait,
+				NULL, test_add_remove_device_nowait);
+
 	test_bredrle("Read Advertising Features - Invalid parameters",
 				&read_adv_features_invalid_param_test,
 				NULL, test_command_generic);
@@ -14018,9 +14217,6 @@ int main(int argc, char *argv[])
 	test_bredrle50("Set PHY coded Succcess", &set_phy_coded_success,
 					NULL, test_command_generic);
 
-	test_bredrle50("Set PHY 1m 2m coded Succcess", &set_phy_all_success,
-					NULL, test_command_generic);
-
 	test_bredrle50("Set PHY 2m tx success", &set_phy_2m_tx_success,
 					NULL, test_command_generic);
 
@@ -14651,5 +14847,29 @@ int main(int argc, char *argv[])
 				setup_ll_privacy_add_device,
 				test_command_generic);
 
+	/* HCI Devcoredump
+	 * Setup : Power on
+	 * Run: Trigger devcoredump via force_devcoredump
+	 * Expect: Devcoredump is generated with correct data
+	 */
+	test_bredrle("HCI Devcoredump - Dump Complete", &dump_complete, NULL,
+			test_hci_devcd);
+
+	/* HCI Devcoredump
+	 * Setup : Power on
+	 * Run: Trigger devcoredump via force_devcoredump
+	 * Expect: Devcoredump is generated with correct data
+	 */
+	test_bredrle("HCI Devcoredump - Dump Abort", &dump_abort, NULL,
+			test_hci_devcd);
+
+	/* HCI Devcoredump
+	 * Setup : Power on
+	 * Run: Trigger devcoredump via force_devcoredump
+	 * Expect: Devcoredump is generated with correct data
+	 */
+	test_bredrle_full("HCI Devcoredump - Dump Timeout", &dump_timeout, NULL,
+				test_hci_devcd, 3);
+
 	return tester_run();
 }
diff --git a/tools/missing.h b/tools/missing.h
new file mode 100644
index 0000000..464df9b
--- /dev/null
+++ b/tools/missing.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2024  Khem Raj <raj.khem@gmail.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#if !HAVE_DECL_BASENAME
+#include <string.h>
+static inline const char *basename(const char *path)
+{
+	const char *base = strrchr(path, '/');
+
+	return base ? base + 1 : path;
+}
+#endif
diff --git a/tools/mpris-proxy.service.in b/tools/mpris-proxy.service.in
new file mode 100644
index 0000000..5307490
--- /dev/null
+++ b/tools/mpris-proxy.service.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=Bluetooth mpris proxy
+Documentation=man:mpris-proxy(1)
+
+Wants=dbus.socket
+After=dbus.socket
+
+[Service]
+Type=simple
+ExecStart=@PKGBINDIR@/mpris-proxy
+
+[Install]
+WantedBy=default.target
diff --git a/tools/obexctl.c b/tools/obexctl.c
index 56a7691..a398b09 100644
--- a/tools/obexctl.c
+++ b/tools/obexctl.c
@@ -33,8 +33,7 @@
 #define COLORED_CHG	COLOR_YELLOW "CHG" COLOR_OFF
 #define COLORED_DEL	COLOR_RED "DEL" COLOR_OFF
 
-#define PROMPT_ON	COLOR_BLUE "[obex]" COLOR_OFF "# "
-#define PROMPT_OFF	"[obex]# "
+#define PROMPT		"[obex]# "
 
 #define OBEX_SESSION_INTERFACE "org.bluez.obex.Session1"
 #define OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
@@ -64,13 +63,13 @@ struct transfer_data {
 static void connect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_attach(fileno(stdin));
-	bt_shell_set_prompt(PROMPT_ON);
+	bt_shell_set_prompt(PROMPT, COLOR_BLUE);
 }
 
 static void disconnect_handler(DBusConnection *connection, void *user_data)
 {
 	bt_shell_detach();
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT, NULL);
 }
 
 static char *generic_generator(const char *text, int state, GList *source)
@@ -114,7 +113,7 @@ static void connect_reply(DBusMessage *message, void *user_data)
 struct connect_args {
 	char *dev;
 	char *target;
-	uint8_t channel;
+	uint16_t channel;
 };
 
 static void connect_args_free(void *data)
@@ -144,9 +143,14 @@ static void connect_setup(DBusMessageIter *iter, void *user_data)
 		g_dbus_dict_append_entry(&dict, "Target",
 					DBUS_TYPE_STRING, &args->target);
 
-	if (args->channel)
-		g_dbus_dict_append_entry(&dict, "Channel",
+	if (args->channel) {
+		if (args->channel > 31)
+			g_dbus_dict_append_entry(&dict, "PSM",
+					DBUS_TYPE_UINT16, &args->channel);
+		else
+			g_dbus_dict_append_entry(&dict, "Channel",
 					DBUS_TYPE_BYTE, &args->channel);
+	}
 
 	dbus_message_iter_close_container(iter, &dict);
 }
@@ -169,8 +173,8 @@ static void cmd_connect(int argc, char *argv[])
 		char *endptr = NULL;
 
 		channel = strtol(argv[3], &endptr, 0);
-		if (!endptr || *endptr != '\0' || channel > UINT8_MAX) {
-			bt_shell_printf("Invalid channel\n");
+		if (!endptr || *endptr != '\0' || channel > UINT16_MAX) {
+			bt_shell_printf("Invalid channel or PSM\n");
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 	}
@@ -404,15 +408,15 @@ static void set_default_session(GDBusProxy *proxy)
 	default_session = proxy;
 
 	if (!g_dbus_proxy_get_property(proxy, "Destination", &iter)) {
-		desc = g_strdup(PROMPT_ON);
+		desc = g_strdup(PROMPT);
 		goto done;
 	}
 
 	dbus_message_iter_get_basic(&iter, &desc);
-	desc = g_strdup_printf(COLOR_BLUE "[%s]" COLOR_OFF "# ", desc);
+	desc = g_strdup_printf("[%s] #", desc);
 
 done:
-	bt_shell_set_prompt(desc);
+	bt_shell_set_prompt(desc, COLOR_BLUE);
 	g_free(desc);
 }
 
@@ -1846,7 +1850,7 @@ static void cmd_mkdir(int argc, char *argv[])
 static const struct bt_shell_menu main_menu = {
 	.name = "main",
 	.entries = {
-	{ "connect",      "<dev> [uuid] [channel]", cmd_connect,
+	{ "connect",      "<dev> [uuid] [channel|PSM]", cmd_connect,
 						"Connect session" },
 	{ "disconnect",   "[session]", cmd_disconnect, "Disconnect session",
 						session_generator },
@@ -2152,7 +2156,7 @@ int main(int argc, char *argv[])
 
 	bt_shell_init(argc, argv, NULL);
 	bt_shell_set_menu(&main_menu);
-	bt_shell_set_prompt(PROMPT_OFF);
+	bt_shell_set_prompt(PROMPT, NULL);
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
 
diff --git a/tools/parse_companies.pl b/tools/parse_companies.pl
deleted file mode 100755
index 9006492..0000000
--- a/tools/parse_companies.pl
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/perl
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-# parse companies from
-# https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
-
-use strict;
-# use URI::Encode qw(uri_decode);
-
-my %known_entities = (
-    'nbsp' => ' ',
-    'aacute' => 'á',
-    'eacute' => 'é',
-    'iacute' => 'í',
-    'oacute' => 'ó',
-    'uacute' => 'ú',
-    'auml' => 'ä',
-    'uuml' => 'ü',
-    'Uuml' => 'Ü',
-);
-
-# better to use URI::Encode if you have it
-sub uri_decode {
-    my $name = $_[0];
-    foreach my $entity (keys %known_entities) {
-        my $to = $known_entities{$entity};
-        $name =~ s/&$entity;/$to/g;
-    }
-    foreach my $entity (map { lc $_ } $name =~ /&([^;]+);/g) {
-        if ($entity ne 'amp') {
-            die "\nparse_companies.pl: Unable to convert &$entity; giving up\n";
-        }
-    }
-    $name =~ s/&amp;/&/ig;
-    $name =~ s/&nbsp;/ /ig;
-    return $name;
-}
-
-# never parse HTML with regex!
-# except when you should
-
-my $identifier;
-my $next_is_name = 0;
-
-while (<>) {
-    s/\xe2\x80\x8b//g; # kill zero width space
-
-    # grab identifier (in hex)
-    if (/\<td.*(0x[0-9A-F]{4})/i) {
-        $identifier = $1;
-        $next_is_name = 1;
-
-    # next <td> should be company name
-    } elsif ($next_is_name && m|\<td.*\>(.*)\<|) {
-        my $name = uri_decode($1);
-        $name =~ s/^\s+//g; # kill leading
-        $name =~ s/\s+$//g; # and trailing space
-        $name =~ s/"/\\"/g; # escape double quotes
-        my $id = hex($identifier);
-        if ($id != 65535) {
-            print "\tcase $id:\n";
-            print "\t\treturn \"$name\";\n";
-        }
-        $next_is_name = 0;
-    }
-}
diff --git a/tools/parser/avrcp.c b/tools/parser/avrcp.c
index e73a631..d574c7e 100644
--- a/tools/parser/avrcp.c
+++ b/tools/parser/avrcp.c
@@ -160,6 +160,7 @@
 #define AVRCP_MEDIA_ATTRIBUTE_TOTAL	0x5
 #define AVRCP_MEDIA_ATTRIBUTE_GENRE	0x6
 #define AVRCP_MEDIA_ATTRIBUTE_DURATION	0x7
+#define AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE	0x08
 
 /* play status */
 #define AVRCP_PLAY_STATUS_STOPPED	0x00
@@ -933,6 +934,8 @@ static const char *mediattr2str(uint32_t attr)
 		return "Genre";
 	case AVRCP_MEDIA_ATTRIBUTE_DURATION:
 		return "Track duration";
+	case AVRCP_MEDIA_ATTRIBUTE_IMG_HANDLE:
+		return "Imaging handle";
 	default:
 		return "Reserved";
 	}
diff --git a/tools/rctest.1 b/tools/rctest.1
new file mode 100644
index 0000000..4bfd9fa
--- /dev/null
+++ b/tools/rctest.1
@@ -0,0 +1,126 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "RCTEST" "1" "Jul 6, 2009" "BlueZ" "Linux System Administration"
+.SH NAME
+rctest \- RFCOMM testing
+.SH SYNOPSIS
+.sp
+\fBrctest\fP <\fIMODE\fP> [\fIOPTIONS\fP] [\fIbdaddr\fP]
+.SH DESCRIPTION
+.sp
+\fBrctest(1)\fP is used to test RFCOMM communications on the BlueZ stack
+.SH MODES
+.INDENT 0.0
+.TP
+.B  \-r
+listen and receive
+.TP
+.B  \-w
+listen and send
+.TP
+.B  \-d
+listen and dump incoming data
+.TP
+.B  \-s
+connect and send
+.TP
+.B  \-u
+connect and receive
+.TP
+.B  \-n
+connect and be silent
+.TP
+.B  \-c
+connect, disconnect, connect, ...
+.TP
+.B  \-m
+multiple connects
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-b \ bytes
+send/receive bytes
+.TP
+.BI \-i \ device
+select the specified device
+.TP
+.BI \-P \ channel
+select the specified channel
+.TP
+.BI \-U \ uuid
+select the specified uuid
+.TP
+.BI \-L \ seconds
+enable SO_LINGER options for seconds
+.TP
+.BI \-W \ seconds
+enable deferred setup for seconds
+.TP
+.BI \-B \ filename
+use data packets from filename
+.TP
+.BI \-N \ num
+send num frames
+.TP
+.BI \-C \ num
+send num frames before delay (default: 1)
+.TP
+.BI \-D \ milliseconds
+delay milliseconds after sending num frames (default: 0)
+.TP
+.B  \-A
+request authentication
+.TP
+.B  \-E
+request encryption
+.TP
+.B  \-S
+secure connection
+.TP
+.B  \-M
+become central
+.TP
+.B  \-T
+enable timestamps
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>, Filippo Giunchedi <filippo@debian.org>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/rctest.c b/tools/rctest.c
index d311808..367e41e 100644
--- a/tools/rctest.c
+++ b/tools/rctest.c
@@ -41,6 +41,8 @@
 #define SIOCGSTAMP_OLD SIOCGSTAMP
 #endif
 
+#define MAX_DATA_SIZE 0x40000000
+
 /* Test modes */
 enum {
 	SEND,
@@ -500,7 +502,7 @@ static void recv_mode(int sk)
 					timestamp = 0;
 					memset(ts, 0, sizeof(ts));
 				} else {
-					sprintf(ts, "[%lld.%lld] ",
+					snprintf(ts, sizeof(ts), "[%lld.%lld] ",
 							(long long)tv.tv_sec,
 							(long long)tv.tv_usec);
 				}
@@ -554,7 +556,8 @@ static void do_send(int sk)
 			exit(1);
 		}
 		len = read(fd, buf, data_size);
-		send(sk, buf, len, 0);
+		if (len > 0)
+			send(sk, buf, len, 0);
 		close(fd);
 		return;
 	} else {
@@ -739,6 +742,9 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'a':
+			if (!optarg)
+				break;
+
 			mode = AUTO;
 
 			if (!strncasecmp(optarg, "hci", 3))
@@ -748,10 +754,14 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'b':
-			data_size = atoi(optarg);
+			if (optarg && atoi(optarg) < MAX_DATA_SIZE)
+				data_size = atoi(optarg);
 			break;
 
 		case 'i':
+			if (!optarg)
+				break;
+
 			if (!strncasecmp(optarg, "hci", 3))
 				hci_devba(atoi(optarg + 3), &bdaddr);
 			else
@@ -759,10 +769,14 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'P':
-			channel = atoi(optarg);
+			if (optarg)
+				channel = atoi(optarg);
 			break;
 
 		case 'U':
+			if (!optarg)
+				break;
+
 			if (!strcasecmp(optarg, "spp"))
 				uuid = SERIAL_PORT_SVCLASS_ID;
 			else if (!strncasecmp(optarg, "0x", 2))
@@ -788,11 +802,13 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'L':
-			linger = atoi(optarg);
+			if (optarg)
+				linger = atoi(optarg);
 			break;
 
 		case 'W':
-			defer_setup = atoi(optarg);
+			if (optarg)
+				defer_setup = atoi(optarg);
 			break;
 
 		case 'B':
@@ -804,19 +820,23 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'N':
-			num_frames = atoi(optarg);
+			if (optarg)
+				num_frames = atoi(optarg);
 			break;
 
 		case 'C':
-			count = atoi(optarg);
+			if (optarg)
+				count = atoi(optarg);
 			break;
 
 		case 'D':
-			delay = atoi(optarg) * 1000;
+			if (optarg)
+				delay = atoi(optarg) * 1000;
 			break;
 
 		case 'Y':
-			priority = atoi(optarg);
+			if (optarg)
+				priority = atoi(optarg);
 			break;
 
 		case 'T':
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index a9adf7f..b78b505 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -30,6 +30,7 @@
 
 #include "src/shared/tester.h"
 #include "src/shared/mgmt.h"
+#include "src/shared/util.h"
 
 struct test_data {
 	struct mgmt *mgmt;
@@ -815,9 +816,7 @@ static void test_server(const void *test_data)
 #define test_rfcomm(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
-		user = malloc(sizeof(struct test_data)); \
-		if (!user) \
-			break; \
+		user = new0(struct test_data, 1); \
 		user->hciemu_type = HCIEMU_TYPE_BREDRLE52; \
 		user->test_data = data; \
 		user->io_id = 0; \
diff --git a/tools/rfcomm.1 b/tools/rfcomm.1
new file mode 100644
index 0000000..9f5fe3b
--- /dev/null
+++ b/tools/rfcomm.1
@@ -0,0 +1,128 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "RFCOMM" "1" "April 28, 2002" "BlueZ" "Linux System Administration"
+.SH NAME
+rfcomm \- RFCOMM configuration utility
+.SH SYNOPSIS
+.sp
+\fBrfcomm\fP [\fIOPTIONS\fP] <\fICOMMAND\fP> <\fIdev\fP>
+.SH DESCRIPTION
+.sp
+\fBrfcomm(1)\fP is used to set up, maintain, and inspect the RFCOMM configuration
+of the Bluetooth subsystem in the Linux kernel. If no \fBcommand\fP is given,
+or if the option \fB\-a\fP is used, \fBrfcomm\fP prints information about the
+configured RFCOMM devices.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-h
+Gives a list of possible commands.
+.TP
+.B  \-a
+Prints information about all configured RFCOMM devices.
+.TP
+.B  \-r
+Switch TTY into raw mode (doesn\(aqt work with \(dqbind\(dq).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-i <\fIhciX\fP> | <\fIbdaddr\fP>
+The command is applied to device \fIhciX\fP, which must be the name or the
+address of an installed Bluetooth device. If not specified, the command
+will be use the first available Bluetooth device.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B  \-A
+Enable authentication
+.TP
+.B  \-E
+Enable encryption
+.TP
+.B  \-S
+Secure connection
+.TP
+.B  \-C
+Become the central of a piconet
+.TP
+.BI \-L \ <seconds>
+Set linger timeout
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B show <\fIdev\fP>
+Display the information about the specified device.
+.TP
+.B connect <\fIdev\fP> [\fIbdaddr\fP] [\fIchannel\fP]
+Connect the RFCOMM device to the remote Bluetooth device on the specified
+channel. If no  channel  is  specified, it will use the channel
+number \fB1\fP\&. This command can be terminated with the key sequence CTRL\-C.
+.TP
+.B listen <\fIdev\fP> [\fIchannel\fP] [\fIcmd\fP]
+Listen  on  a specified RFCOMM channel for incoming connections.  If no
+channel is specified, it will use the channel number \fB1\fP, but a channel
+must be specified before cmd. If cmd is given, it will be executed as soon
+as a  client  connects.  When the child process terminates or the client
+disconnect, the command will terminate. Occurrences of {} in cmd will be
+replaced by the name of the device used by the connection. This command
+can be terminated with the key sequence CTRL\-C.
+.TP
+.B watch <\fIdev\fP> [\fIchannel\fP] [\fIcmd\fP]
+Watch is identical to listen except that when the child process
+terminates or the client disconnect, the command will restart listening
+with the same parameters.
+.TP
+.B bind <\fIdev\fP> [\fIbdaddr\fP] [\fIchannel\fP]
+This binds the RFCOMM device to a remote Bluetooth device. The command
+does not establish a connection to the remote  device, it only creates
+the binding. The connection will be established right after an application
+tries to open the RFCOMM device. If no channel number is specified, it
+uses the channel number \fB1\fP\&.
+.TP
+.B release <\fIdev\fP>
+This command releases a defined RFCOMM binding.
+.sp
+If \fBall\fP is specified for the RFCOMM device, then all bindings will be
+removed.
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Marcel Holtmann <marcel@holtmann.org>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/rfcomm.c b/tools/rfcomm.c
index e013ff5..0139fe6 100644
--- a/tools/rfcomm.c
+++ b/tools/rfcomm.c
@@ -212,6 +212,7 @@ static void run_cmdline(struct pollfd *p, sigset_t *sigs, char *devname,
 	int i;
 	pid_t pid;
 	char **cmdargv;
+	struct sigaction sa;
 
 	cmdargv = malloc((argc + 1) * sizeof(char *));
 	if (!cmdargv)
@@ -225,10 +226,15 @@ static void run_cmdline(struct pollfd *p, sigset_t *sigs, char *devname,
 
 	switch (pid) {
 	case 0:
+		memset(&sa, 0, sizeof(sa));
+		sa.sa_handler = SIG_DFL;
+		sigaction(SIGCHLD, &sa, NULL);
+		sigaction(SIGPIPE, &sa, NULL);
+
 		i = execvp(cmdargv[0], cmdargv);
 		fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",
 				cmdargv[0], errno, strerror(errno));
-		break;
+		_exit(EXIT_FAILURE);
 	case -1:
 		fprintf(stderr, "Couldn't fork to execute command %s\n",
 				cmdargv[0]);
diff --git a/tools/sco-tester.c b/tools/sco-tester.c
index 4460632..a56cb91 100644
--- a/tools/sco-tester.c
+++ b/tools/sco-tester.c
@@ -29,6 +29,9 @@
 
 #include "src/shared/tester.h"
 #include "src/shared/mgmt.h"
+#include "src/shared/util.h"
+
+#include "tester.h"
 
 struct test_data {
 	const void *test_data;
@@ -37,14 +40,24 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	unsigned int io_id;
+	unsigned int err_io_id;
+	int sk;
 	bool disable_esco;
 	bool enable_codecs;
+	int step;
+	struct tx_tstamp_data tx_ts;
 };
 
 struct sco_client_data {
 	int expect_err;
 	const uint8_t *send_data;
 	uint16_t data_len;
+
+	/* Enable SO_TIMESTAMPING with these flags */
+	uint32_t so_timestamping;
+
+	/* Number of additional packets to send. */
+	unsigned int repeat_send;
 };
 
 static void print_debug(const char *str, void *user_data)
@@ -184,6 +197,12 @@ static void read_index_list_callback(uint8_t status, uint16_t length,
 static void test_pre_setup(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct sco_client_data *scodata = test_data;
+
+	if (scodata && scodata->so_timestamping) {
+		if (tester_pre_setup_skip_by_default())
+			return;
+	}
 
 	data->mgmt = mgmt_new_default();
 	if (!data->mgmt) {
@@ -225,7 +244,10 @@ static void test_data_free(void *test_data)
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
 		user->io_id = 0; \
+		user->err_io_id = 0; \
+		user->sk = -1; \
 		user->test_data = data; \
+		user->step = 0; \
 		user->disable_esco = _disable_esco; \
 		user->enable_codecs = _enable_codecs; \
 		tester_add_full(name, data, \
@@ -250,6 +272,10 @@ static const struct sco_client_data connect_failure = {
 	.expect_err = EOPNOTSUPP
 };
 
+static const struct sco_client_data connect_failure_reset = {
+	.expect_err = ECONNRESET
+};
+
 const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
 
 static const struct sco_client_data connect_send_success = {
@@ -258,6 +284,16 @@ static const struct sco_client_data connect_send_success = {
 	.send_data = data
 };
 
+static const struct sco_client_data connect_send_tx_timestamping = {
+	.expect_err = 0,
+	.data_len = sizeof(data),
+	.send_data = data,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_OPT_ID |
+					SOF_TIMESTAMPING_TX_SOFTWARE),
+	.repeat_send = 2,
+};
+
 static void client_connectable_complete(uint16_t opcode, uint8_t status,
 					const void *param, uint8_t len,
 					void *user_data)
@@ -588,6 +624,59 @@ static int connect_sco_sock(struct test_data *data, int sk)
 	return 0;
 }
 
+static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = user_data;
+	const struct sco_client_data *scodata = data->test_data;
+	int sk = g_io_channel_unix_get_fd(io);
+	int err;
+
+	data->step--;
+
+	err = tx_tstamp_recv(&data->tx_ts, sk, scodata->data_len);
+	if (err > 0)
+		return TRUE;
+	else if (!err && !data->step)
+		tester_test_passed();
+	else
+		tester_test_failed();
+
+	data->err_io_id = 0;
+	return FALSE;
+}
+
+static void sco_tx_timestamping(struct test_data *data, GIOChannel *io)
+{
+	const struct sco_client_data *scodata = data->test_data;
+	int so = scodata->so_timestamping;
+	int sk;
+	int err;
+	unsigned int count;
+
+	if (!(scodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+		return;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	tester_print("Enabling TX timestamping");
+
+	tx_tstamp_init(&data->tx_ts, scodata->so_timestamping);
+
+	for (count = 0; count < scodata->repeat_send + 1; ++count)
+		data->step += tx_tstamp_expect(&data->tx_ts);
+
+	err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so));
+	if (err < 0) {
+		tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)",
+						strerror(errno), errno);
+		tester_test_failed();
+		return;
+	}
+
+	data->err_io_id = g_io_add_watch(io, G_IO_ERR, recv_errqueue, data);
+}
+
 static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -611,11 +700,21 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
 		tester_print("Successfully connected");
 
 	if (scodata->send_data) {
-		ssize_t ret;
+		ssize_t ret = 0;
+		unsigned int count;
+
+		data->step = 0;
+
+		sco_tx_timestamping(data, io);
 
-		tester_print("Writing %u bytes of data", scodata->data_len);
+		tester_print("Writing %u*%u bytes of data",
+				scodata->repeat_send + 1, scodata->data_len);
 
-		ret = write(sk, scodata->send_data, scodata->data_len);
+		for (count = 0; count < scodata->repeat_send + 1; ++count) {
+			ret = write(sk, scodata->send_data, scodata->data_len);
+			if (scodata->data_len != ret)
+				break;
+		}
 		if (scodata->data_len != ret) {
 			tester_warn("Failed to write %u bytes: %zu %s (%d)",
 					scodata->data_len, ret, strerror(errno),
@@ -626,7 +725,7 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
 
 	if (-err != scodata->expect_err)
 		tester_test_failed();
-	else
+	else if (!data->step)
 		tester_test_passed();
 
 	return FALSE;
@@ -650,6 +749,8 @@ static void test_connect(const void *test_data)
 		return;
 	}
 
+	data->sk = sk;
+
 	io = g_io_channel_unix_new(sk);
 	g_io_channel_set_close_on_unref(io, TRUE);
 
@@ -745,6 +846,82 @@ static void test_connect_offload_msbc(const void *test_data)
 end:
 	close(sk);
 }
+
+static bool hook_simult_disc(const void *msg, uint16_t len, void *user_data)
+{
+	const struct bt_hci_evt_sync_conn_complete *ev = msg;
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
+
+	tester_print("Simultaneous disconnect");
+
+	if (len != sizeof(struct bt_hci_evt_sync_conn_complete)) {
+		tester_test_failed();
+		return true;
+	}
+
+	/* Disconnect from local and remote sides at the same time */
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_hci_disconnect(bthost, le16_to_cpu(ev->handle), 0x13);
+
+	shutdown(data->sk, SHUT_RDWR);
+
+	return true;
+}
+
+static bool hook_delay_cmd(const void *data, uint16_t len, void *user_data)
+{
+	tester_print("Delaying emulator response...");
+	g_usleep(250000);
+	tester_print("Delaying emulator response... Done.");
+	return true;
+}
+
+static void test_connect_simult_disc(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	/* Kernel shall not crash, but <= 6.5-rc1 crash */
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_EVT,
+					BT_HCI_EVT_SYNC_CONN_COMPLETE,
+					hook_simult_disc, NULL);
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+					BT_HCI_CMD_CREATE_CONN_CANCEL,
+					hook_delay_cmd, NULL);
+
+	test_connect(test_data);
+}
+
+static bool hook_acl_disc(const void *msg, uint16_t len, void *user_data)
+{
+	const struct bt_hci_evt_conn_complete *ev = msg;
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
+
+	tester_print("Disconnect ACL");
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_hci_disconnect(bthost, le16_to_cpu(ev->handle), 0x13);
+
+	hciemu_flush_client_events(data->hciemu);
+
+	return true;
+}
+
+static void test_connect_acl_disc(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	/* ACL disconnected before SCO is established seen.
+	 * Kernel shall not crash, but <= 6.5-rc5 crash.
+	 */
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_EVT,
+					BT_HCI_EVT_CONN_COMPLETE,
+					hook_acl_disc, NULL);
+
+	test_connect(test_data);
+}
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -767,6 +944,14 @@ int main(int argc, char *argv[])
 	test_sco("eSCO mSBC - Success", &connect_success, setup_powered,
 							test_connect_transp);
 
+	test_sco("eSCO Simultaneous Disconnect - Failure",
+					&connect_failure_reset, setup_powered,
+					test_connect_simult_disc);
+
+	test_sco("eSCO ACL Disconnect - Failure",
+					&connect_failure_reset, setup_powered,
+					test_connect_acl_disc);
+
 	test_sco_11("SCO CVSD 1.1 - Success", &connect_success, setup_powered,
 							test_connect);
 
@@ -776,6 +961,10 @@ int main(int argc, char *argv[])
 	test_sco("SCO CVSD Send - Success", &connect_send_success,
 					setup_powered, test_connect);
 
+	test_sco("SCO CVSD Send - TX Timestamping",
+					&connect_send_tx_timestamping,
+					setup_powered, test_connect);
+
 	test_offload_sco("Basic SCO Get Socket Option - Offload - Success",
 				NULL, setup_powered, test_codecs_getsockopt);
 
diff --git a/tools/sdptool.1 b/tools/sdptool.1
new file mode 100644
index 0000000..717fbc7
--- /dev/null
+++ b/tools/sdptool.1
@@ -0,0 +1,122 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "SDPTOOL" "1" "" "BlueZ" "Linux System Administration"
+.SH NAME
+sdptool \- control and interrogate SDP servers
+.SH SYNOPSIS
+.sp
+\fBsdptool\fP [\fIOPTIONS\fP] [\fICOMMAND\fP [\fIPARAMETERS\fP]]
+.SH DESCRIPTION
+.sp
+\fBsdptool(1)\fP provides the interface for performing SDP queries on Bluetooth
+devices, and administering a local SDP database.
+.SH COMMANDS
+.sp
+The following commands are available.  In all cases \fBbdaddr\fP specifies the
+device to search or browse.  If \fIlocal\fP is used for \fBbdaddr\fP, then the local
+SDP database is searched.
+.sp
+Services are identified and manipulated with a 4\-byte \fBrecord_handle\fP (NOT
+the service name). To find a service\(aqs \fBrecord_handle\fP, look for the
+\(dqService RecHandle\(dq line in the \fBsearch\fP or \fBbrowse\fP results
+.INDENT 0.0
+.TP
+.B search [\-\-bdaddr bdaddr] [\-\-tree] [\-\-raw] [\-\-xml] service_name
+Search for services..
+.sp
+Known  service  names  are  \fBDID\fP, \fBSP\fP, \fBDUN\fP, \fBLAN\fP, \fBFAX\fP,
+\fBOPUSH\fP, \fBFTP\fP, \fBHS\fP, \fBHF\fP, \fBHFAG\fP, \fBSAP\fP, \fBNAP\fP, \fBGN\fP,
+\fBPANU\fP, \fBHCRP\fP, \fBHID\fP, \fBCIP\fP, \fBA2SRC\fP, \fBA2SNK\fP, \fBAVRCT\fP,
+\fBAVRTG\fP, \fBUDIUE\fP, \fBUDITE\fP and \fBSYNCML\fP\&.
+.TP
+.B browse [\-\-tree] [\-\-raw] [\-\-xml] [bdaddr]
+Browse all available services on the device specified by a Bluetooth
+address as a parameter.
+.TP
+.B records [\-\-tree] [\-\-raw] [\-\-xml] bdaddr
+Retrieve all possible service records.
+.TP
+.B add [ \-\-handle=N \-\-channel=N ]
+Add a service to the local SDP database.
+.sp
+You can specify a handle for this record using the \fB\-\-handle\fP option.
+.sp
+You can specify a channel to add the service on using the \fB\-\-channel\fP
+option.
+.sp
+NOTE: Local adapters configuration will not be updated and this command
+should  be used only for SDP testing.
+.TP
+.B del record_handle
+Remove a service from the local SDP database.
+.sp
+NOTE: Local adapters configuration will not be updated and this command
+should be used only for SDP testing.
+.TP
+.B get [\-\-tree] [\-\-raw] [\-\-xml] [\-\-bdaddr bdaddr] record_handle
+Retrieve a service from the local SDP database.
+.TP
+.B setattr record_handle attrib_id attrib_value
+Set or add an attribute to an SDP record.
+.TP
+.B setseq record_handle attrib_id attrib_values
+Set or add an attribute sequence to an SDP record.
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B  \-\-help
+Displays help on using sdptool.
+.UNINDENT
+.SH EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.EX
+$ sdptool browse 00:80:98:24:15:6D
+$ sdptool browse local
+$ sdptool add DUN
+$ sdptool del 0x10000
+.EE
+.UNINDENT
+.UNINDENT
+.SH RESOURCES
+.sp
+ <http://www.bluez.org> 
+.SH REPORTING BUGS
+.sp
+ <linux\-bluetooth@vger.kernel.org> 
+.SH AUTHOR
+Maxim Krasnyansky <maxk@qualcomm.com>, Edd Dumbill <ejad@debian.org>
+.SH COPYRIGHT
+Free use of this software is granted under ther terms of the GNU
+Lesser General Public Licenses (LGPL).
+.\" Generated by docutils manpage writer.
+.
diff --git a/tools/test-runner.c b/tools/test-runner.c
index 6660ea8..f0dbb4c 100644
--- a/tools/test-runner.c
+++ b/tools/test-runner.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <poll.h>
+#include <limits.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -54,7 +55,7 @@ static bool start_monitor = false;
 static int num_devs = 0;
 static const char *qemu_binary = NULL;
 static const char *kernel_image = NULL;
-static bool audio_support;
+static char *audio_server;
 
 static const char *qemu_table[] = {
 	"qemu-system-x86_64",
@@ -136,6 +137,24 @@ static const char *config_table[] = {
 	NULL
 };
 
+static void enable_printk(void)
+{
+	FILE *f;
+
+	f = fopen("/proc/sys/kernel/printk", "w");
+	if (!f) {
+		perror("Failed to set printk");
+		return;
+	}
+
+	/* Restore printk loglevel, undoing 'quiet' in cmdline (suppress early
+	 * on-boot messages), to show WARN_ON etc. Suppress level>=6(INFO), set
+	 * default_msg:4(WARN) & min:1, default:7. See man 2 syslog.
+	 */
+	fprintf(f, "6 4 1 7");
+	fclose(f);
+}
+
 static void prepare_sandbox(void)
 {
 	int i;
@@ -181,6 +200,8 @@ static void prepare_sandbox(void)
 				"mode=0755") < 0)
 			perror("Failed to create filesystem");
 	}
+
+	enable_printk();
 }
 
 static char *const qemu_argv[] = {
@@ -247,21 +268,20 @@ static void start_qemu(void)
 
 	snprintf(cmdline, sizeof(cmdline),
 				"console=ttyS0,115200n8 earlyprintk=serial "
-				"rootfstype=9p "
+				"no_hash_pointers=1 rootfstype=9p "
 				"rootflags=trans=virtio,version=9p2000.u "
 				"acpi=off pci=noacpi noapic quiet ro init=%s "
 				"TESTHOME=%s TESTDBUS=%u TESTDAEMON=%u "
 				"TESTDBUSSESSION=%u XDG_RUNTIME_DIR=/run/user/0 "
-				"TESTAUDIO=%u "
 				"TESTMONITOR=%u TESTEMULATOR=%u TESTDEVS=%d "
-				"TESTAUTO=%u TESTARGS=\'%s\'",
+				"TESTAUTO=%u TESTAUDIO='%s' TESTARGS=\'%s\'",
 				initcmd, cwd, start_dbus, start_daemon,
-				start_dbus_session, audio_support,
+				start_dbus_session,
 				start_monitor, start_emulator, num_devs,
-				run_auto, testargs);
+				run_auto, audio_server ? audio_server : "",
+				testargs);
 
 	argv = alloca(sizeof(qemu_argv) +
-				(audio_support ? 4 : 0) +
 				(sizeof(char *) * (4 + (num_devs * 4))));
 	memcpy(argv, qemu_argv, sizeof(qemu_argv));
 
@@ -274,24 +294,6 @@ static void start_qemu(void)
 	}
 	argv[0] = (char *) qemu_binary;
 
-	if (audio_support) {
-		char *xdg_runtime_dir, *audiodev;
-
-		xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
-		if (!xdg_runtime_dir) {
-			fprintf(stderr, "XDG_RUNTIME_DIR not set\n");
-			exit(1);
-		}
-		audiodev = alloca(40 + strlen(xdg_runtime_dir));
-		sprintf(audiodev, "id=audio,driver=pa,server=%s/pulse/native",
-				xdg_runtime_dir);
-
-		argv[pos++] = "-audiodev";
-		argv[pos++] = audiodev;
-		argv[pos++] = "-device";
-		argv[pos++] = "AC97,audiodev=audio";
-	}
-
 	argv[pos++] = "-kernel";
 	argv[pos++] = (char *) kernel_image;
 	argv[pos++] = "-append";
@@ -301,10 +303,10 @@ static void start_qemu(void)
 		const char *path = "/tmp/bt-server-bredr";
 		char *chrdev, *serdev;
 
-		chrdev = alloca(32 + strlen(path));
+		chrdev = alloca(48 + strlen(path));
 		sprintf(chrdev, "socket,path=%s,id=bt%d", path, i);
 
-		serdev = alloca(32);
+		serdev = alloca(48);
 		sprintf(serdev, "pci-serial,chardev=bt%d", i);
 
 		argv[pos++] = "-chardev";
@@ -640,7 +642,7 @@ static const char *monitor_table[] = {
 static pid_t start_btmon(const char *home)
 {
 	const char *monitor = NULL;
-	char *argv[3], *envp[2];
+	char *argv[3];
 	pid_t pid;
 	int i;
 
@@ -678,7 +680,7 @@ static pid_t start_btmon(const char *home)
 	}
 
 	if (pid == 0) {
-		execve(argv[0], argv, envp);
+		execv(argv[0], argv);
 		exit(EXIT_SUCCESS);
 	}
 
@@ -697,7 +699,7 @@ static const char *btvirt_table[] = {
 static pid_t start_btvirt(const char *home)
 {
 	const char *btvirt = NULL;
-	char *argv[3], *envp[2];
+	char *argv[3];
 	pid_t pid;
 	int i;
 
@@ -735,7 +737,7 @@ static pid_t start_btvirt(const char *home)
 	}
 
 	if (pid == 0) {
-		execve(argv[0], argv, envp);
+		execv(argv[0], argv);
 		exit(EXIT_SUCCESS);
 	}
 
@@ -744,61 +746,110 @@ static pid_t start_btvirt(const char *home)
 	return pid;
 }
 
-static void trigger_udev(void)
+static int create_pipewire_conf(void)
 {
-	char *argv[3], *envp[1];
-	pid_t pid;
+	static const char *const dirs[] = {
+		"/run/conf",
+		"/run/conf/wireplumber",
+		"/run/conf/wireplumber/bluetooth.lua.d",
+		"/run/conf/wireplumber/main.lua.d",
+		NULL
+	};
+	int i;
+	FILE *f;
 
-	argv[0] = "/bin/udevadm";
-	argv[1] = "trigger";
-	argv[2] = NULL;
+	for (i = 0; dirs[i]; ++i)
+		mkdir(dirs[i], 0755);
 
-	envp[0] = NULL;
+	/* Enable only Bluetooth part, disable whatever requires user DBus */
+	f = fopen("/run/conf/wireplumber/main.lua.d/51-custom.lua", "w");
+	if (!f)
+		goto fail;
 
-	printf("Triggering udev events\n");
+	fprintf(f, "alsa_monitor.enabled = false\n"
+		"v4l2_monitor.enabled = false\n"
+		"libcamera_monitor.enabled = false\n"
+		"default_access.properties[\"enable-flatpak-portal\"]"
+		" = false\n");
+	fclose(f);
 
-	pid = fork();
-	if (pid < 0) {
-		perror("Failed to fork new process");
-		return;
-	}
+	f = fopen("/run/conf/wireplumber/bluetooth.lua.d/51-custom.lua", "w");
+	if (!f)
+		goto fail;
 
-	if (pid == 0) {
-		execve(argv[0], argv, envp);
-		exit(EXIT_SUCCESS);
-	}
+	fprintf(f, "bluez_monitor.properties[\"with-logind\"] = false\n"
+		"bluez_midi_monitor.enabled = false\n");
+	fclose(f);
 
-	printf("udev trigger process %d created\n", pid);
+	return 0;
+
+fail:
+	perror("Failed to create Pipewire config");
+	return -1;
 }
 
-static pid_t start_udevd(void)
+static int start_audio_server(pid_t pids[2])
 {
-	char *argv[2], *envp[1];
-	pid_t pid;
+	char *daemons[2] = {NULL, NULL};
+	char wp_exe[PATH_MAX];
+	char *ptr;
+	char *envp[5];
+	int i;
 
-	argv[0] = "/lib/systemd/systemd-udevd";
-	argv[1] = NULL;
+	for (i = 0; i < 2; ++i)
+		pids[i] = -1;
 
-	envp[0] = NULL;
+	daemons[0] = audio_server;
+
+	ptr = strrchr(audio_server, '/');
+	if (ptr && !strcmp(ptr, "/pipewire")) {
+		if (create_pipewire_conf())
+			return -1;
 
-	printf("Starting udevd daemon\n");
+		snprintf(wp_exe, sizeof(wp_exe), "%.*s/wireplumber",
+				(int)(ptr - audio_server), audio_server);
+		daemons[1] = wp_exe;
 
-	pid = fork();
-	if (pid < 0) {
-		perror("Failed to fork new process");
-		return -1;
+		setenv("PIPEWIRE_RUNTIME_DIR", "/run", 1);
 	}
 
-	if (pid == 0) {
-		execve(argv[0], argv, envp);
-		exit(EXIT_SUCCESS);
-	}
+	envp[0] = "DBUS_SYSTEM_BUS_ADDRESS=unix:"
+		"path=/run/dbus/system_bus_socket";
+	envp[1] = "XDG_CONFIG_HOME=/run/conf";
+	envp[2] = "XDG_STATE_HOME=/run";
+	envp[3] = "XDG_RUNTIME_DIR=/run";
+	envp[4] = NULL;
 
-	printf("udevd daemon process %d created\n", pid);
+	for (i = 0; i < 2; ++i) {
+		const char *daemon = daemons[i];
+		char *argv[2];
+		pid_t pid;
 
-	trigger_udev();
+		if (!daemon)
+			continue;
 
-	return pid;
+		printf("Starting audio server %s\n", daemon);
+
+		argv[0] = (char *) daemon;
+		argv[1] = NULL;
+
+		pid = fork();
+		if (pid < 0) {
+			perror("Failed to fork new process");
+			return -1;
+		}
+
+		if (pid == 0) {
+			execve(argv[0], argv, envp);
+			exit(EXIT_SUCCESS);
+		}
+
+		pids[i] = pid;
+
+		printf("Audio server process %d created\n", pid);
+	}
+
+	return 0;
 }
 
 static void run_command(char *cmdname, char *home)
@@ -807,7 +858,8 @@ static void run_command(char *cmdname, char *home)
 	int pos = 0, idx = 0;
 	int serial_fd;
 	pid_t pid, dbus_pid, daemon_pid, monitor_pid, emulator_pid,
-	      dbus_session_pid, udevd_pid;
+	      dbus_session_pid, audio_pid[2];
+	int i;
 
 	if (!home) {
 		perror("Invalid parameter: TESTHOME");
@@ -828,11 +880,6 @@ static void run_command(char *cmdname, char *home)
 	} else
 		serial_fd = -1;
 
-	if (audio_support)
-		udevd_pid = start_udevd();
-	else
-		udevd_pid = -1;
-
 	if (start_dbus) {
 		create_dbus_system_conf();
 		dbus_pid = start_dbus_daemon(false);
@@ -860,7 +907,17 @@ static void run_command(char *cmdname, char *home)
 	else
 		emulator_pid = -1;
 
+	if (audio_server)
+		start_audio_server(audio_pid);
+	else
+		audio_pid[0] = audio_pid[1] = -1;
+
 start_next:
+	if (!run_auto && !cmdname) {
+		fprintf(stderr, "Missing command argument\n");
+		return;
+	}
+
 	if (run_auto) {
 		if (chdir(home + 5) < 0) {
 			perror("Failed to change home test directory");
@@ -896,6 +953,8 @@ start_next:
 	pid = fork();
 	if (pid < 0) {
 		perror("Failed to fork new process");
+		if (serial_fd >= 0)
+			close(serial_fd);
 		return;
 	}
 
@@ -961,9 +1020,11 @@ start_next:
 			monitor_pid = -1;
 		}
 
-		if (corpse == udevd_pid) {
-			printf("udevd terminated\n");
-			udevd_pid = -1;
+		for (i = 0; i < 2; ++i) {
+			if (corpse == audio_pid[i]) {
+				printf("Audio server %d terminated\n", i);
+				audio_pid[i] = -1;
+			}
 		}
 
 		if (corpse == pid)
@@ -975,6 +1036,11 @@ start_next:
 		goto start_next;
 	}
 
+	for (i = 0; i < 2; ++i) {
+		if (audio_pid[i] > 0)
+			kill(audio_pid[i], SIGTERM);
+	}
+
 	if (daemon_pid > 0)
 		kill(daemon_pid, SIGTERM);
 
@@ -990,9 +1056,6 @@ start_next:
 	if (monitor_pid > 0)
 		kill(monitor_pid, SIGTERM);
 
-	if (udevd_pid > 0)
-		kill(udevd_pid, SIGTERM);
-
 	if (serial_fd >= 0)
 		close(serial_fd);
 }
@@ -1073,10 +1136,15 @@ static void run_tests(void)
 		start_emulator = true;
 	}
 
-	ptr = strstr(cmdline, "TESTAUDIO=1");
+	ptr = strstr(cmdline, "TESTAUDIO='");
 	if (ptr) {
-		printf("Audio support requested\n");
-		audio_support = true;
+		const char *start = ptr + 11;
+		const char *end = strchr(start, '\'');
+
+		if (end && end != start) {
+			audio_server = strndup(start, end - start);
+			printf("Audio server %s requested\n", audio_server);
+		}
 	}
 
 	ptr = strstr(cmdline, "TESTHOME=");
@@ -1102,10 +1170,10 @@ static void usage(void)
 		"\t-d, --daemon           Start bluetoothd\n"
 		"\t-m, --monitor          Start btmon\n"
 		"\t-l, --emulator         Start btvirt\n"
+		"\t-A, --audio[=path]     Start audio server\n"
 		"\t-u, --unix [path]      Provide serial device\n"
 		"\t-q, --qemu <path>      QEMU binary\n"
 		"\t-k, --kernel <image>   Kernel image (bzImage)\n"
-		"\t-A, --audio            Add audio support\n"
 		"\t-h, --help             Show help options\n");
 }
 
@@ -1120,7 +1188,7 @@ static const struct option main_options[] = {
 	{ "monitor", no_argument,       NULL, 'm' },
 	{ "qemu",    required_argument, NULL, 'q' },
 	{ "kernel",  required_argument, NULL, 'k' },
-	{ "audio",   no_argument,       NULL, 'A' },
+	{ "audio",   optional_argument, NULL, 'A' },
 	{ "version", no_argument,       NULL, 'v' },
 	{ "help",    no_argument,       NULL, 'h' },
 	{ }
@@ -1140,7 +1208,7 @@ int main(int argc, char *argv[])
 	for (;;) {
 		int opt;
 
-		opt = getopt_long(argc, argv, "aubdslmq:k:Avh", main_options,
+		opt = getopt_long(argc, argv, "aubdslmq:k:A::vh", main_options,
 								NULL);
 		if (opt < 0)
 			break;
@@ -1175,7 +1243,7 @@ int main(int argc, char *argv[])
 			kernel_image = optarg;
 			break;
 		case 'A':
-			audio_support = true;
+			audio_server = optarg ? optarg : "/usr/bin/pipewire";
 			break;
 		case 'v':
 			printf("%s\n", VERSION);
diff --git a/tools/tester.h b/tools/tester.h
new file mode 100644
index 0000000..b6de084
--- /dev/null
+++ b/tools/tester.h
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation.
+ *
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <linux/errqueue.h>
+#include <linux/net_tstamp.h>
+
+#include <glib.h>
+
+#define SEC_NSEC(_t)  ((_t) * 1000000000LL)
+#define TS_NSEC(_ts)  (SEC_NSEC((_ts)->tv_sec) + (_ts)->tv_nsec)
+
+struct tx_tstamp_data {
+	struct {
+		uint32_t id;
+		uint32_t type;
+	} expect[16];
+	unsigned int pos;
+	unsigned int count;
+	unsigned int sent;
+	uint32_t so_timestamping;
+};
+
+static inline void tx_tstamp_init(struct tx_tstamp_data *data,
+				uint32_t so_timestamping)
+{
+	memset(data, 0, sizeof(*data));
+	memset(data->expect, 0xff, sizeof(data->expect));
+
+	data->so_timestamping = so_timestamping;
+}
+
+static inline int tx_tstamp_expect(struct tx_tstamp_data *data)
+{
+	unsigned int pos = data->count;
+	int steps;
+
+	if (data->so_timestamping & SOF_TIMESTAMPING_TX_SCHED) {
+		g_assert(pos < ARRAY_SIZE(data->expect));
+		data->expect[pos].type = SCM_TSTAMP_SCHED;
+		data->expect[pos].id = data->sent;
+		pos++;
+	}
+
+	if (data->so_timestamping & SOF_TIMESTAMPING_TX_SOFTWARE) {
+		g_assert(pos < ARRAY_SIZE(data->expect));
+		data->expect[pos].type = SCM_TSTAMP_SND;
+		data->expect[pos].id = data->sent;
+		pos++;
+	}
+
+	data->sent++;
+
+	steps = pos - data->count;
+	data->count = pos;
+	return steps;
+}
+
+static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len)
+{
+	unsigned char control[512];
+	ssize_t ret;
+	char buf[1024];
+	struct msghdr msg;
+	struct iovec iov;
+	struct cmsghdr *cmsg;
+	struct scm_timestamping *tss = NULL;
+	struct sock_extended_err *serr = NULL;
+	struct timespec now;
+
+	iov.iov_base = buf;
+	iov.iov_len = sizeof(buf);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = control;
+	msg.msg_controllen = sizeof(control);
+
+	ret = recvmsg(sk, &msg, MSG_ERRQUEUE);
+	if (ret < 0) {
+		if (ret == EAGAIN || ret == EWOULDBLOCK)
+			return data->count - data->pos;
+
+		tester_warn("Failed to read from errqueue: %s (%d)",
+							strerror(errno), errno);
+		return -EINVAL;
+	}
+
+	if (data->so_timestamping & SOF_TIMESTAMPING_OPT_TSONLY) {
+		if (ret != 0) {
+			tester_warn("Packet copied back to errqueue");
+			return -EINVAL;
+		}
+	} else if (len > ret) {
+		tester_warn("Packet not copied back to errqueue: %zd", ret);
+		return -EINVAL;
+	}
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (cmsg->cmsg_level == SOL_SOCKET &&
+					cmsg->cmsg_type == SCM_TIMESTAMPING) {
+			tss = (void *)CMSG_DATA(cmsg);
+		} else if (cmsg->cmsg_level == SOL_BLUETOOTH &&
+					cmsg->cmsg_type == BT_SCM_ERROR) {
+			serr = (void *)CMSG_DATA(cmsg);
+		}
+	}
+
+	if (!tss) {
+		tester_warn("SCM_TIMESTAMPING not found");
+		return -EINVAL;
+	}
+
+	if (!serr) {
+		tester_warn("BT_SCM_ERROR not found");
+		return -EINVAL;
+	}
+
+	if (serr->ee_errno != ENOMSG ||
+				serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
+		tester_warn("BT_SCM_ERROR wrong for timestamping");
+		return -EINVAL;
+	}
+
+	clock_gettime(CLOCK_REALTIME, &now);
+
+	if (TS_NSEC(&now) < TS_NSEC(tss->ts) ||
+			TS_NSEC(&now) > TS_NSEC(tss->ts) + SEC_NSEC(10)) {
+		tester_warn("nonsense in timestamp");
+		return -EINVAL;
+	}
+
+	if (data->pos >= data->count) {
+		tester_warn("Too many timestamps");
+		return -EINVAL;
+	}
+
+	if ((data->so_timestamping & SOF_TIMESTAMPING_OPT_ID) &&
+				serr->ee_data != data->expect[data->pos].id) {
+		tester_warn("Bad timestamp id %u", serr->ee_data);
+		return -EINVAL;
+	}
+
+	if (serr->ee_info != data->expect[data->pos].type) {
+		tester_warn("Bad timestamp type %u", serr->ee_info);
+		return -EINVAL;
+	}
+
+	tester_print("Got valid TX timestamp %u", data->pos);
+
+	++data->pos;
+
+	return data->count - data->pos;
+}
diff --git a/tools/update_compids.sh b/tools/update_compids.sh
deleted file mode 100755
index 606d6cf..0000000
--- a/tools/update_compids.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0-or-later
-# Download the list of company IDs from bluetooth.org and generate a diff which
-# can be applied to source tree to update bt_compidtostr(). Usage:
-#
-# 1) ./tools/update_compids.sh | git apply -p0
-# 2) Inspect changes to make sure they are sane
-# 3) git commit -m "lib: Update list of company identifiers" lib/bluetooth.c
-#
-# Requires html2text: http://www.mbayer.de/html2text/
-#
-set -e -u
-
-tmpdir=$(mktemp -d)
-trap "rm -rf $tmpdir" EXIT
-
-scriptdir=$(pwd)
-
-mkdir $tmpdir/lib
-cp lib/bluetooth.c $tmpdir/lib/bluetooth.c.orig
-cp lib/bluetooth.c $tmpdir/lib/bluetooth.c
-
-cd $tmpdir
-
-echo -e 'const char *bt_compidtostr(int compid)\n{\n\tswitch (compid) {' > new.c
-
-path=specifications/assigned-numbers/company-identifiers/
-# Use "iconv -c" to strip unwanted unicode characters
-curl --insecure https://www.bluetooth.com/$path | \
-    $scriptdir/tools/parse_companies.pl >> new.c
-
-if ! grep -q "return \"" new.c; then
-    echo "ERROR: could not parse company IDs from bluetooth.org" >&2
-    exit 1
-fi
-echo -e '\tcase 65535:\n\t\treturn "internal use";' >> new.c
-echo -e '\tdefault:\n\t\treturn "not assigned";\n\t}\n}' >> new.c
-
-sed -n '/^const char \*bt_compidtostr(int compid)/,/^}/p' \
-    lib/bluetooth.c > old.c
-
-diff -Naur old.c new.c | patch -sp0 lib/bluetooth.c
-diff -Naur lib/bluetooth.c.orig lib/bluetooth.c
diff --git a/tools/valgrind.supp b/tools/valgrind.supp
deleted file mode 100644
index d264657..0000000
--- a/tools/valgrind.supp
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-   ecb_bind
-   Memcheck:Param
-   socketcall.bind(my_addr.sa_data)
-   fun:bind
-   fun:ecb_aes_setup
-}
-{
-   cmac_bind
-   Memcheck:Param
-   socketcall.bind(my_addr.sa_data)
-   fun:bind
-   fun:cmac_aes_setup
-}
-{
-   logging_open
-   Memcheck:Param
-   socketcall.bind(my_addr.rc_bdaddr)
-   fun:bind
-   fun:logging_open
-}
-{
-   bind
-   Memcheck:Param
-   socketcall.bind(my_addr.rc_channel)
-   fun:bind
-}
-{
-   bt_log_open
-   Memcheck:Param
-   socketcall.bind(my_addr.rc_bdaddr)
-   fun:bind
-   fun:bt_log_open
-}
diff --git a/unit/test-bap.c b/unit/test-bap.c
new file mode 100644
index 0000000..0c190d7
--- /dev/null
+++ b/unit/test-bap.c
@@ -0,0 +1,7380 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation.
+ *  Copyright 2024 NXP
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "src/shared/util.h"
+#include "src/shared/io.h"
+#include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/bap.h"
+#include "src/shared/lc3.h"
+
+struct test_config {
+	struct bt_bap_pac_qos pqos;
+	struct iovec cc;
+	struct iovec base;
+	struct bt_bap_qos qos;
+	bool snk;
+	bool src;
+	bool vs;
+	uint8_t state;
+	bt_bap_state_func_t state_func;
+	uint8_t streams;
+};
+
+struct test_data {
+	struct bt_gatt_client *client;
+	struct gatt_db *db;
+	struct bt_bap *bap;
+	struct bt_bap_pac *snk;
+	struct bt_bap_pac *src;
+	struct bt_bap_pac *bsrc;
+	struct bt_bap_pac *bsnk;
+	struct iovec *base;
+	struct iovec *caps;
+	struct test_config *cfg;
+	struct queue *streams;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+/*
+ * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
+ * Duration: 7.5 ms 10 ms
+ * Channel count: 3
+ * Frame length: 26-240
+ */
+static struct iovec lc3_caps = LC3_CAPABILITIES(LC3_FREQ_ANY, LC3_DURATION_ANY,
+								3u, 26, 240);
+
+#define iov_data(args...) ((const struct iovec[]) { args })
+
+#define define_test(name, setup, function, _cfg, args...)		\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data data;			\
+		data.caps = &lc3_caps;				\
+		data.cfg = _cfg;				\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		data.streams = queue_new(); \
+		tester_add(name, &data, setup, function,	\
+				test_teardown);			\
+	} while (0)
+
+static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
+{
+	if (!success)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+/* GATT Discover All procedure */
+static const struct iovec setup_data[] = {
+	/* ATT: Exchange MTU Response (0x03) len 2
+	 *   Server RX MTU: 64
+	 */
+	IOV_DATA(0x02, 0x40, 0x00),
+	/* ATT: Exchange MTU Request (0x02) len 2
+	 *    Client RX MTU: 64
+	 */
+	IOV_DATA(0x03, 0x40, 0x00),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute type: Server Supported Features (0x2b3a)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0xff, 0xff, 0x3a, 0x2b),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+	/*
+	 * ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute group type: Primary Service (0x2800)
+	 */
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28),
+	/*
+	 * ATT: Read By Group Type Response (0x11) len 37
+	 *   Attribute data length: 6
+	 *   Attribute group list: 2 entries
+	 *   Handle range: 0x0001-0x0013
+	 *   UUID: Published Audio Capabilities (0x1850)
+	 *   Handle range: 0x0014-0x0023
+	 *   UUID: Audio Stream Control (0x184e)
+	 */
+	IOV_DATA(0x11, 0x06,
+		0x01, 0x00, 0x13, 0x00, 0x50, 0x18,
+		0x14, 0x00, 0x23, 0x00, 0x4e, 0x18),
+	/* ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0024-0xffff
+	 *   Attribute group type: Primary Service (0x2800)
+	 */
+	IOV_DATA(0x10, 0x24, 0x00, 0xff, 0xff, 0x00, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0024
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x10, 0x24, 0x00, 0x0a),
+	/* ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute group type: Secondary Service (0x2801)
+	 */
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x10, 0x01, 0x00, 0x0a),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute group type: Include (0x2802)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0x23, 0x00, 0x02, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Read By Type Response (0x09) len 57
+	 * Attribute data length: 7
+	 * Attribute data list: 8 entries
+	 *   Handle: 0x0002
+	 *   Value: 120300c92b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0003
+	 *   Value UUID: Sink PAC (0x2bc9)
+	 *   Handle: 0x0005
+	 *   Value: 120600ca2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0006
+	 *   Value UUID: Sink Audio Locations (0x2bca)
+	 *   Handle: 0x0008
+	 *   Value: 120900cb2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0009
+	 *   Value UUID: Source PAC (0x2bcb)
+	 *   Handle: 0x000b
+	 *   Value: 120c00cc2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *  Value Handle: 0x000c
+	 *  Value UUID: Source Audio Locations (0x2bcc)
+	 *  Handle: 0x000e
+	 *  Value: 120f00cd2b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x000f
+	 *  Value UUID: Available Audio Contexts (0x2bcd)
+	 *  Handle: 0x0011
+	 *  Value: 121200ce2b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0012
+	 *  Value UUID: Supported Audio Contexts (0x2bce)
+	 *  Handle: 0x0015
+	 *  Value: 121600c42b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0016
+	 *  Value UUID: Sink ASE (0x2bc4)
+	 *  Handle: 0x0018
+	 *  Value: 121900c42b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0019
+	 *  Value UUID: Sink ASE (0x2bc4)
+	 */
+	IOV_DATA(0x09, 0x07,
+		0x02, 0x00, 0x12, 0x03, 0x00, 0xc9, 0x2b,
+		0x05, 0x00, 0x12, 0x06, 0x00, 0xca, 0x2b,
+		0x08, 0x00, 0x12, 0x09, 0x00, 0xcb, 0x2b,
+		0x0b, 0x00, 0x12, 0x0c, 0x00, 0xcc, 0x2b,
+		0x0e, 0x00, 0x12, 0x0f, 0x00, 0xcd, 0x2b,
+		0x11, 0x00, 0x12, 0x12, 0x00, 0xce, 0x2b,
+		0x15, 0x00, 0x12, 0x16, 0x00, 0xc4, 0x2b,
+		0x18, 0x00, 0x12, 0x19, 0x00, 0xc4, 0x2b),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x19, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Read By Type Response (0x09) len 22
+	 * Attribute data length: 7
+	 * Attribute data list: 3 entries
+	 *   Handle: 0x001b
+	 *   Value: 121c00c52b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x001c
+	 *   Value UUID: Source ASE (0x2bc5)
+	 *   Handle: 0x001e
+	 *   Value: 121f00c52b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x001f
+	 *   Value UUID: Source ASE (0x2bc5)
+	 *   Handle: 0x0021
+	 *   Value: 182200c62b
+	 *   Properties: 0x18
+	 *     Write (0x08)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0022
+	 *   Value UUID: ASE Control Point (0x2bc6)
+	 */
+	IOV_DATA(0x09, 0x07,
+		0x1b, 0x00, 0x12, 0x1c, 0x00, 0xc5, 0x2b,
+		0x1e, 0x00, 0x12, 0x1f, 0x00, 0xc5, 0x2b,
+		0x21, 0x00, 0x18, 0x22, 0x00, 0xc6, 0x2b),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0022-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x22, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0022
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x23, 0x00, 0x0a),
+	/* ACL Data TX: Handle 42 flags 0x00 dlen 11
+	 *   ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute type: Database Hash (0x2b2a)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0xff, 0xff, 0x2a, 0x2b),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+};
+
+static void print_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	if (tester_use_debug())
+		tester_debug("%s%s", prefix, str);
+}
+
+static void test_setup(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct bt_att *att;
+	struct gatt_db *db;
+	struct io *io;
+
+	io = tester_setup_io(setup_data, ARRAY_SIZE(setup_data));
+	g_assert(io);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	db = gatt_db_new();
+	g_assert(db);
+
+	data->client = bt_gatt_client_new(db, att, 64, 0);
+	g_assert(data->client);
+
+	bt_gatt_client_set_debug(data->client, print_debug, "bt_gatt_client:",
+						NULL);
+
+	bt_gatt_client_ready_register(data->client, client_ready_cb, data,
+						NULL);
+
+	bt_att_unref(att);
+	gatt_db_unref(db);
+}
+
+static void test_complete_cb(const void *user_data)
+{
+	tester_test_passed();
+}
+
+static void bap_disable(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	if (code)
+		tester_test_failed();
+}
+
+static void bap_start(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	if (code)
+		tester_test_failed();
+}
+
+static void bap_enable(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	unsigned int id = 0;
+
+	if (code) {
+		tester_test_failed();
+		return;
+	}
+
+	switch (data->cfg->state) {
+	case BT_BAP_STREAM_STATE_ENABLING:
+		return;
+	case BT_BAP_STREAM_STATE_DISABLING:
+		id = bt_bap_stream_disable(stream, true, bap_disable,
+						data);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		if (data->cfg->snk)
+			return;
+		id = bt_bap_stream_start(stream, bap_start, data);
+		break;
+	}
+
+	g_assert(id);
+}
+
+static void bap_qos(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+
+	if (code) {
+		tester_test_failed();
+		return;
+	}
+
+	if (data->cfg->state > BT_BAP_STREAM_STATE_QOS) {
+		unsigned int qos_id;
+
+		qos_id = bt_bap_stream_enable(stream, true, NULL,
+							bap_enable, data);
+		g_assert(qos_id);
+	}
+}
+
+static void bap_config(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+
+	if (code) {
+		tester_test_failed();
+		return;
+	}
+
+	if (data->cfg->state > BT_BAP_STREAM_STATE_CONFIG) {
+		unsigned int qos_id;
+
+		qos_id = bt_bap_stream_qos(stream, &data->cfg->qos,
+					   bap_qos, data);
+		g_assert(qos_id);
+	}
+}
+
+static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+							void *user_data)
+{
+	struct test_data *data = user_data;
+	unsigned int config_id;
+	struct bt_bap_stream *stream;
+
+	stream = bt_bap_stream_new(data->bap, lpac, rpac,
+						&data->cfg->qos,
+						&data->cfg->cc);
+	g_assert(stream);
+
+	queue_push_tail(data->streams, stream);
+
+	config_id = bt_bap_stream_config(stream, &data->cfg->qos,
+					&data->cfg->cc, bap_config, data);
+	g_assert(config_id);
+
+	return true;
+}
+
+static void bap_ready(struct bt_bap *bap, void *user_data)
+{
+	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_found, user_data);
+	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_found, user_data);
+}
+
+static void test_client_config(struct test_data *data)
+{
+	if (!data->cfg)
+		return;
+
+	if (data->cfg->src) {
+		if (data->cfg->vs)
+			data->snk = bt_bap_add_vendor_pac(data->db,
+							"test-bap-snk",
+							BT_BAP_SINK, 0x0ff,
+							0x0001, 0x0001,
+							NULL, data->caps, NULL);
+		else
+			data->snk = bt_bap_add_pac(data->db, "test-bap-snk",
+							BT_BAP_SINK, LC3_ID,
+							NULL, data->caps, NULL);
+		g_assert(data->snk);
+	}
+
+	if (data->cfg->snk) {
+		if (data->cfg->vs)
+			data->src = bt_bap_add_vendor_pac(data->db,
+							"test-bap-src",
+							BT_BAP_SOURCE, 0x0ff,
+							0x0001, 0x0001,
+							NULL, data->caps, NULL);
+		else
+			data->src = bt_bap_add_pac(data->db, "test-bap-src",
+							BT_BAP_SOURCE, LC3_ID,
+							NULL, data->caps, NULL);
+		g_assert(data->src);
+	}
+}
+
+static void test_client(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct io *io;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	test_client_config(data);
+
+	data->bap = bt_bap_new(data->db, bt_gatt_client_get_db(data->client));
+	g_assert(data->bap);
+
+	bt_bap_set_debug(data->bap, print_debug, "bt_bap:", NULL);
+
+	bt_bap_ready_register(data->bap, bap_ready, data, NULL);
+
+	if (data->cfg && data->cfg->state_func)
+		bt_bap_state_register(data->bap, data->cfg->state_func, NULL,
+						data, NULL);
+
+	bt_bap_attach(data->bap, data->client);
+}
+
+static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
+			struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
+			void *user_data)
+{
+	cb(stream, 0);
+
+	return 0;
+}
+
+static struct bt_bap_pac_ops bcast_pac_ops = {
+	.config = pac_config,
+};
+
+static void bsrc_pac_added(struct bt_bap_pac *pac, void *user_data)
+{
+	struct test_data *data = user_data;
+	struct bt_bap_stream *stream;
+
+	bt_bap_pac_set_ops(pac, &bcast_pac_ops, NULL);
+
+	for (uint8_t i = 0; i < data->cfg->streams; i++) {
+		stream = bt_bap_stream_new(data->bap, pac, NULL,
+							&data->cfg->qos,
+							&data->cfg->cc);
+		g_assert(stream);
+
+		queue_push_tail(data->streams, stream);
+
+		bt_bap_stream_config(stream, &data->cfg->qos,
+						&data->cfg->cc, NULL, data);
+	}
+}
+
+static void bsrc_state_cfg(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct test_data *data = user_data;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		data->base = bt_bap_stream_get_base(stream);
+
+		g_assert(data->base);
+		g_assert(data->base->iov_len == data->cfg->base.iov_len);
+		g_assert(memcmp(data->base->iov_base, data->cfg->base.iov_base,
+				data->base->iov_len) == 0);
+
+		tester_test_passed();
+		break;
+	}
+}
+
+static void bsnk_pac_added(struct bt_bap_pac *pac, void *user_data)
+{
+	struct test_data *data = user_data;
+	struct bt_bap_pac *lpac;
+	struct iovec *cc;
+	struct bt_bap_stream *stream;
+	uint8_t bis_idx = 1;
+
+	bt_bap_pac_set_ops(pac, &bcast_pac_ops, NULL);
+
+	for (uint8_t i = 0; i < data->cfg->streams; i++) {
+		cc = bt_bap_merge_caps(&data->cfg->cc, NULL);
+		g_assert(cc);
+
+		bt_bap_verify_bis(data->bap, bis_idx++, cc, &lpac);
+
+		g_assert(lpac);
+		g_assert(pac == lpac);
+
+		stream = bt_bap_stream_new(data->bap,
+			pac, NULL, &data->cfg->qos, cc);
+
+		g_assert(stream);
+
+		queue_push_tail(data->streams, stream);
+
+		bt_bap_stream_config(stream, &data->cfg->qos,
+				cc, NULL, NULL);
+
+		util_iov_free(cc, 1);
+	}
+}
+
+static void bsnk_state(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct test_data *data = user_data;
+	struct iovec *cc;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		/* Check that stream has been configured as expected */
+		cc = bt_bap_stream_get_config(stream);
+
+		g_assert(cc);
+		g_assert(cc->iov_len == data->cfg->cc.iov_len);
+		g_assert(memcmp(cc->iov_base, data->cfg->cc.iov_base,
+				cc->iov_len) == 0);
+
+		tester_test_passed();
+		break;
+	}
+}
+
+static void test_bcast_config(struct test_data *data)
+{
+	if (!data->cfg)
+		return;
+
+	if (data->cfg->src) {
+		bt_bap_pac_register(data->bap, bsrc_pac_added,
+						NULL, data, NULL);
+
+		if (data->cfg->vs)
+			data->bsrc = bt_bap_add_vendor_pac(data->db,
+							"test-bap-bsrc",
+							BT_BAP_BCAST_SOURCE,
+							0x0ff, 0x0000, 0x0000,
+							NULL, data->caps,
+							NULL);
+		else
+			data->bsrc = bt_bap_add_pac(data->db, "test-bap-bsrc",
+							BT_BAP_BCAST_SOURCE,
+							LC3_ID,
+							NULL, data->caps,
+							NULL);
+
+		g_assert(data->bsrc);
+	}
+
+	if (data->cfg->snk) {
+		bt_bap_pac_register(data->bap, bsnk_pac_added,
+						NULL, data, NULL);
+
+		if (data->cfg->vs)
+			data->bsnk = bt_bap_add_vendor_pac(data->db,
+							"test-bap-bsnk",
+							BT_BAP_BCAST_SINK,
+							0xff, 0x0000, 0x0000,
+							NULL, data->caps,
+							NULL);
+		else
+			data->bsnk = bt_bap_add_pac(data->db, "test-bap-bsnk",
+							BT_BAP_BCAST_SINK,
+							LC3_ID,
+							NULL, data->caps,
+							NULL);
+
+		g_assert(data->bsnk);
+	}
+}
+
+static void test_bcast(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	data->bap = bt_bap_new(data->db, data->db);
+	g_assert(data->bap);
+
+	bt_bap_set_debug(data->bap, print_debug, "bt_bap:", NULL);
+
+	bt_bap_attach_broadcast(data->bap);
+
+	if (data->cfg && data->cfg->state_func)
+		bt_bap_state_register(data->bap, data->cfg->state_func, NULL,
+						data, NULL);
+
+	test_bcast_config(data);
+}
+
+static void test_teardown(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+
+	bt_bap_unref(data->bap);
+	bt_gatt_client_unref(data->client);
+	util_iov_free(data->iov, data->iovcnt);
+
+	util_iov_free(data->base, 1);
+
+	bt_bap_remove_pac(data->snk);
+	bt_bap_remove_pac(data->src);
+	bt_bap_remove_pac(data->bsrc);
+	bt_bap_remove_pac(data->bsnk);
+	gatt_db_unref(data->db);
+
+	queue_destroy(data->streams, NULL);
+
+	tester_teardown_complete();
+}
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0003 Type: Sink PAC (0x2bc9)
+ * ATT: Read Response (0x0b) len 24
+ *   Value: 010600000000100301ff0002020302030305041e00f00000
+ *   Handle: 0x0003 Type: Sink PAC (0x2bc9)
+ *     Number of PAC(s): 1
+ *       PAC #0:
+ *         Codec: LC3 (0x06)
+ *         Codec Specific Capabilities #0: len 0x03 type 0x01
+ *         Sampling Frequencies: 0x00ff
+ *           8 Khz (0x0001)
+ *           11.25 Khz (0x0002)
+ *           16 Khz (0x0004)
+ *           22.05 Khz (0x0008)
+ *           24 Khz (0x0010)
+ *           32 Khz (0x0020)
+ *           44.1 Khz (0x0040)
+ *           48 Khz (0x0080)
+ *       Codec Specific Capabilities #1: len 0x02 type 0x02
+ *         Frame Duration: 0x0003
+ *           7.5 ms (0x01)
+ *           10 ms (0x02)
+ *       Codec Specific Capabilities #2: len 0x02 type 0x03
+ *         Audio Channel Count: 0x03
+ *           1 channel (0x01)
+ *           2 channels (0x02)
+ *       Codec Specific Capabilities #3: len 0x05 type 0x04
+ *         Frame Length: 30 (0x001e) - 240 (0x00f0)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0006 Type: Sink Audio Location (0x2bca)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 03000000
+ *   Handle: 0x0006 Type: Sink Audio Locations (0x2bca)
+ *     Location: 0x00000003
+ *       Front Left (0x00000001)
+ *       Front Right (0x00000002)
+ */
+#define DISC_SNK_PAC(_caps...) \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01, _caps), \
+	IOV_DATA(0x0a, 0x06, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00, 0x00, 0x00)
+
+#define DISC_SNK_LC3 \
+	DISC_SNK_PAC(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0009 Type: Source PAC (0x2bcb)
+ * ATT: Read Response (0x0b) len 24
+ *   Value: 010600000000100301ff0002020302030305041e00f00000
+ *   Handle: 0x0009 Type: Source PAC (0x2bcb)
+ *     Number of PAC(s): 1
+ *       PAC #0:
+ *         Codec: LC3 (0x06)
+ *         Codec Specific Capabilities #0: len 0x03 type 0x01
+ *         Sampling Frequencies: 0x00ff
+ *           8 Khz (0x0001)
+ *           11.25 Khz (0x0002)
+ *           16 Khz (0x0004)
+ *           22.05 Khz (0x0008)
+ *           24 Khz (0x0010)
+ *           32 Khz (0x0020)
+ *           44.1 Khz (0x0040)
+ *           48 Khz (0x0080)
+ *       Codec Specific Capabilities #1: len 0x02 type 0x02
+ *         Frame Duration: 0x0003
+ *           7.5 ms (0x01)
+ *           10 ms (0x02)
+ *       Codec Specific Capabilities #2: len 0x02 type 0x03
+ *         Audio Channel Count: 0x03
+ *           1 channel (0x01)
+ *           2 channels (0x02)
+ *       Codec Specific Capabilities #3: len 0x05 type 0x04
+ *         Frame Length: 30 (0x001e) - 240 (0x00f0)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x000c Type: Source Audio Location (0x2bcc)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 03000000
+ *   Handle: 0x000c Type: Source Audio Locations (0x2bcc)
+ *     Location: 0x00000003
+ *       Front Left (0x00000001)
+ *       Front Right (0x00000002)
+ */
+#define DISC_SRC_PAC(_caps...) \
+	DISC_SNK_PAC(_caps), \
+	IOV_DATA(0x0a, 0x09, 0x00), \
+	IOV_DATA(0x0b, 0x01, _caps), \
+	IOV_DATA(0x0a, 0x0c, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00, 0x00, 0x00)
+
+#define DISC_SRC_LC3 \
+	DISC_SRC_PAC(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: ff0f0e00
+ *   Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
+ */
+#define DISC_CTX(_caps...) \
+	DISC_SRC_PAC(_caps), \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0xff, 0x0f, 0x0e, 0x00)
+
+#define DISC_CTX_LC3 \
+	DISC_CTX(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: ff0f0e00
+ *   Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
+ */
+#define DISC_SUP_CTX(_caps...) \
+	DISC_CTX(_caps), \
+	IOV_DATA(0x0a, 0x12, 0x00), \
+	IOV_DATA(0x0b, 0xff, 0x0f, 0x0e, 0x00)
+
+#define DISC_SUP_CTX_LC3 \
+	DISC_SUP_CTX(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0016 Type: Sink ASE (0x2bc4)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0100
+ *   Handle: 0x0016 Type: Sink ASE (0x2bc4)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0017 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0019 Type: Sink ASE (0x2bc4)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0200
+ *   Handle: 0x0019 Type: Sink ASE (0x2bc4)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x001a Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define DISC_SNK_ASE(_caps...) \
+	DISC_SUP_CTX(_caps), \
+	IOV_DATA(0x0a, 0x16, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x00), \
+	IOV_DATA(0x12, 0x17, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x0a, 0x19, 0x00), \
+	IOV_DATA(0x0b, 0x02, 0x00), \
+	IOV_DATA(0x12, 0x1a, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+#define DISC_SNK_ASE_LC3 \
+	DISC_SNK_ASE(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x001c Type: Source ASE (0x2bc5)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0300
+ *   Handle: 0x001c Type: Source ASE (0x2bc5)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x001d Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x001f Type: Source ASE (0x2bc5)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0400
+ *   Handle: 0x001f Type: Source ASE (0x2bc5)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0020 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0023 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define DISC_SRC_ASE(_cfg...) \
+	DISC_SNK_ASE(_cfg), \
+	IOV_DATA(0x0a, 0x1c, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00), \
+	IOV_DATA(0x12, 0x1d, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x0a, 0x1f, 0x00), \
+	IOV_DATA(0x0b, 0x04, 0x00), \
+	IOV_DATA(0x12, 0x20, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x12, 0x23, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+#define DISC_SRC_ASE_LC3 \
+	DISC_SRC_ASE(0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00)
+
+static void test_disc(void)
+{
+	/* The IUT discovers the characteristics specified in the PAC
+	 * Characteristic and Location Characteristic columns in Table 4.4.
+	 * The IUT reads the values of the characteristics specified in the PAC
+	 * Characteristic and Location Characteristic columns.
+	 */
+	define_test("BAP/UCL/DISC/BV-01-C", test_setup, test_client, NULL,
+						DISC_SNK_LC3);
+	define_test("BAP/UCL/DISC/BV-02-C", test_setup, test_client, NULL,
+						DISC_SRC_LC3);
+
+	/* BAP/UCL/DISC/BV-06-C [Discover Available Audio Contexts]
+	 *
+	 * The IUT successfully reads the value of the Available Audio Contexts
+	 * characteristic on the LowerTester.
+	 */
+	define_test("BAP/UCL/DISC/BV-06-C", test_setup, test_client, NULL,
+						DISC_CTX_LC3);
+
+	/* BAP/UCL/DISC/BV-05-C [Discover Supported Audio Contexts]
+	 *
+	 * The IUT successfully reads the value of the Supported Audio Contexts
+	 * characteristic on the Lower Tester.
+	 */
+	define_test("BAP/UCL/DISC/BV-05-C", test_setup, test_client, NULL,
+						DISC_SUP_CTX_LC3);
+
+	/* BAP/UCL/DISC/BV-03-C [Discover Sink ASE_ID]
+	 * BAP/UCL/DISC/BV-04-C [Discover Source ASE_ID]
+	 *
+	 * The IUT successfully reads the ASE_ID values of each discovered ASE
+	 * characteristic on the LowerTester.
+	 */
+	define_test("BAP/UCL/DISC/BV-03-C", test_setup, test_client, NULL,
+						DISC_SNK_ASE_LC3);
+	define_test("BAP/UCL/DISC/BV-04-C", test_setup, test_client, NULL,
+						DISC_SRC_ASE_LC3);
+}
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 0101010202_cfg
+ * ATT: Handle Value Notification (0x1b) len 7
+ *   Handle: 0x0022
+ *     Data: 0101010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 01010102010a00204e00409c00204e00409c00_cfg
+ */
+#define SCC_SNK(_cfg...) \
+	IOV_DATA(0x52, 0x22, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, _cfg), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x0a, 0x00, \
+			0x20, 0x4e, 0x00, 0x40, 0x9c, 0x00, 0x20, 0x4e, 0x00, \
+			0x40, 0x9c, 0x00, _cfg)
+
+#define SCC_SNK_LC3(_cc...) \
+	DISC_SRC_ASE_LC3, \
+	SCC_SNK(0x06, 0x00, 0x00, 0x00, 0x00, _cc)
+
+#define QOS_BALANCED_2M \
+	{ \
+		.target_latency = BT_BAP_CONFIG_LATENCY_BALANCED, \
+		.io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
+	}
+#define QOS_UCAST \
+{\
+	.ucast = QOS_BALANCED_2M, \
+}
+static struct test_config cfg_snk_8_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_8_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x1a, 0x00)
+
+static struct test_config cfg_snk_8_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_8_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x1e, 0x00)
+
+static struct test_config cfg_snk_16_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_16_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x03, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x1e, 0x00)
+
+static struct test_config cfg_snk_16_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_16_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x03, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x28, 0x00)
+
+static struct test_config cfg_snk_24_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_24_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x05, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x2d, 0x00)
+
+static struct test_config cfg_snk_24_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_24_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x05, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x3c, 0x00)
+
+static struct test_config cfg_snk_32_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_32_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x06, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x3c, 0x00)
+
+static struct test_config cfg_snk_32_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_32_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x06, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x50, 0x00)
+
+static struct test_config cfg_snk_44_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_44_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x07, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x62, 0x00)
+
+static struct test_config cfg_snk_44_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_44_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x07, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x82, 0x00)
+
+static struct test_config cfg_snk_48_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_1 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x4b, 0x00)
+
+static struct test_config cfg_snk_48_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_2 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x64, 0x00)
+
+static struct test_config cfg_snk_48_3 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_3 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x5a, 0x00)
+
+static struct test_config cfg_snk_48_4 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_4 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x78, 0x00)
+
+static struct test_config cfg_snk_48_5 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_5 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x75, 0x00)
+
+static struct test_config cfg_snk_48_6 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = QOS_UCAST,
+	.snk = true,
+};
+
+#define SCC_SNK_48_6 \
+	SCC_SNK_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x9b, 0x00)
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 0101030202_cfg
+ * ATT: Handle Value Notification (0x1b) len 7
+ *   Handle: 0x0022
+ *     Data: 0101030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 03010102010a00204e00409c00204e00409c00_cfg
+ */
+#define SCC_SRC(_cfg...) \
+	IOV_DATA(0x52, 0x22, 0x00, 0x01, 0x01, 0x03, 0x02, 0x02, _cfg), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x0a, 0x00, \
+			0x20, 0x4e, 0x00, 0x40, 0x9c, 0x00, 0x20, 0x4e, 0x00, \
+			0x40, 0x9c, 0x00, _cfg)
+
+#define SCC_SRC_LC3(_cc...) \
+	DISC_SRC_ASE_LC3, \
+	SCC_SRC(0x06, 0x00, 0x00, 0x00, 0x00, _cc)
+
+static struct test_config cfg_src_8_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_8_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			    0x1a, 0x00)
+
+static struct test_config cfg_src_8_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_8_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x1e, 0x00)
+
+static struct test_config cfg_src_16_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_16_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x03, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x1e, 0x00)
+
+static struct test_config cfg_src_16_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_16_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x03, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x28, 0x00)
+
+static struct test_config cfg_src_24_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_24_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x05, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x2d, 0x00)
+
+static struct test_config cfg_src_24_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_24_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x05, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x3c, 0x00)
+
+static struct test_config cfg_src_32_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_32_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x06, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x3c, 0x00)
+
+static struct test_config cfg_src_32_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_32_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x06, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x50, 0x00)
+
+static struct test_config cfg_src_44_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_44_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x07, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x62, 0x00)
+
+static struct test_config cfg_src_44_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_44_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x07, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x82, 0x00)
+
+static struct test_config cfg_src_48_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_1 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x4b, 0x00)
+
+static struct test_config cfg_src_48_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_2 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x64, 0x00)
+
+static struct test_config cfg_src_48_3 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_3 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x5a, 0x00)
+
+static struct test_config cfg_src_48_4 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_4 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x78, 0x00)
+
+static struct test_config cfg_src_48_5 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_5 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0x03, 0x04, \
+			0x75, 0x00)
+
+static struct test_config cfg_src_48_6 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = QOS_UCAST,
+	.src = true,
+};
+
+#define SCC_SRC_48_6 \
+	SCC_SRC_LC3(0x0a, 0x02, 0x01, 0x08, 0x02, 0x02, 0x01, 0x03, 0x04, \
+			0x9b, 0x00)
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate a Config Codec
+ * operation for an LC3 codec.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control point with the opcode
+ * set to 0x01 (Config Codec) and correctly formatted parameter values
+ * from Table 4.9. The Codec_ID field is a 5-octet field with octet 0
+ * set to the LC3 Coding_Format value defined in Bluetooth Assigned
+ * Numbers, octets 1–4 set to 0x0000. Each parameter (if present)
+ * included in the data sent in Codec_Specific_Configuration is
+ * formatted in an LTV structure with the length, type, and value
+ * specified in Table 4.10.
+ */
+static void test_scc_cc_lc3(void)
+{
+	define_test("BAP/UCL/SCC/BV-001-C [UCL SRC Config Codec, LC3 8_1]",
+			test_setup, test_client, &cfg_snk_8_1, SCC_SNK_8_1);
+	define_test("BAP/UCL/SCC/BV-002-C [UCL SRC Config Codec, LC3 8_2]",
+			test_setup, test_client, &cfg_snk_8_2, SCC_SNK_8_2);
+	define_test("BAP/UCL/SCC/BV-003-C [UCL SRC Config Codec, LC3 16_1]",
+			test_setup, test_client, &cfg_snk_16_1, SCC_SNK_16_1);
+	define_test("BAP/UCL/SCC/BV-004-C [UCL SRC Config Codec, LC3 16_2]",
+			test_setup, test_client, &cfg_snk_16_2, SCC_SNK_16_2);
+	define_test("BAP/UCL/SCC/BV-005-C [UCL SRC Config Codec, LC3 24_1]",
+			test_setup, test_client, &cfg_snk_24_1, SCC_SNK_24_1);
+	define_test("BAP/UCL/SCC/BV-006-C [UCL SRC Config Codec, LC3 24_2]",
+			test_setup, test_client, &cfg_snk_24_2, SCC_SNK_24_2);
+	define_test("BAP/UCL/SCC/BV-007-C [UCL SRC Config Codec, LC3 32_1]",
+			test_setup, test_client, &cfg_snk_32_1, SCC_SNK_32_1);
+	define_test("BAP/UCL/SCC/BV-008-C [UCL SRC Config Codec, LC3 32_2]",
+			test_setup, test_client, &cfg_snk_32_2, SCC_SNK_32_2);
+	define_test("BAP/UCL/SCC/BV-009-C [UCL SRC Config Codec, LC3 44.1_1]",
+			test_setup, test_client, &cfg_snk_44_1, SCC_SNK_44_1);
+	define_test("BAP/UCL/SCC/BV-010-C [UCL SRC Config Codec, LC3 44.1_2]",
+			test_setup, test_client, &cfg_snk_44_2, SCC_SNK_44_2);
+	define_test("BAP/UCL/SCC/BV-011-C [UCL SRC Config Codec, LC3 48_1]",
+			test_setup, test_client, &cfg_snk_48_1, SCC_SNK_48_1);
+	define_test("BAP/UCL/SCC/BV-012-C [UCL SRC Config Codec, LC3 48_2]",
+			test_setup, test_client, &cfg_snk_48_2, SCC_SNK_48_2);
+	define_test("BAP/UCL/SCC/BV-013-C [UCL SRC Config Codec, LC3 48_3]",
+			test_setup, test_client, &cfg_snk_48_3, SCC_SNK_48_3);
+	define_test("BAP/UCL/SCC/BV-014-C [UCL SRC Config Codec, LC3 48_4]",
+			test_setup, test_client, &cfg_snk_48_4, SCC_SNK_48_4);
+	define_test("BAP/UCL/SCC/BV-015-C [UCL SRC Config Codec, LC3 48_5]",
+			test_setup, test_client, &cfg_snk_48_5, SCC_SNK_48_5);
+	define_test("BAP/UCL/SCC/BV-016-C [UCL SRC Config Codec, LC3 48_6]",
+			test_setup, test_client, &cfg_snk_48_6, SCC_SNK_48_6);
+	define_test("BAP/UCL/SCC/BV-017-C [UCL SNK Config Codec, LC3 8_1]",
+			test_setup, test_client, &cfg_src_8_1, SCC_SRC_8_1);
+	define_test("BAP/UCL/SCC/BV-018-C [UCL SNK Config Codec, LC3 8_2]",
+			test_setup, test_client, &cfg_src_8_2, SCC_SRC_8_2);
+	define_test("BAP/UCL/SCC/BV-019-C [UCL SNK Config Codec, LC3 16_1]",
+			test_setup, test_client, &cfg_src_16_1, SCC_SRC_16_1);
+	define_test("BAP/UCL/SCC/BV-020-C [UCL SNK Config Codec, LC3 16_2]",
+			test_setup, test_client, &cfg_src_16_2, SCC_SRC_16_2);
+	define_test("BAP/UCL/SCC/BV-021-C [UCL SNK Config Codec, LC3 24_1]",
+			test_setup, test_client, &cfg_src_24_1, SCC_SRC_24_1);
+	define_test("BAP/UCL/SCC/BV-022-C [UCL SNK Config Codec, LC3 24_2]",
+			test_setup, test_client, &cfg_src_24_2, SCC_SRC_24_2);
+	define_test("BAP/UCL/SCC/BV-023-C [UCL SNK Config Codec, LC3 32_1]",
+			test_setup, test_client, &cfg_src_32_1, SCC_SRC_32_1);
+	define_test("BAP/UCL/SCC/BV-024-C [UCL SNK Config Codec, LC3 32_2]",
+			test_setup, test_client, &cfg_src_32_2, SCC_SRC_32_2);
+	define_test("BAP/UCL/SCC/BV-025-C [UCL SNK Config Codec, LC3 44.1_1]",
+			test_setup, test_client, &cfg_src_44_1, SCC_SRC_44_1);
+	define_test("BAP/UCL/SCC/BV-026-C [UCL SNK Config Codec, LC3 44.1_2]",
+			test_setup, test_client, &cfg_src_44_2, SCC_SRC_44_2);
+	define_test("BAP/UCL/SCC/BV-027-C [UCL SNK Config Codec, LC3 48_1]",
+			test_setup, test_client, &cfg_src_48_1, SCC_SRC_48_1);
+	define_test("BAP/UCL/SCC/BV-028-C [UCL SNK Config Codec, LC3 48_2]",
+			test_setup, test_client, &cfg_src_48_2, SCC_SRC_48_2);
+	define_test("BAP/UCL/SCC/BV-029-C [UCL SNK Config Codec, LC3 48_3]",
+			test_setup, test_client, &cfg_src_48_3, SCC_SRC_48_3);
+	define_test("BAP/UCL/SCC/BV-030-C [UCL SNK Config Codec, LC3 48_4]",
+			test_setup, test_client, &cfg_src_48_4, SCC_SRC_48_4);
+	define_test("BAP/UCL/SCC/BV-031-C [UCL SNK Config Codec, LC3 48_5]",
+			test_setup, test_client, &cfg_src_48_5, SCC_SRC_48_5);
+	define_test("BAP/UCL/SCC/BV-032-C [UCL SNK Config Codec, LC3 48_6]",
+			test_setup, test_client, &cfg_src_48_6, SCC_SRC_48_6);
+}
+
+static struct test_config cfg_snk_vs = {
+	.cc = IOV_NULL,
+	.qos = QOS_UCAST,
+	.snk = true,
+	.vs = true,
+};
+
+#define DISC_SRC_ASE_VS \
+	DISC_SRC_ASE(0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00)
+
+#define SCC_SNK_VS \
+	DISC_SRC_ASE_VS,  \
+	SCC_SNK(0xff, 0x01, 0x00, 0x01, 0x00, 0x00)
+
+static struct test_config cfg_src_vs = {
+	.cc = IOV_NULL,
+	.qos = QOS_UCAST,
+	.src = true,
+	.vs = true,
+};
+
+#define SCC_SRC_VS \
+	DISC_SRC_ASE_VS,  \
+	SCC_SRC(0xff, 0x01, 0x00, 0x01, 0x00, 0x00)
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate a Config Codec operation for a
+ * vendor-specific codec.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x01 (Config Codec) and the specified parameters. The Codec_ID
+ * parameter is formatted with octet 0 set to 0xFF, octets 1–2 set to
+ * TSPX_VS_Company_ID, and octets 3–4 set to TSPX_VS_Codec_ID.
+ */
+static void test_scc_cc_vs(void)
+{
+	define_test("BAP/UCL/SCC/BV-033-C [UCL SRC Config Codec, VS]",
+			test_setup, test_client, &cfg_snk_vs, SCC_SNK_VS);
+	define_test("BAP/UCL/SCC/BV-034-C [UCL SNK Config Codec, VS]",
+			test_setup, test_client, &cfg_src_vs, SCC_SRC_VS);
+}
+
+static struct test_config cfg_snk_8_1_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_8_2_1 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_16_1_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_16_2_1 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_24_1_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_24_2_1 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_32_1_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_32_2_1 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_44_1_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_44_2_1 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_1_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_2_1 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_3_1 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_4_1 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_5_1 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_6_1 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 02010000_qos
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0201010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 01010102010a00204e00409c00204e00409c00_qos
+ */
+#define QOS_SNK(_qos...) \
+	IOV_DATA(0x52, 0x22, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, _qos), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x02, 0x00, 0x00, _qos)
+
+#define SCC_SNK_8_1_1 \
+	SCC_SNK_8_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_8_2_1 \
+	SCC_SNK_8_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_16_1_1 \
+	SCC_SNK_16_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_16_2_1 \
+	SCC_SNK_16_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_24_1_1 \
+	SCC_SNK_24_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_24_2_1 \
+	SCC_SNK_24_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_32_1_1 \
+	SCC_SNK_32_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_32_2_1 \
+	SCC_SNK_32_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x50, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_44_1_1 \
+	SCC_SNK_44_1, \
+	QOS_SNK(0xe3, 0x1f, 0x00, 0x01, 0x02, 0x62, 0x00, 0x05, 0x18, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_44_2_1 \
+	SCC_SNK_44_2, \
+	QOS_SNK(0x84, 0x2a, 0x00, 0x01, 0x02, 0x82, 0x00, 0x05, 0x1f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_1_1 \
+	SCC_SNK_48_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_2_1 \
+	SCC_SNK_48_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x64, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_3_1 \
+	SCC_SNK_48_3, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_4_1 \
+	SCC_SNK_48_4, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x78, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_5_1 \
+	SCC_SNK_48_5, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x75, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_6_1 \
+	SCC_SNK_48_6, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x9b, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+static struct test_config cfg_src_8_1_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_8_2_1 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_16_1_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_16_2_1 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_24_1_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_24_2_1 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_32_1_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_32_2_1 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_44_1_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_44_2_1 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_1_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_2_1 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_3_1 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_4_1 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_5_1 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_6_1 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 02030000_qos
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0201030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 03010102010a00204e00409c00204e00409c00_qos
+ */
+#define QOS_SRC(_qos...) \
+	IOV_DATA(0x52, 0x22, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, _qos), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x02, 0x00, 0x00, _qos)
+
+#define SCC_SRC_8_1_1 \
+	SCC_SRC_8_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_8_2_1 \
+	SCC_SRC_8_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_16_1_1 \
+	SCC_SRC_16_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_16_2_1 \
+	SCC_SRC_16_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_24_1_1 \
+	SCC_SRC_24_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_24_2_1 \
+	SCC_SRC_24_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_32_1_1 \
+	SCC_SRC_32_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x02, 0x08, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_32_2_1 \
+	SCC_SRC_32_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x50, 0x00, 0x02, 0x0a, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_44_1_1 \
+	SCC_SRC_44_1, \
+	QOS_SRC(0xe3, 0x1f, 0x00, 0x01, 0x02, 0x62, 0x00, 0x05, 0x18, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_44_2_1 \
+	SCC_SRC_44_2, \
+	QOS_SRC(0x84, 0x2a, 0x00, 0x01, 0x02, 0x82, 0x00, 0x05, 0x1f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_1_1 \
+	SCC_SRC_48_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_2_1 \
+	SCC_SRC_48_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x64, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_3_1 \
+	SCC_SRC_48_3, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_4_1 \
+	SCC_SRC_48_4, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x78, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_5_1 \
+	SCC_SRC_48_5, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x75, 0x00, 0x05, 0x0f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_6_1 \
+	SCC_SRC_48_6, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x9b, 0x00, 0x05, 0x14, 0x00, \
+		0x40, 0x9c, 0x00)
+
+static struct test_config cfg_snk_8_1_2 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_8_2_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_16_1_2 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_16_2_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_24_1_2 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_24_2_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_32_1_2 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_32_2_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_44_1_2 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_44_2_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_1_2 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_2_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_3_2 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_4_2 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_5_2 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_snk_48_6_2 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_2,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+#define SCC_SNK_8_1_2 \
+	SCC_SNK_8_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_8_2_2 \
+	SCC_SNK_8_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_16_1_2 \
+	SCC_SNK_16_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_16_2_2 \
+	SCC_SNK_16_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_24_1_2 \
+	SCC_SNK_24_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_24_2_2 \
+	SCC_SNK_24_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_32_1_2 \
+	SCC_SNK_32_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_32_2_2 \
+	SCC_SNK_32_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x50, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_44_1_2 \
+	SCC_SNK_44_1, \
+	QOS_SNK(0xe3, 0x1f, 0x00, 0x01, 0x02, 0x62, 0x00, 0x0d, 0x50, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_44_2_2 \
+	SCC_SNK_44_2, \
+	QOS_SNK(0x84, 0x2a, 0x00, 0x01, 0x02, 0x82, 0x00, 0x0d, 0x55, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_1_2 \
+	SCC_SNK_48_1, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_2_2 \
+	SCC_SNK_48_2, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x64, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_3_2 \
+	SCC_SNK_48_3, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_4_2 \
+	SCC_SNK_48_4, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x78, 0x00, 0x0d, 0x64, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_5_2 \
+	SCC_SNK_48_5, \
+	QOS_SNK(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x75, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SNK_48_6_2 \
+	SCC_SNK_48_6, \
+	QOS_SNK(0x10, 0x27, 0x00, 0x00, 0x02, 0x9b, 0x00, 0x0d, 0x64, 0x00, \
+		0x40, 0x9c, 0x00)
+
+static struct test_config cfg_src_8_1_2 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_8_2_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_16_1_2 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_16_2_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_24_1_2 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_24_2_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_32_1_2 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_32_2_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_44_1_2 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_44_2_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_1_2 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_2_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_3_2 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_4_2 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_5_2 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+static struct test_config cfg_src_48_6_2 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_2,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+};
+
+#define SCC_SRC_8_1_2 \
+	SCC_SRC_8_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_8_2_2 \
+	SCC_SRC_8_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_16_1_2 \
+	SCC_SRC_16_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_16_2_2 \
+	SCC_SRC_16_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_24_1_2 \
+	SCC_SRC_24_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_24_2_2 \
+	SCC_SRC_24_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_32_1_2 \
+	SCC_SRC_32_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_32_2_2 \
+	SCC_SRC_32_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x50, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_44_1_2 \
+	SCC_SRC_44_1, \
+	QOS_SRC(0xe3, 0x1f, 0x00, 0x01, 0x02, 0x62, 0x00, 0x0d, 0x50, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_44_2_2 \
+	SCC_SRC_44_2, \
+	QOS_SRC(0x84, 0x2a, 0x00, 0x01, 0x02, 0x82, 0x00, 0x0d, 0x55, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_1_2 \
+	SCC_SRC_48_1, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_2_2 \
+	SCC_SRC_48_2, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x64, 0x00, 0x0d, 0x5f, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_3_2 \
+	SCC_SRC_48_3, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_4_2 \
+	SCC_SRC_48_4, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x78, 0x00, 0x0d, 0x64, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_5_2 \
+	SCC_SRC_48_5, \
+	QOS_SRC(0x4c, 0x1d, 0x00, 0x00, 0x02, 0x75, 0x00, 0x0d, 0x4b, 0x00, \
+		0x40, 0x9c, 0x00)
+
+#define SCC_SRC_48_6_2 \
+	SCC_SRC_48_6, \
+	QOS_SRC(0x10, 0x27, 0x00, 0x00, 0x02, 0x9b, 0x00, 0x0d, 0x64, 0x00, \
+		0x40, 0x9c, 0x00)
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate a Config QoS operation for the
+ * LC3 codec.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x02 (Config QoS) and the specified parameters.
+ */
+static void test_scc_qos_lc3(void)
+{
+	define_test("BAP/UCL/SCC/BV-035-C [UCL SRC Config QoS, LC3 8_1_1]",
+			test_setup, test_client, &cfg_snk_8_1_1,
+			SCC_SNK_8_1_1);
+	define_test("BAP/UCL/SCC/BV-036-C [UCL SRC Config QoS, LC3 8_2_1]",
+			test_setup, test_client, &cfg_snk_8_2_1,
+			SCC_SNK_8_2_1);
+	define_test("BAP/UCL/SCC/BV-037-C [UCL SRC Config QoS, LC3 16_1_1]",
+			test_setup, test_client, &cfg_snk_16_1_1,
+			SCC_SNK_16_1_1);
+	define_test("BAP/UCL/SCC/BV-038-C [UCL SRC Config QoS, LC3 16_2_1]",
+			test_setup, test_client, &cfg_snk_16_2_1,
+			SCC_SNK_16_2_1);
+	define_test("BAP/UCL/SCC/BV-039-C [UCL SRC Config QoS, LC3 24_1_1]",
+			test_setup, test_client, &cfg_snk_24_1_1,
+			SCC_SNK_24_1_1);
+	define_test("BAP/UCL/SCC/BV-040-C [UCL SRC Config QoS, LC3 24_2_1]",
+			test_setup, test_client, &cfg_snk_24_2_1,
+			SCC_SNK_24_2_1);
+	define_test("BAP/UCL/SCC/BV-041-C [UCL SRC Config QoS, LC3 32_1_1]",
+			test_setup, test_client, &cfg_snk_32_1_1,
+			SCC_SNK_32_1_1);
+	define_test("BAP/UCL/SCC/BV-042-C [UCL SRC Config QoS, LC3 32_2_1]",
+			test_setup, test_client, &cfg_snk_32_2_1,
+			SCC_SNK_32_2_1);
+	define_test("BAP/UCL/SCC/BV-043-C [UCL SRC Config QoS, LC3 44.1_1_1]",
+			test_setup, test_client, &cfg_snk_44_1_1,
+			SCC_SNK_44_1_1);
+	define_test("BAP/UCL/SCC/BV-044-C [UCL SRC Config QoS, LC3 44.1_2_1]",
+			test_setup, test_client, &cfg_snk_44_2_1,
+			SCC_SNK_44_2_1);
+	define_test("BAP/UCL/SCC/BV-045-C [UCL SRC Config QoS, LC3 48_1_1]",
+			test_setup, test_client, &cfg_snk_48_1_1,
+			SCC_SNK_48_1_1);
+	define_test("BAP/UCL/SCC/BV-046-C [UCL SRC Config QoS, LC3 48_2_1]",
+			test_setup, test_client, &cfg_snk_48_2_1,
+			SCC_SNK_48_2_1);
+	define_test("BAP/UCL/SCC/BV-047-C [UCL SRC Config QoS, LC3 48_3_1]",
+			test_setup, test_client, &cfg_snk_48_3_1,
+			SCC_SNK_48_3_1);
+	define_test("BAP/UCL/SCC/BV-048-C [UCL SRC Config QoS, LC3 48_4_1]",
+			test_setup, test_client, &cfg_snk_48_4_1,
+			SCC_SNK_48_4_1);
+	define_test("BAP/UCL/SCC/BV-049-C [UCL SRC Config QoS, LC3 48_5_1]",
+			test_setup, test_client, &cfg_snk_48_5_1,
+			SCC_SNK_48_5_1);
+	define_test("BAP/UCL/SCC/BV-050-C [UCL SRC Config QoS, LC3 48_6_1]",
+			test_setup, test_client, &cfg_snk_48_6_1,
+			SCC_SNK_48_6_1);
+	define_test("BAP/UCL/SCC/BV-051-C [UCL SNK Config QoS, LC3 8_1_1]",
+			test_setup, test_client, &cfg_src_8_1_1,
+			SCC_SRC_8_1_1);
+	define_test("BAP/UCL/SCC/BV-052-C [UCL SNK Config QoS, LC3 8_2_1]",
+			test_setup, test_client, &cfg_src_8_2_1,
+			SCC_SRC_8_2_1);
+	define_test("BAP/UCL/SCC/BV-053-C [UCL SNK Config QoS, LC3 16_1_1]",
+			test_setup, test_client, &cfg_src_16_1_1,
+			SCC_SRC_16_1_1);
+	define_test("BAP/UCL/SCC/BV-054-C [UCL SNK Config QoS, LC3 16_2_1]",
+			test_setup, test_client, &cfg_src_16_2_1,
+			SCC_SRC_16_2_1);
+	define_test("BAP/UCL/SCC/BV-055-C [UCL SNK Config QoS, LC3 24_1_1]",
+			test_setup, test_client, &cfg_src_24_1_1,
+			SCC_SRC_24_1_1);
+	define_test("BAP/UCL/SCC/BV-056-C [UCL SNK Config QoS, LC3 24_2_1]",
+			test_setup, test_client, &cfg_src_24_2_1,
+			SCC_SRC_24_2_1);
+	define_test("BAP/UCL/SCC/BV-057-C [UCL SNK Config QoS, LC3 32_1_1]",
+			test_setup, test_client, &cfg_src_32_1_1,
+			SCC_SRC_32_1_1);
+	define_test("BAP/UCL/SCC/BV-058-C [UCL SNK Config QoS, LC3 32_2_1]",
+			test_setup, test_client, &cfg_src_32_2_1,
+			SCC_SRC_32_2_1);
+	define_test("BAP/UCL/SCC/BV-059-C [UCL SNK Config QoS, LC3 44.1_1_1]",
+			test_setup, test_client, &cfg_src_44_1_1,
+			SCC_SRC_44_1_1);
+	define_test("BAP/UCL/SCC/BV-060-C [UCL SNK Config QoS, LC3 44.1_2_1]",
+			test_setup, test_client, &cfg_src_44_2_1,
+			SCC_SRC_44_2_1);
+	define_test("BAP/UCL/SCC/BV-061-C [UCL SNK Config QoS, LC3 48_1_1]",
+			test_setup, test_client, &cfg_src_48_1_1,
+			SCC_SRC_48_1_1);
+	define_test("BAP/UCL/SCC/BV-062-C [UCL SNK Config QoS, LC3 48_2_1]",
+			test_setup, test_client, &cfg_src_48_2_1,
+			SCC_SRC_48_2_1);
+	define_test("BAP/UCL/SCC/BV-063-C [UCL SNK Config QoS, LC3 48_3_1]",
+			test_setup, test_client, &cfg_src_48_3_1,
+			SCC_SRC_48_3_1);
+	define_test("BAP/UCL/SCC/BV-064-C [UCL SNK Config QoS, LC3 48_4_1]",
+			test_setup, test_client, &cfg_src_48_4_1,
+			SCC_SRC_48_4_1);
+	define_test("BAP/UCL/SCC/BV-065-C [UCL SNK Config QoS, LC3 48_5_1]",
+			test_setup, test_client, &cfg_src_48_5_1,
+			SCC_SRC_48_5_1);
+	define_test("BAP/UCL/SCC/BV-066-C [UCL SNK Config QoS, LC3 48_6_1]",
+			test_setup, test_client, &cfg_src_48_6_1,
+			SCC_SRC_48_6_1);
+	define_test("BAP/UCL/SCC/BV-067-C [UCL SRC Config QoS, LC3 8_1_2]",
+			test_setup, test_client, &cfg_snk_8_1_2,
+			SCC_SNK_8_1_2);
+	define_test("BAP/UCL/SCC/BV-068-C [UCL SRC Config QoS, LC3 8_2_2]",
+			test_setup, test_client, &cfg_snk_8_2_2,
+			SCC_SNK_8_2_2);
+	define_test("BAP/UCL/SCC/BV-069-C [UCL SRC Config QoS, LC3 16_1_2]",
+			test_setup, test_client, &cfg_snk_16_1_2,
+			SCC_SNK_16_1_2);
+	define_test("BAP/UCL/SCC/BV-070-C [UCL SRC Config QoS, LC3 16_2_2]",
+			test_setup, test_client, &cfg_snk_16_2_2,
+			SCC_SNK_16_2_2);
+	define_test("BAP/UCL/SCC/BV-071-C [UCL SRC Config QoS, LC3 24_1_2]",
+			test_setup, test_client, &cfg_snk_24_1_2,
+			SCC_SNK_24_1_2);
+	define_test("BAP/UCL/SCC/BV-072-C [UCL SRC Config QoS, LC3 24_2_2]",
+			test_setup, test_client, &cfg_snk_24_2_2,
+			SCC_SNK_24_2_2);
+	define_test("BAP/UCL/SCC/BV-073-C [UCL SRC Config QoS, LC3 32_1_2]",
+			test_setup, test_client, &cfg_snk_32_1_2,
+			SCC_SNK_32_1_2);
+	define_test("BAP/UCL/SCC/BV-074-C [UCL SRC Config QoS, LC3 32_2_2]",
+			test_setup, test_client, &cfg_snk_32_2_2,
+			SCC_SNK_32_2_2);
+	define_test("BAP/UCL/SCC/BV-075-C [UCL SRC Config QoS, LC3 44.1_1_2]",
+			test_setup, test_client, &cfg_snk_44_1_2,
+			SCC_SNK_44_1_2);
+	define_test("BAP/UCL/SCC/BV-076-C [UCL SRC Config QoS, LC3 44.1_2_2]",
+			test_setup, test_client, &cfg_snk_44_2_2,
+			SCC_SNK_44_2_2);
+	define_test("BAP/UCL/SCC/BV-077-C [UCL SRC Config QoS, LC3 48_1_2]",
+			test_setup, test_client, &cfg_snk_48_1_2,
+			SCC_SNK_48_1_2);
+	define_test("BAP/UCL/SCC/BV-078-C [UCL SRC Config QoS, LC3 48_2_2]",
+			test_setup, test_client, &cfg_snk_48_2_2,
+			SCC_SNK_48_2_2);
+	define_test("BAP/UCL/SCC/BV-079-C [UCL SRC Config QoS, LC3 48_3_2]",
+			test_setup, test_client, &cfg_snk_48_3_2,
+			SCC_SNK_48_3_2);
+	define_test("BAP/UCL/SCC/BV-080-C [UCL SRC Config QoS, LC3 48_4_2]",
+			test_setup, test_client, &cfg_snk_48_4_2,
+			SCC_SNK_48_4_2);
+	define_test("BAP/UCL/SCC/BV-081-C [UCL SRC Config QoS, LC3 48_5_2]",
+			test_setup, test_client, &cfg_snk_48_5_2,
+			SCC_SNK_48_5_2);
+	define_test("BAP/UCL/SCC/BV-082-C [UCL SRC Config QoS, LC3 48_6_2]",
+			test_setup, test_client, &cfg_snk_48_6_2,
+			SCC_SNK_48_6_2);
+	define_test("BAP/UCL/SCC/BV-083-C [UCL SNK Config QoS, LC3 8_1_2]",
+			test_setup, test_client, &cfg_src_8_1_2,
+			SCC_SRC_8_1_2);
+	define_test("BAP/UCL/SCC/BV-084-C [UCL SNK Config QoS, LC3 8_2_2]",
+			test_setup, test_client, &cfg_src_8_2_2,
+			SCC_SRC_8_2_2);
+	define_test("BAP/UCL/SCC/BV-085-C [UCL SNK Config QoS, LC3 16_1_2]",
+			test_setup, test_client, &cfg_src_16_1_2,
+			SCC_SRC_16_1_2);
+	define_test("BAP/UCL/SCC/BV-086-C [UCL SNK Config QoS, LC3 16_2_2]",
+			test_setup, test_client, &cfg_src_16_2_2,
+			SCC_SRC_16_2_2);
+	define_test("BAP/UCL/SCC/BV-087-C [UCL SNK Config QoS, LC3 24_1_2]",
+			test_setup, test_client, &cfg_src_24_1_2,
+			SCC_SRC_24_1_2);
+	define_test("BAP/UCL/SCC/BV-088-C [UCL SNK Config QoS, LC3 24_2_2]",
+			test_setup, test_client, &cfg_src_24_2_2,
+			SCC_SRC_24_2_2);
+	define_test("BAP/UCL/SCC/BV-089-C [UCL SNK Config QoS, LC3 32_1_2]",
+			test_setup, test_client, &cfg_src_32_1_2,
+			SCC_SRC_32_1_2);
+	define_test("BAP/UCL/SCC/BV-090-C [UCL SNK Config QoS, LC3 32_2_2]",
+			test_setup, test_client, &cfg_src_32_2_2,
+			SCC_SRC_32_2_2);
+	define_test("BAP/UCL/SCC/BV-091-C [UCL SNK Config QoS, LC3 44.1_1_2]",
+			test_setup, test_client, &cfg_src_44_1_2,
+			SCC_SRC_44_1_2);
+	define_test("BAP/UCL/SCC/BV-092-C [UCL SNK Config QoS, LC3 44.1_2_2]",
+			test_setup, test_client, &cfg_src_44_2_2,
+			SCC_SRC_44_2_2);
+	define_test("BAP/UCL/SCC/BV-093-C [UCL SNK Config QoS, LC3 48_1_2]",
+			test_setup, test_client, &cfg_src_48_1_2,
+			SCC_SRC_48_1_2);
+	define_test("BAP/UCL/SCC/BV-094-C [UCL SNK Config QoS, LC3 48_2_2]",
+			test_setup, test_client, &cfg_src_48_2_2,
+			SCC_SRC_48_2_2);
+	define_test("BAP/UCL/SCC/BV-095-C [UCL SNK Config QoS, LC3 48_3_2]",
+			test_setup, test_client, &cfg_src_48_3_2,
+			SCC_SRC_48_3_2);
+	define_test("BAP/UCL/SCC/BV-096-C [UCL SNK Config QoS, LC3 48_4_2]",
+			test_setup, test_client, &cfg_src_48_4_2,
+			SCC_SRC_48_4_2);
+	define_test("BAP/UCL/SCC/BV-097-C [UCL SNK Config QoS, LC3 48_5_2]",
+			test_setup, test_client, &cfg_src_48_5_2,
+			SCC_SRC_48_5_2);
+	define_test("BAP/UCL/SCC/BV-098-C [UCL SNK Config QoS, LC3 48_6_2]",
+			test_setup, test_client, &cfg_src_48_6_2,
+			SCC_SRC_48_6_2);
+}
+
+static struct test_config cfg_snk_qos_vs = {
+	.cc = IOV_NULL,
+	.qos = QOS_UCAST,
+	.snk = true,
+	.vs = true,
+	.state = BT_BAP_STREAM_STATE_QOS
+};
+
+#define SCC_SNK_QOS_VS \
+	SCC_SNK_VS, \
+	QOS_SNK(0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, \
+		0x00, 0x00, 0x00)
+
+static struct test_config cfg_src_qos_vs = {
+	.cc = IOV_NULL,
+	.qos = QOS_UCAST,
+	.src = true,
+	.vs = true,
+	.state = BT_BAP_STREAM_STATE_QOS
+};
+
+#define SCC_SRC_QOS_VS \
+	SCC_SRC_VS, \
+	QOS_SRC(0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, \
+		0x00, 0x00, 0x00)
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate a Config QoS operation for a
+ * vendor-specific codec.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x02 (Config QoS) and the specified parameters.
+ */
+static void test_scc_qos_vs(void)
+{
+	define_test("BAP/UCL/SCC/BV-099-C [UCL SNK Config QoS, VS]",
+			test_setup, test_client, &cfg_src_qos_vs,
+			SCC_SRC_QOS_VS);
+	define_test("BAP/UCL/SCC/BV-100-C [UCL SRC QoS Codec, VS]",
+			test_setup, test_client, &cfg_snk_qos_vs,
+			SCC_SNK_QOS_VS);
+}
+
+static struct test_config cfg_snk_enable = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 03010104030201
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0301010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 0101010300403020100
+ */
+#define SCC_SNK_ENABLE \
+	SCC_SNK_16_2_1, \
+	IOV_DATA(0x52, 0x22, 0x00, 0x03, 0x01, 0x01, 0x04, 0x03, 0x02, 0x01, \
+			00), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x03, 0x00, 0x00, 0x04, 0x03, 0x02, \
+			0x01, 0x00)
+
+static struct test_config cfg_src_enable = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 0301030403020100
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0301030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 030300000403020100
+ */
+#define SRC_ENABLE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x03, 0x01, 0x03, 0x04, 0x03, 0x02, 0x01, \
+			00), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x03, 0x00, 0x00, 0x04, 0x03, 0x02, \
+			0x01, 0x00)
+
+#define SCC_SRC_ENABLE \
+	SCC_SRC_16_2_1, \
+	SRC_ENABLE
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate an Enable operation for an ASE
+ * with a Unicast Server that is either in the Audio Sink role or the Audio
+ * Source role.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x03 (Enable) and the specified parameters.
+ */
+static void test_scc_enable(void)
+{
+	define_test("BAP/UCL/SCC/BV-101-C [UCL SRC Enable]",
+			test_setup, test_client, &cfg_snk_enable,
+			SCC_SNK_ENABLE);
+	define_test("BAP/UCL/SCC/BV-102-C [UCL SNK Enable]",
+			test_setup, test_client, &cfg_src_enable,
+			SCC_SRC_ENABLE);
+}
+
+static struct test_config cfg_snk_disable = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_DISABLING
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 050101
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0501010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 01010102010a00204e00409c00204e00409c00_qos
+ */
+#define ASE_SNK_DISABLE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x05, 0x01, 0x01), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x05, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x02, 0x00, 0x00, 0x4c, 0x1d, 0x00, \
+			0x00, 0x02, 0x1a, 0x00, 0x02, 0x08, 0x00, 0x40, 0x9c, \
+			0x00)
+
+#define SCC_SNK_DISABLE \
+	SCC_SNK_ENABLE, \
+	ASE_SNK_DISABLE
+
+static struct test_config cfg_src_disable = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_DISABLING
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 050103
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0301030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 030300000403020100
+ */
+#define ASE_SRC_DISABLE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x05, 0x01, 0x03), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x05, 0x01, 0x03, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x05, 0x00, 0x00, 0x4c, 0x1d, 0x00, \
+			0x00, 0x02, 0x1a, 0x00, 0x04, 0x08, 0x00, 0x40, 0x9c, \
+			0x00)
+#define SCC_SRC_DISABLE \
+	SCC_SRC_ENABLE, \
+	ASE_SRC_DISABLE
+
+static void state_start_disable(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_STREAMING:
+		id = bt_bap_stream_disable(stream, true, bap_disable,
+						data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_disable_streaming = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+	.state_func = state_start_disable
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 040101
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0401010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 0101010400403020100
+ */
+#define SRC_START \
+	IOV_DATA(0x52, 0x22, 0x00, 0x04, 0x01, 0x03), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x04, 0x01, 0x03, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x04, 0x00, 0x00, 0x04, 0x03, 0x02, \
+			0x01, 0x00)
+
+#define SCC_SRC_DISABLE_STREAMING \
+	SCC_SRC_ENABLE, \
+	SRC_START, \
+	ASE_SRC_DISABLE
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can initiate a Disable operation for an ASE
+ * in the Enabling or Streaming state.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x05 (Disable) and the specified parameters.
+ */
+static void test_scc_disable(void)
+{
+	define_test("BAP/UCL/SCC/BV-103-C [UCL SNK Disable in Enabling State]",
+			test_setup, test_client, &cfg_src_disable,
+			SCC_SRC_DISABLE);
+	define_test("BAP/UCL/SCC/BV-104-C [UCL SRC Disable in Enabling or "
+			"Streaming state]",
+			test_setup, test_client, &cfg_snk_disable,
+			SCC_SNK_DISABLE);
+	define_test("BAP/UCL/SCC/BV-105-C [UCL SNK Disable in Streaming State]",
+			test_setup, test_client, &cfg_src_disable_streaming,
+			SCC_SRC_DISABLE_STREAMING);
+}
+
+static void bap_release(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	if (code)
+		tester_test_failed();
+}
+
+static void state_cc_release(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		id = bt_bap_stream_release(stream, bap_release, data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_cc_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_UCAST,
+	.src = true,
+	.state_func = state_cc_release,
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 080103
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0801030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 0300
+ */
+#define ASE_SRC_RELEASE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x08, 0x01, 0x03), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x00)
+
+#define SCC_SRC_CC_RELEASE \
+	SCC_SRC_16_2, \
+	ASE_SRC_RELEASE
+
+static struct test_config cfg_snk_cc_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_UCAST,
+	.snk = true,
+	.state_func = state_cc_release,
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 080101
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0801010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 0300
+ */
+#define ASE_SNK_RELEASE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x08, 0x01, 0x01), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x03, 0x00)
+
+#define SCC_SNK_CC_RELEASE \
+	SCC_SNK_16_2, \
+	ASE_SNK_RELEASE
+
+static void state_qos_release(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_QOS:
+		id = bt_bap_stream_release(stream, bap_release, data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_qos_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+	.state_func = state_qos_release,
+};
+
+#define SCC_SRC_QOS_RELEASE \
+	SCC_SRC_16_2_1, \
+	ASE_SRC_RELEASE
+
+static struct test_config cfg_snk_qos_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_QOS,
+	.state_func = state_qos_release,
+};
+
+#define SCC_SNK_QOS_RELEASE \
+	SCC_SNK_16_2_1, \
+	ASE_SNK_RELEASE
+
+static void state_enable_release(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_ENABLING:
+		id = bt_bap_stream_release(stream, bap_release, data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_enable_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING,
+	.state_func = state_enable_release,
+};
+
+#define SCC_SRC_ENABLE_RELEASE \
+	SCC_SRC_ENABLE, \
+	ASE_SRC_RELEASE
+
+static struct test_config cfg_snk_enable_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING,
+	.state_func = state_enable_release,
+};
+
+#define SCC_SNK_ENABLE_RELEASE \
+	SCC_SNK_ENABLE, \
+	ASE_SNK_RELEASE
+
+static void state_start_release(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_STREAMING:
+		id = bt_bap_stream_release(stream, bap_release, data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_start_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+	.state_func = state_start_release,
+};
+
+#define SCC_SRC_START_RELEASE \
+	SCC_SRC_ENABLE, \
+	SRC_START, \
+	ASE_SRC_RELEASE
+
+static void state_disable_release(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_DISABLING:
+		id = bt_bap_stream_release(stream, bap_release, data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_disable_release = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_DISABLING,
+	.state_func = state_disable_release,
+};
+
+#define SCC_SRC_DISABLE_RELEASE \
+	SCC_SRC_DISABLE, \
+	ASE_SRC_RELEASE
+
+/* Test Purpose:
+ * Verify that a Unicast Client IUT can release an ASE by initiating a Release
+ * operation.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x08 (Release) and the specified parameters.
+ */
+static void test_scc_release(void)
+{
+	define_test("BAP/UCL/SCC/BV-106-C [UCL SNK Release in Codec Configured"
+			" state]",
+			test_setup, test_client, &cfg_src_cc_release,
+			SCC_SRC_CC_RELEASE);
+	define_test("BAP/UCL/SCC/BV-107-C [UCL SRC Release in Codec Configured"
+			" state]",
+			test_setup, test_client, &cfg_snk_cc_release,
+			SCC_SNK_CC_RELEASE);
+	define_test("BAP/UCL/SCC/BV-108-C [UCL SNK Release in QoS Configured"
+			" state]",
+			test_setup, test_client, &cfg_src_qos_release,
+			SCC_SRC_QOS_RELEASE);
+	define_test("BAP/UCL/SCC/BV-109-C [UCL SRC Release in QoS Configured"
+			" state]",
+			test_setup, test_client, &cfg_snk_qos_release,
+			SCC_SNK_QOS_RELEASE);
+	define_test("BAP/UCL/SCC/BV-110-C [UCL SNK Release in Enabling state]",
+			test_setup, test_client, &cfg_src_enable_release,
+			SCC_SRC_ENABLE_RELEASE);
+	define_test("BAP/UCL/SCC/BV-111-C [UCL SRC Release in Enabling or"
+			" Streaming state]",
+			test_setup, test_client, &cfg_snk_enable_release,
+			SCC_SNK_ENABLE_RELEASE);
+	define_test("BAP/UCL/SCC/BV-112-C [UCL SNK Release in Streaming state]",
+			test_setup, test_client, &cfg_src_start_release,
+			SCC_SRC_START_RELEASE);
+	define_test("BAP/UCL/SCC/BV-113-C [UCL SNK Release in Disabling state]",
+			test_setup, test_client, &cfg_src_disable_release,
+			SCC_SRC_DISABLE_RELEASE);
+}
+
+static void bap_metadata(struct bt_bap_stream *stream,
+					uint8_t code, uint8_t reason,
+					void *user_data)
+{
+	if (code)
+		tester_test_failed();
+}
+
+static void state_enable_metadata(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	struct iovec iov = {};
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_ENABLING:
+		id = bt_bap_stream_metadata(stream, &iov, bap_metadata,
+						data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_snk_metadata = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING,
+	.state_func = state_enable_metadata
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 07010100
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0701010000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x0016
+ *     Data: 01010102010a00204e00409c00204e00409c00_qos
+ */
+#define ASE_SNK_METADATA \
+	IOV_DATA(0x52, 0x22, 0x00, 0x07, 0x01, 0x01, 0x00), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x05, 0x00, 0x00, 0x4c, 0x1d, 0x00, \
+			0x00, 0x02, 0x1a, 0x00, 0x02, 0x08, 0x00, 0x40, 0x9c, \
+			0x00)
+
+#define SCC_SNK_METADATA \
+	SCC_SNK_ENABLE, \
+	ASE_SNK_METADATA
+
+static struct test_config cfg_src_metadata = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_ENABLING,
+	.state_func = state_enable_metadata
+};
+
+/* ATT: Write Command (0x52) len 23
+ *  Handle: 0x0022
+ *    Data: 07010300
+ * ATT: Handle Value Notification (0x1b) len 7
+ *  Handle: 0x0022
+ *    Data: 0701030000
+ * ATT: Handle Value Notification (0x1b) len 37
+ *   Handle: 0x001c
+ *     Data: 030300000403020100
+ */
+#define ASE_SRC_METADATA \
+	IOV_DATA(0x52, 0x22, 0x00, 0x07, 0x01, 0x03, 0x00), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x07, 0x01, 0x03, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x1c, 0x00, 0x03, 0x05, 0x00, 0x00, 0x4c, 0x1d, 0x00, \
+			0x00, 0x02, 0x1a, 0x00, 0x04, 0x08, 0x00, 0x40, 0x9c, \
+			0x00)
+#define SCC_SRC_METADATA \
+	SCC_SRC_ENABLE, \
+	ASE_SRC_METADATA
+
+static void state_start_metadata(struct bt_bap_stream *stream,
+					uint8_t old_state, uint8_t new_state,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	struct iovec iov = {};
+	uint8_t id;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_STREAMING:
+		id = bt_bap_stream_metadata(stream, &iov, bap_metadata,
+						data);
+		g_assert(id);
+		break;
+	}
+}
+
+static struct test_config cfg_src_metadata_streaming = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1,
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+	.state_func = state_start_metadata
+};
+
+#define SCC_SRC_METADATA_STREAMING \
+	SCC_SRC_ENABLE, \
+	SRC_START, \
+	ASE_SRC_METADATA
+
+/* Unicast Client Initiates Update Metadata Operation
+ *
+ * Test Purpose:
+ * Verify that a Unicast Client IUT can update the Metadata of an ASE by
+ * initiating an Update Metadata operation.
+ *
+ * Pass verdict:
+ * The IUT successfully writes to the ASE Control Point characteristic with the
+ * opcode set to 0x07 (Update Metadata) and the specified parameters.
+ */
+static void test_scc_metadata(void)
+{
+	define_test("BAP/UCL/SCC/BV-115-C [UCL SNK Update Metadata in Enabling "
+			"State]",
+			test_setup, test_client, &cfg_src_metadata,
+			SCC_SRC_METADATA);
+	define_test("BAP/UCL/SCC/BV-116-C [UCL SRC Update Metadata in Enabling "
+			"or Streaming state]",
+			test_setup, test_client, &cfg_snk_metadata,
+			SCC_SNK_METADATA);
+	define_test("BAP/UCL/SCC/BV-117-C [UCL SNK Update Metadata in Streaming"
+			" State]",
+			test_setup, test_client, &cfg_src_metadata_streaming,
+			SCC_SRC_METADATA_STREAMING);
+}
+
+#define SNK_ENABLE \
+	IOV_DATA(0x52, 0x22, 0x00, 0x03, 0x01, 0x01, 0x04, 0x03, 0x02, 0x01, \
+			00), \
+	IOV_DATA(0x1b, 0x22, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00), \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x03, 0x00, 0x00, 0x04, 0x03, 0x02, \
+			0x01, 0x00)
+
+#define SNK_START \
+	IOV_NULL, \
+	IOV_DATA(0x1b, 0x16, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x03, 0x02, \
+			0x01, 0x00)
+
+static struct test_config str_snk_ac2_8_1_1 = {
+	.cc = LC3_CONFIG_8_1_AC(1),
+	.qos = LC3_QOS_8_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK(_freq, _ac, _dur, _len) \
+	SCC_SNK_LC3(0x10, 0x02, 0x01, _freq, 0x02, 0x02, _dur, 0x03, 0x04, \
+			_len, _len >> 8, 0x05, 0x03, _ac, 0x00, 0x00, 0x00)
+
+#define STR_SNK_8(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_8KHZ, _ac, _dur, _len)
+
+#define STR_SNK_8_1(_ac) \
+	STR_SNK_8(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_8_1)
+
+#define STR_SNK_QOS(_interval, _frame, _sdu, _rtn, _latency) \
+	QOS_SNK(_interval & 0xff, _interval >> 8 & 0xff, \
+		_interval >> 16 & 0xff, _frame, 0x02, _sdu & 0xff, \
+		_sdu >> 8 & 0xff, _rtn, \
+		_latency, _latency >> 8, 0x40, 0x9c, 0x00)
+
+#define STR_SNK_QOS_1(_sdu, _rtn, _latency) \
+	STR_SNK_QOS(7500u, LC3_QOS_UNFRAMED, _sdu, _rtn, _latency)
+
+#define STR_SNK_8_1_1(_chans) \
+	STR_SNK_8_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_8_1, LC3_QOS_8_1_1_RTN, \
+			LC3_QOS_8_1_1_LATENCY)
+
+#define STR_SNK_AC2_8_1_1 \
+	STR_SNK_8_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_8_1_1 = {
+	.cc = LC3_CONFIG_8_1_AC(2),
+	.qos = LC3_QOS_8_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_8_1_1 \
+	STR_SNK_8_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_8_2_1 = {
+	.cc = LC3_CONFIG_8_2_AC(1),
+	.qos = LC3_QOS_8_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_8_2(_ac) \
+	STR_SNK_8(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_8_2)
+
+#define STR_SNK_QOS_2(_sdu, _rtn, _latency) \
+	STR_SNK_QOS(10000u, LC3_QOS_UNFRAMED, _sdu, _rtn, _latency)
+
+#define STR_SNK_8_2_1(_chans) \
+	STR_SNK_8_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_8_2, LC3_QOS_8_2_1_RTN, \
+			LC3_QOS_8_2_1_LATENCY)
+
+#define STR_SNK_AC2_8_2_1 \
+	STR_SNK_8_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_8_2_1 = {
+	.cc = LC3_CONFIG_8_2_AC(2),
+	.qos = LC3_QOS_8_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_8_2_1 \
+	STR_SNK_8_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_8_1_2 = {
+	.cc = LC3_CONFIG_8_1_AC(1),
+	.qos = LC3_QOS_8_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_8_1_2(_chans) \
+	STR_SNK_8_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_8_1, LC3_QOS_8_1_2_RTN, \
+			LC3_QOS_8_1_2_LATENCY)
+
+#define STR_SNK_AC2_8_1_2 \
+	STR_SNK_8_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_8_1_2 = {
+	.cc = LC3_CONFIG_8_1_AC(2),
+	.qos = LC3_QOS_8_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_8_1_2 \
+	STR_SNK_8_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_8_2_2 = {
+	.cc = LC3_CONFIG_8_2_AC(1),
+	.qos = LC3_QOS_8_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_8_2_2(_chans) \
+	STR_SNK_8_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_8_2, LC3_QOS_8_2_2_RTN, \
+			LC3_QOS_8_2_2_LATENCY)
+
+#define STR_SNK_AC2_8_2_2 \
+	STR_SNK_8_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_8_2_2 = {
+	.cc = LC3_CONFIG_8_2_AC(2),
+	.qos = LC3_QOS_8_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_8_2_2 \
+	STR_SNK_8_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_16_1_1 = {
+	.cc = LC3_CONFIG_16_1_AC(1),
+	.qos = LC3_QOS_16_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_16(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_16KHZ, _ac, _dur, _len)
+
+#define STR_SNK_16_1(_ac) \
+	STR_SNK_16(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_16_1)
+
+#define STR_SNK_16_1_1(_chans) \
+	STR_SNK_16_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_16_1, LC3_QOS_16_1_1_RTN, \
+			LC3_QOS_16_1_1_LATENCY)
+
+#define STR_SNK_AC2_16_1_1 \
+	STR_SNK_16_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_16_1_1 = {
+	.cc = LC3_CONFIG_16_1_AC(2),
+	.qos = LC3_QOS_16_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_16_1_1 \
+	STR_SNK_16_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_16_2_1 = {
+	.cc = LC3_CONFIG_16_2_AC(1),
+	.qos = LC3_QOS_16_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_16_2(_ac) \
+	STR_SNK_16(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_16_2)
+
+#define STR_SNK_16_2_1(_chans) \
+	STR_SNK_16_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_16_2, LC3_QOS_16_2_1_RTN, \
+			LC3_QOS_16_2_1_LATENCY)
+
+#define STR_SNK_AC2_16_2_1 \
+	STR_SNK_16_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_16_2_1 = {
+	.cc = LC3_CONFIG_16_2_AC(2),
+	.qos = LC3_QOS_16_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_16_2_1 \
+	STR_SNK_16_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_16_1_2 = {
+	.cc = LC3_CONFIG_16_1_AC(1),
+	.qos = LC3_QOS_16_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_16(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_16KHZ, _ac, _dur, _len)
+
+#define STR_SNK_16_1_2(_chans) \
+	STR_SNK_16_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_16_1, LC3_QOS_16_1_2_RTN, \
+			LC3_QOS_16_1_2_LATENCY)
+
+#define STR_SNK_AC2_16_1_2 \
+	STR_SNK_16_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_16_1_2 = {
+	.cc = LC3_CONFIG_16_1_AC(2),
+	.qos = LC3_QOS_16_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_16_1_2 \
+	STR_SNK_16_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_16_2_2 = {
+	.cc = LC3_CONFIG_16_2_AC(1),
+	.qos = LC3_QOS_16_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_16_2(_ac) \
+	STR_SNK_16(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_16_2)
+
+#define STR_SNK_16_2_2(_chans) \
+	STR_SNK_16_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_16_2, LC3_QOS_16_2_2_RTN, \
+			LC3_QOS_16_2_2_LATENCY)
+
+#define STR_SNK_AC2_16_2_2 \
+	STR_SNK_16_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_16_2_2 = {
+	.cc = LC3_CONFIG_16_2_AC(2),
+	.qos = LC3_QOS_16_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_16_2_2 \
+	STR_SNK_16_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_24_1_1 = {
+	.cc = LC3_CONFIG_24_1_AC(1),
+	.qos = LC3_QOS_24_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_24(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_24KHZ, _ac, _dur, _len)
+
+#define STR_SNK_24_1(_ac) \
+	STR_SNK_24(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_24_1)
+
+#define STR_SNK_24_1_1(_chans) \
+	STR_SNK_24_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_24_1, LC3_QOS_24_1_1_RTN, \
+			LC3_QOS_24_1_1_LATENCY)
+
+#define STR_SNK_AC2_24_1_1 \
+	STR_SNK_24_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_24_1_1 = {
+	.cc = LC3_CONFIG_24_1_AC(2),
+	.qos = LC3_QOS_24_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_24_1_1 \
+	STR_SNK_24_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_24_2_1 = {
+	.cc = LC3_CONFIG_24_2_AC(1),
+	.qos = LC3_QOS_24_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_24_2(_ac) \
+	STR_SNK_24(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_24_2)
+
+#define STR_SNK_24_2_1(_chans) \
+	STR_SNK_24_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_24_2, LC3_QOS_24_2_1_RTN, \
+			LC3_QOS_24_2_1_LATENCY)
+
+#define STR_SNK_AC2_24_2_1 \
+	STR_SNK_24_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_24_2_1 = {
+	.cc = LC3_CONFIG_24_2_AC(2),
+	.qos = LC3_QOS_24_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_24_2_1 \
+	STR_SNK_24_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_24_1_2 = {
+	.cc = LC3_CONFIG_24_1_AC(1),
+	.qos = LC3_QOS_24_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_24_1_2(_chans) \
+	STR_SNK_24_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_24_1, LC3_QOS_24_1_2_RTN, \
+			LC3_QOS_24_1_2_LATENCY)
+
+#define STR_SNK_AC2_24_1_2 \
+	STR_SNK_24_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_24_1_2 = {
+	.cc = LC3_CONFIG_24_1_AC(2),
+	.qos = LC3_QOS_24_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_24_1_2 \
+	STR_SNK_24_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_24_2_2 = {
+	.cc = LC3_CONFIG_24_2_AC(1),
+	.qos = LC3_QOS_24_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_24_2_2(_chans) \
+	STR_SNK_24_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_24_2, LC3_QOS_24_2_2_RTN, \
+			LC3_QOS_24_2_2_LATENCY)
+
+#define STR_SNK_AC2_24_2_2 \
+	STR_SNK_24_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_24_2_2 = {
+	.cc = LC3_CONFIG_24_2_AC(2),
+	.qos = LC3_QOS_24_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_24_2_2 \
+	STR_SNK_24_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_32_1_1 = {
+	.cc = LC3_CONFIG_32_1_AC(1),
+	.qos = LC3_QOS_32_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_32(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_32KHZ, _ac, _dur, _len)
+
+#define STR_SNK_32_1(_ac) \
+	STR_SNK_32(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_32_1)
+
+#define STR_SNK_32_1_1(_chans) \
+	STR_SNK_32_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_32_1, LC3_QOS_32_1_1_RTN, \
+			LC3_QOS_32_1_1_LATENCY)
+
+#define STR_SNK_AC2_32_1_1 \
+	STR_SNK_32_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_32_1_1 = {
+	.cc = LC3_CONFIG_32_1_AC(2),
+	.qos = LC3_QOS_32_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_32_1_1 \
+	STR_SNK_32_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_32_2_1 = {
+	.cc = LC3_CONFIG_32_2_AC(1),
+	.qos = LC3_QOS_32_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_32_2(_ac) \
+	STR_SNK_32(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_32_2)
+
+#define STR_SNK_32_2_1(_chans) \
+	STR_SNK_32_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_32_2, LC3_QOS_32_2_1_RTN, \
+			LC3_QOS_32_2_1_LATENCY)
+
+#define STR_SNK_AC2_32_2_1 \
+	STR_SNK_32_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_32_2_1 = {
+	.cc = LC3_CONFIG_32_2_AC(2),
+	.qos = LC3_QOS_32_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_32_2_1 \
+	STR_SNK_32_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_32_1_2 = {
+	.cc = LC3_CONFIG_32_1_AC(1),
+	.qos = LC3_QOS_32_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_32_1_2(_chans) \
+	STR_SNK_32_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_32_1, LC3_QOS_32_1_2_RTN, \
+			LC3_QOS_32_1_2_LATENCY)
+
+#define STR_SNK_AC2_32_1_2 \
+	STR_SNK_32_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_32_1_2 = {
+	.cc = LC3_CONFIG_32_1_AC(2),
+	.qos = LC3_QOS_32_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_32_1_2 \
+	STR_SNK_32_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_32_2_2 = {
+	.cc = LC3_CONFIG_32_2_AC(1),
+	.qos = LC3_QOS_32_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_32_2_2(_chans) \
+	STR_SNK_32_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_32_2, LC3_QOS_32_2_2_RTN, \
+			LC3_QOS_32_2_2_LATENCY)
+
+#define STR_SNK_AC2_32_2_2 \
+	STR_SNK_32_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_32_2_2 = {
+	.cc = LC3_CONFIG_32_2_AC(2),
+	.qos = LC3_QOS_32_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_32_2_2 \
+	STR_SNK_32_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_44_1_1 = {
+	.cc = LC3_CONFIG_44_1_AC(1),
+	.qos = LC3_QOS_44_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_44(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_44KHZ, _ac, _dur, _len)
+
+#define STR_SNK_44_1(_ac) \
+	STR_SNK_44(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_44_1)
+
+#define STR_SNK_QOS_44_1(_sdu, _rtn, _latency) \
+	STR_SNK_QOS(LC3_QOS_44_1_INTERVAL, LC3_QOS_FRAMED, _sdu, _rtn, \
+			_latency)
+
+#define STR_SNK_44_1_1(_chans) \
+	STR_SNK_44_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_44_1(_chans * LC3_CONFIG_FRAME_LEN_44_1, \
+			LC3_QOS_44_1_1_RTN, LC3_QOS_44_1_1_LATENCY)
+
+#define STR_SNK_AC2_44_1_1 \
+	STR_SNK_44_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_44_1_1 = {
+	.cc = LC3_CONFIG_44_1_AC(2),
+	.qos = LC3_QOS_44_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_44_1_1 \
+	STR_SNK_44_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_44_2_1 = {
+	.cc = LC3_CONFIG_44_2_AC(1),
+	.qos = LC3_QOS_44_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_44_2(_ac) \
+	STR_SNK_44(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_44_2)
+
+#define STR_SNK_QOS_44_2(_sdu, _rtn, _latency) \
+	STR_SNK_QOS(LC3_QOS_44_2_INTERVAL, LC3_QOS_FRAMED, _sdu, _rtn, \
+			_latency)
+
+#define STR_SNK_44_2_1(_chans) \
+	STR_SNK_44_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_44_2(_chans * LC3_CONFIG_FRAME_LEN_44_2, \
+			LC3_QOS_44_2_1_RTN, LC3_QOS_44_2_1_LATENCY)
+
+#define STR_SNK_AC2_44_2_1 \
+	STR_SNK_44_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_44_2_1 = {
+	.cc = LC3_CONFIG_44_2_AC(2),
+	.qos = LC3_QOS_44_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_44_2_1 \
+	STR_SNK_44_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_44_1_2 = {
+	.cc = LC3_CONFIG_44_1_AC(1),
+	.qos = LC3_QOS_44_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_44_1_2(_chans) \
+	STR_SNK_44_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_44_1(_chans * LC3_CONFIG_FRAME_LEN_44_1, \
+			LC3_QOS_44_1_2_RTN, LC3_QOS_44_1_2_LATENCY)
+
+#define STR_SNK_AC2_44_1_2 \
+	STR_SNK_44_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_44_1_2 = {
+	.cc = LC3_CONFIG_44_1_AC(2),
+	.qos = LC3_QOS_44_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_44_1_2 \
+	STR_SNK_44_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_44_2_2 = {
+	.cc = LC3_CONFIG_44_2_AC(1),
+	.qos = LC3_QOS_44_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_44_2_2(_chans) \
+	STR_SNK_44_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_44_2(_chans * LC3_CONFIG_FRAME_LEN_44_2, \
+			LC3_QOS_44_2_2_RTN, LC3_QOS_44_2_2_LATENCY)
+
+#define STR_SNK_AC2_44_2_2 \
+	STR_SNK_44_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_44_2_2 = {
+	.cc = LC3_CONFIG_44_2_AC(2),
+	.qos = LC3_QOS_44_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_44_2_2 \
+	STR_SNK_44_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_1_1 = {
+	.cc = LC3_CONFIG_48_1_AC(1),
+	.qos = LC3_QOS_48_1_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48(_ac, _dur, _len) \
+	STR_SNK(LC3_CONFIG_FREQ_48KHZ, _ac, _dur, _len)
+
+#define STR_SNK_48_1(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_1)
+
+#define STR_SNK_48_1_1(_chans) \
+	STR_SNK_48_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_1, LC3_QOS_48_1_1_RTN, \
+			LC3_QOS_48_1_1_LATENCY)
+
+#define STR_SNK_AC2_48_1_1 \
+	STR_SNK_48_1_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_1_1 = {
+	.cc = LC3_CONFIG_48_1_AC(2),
+	.qos = LC3_QOS_48_1_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_1_1 \
+	STR_SNK_48_1_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_2_1 = {
+	.cc = LC3_CONFIG_48_2_AC(1),
+	.qos = LC3_QOS_48_2_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_2(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_2)
+
+#define STR_SNK_48_2_1(_chans) \
+	STR_SNK_48_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_2, LC3_QOS_48_2_1_RTN, \
+			LC3_QOS_48_2_1_LATENCY)
+
+#define STR_SNK_AC2_48_2_1 \
+	STR_SNK_48_2_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_2_1 = {
+	.cc = LC3_CONFIG_48_2_AC(2),
+	.qos = LC3_QOS_48_2_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_2_1 \
+	STR_SNK_48_2_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_3_1 = {
+	.cc = LC3_CONFIG_48_3_AC(1),
+	.qos = LC3_QOS_48_3_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_3(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_3)
+
+#define STR_SNK_48_3_1(_chans) \
+	STR_SNK_48_3((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_3, LC3_QOS_48_3_1_RTN, \
+			LC3_QOS_48_3_1_LATENCY)
+
+#define STR_SNK_AC2_48_3_1 \
+	STR_SNK_48_3_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_3_1 = {
+	.cc = LC3_CONFIG_48_3_AC(2),
+	.qos = LC3_QOS_48_3_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_3_1 \
+	STR_SNK_48_3_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_4_1 = {
+	.cc = LC3_CONFIG_48_4_AC(1),
+	.qos = LC3_QOS_48_4_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_4(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_4)
+
+#define STR_SNK_48_4_1(_chans) \
+	STR_SNK_48_4((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_4, LC3_QOS_48_4_1_RTN, \
+			LC3_QOS_48_4_1_LATENCY)
+
+#define STR_SNK_AC2_48_4_1 \
+	STR_SNK_48_4_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_4_1 = {
+	.cc = LC3_CONFIG_48_4_AC(2),
+	.qos = LC3_QOS_48_4_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_4_1 \
+	STR_SNK_48_4_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_5_1 = {
+	.cc = LC3_CONFIG_48_5_AC(1),
+	.qos = LC3_QOS_48_5_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_5(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_5)
+
+#define STR_SNK_48_5_1(_chans) \
+	STR_SNK_48_5((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_5, LC3_QOS_48_5_1_RTN, \
+			LC3_QOS_48_5_1_LATENCY)
+
+#define STR_SNK_AC2_48_5_1 \
+	STR_SNK_48_5_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_5_1 = {
+	.cc = LC3_CONFIG_48_5_AC(2),
+	.qos = LC3_QOS_48_5_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_5_1 \
+	STR_SNK_48_5_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_6_1 = {
+	.cc = LC3_CONFIG_48_6_AC(1),
+	.qos = LC3_QOS_48_6_1_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_6(_ac) \
+	STR_SNK_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_6)
+
+#define STR_SNK_48_6_1(_chans) \
+	STR_SNK_48_6((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_6, LC3_QOS_48_6_1_RTN, \
+			LC3_QOS_48_6_1_LATENCY)
+
+#define STR_SNK_AC2_48_6_1 \
+	STR_SNK_48_6_1(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_6_1 = {
+	.cc = LC3_CONFIG_48_6_AC(2),
+	.qos = LC3_QOS_48_6_1_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_6_1 \
+	STR_SNK_48_6_1(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_1_2 = {
+	.cc = LC3_CONFIG_48_1_AC(1),
+	.qos = LC3_QOS_48_1_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_1_2(_chans) \
+	STR_SNK_48_1((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_1, LC3_QOS_48_1_2_RTN, \
+			LC3_QOS_48_1_2_LATENCY)
+
+#define STR_SNK_AC2_48_1_2 \
+	STR_SNK_48_1_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_1_2 = {
+	.cc = LC3_CONFIG_48_1_AC(2),
+	.qos = LC3_QOS_48_1_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_1_2 \
+	STR_SNK_48_1_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_2_2 = {
+	.cc = LC3_CONFIG_48_2_AC(1),
+	.qos = LC3_QOS_48_2_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_2_2(_chans) \
+	STR_SNK_48_2((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_2, LC3_QOS_48_2_2_RTN, \
+			LC3_QOS_48_2_2_LATENCY)
+
+#define STR_SNK_AC2_48_2_2 \
+	STR_SNK_48_2_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_2_2 = {
+	.cc = LC3_CONFIG_48_2_AC(2),
+	.qos = LC3_QOS_48_2_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_2_2 \
+	STR_SNK_48_2_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_3_2 = {
+	.cc = LC3_CONFIG_48_3_AC(1),
+	.qos = LC3_QOS_48_3_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_3_2(_chans) \
+	STR_SNK_48_3((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_3, LC3_QOS_48_3_2_RTN, \
+			LC3_QOS_48_3_2_LATENCY)
+
+#define STR_SNK_AC2_48_3_2 \
+	STR_SNK_48_3_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_3_2 = {
+	.cc = LC3_CONFIG_48_3_AC(2),
+	.qos = LC3_QOS_48_3_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_3_2 \
+	STR_SNK_48_3_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_4_2 = {
+	.cc = LC3_CONFIG_48_4_AC(1),
+	.qos = LC3_QOS_48_4_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_4_2(_chans) \
+	STR_SNK_48_4((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_4, LC3_QOS_48_4_2_RTN, \
+			LC3_QOS_48_4_2_LATENCY)
+
+#define STR_SNK_AC2_48_4_2 \
+	STR_SNK_48_4_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_4_2 = {
+	.cc = LC3_CONFIG_48_4_AC(2),
+	.qos = LC3_QOS_48_4_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_4_2 \
+	STR_SNK_48_4_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_5_2 = {
+	.cc = LC3_CONFIG_48_5_AC(1),
+	.qos = LC3_QOS_48_5_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_5_2(_chans) \
+	STR_SNK_48_5((BIT(_chans) - 1)), \
+	STR_SNK_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_5, LC3_QOS_48_5_2_RTN, \
+			LC3_QOS_48_5_2_LATENCY)
+
+#define STR_SNK_AC2_48_5_2 \
+	STR_SNK_48_5_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_5_2 = {
+	.cc = LC3_CONFIG_48_5_AC(2),
+	.qos = LC3_QOS_48_5_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_5_2 \
+	STR_SNK_48_5_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac2_48_6_2 = {
+	.cc = LC3_CONFIG_48_6_AC(1),
+	.qos = LC3_QOS_48_6_2_AC(1),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_48_6_2(_chans) \
+	STR_SNK_48_6((BIT(_chans) - 1)), \
+	STR_SNK_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_6, LC3_QOS_48_6_2_RTN, \
+			LC3_QOS_48_6_2_LATENCY)
+
+#define STR_SNK_AC2_48_6_2 \
+	STR_SNK_48_6_2(1), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_snk_ac10_48_6_2 = {
+	.cc = LC3_CONFIG_48_6_AC(2),
+	.qos = LC3_QOS_48_6_2_AC(2),
+	.snk = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SNK_AC10_48_6_2 \
+	STR_SNK_48_6_2(2), \
+	SNK_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac1_8_1_1 = {
+	.cc = LC3_CONFIG_8_1_AC(1),
+	.qos = LC3_QOS_8_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC(_freq, _ac, _dur, _len) \
+	SCC_SRC_LC3(0x10, 0x02, 0x01, _freq, 0x02, 0x02, _dur, 0x03, 0x04, \
+			_len, _len >> 8, 0x05, 0x03, _ac, 0x00, 0x00, 0x00)
+
+#define STR_SRC_8(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_8KHZ, _ac, _dur, _len)
+
+#define STR_SRC_8_1(_ac) \
+	STR_SRC_8(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_8_1)
+
+#define STR_SRC_QOS(_interval, _frame, _sdu, _rtn, _latency) \
+	QOS_SRC(_interval & 0xff, _interval >> 8 & 0xff, \
+		_interval >> 16 & 0xff, _frame, 0x02, _sdu & 0xff, \
+		_sdu >> 8 & 0xff, _rtn, \
+		_latency, _latency >> 8, 0x40, 0x9c, 0x00)
+
+#define STR_SRC_QOS_1(_sdu, _rtn, _latency) \
+	STR_SRC_QOS(7500u, LC3_QOS_UNFRAMED, _sdu, _rtn, _latency)
+
+#define STR_SRC_8_1_1(_chans) \
+	STR_SRC_8_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_8_1, LC3_QOS_8_1_1_RTN, \
+			LC3_QOS_8_1_1_LATENCY)
+
+#define STR_SRC_AC1_8_1_1 \
+	STR_SRC_8_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_8_1_1 = {
+	.cc = LC3_CONFIG_8_1_AC(2),
+	.qos = LC3_QOS_8_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_8_1_1 \
+	STR_SRC_8_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_8_2_1 = {
+	.cc = LC3_CONFIG_8_2_AC(1),
+	.qos = LC3_QOS_8_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_8_2(_ac) \
+	STR_SRC_8(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_8_2)
+
+#define STR_SRC_QOS_2(_sdu, _rtn, _latency) \
+	STR_SRC_QOS(10000u, LC3_QOS_UNFRAMED, _sdu, _rtn, _latency)
+
+#define STR_SRC_8_2_1(_chans) \
+	STR_SRC_8_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_8_2, LC3_QOS_8_2_1_RTN, \
+			LC3_QOS_8_2_1_LATENCY)
+
+#define STR_SRC_AC1_8_2_1 \
+	STR_SRC_8_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_8_2_1 = {
+	.cc = LC3_CONFIG_8_2_AC(2),
+	.qos = LC3_QOS_8_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_8_2_1 \
+	STR_SRC_8_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_16_1_1 = {
+	.cc = LC3_CONFIG_16_1_AC(1),
+	.qos = LC3_QOS_16_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_16(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_16KHZ, _ac, _dur, _len)
+
+#define STR_SRC_16_1(_ac) \
+	STR_SRC_16(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_16_1)
+
+#define STR_SRC_16_1_1(_chans) \
+	STR_SRC_16_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_16_1, LC3_QOS_16_1_1_RTN, \
+			LC3_QOS_16_1_1_LATENCY)
+
+#define STR_SRC_AC1_16_1_1 \
+	STR_SRC_16_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_16_1_1 = {
+	.cc = LC3_CONFIG_16_1_AC(2),
+	.qos = LC3_QOS_16_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_16_1_1 \
+	STR_SRC_16_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_16_2_1 = {
+	.cc = LC3_CONFIG_16_2_AC(1),
+	.qos = LC3_QOS_16_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_16_2(_ac) \
+	STR_SRC_16(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_16_2)
+
+#define STR_SRC_16_2_1(_chans) \
+	STR_SRC_16_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_16_2, LC3_QOS_16_2_1_RTN, \
+			LC3_QOS_16_2_1_LATENCY)
+
+#define STR_SRC_AC1_16_2_1 \
+	STR_SRC_16_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_16_2_1 = {
+	.cc = LC3_CONFIG_16_2_AC(2),
+	.qos = LC3_QOS_16_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_16_2_1 \
+	STR_SRC_16_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_24_1_1 = {
+	.cc = LC3_CONFIG_24_1_AC(1),
+	.qos = LC3_QOS_24_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_24(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_24KHZ, _ac, _dur, _len)
+
+#define STR_SRC_24_1(_ac) \
+	STR_SRC_24(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_24_1)
+
+#define STR_SRC_24_1_1(_chans) \
+	STR_SRC_24_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_24_1, LC3_QOS_24_1_1_RTN, \
+			LC3_QOS_24_1_1_LATENCY)
+
+#define STR_SRC_AC1_24_1_1 \
+	STR_SRC_24_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_24_1_1 = {
+	.cc = LC3_CONFIG_24_1_AC(2),
+	.qos = LC3_QOS_24_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_24_1_1 \
+	STR_SRC_24_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_24_2_1 = {
+	.cc = LC3_CONFIG_24_2_AC(1),
+	.qos = LC3_QOS_24_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_24_2(_ac) \
+	STR_SRC_24(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_24_2)
+
+#define STR_SRC_24_2_1(_chans) \
+	STR_SRC_24_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_24_2, LC3_QOS_24_2_1_RTN, \
+			LC3_QOS_24_2_1_LATENCY)
+
+#define STR_SRC_AC1_24_2_1 \
+	STR_SRC_24_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_24_2_1 = {
+	.cc = LC3_CONFIG_24_2_AC(2),
+	.qos = LC3_QOS_24_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_24_2_1 \
+	STR_SRC_24_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_32_1_1 = {
+	.cc = LC3_CONFIG_32_1_AC(1),
+	.qos = LC3_QOS_32_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_32(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_32KHZ, _ac, _dur, _len)
+
+#define STR_SRC_32_1(_ac) \
+	STR_SRC_32(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_32_1)
+
+#define STR_SRC_32_1_1(_chans) \
+	STR_SRC_32_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_32_1, LC3_QOS_32_1_1_RTN, \
+			LC3_QOS_32_1_1_LATENCY)
+
+#define STR_SRC_AC1_32_1_1 \
+	STR_SRC_32_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_32_1_1 = {
+	.cc = LC3_CONFIG_32_1_AC(2),
+	.qos = LC3_QOS_32_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_32_1_1 \
+	STR_SRC_32_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_32_2_1 = {
+	.cc = LC3_CONFIG_32_2_AC(1),
+	.qos = LC3_QOS_32_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_32_2(_ac) \
+	STR_SRC_32(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_32_2)
+
+#define STR_SRC_32_2_1(_chans) \
+	STR_SRC_32_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_32_2, LC3_QOS_32_2_1_RTN, \
+			LC3_QOS_32_2_1_LATENCY)
+
+#define STR_SRC_AC1_32_2_1 \
+	STR_SRC_32_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_32_2_1 = {
+	.cc = LC3_CONFIG_32_2_AC(2),
+	.qos = LC3_QOS_32_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_32_2_1 \
+	STR_SRC_32_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_44_1_1 = {
+	.cc = LC3_CONFIG_44_1_AC(1),
+	.qos = LC3_QOS_44_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_44(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_44KHZ, _ac, _dur, _len)
+
+#define STR_SRC_44_1(_ac) \
+	STR_SRC_44(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_44_1)
+
+#define STR_SRC_QOS_44_1(_sdu, _rtn, _latency) \
+	STR_SRC_QOS(LC3_QOS_44_1_INTERVAL, LC3_QOS_FRAMED, _sdu, _rtn, \
+			_latency)
+
+#define STR_SRC_44_1_1(_chans) \
+	STR_SRC_44_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_44_1(_chans * LC3_CONFIG_FRAME_LEN_44_1, \
+			LC3_QOS_44_1_1_RTN, LC3_QOS_44_1_1_LATENCY)
+
+#define STR_SRC_AC1_44_1_1 \
+	STR_SRC_44_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_44_1_1 = {
+	.cc = LC3_CONFIG_44_1_AC(2),
+	.qos = LC3_QOS_44_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_44_1_1 \
+	STR_SRC_44_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_44_2_1 = {
+	.cc = LC3_CONFIG_44_2_AC(1),
+	.qos = LC3_QOS_44_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_44_2(_ac) \
+	STR_SRC_44(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_44_2)
+
+#define STR_SRC_QOS_44_2(_sdu, _rtn, _latency) \
+	STR_SRC_QOS(LC3_QOS_44_2_INTERVAL, LC3_QOS_FRAMED, _sdu, _rtn, \
+			_latency)
+
+#define STR_SRC_44_2_1(_chans) \
+	STR_SRC_44_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_44_2(_chans * LC3_CONFIG_FRAME_LEN_44_2, \
+			LC3_QOS_44_2_1_RTN, LC3_QOS_44_2_1_LATENCY)
+
+#define STR_SRC_AC1_44_2_1 \
+	STR_SRC_44_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_44_2_1 = {
+	.cc = LC3_CONFIG_44_2_AC(2),
+	.qos = LC3_QOS_44_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_44_2_1 \
+	STR_SRC_44_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_1_1 = {
+	.cc = LC3_CONFIG_48_1_AC(1),
+	.qos = LC3_QOS_48_1_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48(_ac, _dur, _len) \
+	STR_SRC(LC3_CONFIG_FREQ_48KHZ, _ac, _dur, _len)
+
+#define STR_SRC_48_1(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_1)
+
+#define STR_SRC_48_1_1(_chans) \
+	STR_SRC_48_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_1, LC3_QOS_48_1_1_RTN, \
+			LC3_QOS_48_1_1_LATENCY)
+
+#define STR_SRC_AC1_48_1_1 \
+	STR_SRC_48_1_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_1_1 = {
+	.cc = LC3_CONFIG_48_1_AC(2),
+	.qos = LC3_QOS_48_1_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_1_1 \
+	STR_SRC_48_1_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_2_1 = {
+	.cc = LC3_CONFIG_48_2_AC(1),
+	.qos = LC3_QOS_48_2_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_2(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_2)
+
+#define STR_SRC_48_2_1(_chans) \
+	STR_SRC_48_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_2, LC3_QOS_48_2_1_RTN, \
+			LC3_QOS_48_2_1_LATENCY)
+
+#define STR_SRC_AC1_48_2_1 \
+	STR_SRC_48_2_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_2_1 = {
+	.cc = LC3_CONFIG_48_2_AC(2),
+	.qos = LC3_QOS_48_2_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_2_1 \
+	STR_SRC_48_2_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_3_1 = {
+	.cc = LC3_CONFIG_48_3_AC(1),
+	.qos = LC3_QOS_48_3_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_3(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_3)
+
+#define STR_SRC_48_3_1(_chans) \
+	STR_SRC_48_3((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_3, LC3_QOS_48_3_1_RTN, \
+			LC3_QOS_48_3_1_LATENCY)
+
+#define STR_SRC_AC1_48_3_1 \
+	STR_SRC_48_3_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_3_1 = {
+	.cc = LC3_CONFIG_48_3_AC(2),
+	.qos = LC3_QOS_48_3_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_3_1 \
+	STR_SRC_48_3_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_4_1 = {
+	.cc = LC3_CONFIG_48_4_AC(1),
+	.qos = LC3_QOS_48_4_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_4(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_4)
+
+#define STR_SRC_48_4_1(_chans) \
+	STR_SRC_48_4((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_4, LC3_QOS_48_4_1_RTN, \
+			LC3_QOS_48_4_1_LATENCY)
+
+#define STR_SRC_AC1_48_4_1 \
+	STR_SRC_48_4_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_4_1 = {
+	.cc = LC3_CONFIG_48_4_AC(2),
+	.qos = LC3_QOS_48_4_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_4_1 \
+	STR_SRC_48_4_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_5_1 = {
+	.cc = LC3_CONFIG_48_5_AC(1),
+	.qos = LC3_QOS_48_5_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_5(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_7_5, LC3_CONFIG_FRAME_LEN_48_5)
+
+#define STR_SRC_48_5_1(_chans) \
+	STR_SRC_48_5((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_5, LC3_QOS_48_5_1_RTN, \
+			LC3_QOS_48_5_1_LATENCY)
+
+#define STR_SRC_AC1_48_5_1 \
+	STR_SRC_48_5_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_5_1 = {
+	.cc = LC3_CONFIG_48_5_AC(2),
+	.qos = LC3_QOS_48_5_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_5_1 \
+	STR_SRC_48_5_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_6_1 = {
+	.cc = LC3_CONFIG_48_6_AC(1),
+	.qos = LC3_QOS_48_6_1_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_6(_ac) \
+	STR_SRC_48(_ac, LC3_CONFIG_DURATION_10, LC3_CONFIG_FRAME_LEN_48_6)
+
+#define STR_SRC_48_6_1(_chans) \
+	STR_SRC_48_6((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_6, LC3_QOS_48_6_1_RTN, \
+			LC3_QOS_48_6_1_LATENCY)
+
+#define STR_SRC_AC1_48_6_1 \
+	STR_SRC_48_6_1(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_6_1 = {
+	.cc = LC3_CONFIG_48_6_AC(2),
+	.qos = LC3_QOS_48_6_1_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_6_1 \
+	STR_SRC_48_6_1(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_8_1_2 = {
+	.cc = LC3_CONFIG_8_1_AC(1),
+	.qos = LC3_QOS_8_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_8_1_2(_chans) \
+	STR_SRC_8_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_8_1, LC3_QOS_8_1_2_RTN, \
+			LC3_QOS_8_1_2_LATENCY)
+
+#define STR_SRC_AC1_8_1_2 \
+	STR_SRC_8_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_8_1_2 = {
+	.cc = LC3_CONFIG_8_1_AC(2),
+	.qos = LC3_QOS_8_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_8_1_2 \
+	STR_SRC_8_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_8_2_2 = {
+	.cc = LC3_CONFIG_8_2_AC(1),
+	.qos = LC3_QOS_8_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_8_2_2(_chans) \
+	STR_SRC_8_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_8_2, LC3_QOS_8_2_2_RTN, \
+			LC3_QOS_8_2_2_LATENCY)
+
+#define STR_SRC_AC1_8_2_2 \
+	STR_SRC_8_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_8_2_2 = {
+	.cc = LC3_CONFIG_8_2_AC(2),
+	.qos = LC3_QOS_8_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_8_2_2 \
+	STR_SRC_8_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_16_1_2 = {
+	.cc = LC3_CONFIG_16_1_AC(1),
+	.qos = LC3_QOS_16_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_16_1_2(_chans) \
+	STR_SRC_16_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_16_1, LC3_QOS_16_1_2_RTN, \
+			LC3_QOS_16_1_2_LATENCY)
+
+#define STR_SRC_AC1_16_1_2 \
+	STR_SRC_16_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_16_1_2 = {
+	.cc = LC3_CONFIG_16_1_AC(2),
+	.qos = LC3_QOS_16_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_16_1_2 \
+	STR_SRC_16_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_16_2_2 = {
+	.cc = LC3_CONFIG_16_2_AC(1),
+	.qos = LC3_QOS_16_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_16_2_2(_chans) \
+	STR_SRC_16_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_16_2, LC3_QOS_16_2_2_RTN, \
+			LC3_QOS_16_2_2_LATENCY)
+
+#define STR_SRC_AC1_16_2_2 \
+	STR_SRC_16_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_16_2_2 = {
+	.cc = LC3_CONFIG_16_2_AC(2),
+	.qos = LC3_QOS_16_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_16_2_2 \
+	STR_SRC_16_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_24_1_2 = {
+	.cc = LC3_CONFIG_24_1_AC(1),
+	.qos = LC3_QOS_24_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_24_1_2(_chans) \
+	STR_SRC_24_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_24_1, LC3_QOS_24_1_2_RTN, \
+			LC3_QOS_24_1_2_LATENCY)
+
+#define STR_SRC_AC1_24_1_2 \
+	STR_SRC_24_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_24_1_2 = {
+	.cc = LC3_CONFIG_24_1_AC(2),
+	.qos = LC3_QOS_24_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_24_1_2 \
+	STR_SRC_24_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_24_2_2 = {
+	.cc = LC3_CONFIG_24_2_AC(1),
+	.qos = LC3_QOS_24_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_24_2_2(_chans) \
+	STR_SRC_24_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_24_2, LC3_QOS_24_2_2_RTN, \
+			LC3_QOS_24_2_2_LATENCY)
+
+#define STR_SRC_AC1_24_2_2 \
+	STR_SRC_24_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_24_2_2 = {
+	.cc = LC3_CONFIG_24_2_AC(2),
+	.qos = LC3_QOS_24_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_24_2_2 \
+	STR_SRC_24_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_32_1_2 = {
+	.cc = LC3_CONFIG_32_1_AC(1),
+	.qos = LC3_QOS_32_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_32_1_2(_chans) \
+	STR_SRC_32_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_32_1, LC3_QOS_32_1_2_RTN, \
+			LC3_QOS_32_1_2_LATENCY)
+
+#define STR_SRC_AC1_32_1_2 \
+	STR_SRC_32_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_32_1_2 = {
+	.cc = LC3_CONFIG_32_1_AC(2),
+	.qos = LC3_QOS_32_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_32_1_2 \
+	STR_SRC_32_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_32_2_2 = {
+	.cc = LC3_CONFIG_32_2_AC(1),
+	.qos = LC3_QOS_32_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_32_2_2(_chans) \
+	STR_SRC_32_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_32_2, LC3_QOS_32_2_2_RTN, \
+			LC3_QOS_32_2_2_LATENCY)
+
+#define STR_SRC_AC1_32_2_2 \
+	STR_SRC_32_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_32_2_2 = {
+	.cc = LC3_CONFIG_32_2_AC(2),
+	.qos = LC3_QOS_32_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_32_2_2 \
+	STR_SRC_32_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_44_1_2 = {
+	.cc = LC3_CONFIG_44_1_AC(1),
+	.qos = LC3_QOS_44_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+
+#define STR_SRC_44_1_2(_chans) \
+	STR_SRC_44_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_44_1(_chans * LC3_CONFIG_FRAME_LEN_44_1, \
+			 LC3_QOS_44_1_2_RTN, LC3_QOS_44_1_2_LATENCY)
+
+#define STR_SRC_AC1_44_1_2 \
+	STR_SRC_44_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_44_1_2 = {
+	.cc = LC3_CONFIG_44_1_AC(2),
+	.qos = LC3_QOS_44_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_44_1_2 \
+	STR_SRC_44_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_44_2_2 = {
+	.cc = LC3_CONFIG_44_2_AC(1),
+	.qos = LC3_QOS_44_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_44_2_2(_chans) \
+	STR_SRC_44_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_44_2(_chans * LC3_CONFIG_FRAME_LEN_44_2, \
+			LC3_QOS_44_2_2_RTN, LC3_QOS_44_2_2_LATENCY)
+
+#define STR_SRC_AC1_44_2_2 \
+	STR_SRC_44_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_44_2_2 = {
+	.cc = LC3_CONFIG_44_2_AC(2),
+	.qos = LC3_QOS_44_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_44_2_2 \
+	STR_SRC_44_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_1_2 = {
+	.cc = LC3_CONFIG_48_1_AC(1),
+	.qos = LC3_QOS_48_1_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+
+#define STR_SRC_48_1_2(_chans) \
+	STR_SRC_48_1((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_1, LC3_QOS_48_1_2_RTN, \
+			LC3_QOS_48_1_2_LATENCY)
+
+#define STR_SRC_AC1_48_1_2 \
+	STR_SRC_48_1_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_1_2 = {
+	.cc = LC3_CONFIG_48_1_AC(2),
+	.qos = LC3_QOS_48_1_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_1_2 \
+	STR_SRC_48_1_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_2_2 = {
+	.cc = LC3_CONFIG_48_2_AC(1),
+	.qos = LC3_QOS_48_2_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_2_2(_chans) \
+	STR_SRC_48_2((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_2, LC3_QOS_48_2_2_RTN, \
+			LC3_QOS_48_2_2_LATENCY)
+
+#define STR_SRC_AC1_48_2_2 \
+	STR_SRC_48_2_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_48_2_2 = {
+	.cc = LC3_CONFIG_48_2_AC(2),
+	.qos = LC3_QOS_48_2_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_2_2 \
+	STR_SRC_48_2_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_3_2 = {
+	.cc = LC3_CONFIG_48_3_AC(1),
+	.qos = LC3_QOS_48_3_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+
+#define STR_SRC_48_3_2(_chans) \
+	STR_SRC_48_3((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_3, LC3_QOS_48_3_2_RTN, \
+			LC3_QOS_48_3_2_LATENCY)
+
+#define STR_SRC_AC1_48_3_2 \
+	STR_SRC_48_3_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_3_2 = {
+	.cc = LC3_CONFIG_48_3_AC(2),
+	.qos = LC3_QOS_48_3_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_3_2 \
+	STR_SRC_48_3_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_4_2 = {
+	.cc = LC3_CONFIG_48_4_AC(1),
+	.qos = LC3_QOS_48_4_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_4_2(_chans) \
+	STR_SRC_48_4((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_4, LC3_QOS_48_4_2_RTN, \
+			LC3_QOS_48_4_2_LATENCY)
+
+#define STR_SRC_AC1_48_4_2 \
+	STR_SRC_48_4_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_48_4_2 = {
+	.cc = LC3_CONFIG_48_4_AC(2),
+	.qos = LC3_QOS_48_4_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_4_2 \
+	STR_SRC_48_4_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_5_2 = {
+	.cc = LC3_CONFIG_48_5_AC(1),
+	.qos = LC3_QOS_48_5_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+
+#define STR_SRC_48_5_2(_chans) \
+	STR_SRC_48_5((BIT(_chans) - 1)), \
+	STR_SRC_QOS_1(_chans * LC3_CONFIG_FRAME_LEN_48_5, LC3_QOS_48_5_2_RTN, \
+			LC3_QOS_48_5_2_LATENCY)
+
+#define STR_SRC_AC1_48_5_2 \
+	STR_SRC_48_5_2(1), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac4_48_5_2 = {
+	.cc = LC3_CONFIG_48_5_AC(2),
+	.qos = LC3_QOS_48_5_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_5_2 \
+	STR_SRC_48_5_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+static struct test_config str_src_ac1_48_6_2 = {
+	.cc = LC3_CONFIG_48_6_AC(1),
+	.qos = LC3_QOS_48_6_2_AC(1),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_48_6_2(_chans) \
+	STR_SRC_48_6((BIT(_chans) - 1)), \
+	STR_SRC_QOS_2(_chans * LC3_CONFIG_FRAME_LEN_48_6, LC3_QOS_48_6_2_RTN, \
+			LC3_QOS_48_6_2_LATENCY)
+
+#define STR_SRC_AC1_48_6_2 \
+	STR_SRC_48_6_2(1), \
+	SRC_ENABLE, \
+	SNK_START
+
+static struct test_config str_src_ac4_48_6_2 = {
+	.cc = LC3_CONFIG_48_6_AC(2),
+	.qos = LC3_QOS_48_6_2_AC(2),
+	.src = true,
+	.state = BT_BAP_STREAM_STATE_STREAMING,
+};
+
+#define STR_SRC_AC4_48_6_2 \
+	STR_SRC_48_6_2(2), \
+	SRC_ENABLE, \
+	SRC_START
+
+/* Unicast Client Streaming – 1 Unicast Server, 1 Stream, 1 CIS – LC3
+ *
+ * Test Purpose:
+ * Verify that a Unicast Client IUT can stream audio data over one unicast
+ * Audio Stream to or from a Unicast Server.
+ *
+ * Pass verdict:
+ * If the IUT is in the Audio Sink role, the IUT receives SDUs with a zero or
+ * more length that contains LC3-encoded data formatted using the LC3 Media
+ * Packet format (defined in [3] Section 4.2).
+ */
+static void test_str_1_1_1_lc3(void)
+{
+	define_test("BAP/UCL/STR/BV-001-C [UCL, AC 2, LC3 8_1_1]",
+			test_setup, test_client, &str_snk_ac2_8_1_1,
+			STR_SNK_AC2_8_1_1);
+	define_test("BAP/UCL/STR/BV-002-C [UCL, AC 10, LC3 8_1_1]",
+			test_setup, test_client, &str_snk_ac10_8_1_1,
+			STR_SNK_AC10_8_1_1);
+	define_test("BAP/UCL/STR/BV-003-C [UCL, AC 2, LC3 8_2_1]",
+			test_setup, test_client, &str_snk_ac2_8_2_1,
+			STR_SNK_AC2_8_2_1);
+	define_test("BAP/UCL/STR/BV-004-C [UCL, AC 10, LC3 8_2_1]",
+			test_setup, test_client, &str_snk_ac10_8_2_1,
+			STR_SNK_AC10_8_2_1);
+	define_test("BAP/UCL/STR/BV-005-C [UCL, AC 2, LC3 16_1_1]",
+			test_setup, test_client, &str_snk_ac2_16_1_1,
+			STR_SNK_AC2_16_1_1);
+	define_test("BAP/UCL/STR/BV-006-C [UCL, AC 10, LC3 16_1_1]",
+			test_setup, test_client, &str_snk_ac10_16_1_1,
+			STR_SNK_AC10_16_1_1);
+	define_test("BAP/UCL/STR/BV-007-C [UCL, AC 2, LC3 16_2_1]",
+			test_setup, test_client, &str_snk_ac2_16_2_1,
+			STR_SNK_AC2_16_2_1);
+	define_test("BAP/UCL/STR/BV-008-C [UCL, AC 10, LC3 16_2_1]",
+			test_setup, test_client, &str_snk_ac10_16_2_1,
+			STR_SNK_AC10_16_2_1);
+	define_test("BAP/UCL/STR/BV-009-C [UCL, AC 2, LC3 24_1_1]",
+			test_setup, test_client, &str_snk_ac2_24_1_1,
+			STR_SNK_AC2_24_1_1);
+	define_test("BAP/UCL/STR/BV-010-C [UCL, AC 10, LC3 24_1_1]",
+			test_setup, test_client, &str_snk_ac10_24_1_1,
+			STR_SNK_AC10_24_1_1);
+	define_test("BAP/UCL/STR/BV-011-C [UCL, AC 2, LC3 24_2_1]",
+			test_setup, test_client, &str_snk_ac2_24_2_1,
+			STR_SNK_AC2_24_2_1);
+	define_test("BAP/UCL/STR/BV-012-C [UCL, AC 10, LC3 24_2_1]",
+			test_setup, test_client, &str_snk_ac10_24_2_1,
+			STR_SNK_AC10_24_2_1);
+	define_test("BAP/UCL/STR/BV-013-C [UCL, AC 2, LC3 32_1_1]",
+			test_setup, test_client, &str_snk_ac2_32_1_1,
+			STR_SNK_AC2_32_1_1);
+	define_test("BAP/UCL/STR/BV-014-C [UCL, AC 10, LC3 32_1_1]",
+			test_setup, test_client, &str_snk_ac10_32_1_1,
+			STR_SNK_AC10_32_1_1);
+	define_test("BAP/UCL/STR/BV-015-C [UCL, AC 2, LC3 32_2_1]",
+			test_setup, test_client, &str_snk_ac2_32_2_1,
+			STR_SNK_AC2_32_2_1);
+	define_test("BAP/UCL/STR/BV-016-C [UCL, AC 10, LC3 32_2_1]",
+			test_setup, test_client, &str_snk_ac10_32_2_1,
+			STR_SNK_AC10_32_2_1);
+	define_test("BAP/UCL/STR/BV-017-C [UCL, AC 2, LC3 441_1_1]",
+			test_setup, test_client, &str_snk_ac2_44_1_1,
+			STR_SNK_AC2_44_1_1);
+	define_test("BAP/UCL/STR/BV-018-C [UCL, AC 10, LC3 441_1_1]",
+			test_setup, test_client, &str_snk_ac10_44_1_1,
+			STR_SNK_AC10_44_1_1);
+	define_test("BAP/UCL/STR/BV-019-C [UCL, AC 2, LC3 44_2_1]",
+			test_setup, test_client, &str_snk_ac2_44_2_1,
+			STR_SNK_AC2_44_2_1);
+	define_test("BAP/UCL/STR/BV-020-C [UCL, AC 10, LC3 44_2_1]",
+			test_setup, test_client, &str_snk_ac10_44_2_1,
+			STR_SNK_AC10_44_2_1);
+	define_test("BAP/UCL/STR/BV-021-C [UCL, AC 2, LC3 48_1_1]",
+			test_setup, test_client, &str_snk_ac2_48_1_1,
+			STR_SNK_AC2_48_1_1);
+	define_test("BAP/UCL/STR/BV-022-C [UCL, AC 10, LC3 48_1_1]",
+			test_setup, test_client, &str_snk_ac10_48_1_1,
+			STR_SNK_AC10_48_1_1);
+	define_test("BAP/UCL/STR/BV-023-C [UCL, AC 2, LC3 48_2_1]",
+			test_setup, test_client, &str_snk_ac2_48_2_1,
+			STR_SNK_AC2_48_2_1);
+	define_test("BAP/UCL/STR/BV-024-C [UCL, AC 10, LC3 48_2_1]",
+			test_setup, test_client, &str_snk_ac10_48_2_1,
+			STR_SNK_AC10_48_2_1);
+	define_test("BAP/UCL/STR/BV-025-C [UCL, AC 2, LC3 48_3_1]",
+			test_setup, test_client, &str_snk_ac2_48_3_1,
+			STR_SNK_AC2_48_3_1);
+	define_test("BAP/UCL/STR/BV-026-C [UCL, AC 10, LC3 48_3_1]",
+			test_setup, test_client, &str_snk_ac10_48_3_1,
+			STR_SNK_AC10_48_3_1);
+	define_test("BAP/UCL/STR/BV-027-C [UCL, AC 2, LC3 48_4_1]",
+			test_setup, test_client, &str_snk_ac2_48_4_1,
+			STR_SNK_AC2_48_4_1);
+	define_test("BAP/UCL/STR/BV-028-C [UCL, AC 10, LC3 48_4_1]",
+			test_setup, test_client, &str_snk_ac10_48_4_1,
+			STR_SNK_AC10_48_4_1);
+	define_test("BAP/UCL/STR/BV-029-C [UCL, AC 2, LC3 48_5_1]",
+			test_setup, test_client, &str_snk_ac2_48_5_1,
+			STR_SNK_AC2_48_5_1);
+	define_test("BAP/UCL/STR/BV-030-C [UCL, AC 10, LC3 48_5_1]",
+			test_setup, test_client, &str_snk_ac10_48_5_1,
+			STR_SNK_AC10_48_5_1);
+	define_test("BAP/UCL/STR/BV-031-C [UCL, AC 2, LC3 48_6_1]",
+			test_setup, test_client, &str_snk_ac2_48_6_1,
+			STR_SNK_AC2_48_6_1);
+	define_test("BAP/UCL/STR/BV-032-C [UCL, AC 10, LC3 48_6_1]",
+			test_setup, test_client, &str_snk_ac10_48_6_1,
+			STR_SNK_AC10_48_6_1);
+	define_test("BAP/UCL/STR/BV-033-C [UCL, SRC, AC 1, LC3 8_1_1]",
+			test_setup, test_client, &str_src_ac1_8_1_1,
+			STR_SRC_AC1_8_1_1);
+	define_test("BAP/UCL/STR/BV-034-C [UCL, SRC, AC 4, LC3 8_1_1]",
+			test_setup, test_client, &str_src_ac4_8_1_1,
+			STR_SRC_AC4_8_1_1);
+	define_test("BAP/UCL/STR/BV-035-C [UCL, SRC, AC 1, LC3 8_2_1]",
+			test_setup, test_client, &str_src_ac1_8_2_1,
+			STR_SRC_AC1_8_2_1);
+	define_test("BAP/UCL/STR/BV-036-C [UCL, SRC, AC 4, LC3 8_2_1]",
+			test_setup, test_client, &str_src_ac4_8_2_1,
+			STR_SRC_AC4_8_2_1);
+	define_test("BAP/UCL/STR/BV-037-C [UCL, SRC, AC 1, LC3 16_1_1]",
+			test_setup, test_client, &str_src_ac1_16_1_1,
+			STR_SRC_AC1_16_1_1);
+	define_test("BAP/UCL/STR/BV-038-C [UCL, SRC, AC 4, LC3 16_1_1]",
+			test_setup, test_client, &str_src_ac4_16_1_1,
+			STR_SRC_AC4_16_1_1);
+	define_test("BAP/UCL/STR/BV-039-C [UCL, SRC, AC 1, LC3 16_2_1]",
+			test_setup, test_client, &str_src_ac1_16_2_1,
+			STR_SRC_AC1_16_2_1);
+	define_test("BAP/UCL/STR/BV-040-C [UCL, SRC, AC 4, LC3 16_2_1]",
+			test_setup, test_client, &str_src_ac4_16_2_1,
+			STR_SRC_AC4_16_2_1);
+	define_test("BAP/UCL/STR/BV-041-C [UCL, SRC, AC 1, LC3 24_1_1]",
+			test_setup, test_client, &str_src_ac1_24_1_1,
+			STR_SRC_AC1_24_1_1);
+	define_test("BAP/UCL/STR/BV-042-C [UCL, SRC, AC 4, LC3 24_1_1]",
+			test_setup, test_client, &str_src_ac4_24_1_1,
+			STR_SRC_AC4_24_1_1);
+	define_test("BAP/UCL/STR/BV-043-C [UCL, SRC, AC 1, LC3 24_2_1]",
+			test_setup, test_client, &str_src_ac1_24_2_1,
+			STR_SRC_AC1_24_2_1);
+	define_test("BAP/UCL/STR/BV-044-C [UCL, SRC, AC 4, LC3 24_2_1]",
+			test_setup, test_client, &str_src_ac4_24_2_1,
+			STR_SRC_AC4_24_2_1);
+	define_test("BAP/UCL/STR/BV-045-C [UCL, SRC, AC 1, LC3 32_1_1]",
+			test_setup, test_client, &str_src_ac1_32_1_1,
+			STR_SRC_AC1_32_1_1);
+	define_test("BAP/UCL/STR/BV-046-C [UCL, SRC, AC 4, LC3 32_1_1]",
+			test_setup, test_client, &str_src_ac4_32_1_1,
+			STR_SRC_AC4_32_1_1);
+	define_test("BAP/UCL/STR/BV-047-C [UCL, SRC, AC 1, LC3 32_2_1]",
+			test_setup, test_client, &str_src_ac1_32_2_1,
+			STR_SRC_AC1_32_2_1);
+	define_test("BAP/UCL/STR/BV-048-C [UCL, SRC, AC 4, LC3 32_2_1]",
+			test_setup, test_client, &str_src_ac4_32_2_1,
+			STR_SRC_AC4_32_2_1);
+	define_test("BAP/UCL/STR/BV-049-C [UCL, SRC, AC 1, LC3 44_1_1]",
+			test_setup, test_client, &str_src_ac1_44_1_1,
+			STR_SRC_AC1_44_1_1);
+	define_test("BAP/UCL/STR/BV-050-C [UCL, SRC, AC 4, LC3 44_1_1]",
+			test_setup, test_client, &str_src_ac4_44_1_1,
+			STR_SRC_AC4_44_1_1);
+	define_test("BAP/UCL/STR/BV-051-C [UCL, SRC, AC 1, LC3 44_2_1]",
+			test_setup, test_client, &str_src_ac1_44_2_1,
+			STR_SRC_AC1_44_2_1);
+	define_test("BAP/UCL/STR/BV-052-C [UCL, SRC, AC 4, LC3 44_2_1]",
+			test_setup, test_client, &str_src_ac4_44_2_1,
+			STR_SRC_AC4_44_2_1);
+	define_test("BAP/UCL/STR/BV-053-C [UCL, SRC, AC 1, LC3 48_1_1]",
+			test_setup, test_client, &str_src_ac1_48_1_1,
+			STR_SRC_AC1_48_1_1);
+	define_test("BAP/UCL/STR/BV-054-C [UCL, SRC, AC 4, LC3 48_1_1]",
+			test_setup, test_client, &str_src_ac4_48_1_1,
+			STR_SRC_AC4_48_1_1);
+	define_test("BAP/UCL/STR/BV-055-C [UCL, SRC, AC 1, LC3 48_2_1]",
+			test_setup, test_client, &str_src_ac1_48_2_1,
+			STR_SRC_AC1_48_2_1);
+	define_test("BAP/UCL/STR/BV-056-C [UCL, SRC, AC 4, LC3 48_2_1]",
+			test_setup, test_client, &str_src_ac4_48_2_1,
+			STR_SRC_AC4_48_2_1);
+	define_test("BAP/UCL/STR/BV-057-C [UCL, SRC, AC 1, LC3 48_3_1]",
+			test_setup, test_client, &str_src_ac1_48_3_1,
+			STR_SRC_AC1_48_3_1);
+	define_test("BAP/UCL/STR/BV-058-C [UCL, SRC, AC 4, LC3 48_3_1]",
+			test_setup, test_client, &str_src_ac4_48_3_1,
+			STR_SRC_AC4_48_3_1);
+	define_test("BAP/UCL/STR/BV-059-C [UCL, SRC, AC 1, LC3 48_4_1]",
+			test_setup, test_client, &str_src_ac1_48_4_1,
+			STR_SRC_AC1_48_4_1);
+	define_test("BAP/UCL/STR/BV-060-C [UCL, SRC, AC 4, LC3 48_4_1]",
+			test_setup, test_client, &str_src_ac4_48_4_1,
+			STR_SRC_AC4_48_4_1);
+	define_test("BAP/UCL/STR/BV-061-C [UCL, SRC, AC 1, LC3 48_5_1]",
+			test_setup, test_client, &str_src_ac1_48_5_1,
+			STR_SRC_AC1_48_5_1);
+	define_test("BAP/UCL/STR/BV-062-C [UCL, SRC, AC 4, LC3 48_5_1]",
+			test_setup, test_client, &str_src_ac4_48_5_1,
+			STR_SRC_AC4_48_5_1);
+	define_test("BAP/UCL/STR/BV-063-C [UCL, SRC, AC 1, LC3 48_6_1]",
+			test_setup, test_client, &str_src_ac1_48_6_1,
+			STR_SRC_AC1_48_6_1);
+	define_test("BAP/UCL/STR/BV-064-C [UCL, SRC, AC 4, LC3 48_6_1]",
+			test_setup, test_client, &str_src_ac4_48_6_1,
+			STR_SRC_AC4_48_6_1);
+	define_test("BAP/UCL/STR/BV-065-C [UCL, AC 2, LC3 8_1_2]",
+			test_setup, test_client, &str_snk_ac2_8_1_2,
+			STR_SNK_AC2_8_1_2);
+	define_test("BAP/UCL/STR/BV-066-C [UCL, AC 10, LC3 8_1_2]",
+			test_setup, test_client, &str_snk_ac10_8_1_2,
+			STR_SNK_AC10_8_1_2);
+	define_test("BAP/UCL/STR/BV-067-C [UCL, AC 2, LC3 8_2_2]",
+			test_setup, test_client, &str_snk_ac2_8_2_2,
+			STR_SNK_AC2_8_2_2);
+	define_test("BAP/UCL/STR/BV-068-C [UCL, AC 10, LC3 8_2_2]",
+			test_setup, test_client, &str_snk_ac10_8_2_2,
+			STR_SNK_AC10_8_2_2);
+	define_test("BAP/UCL/STR/BV-069-C [UCL, AC 2, LC3 16_1_2]",
+			test_setup, test_client, &str_snk_ac2_16_1_2,
+			STR_SNK_AC2_16_1_2);
+	define_test("BAP/UCL/STR/BV-070-C [UCL, AC 10, LC3 16_1_2]",
+			test_setup, test_client, &str_snk_ac10_16_1_2,
+			STR_SNK_AC10_16_1_2);
+	define_test("BAP/UCL/STR/BV-071-C [UCL, AC 2, LC3 16_2_2]",
+			test_setup, test_client, &str_snk_ac2_16_2_2,
+			STR_SNK_AC2_16_2_2);
+	define_test("BAP/UCL/STR/BV-072-C [UCL, AC 10, LC3 16_2_2]",
+			test_setup, test_client, &str_snk_ac10_16_2_2,
+			STR_SNK_AC10_16_2_2);
+	define_test("BAP/UCL/STR/BV-073-C [UCL, AC 2, LC3 24_1_2]",
+			test_setup, test_client, &str_snk_ac2_24_1_2,
+			STR_SNK_AC2_24_1_2);
+	define_test("BAP/UCL/STR/BV-074-C [UCL, AC 10, LC3 24_1_2]",
+			test_setup, test_client, &str_snk_ac10_24_1_2,
+			STR_SNK_AC10_24_1_2);
+	define_test("BAP/UCL/STR/BV-075-C [UCL, AC 2, LC3 24_2_2]",
+			test_setup, test_client, &str_snk_ac2_24_2_2,
+			STR_SNK_AC2_24_2_2);
+	define_test("BAP/UCL/STR/BV-076-C [UCL, AC 10, LC3 24_2_2]",
+			test_setup, test_client, &str_snk_ac10_24_2_2,
+			STR_SNK_AC10_24_2_2);
+	define_test("BAP/UCL/STR/BV-077-C [UCL, AC 2, LC3 32_1_2]",
+			test_setup, test_client, &str_snk_ac2_32_1_2,
+			STR_SNK_AC2_32_1_2);
+	define_test("BAP/UCL/STR/BV-078-C [UCL, AC 10, LC3 32_1_2]",
+			test_setup, test_client, &str_snk_ac10_32_1_2,
+			STR_SNK_AC10_32_1_2);
+	define_test("BAP/UCL/STR/BV-079-C [UCL, AC 2, LC3 32_2_2]",
+			test_setup, test_client, &str_snk_ac2_32_2_2,
+			STR_SNK_AC2_32_2_2);
+	define_test("BAP/UCL/STR/BV-080-C [UCL, AC 10, LC3 32_2_2]",
+			test_setup, test_client, &str_snk_ac10_32_2_2,
+			STR_SNK_AC10_32_2_2);
+	define_test("BAP/UCL/STR/BV-081-C [UCL, AC 2, LC3 44_1_2]",
+			test_setup, test_client, &str_snk_ac2_44_1_2,
+			STR_SNK_AC2_44_1_2);
+	define_test("BAP/UCL/STR/BV-082-C [UCL, AC 10, LC3 44_1_2]",
+			test_setup, test_client, &str_snk_ac10_44_1_2,
+			STR_SNK_AC10_44_1_2);
+	define_test("BAP/UCL/STR/BV-083-C [UCL, AC 2, LC3 44_2_2]",
+			test_setup, test_client, &str_snk_ac2_44_2_2,
+			STR_SNK_AC2_44_2_2);
+	define_test("BAP/UCL/STR/BV-084-C [UCL, AC 10, LC3 44_2_2]",
+			test_setup, test_client, &str_snk_ac10_44_2_2,
+			STR_SNK_AC10_44_2_2);
+	define_test("BAP/UCL/STR/BV-085-C [UCL, AC 2, LC3 48_1_2]",
+			test_setup, test_client, &str_snk_ac2_48_1_2,
+			STR_SNK_AC2_48_1_2);
+	define_test("BAP/UCL/STR/BV-086-C [UCL, AC 10, LC3 48_1_2]",
+			test_setup, test_client, &str_snk_ac10_48_1_2,
+			STR_SNK_AC10_48_1_2);
+	define_test("BAP/UCL/STR/BV-087-C [UCL, AC 2, LC3 48_2_2]",
+			test_setup, test_client, &str_snk_ac2_48_2_2,
+			STR_SNK_AC2_48_2_2);
+	define_test("BAP/UCL/STR/BV-088-C [UCL, AC 10, LC3 48_2_2]",
+			test_setup, test_client, &str_snk_ac10_48_2_2,
+			STR_SNK_AC10_48_2_2);
+	define_test("BAP/UCL/STR/BV-089-C [UCL, AC 2, LC3 48_3_2]",
+			test_setup, test_client, &str_snk_ac2_48_3_2,
+			STR_SNK_AC2_48_3_2);
+	define_test("BAP/UCL/STR/BV-090-C [UCL, AC 10, LC3 48_3_2]",
+			test_setup, test_client, &str_snk_ac10_48_3_2,
+			STR_SNK_AC10_48_3_2);
+	define_test("BAP/UCL/STR/BV-091-C [UCL, AC 2, LC3 48_4_2]",
+			test_setup, test_client, &str_snk_ac2_48_4_2,
+			STR_SNK_AC2_48_4_2);
+	define_test("BAP/UCL/STR/BV-092-C [UCL, AC 10, LC3 48_4_2]",
+			test_setup, test_client, &str_snk_ac10_48_4_2,
+			STR_SNK_AC10_48_4_2);
+	define_test("BAP/UCL/STR/BV-093-C [UCL, AC 2, LC3 48_5_2]",
+			test_setup, test_client, &str_snk_ac2_48_5_2,
+			STR_SNK_AC2_48_5_2);
+	define_test("BAP/UCL/STR/BV-094-C [UCL, AC 10, LC3 48_5_2]",
+			test_setup, test_client, &str_snk_ac10_48_5_2,
+			STR_SNK_AC10_48_5_2);
+	define_test("BAP/UCL/STR/BV-095-C [UCL, AC 2, LC3 48_6_2]",
+			test_setup, test_client, &str_snk_ac2_48_6_2,
+			STR_SNK_AC2_48_6_2);
+	define_test("BAP/UCL/STR/BV-096-C [UCL, AC 10, LC3 48_6_2]",
+			test_setup, test_client, &str_snk_ac10_48_6_2,
+			STR_SNK_AC10_48_6_2);
+	define_test("BAP/UCL/STR/BV-097-C [UCL, SRC, AC 1, LC3 8_1_2]",
+			test_setup, test_client, &str_src_ac1_8_1_2,
+			STR_SRC_AC1_8_1_2);
+	define_test("BAP/UCL/STR/BV-098-C [UCL, SRC, AC 4, LC3 8_1_2]",
+			test_setup, test_client, &str_src_ac4_8_1_2,
+			STR_SRC_AC4_8_1_2);
+	define_test("BAP/UCL/STR/BV-099-C [UCL, SRC, AC 1, LC3 8_2_2]",
+			test_setup, test_client, &str_src_ac1_8_2_2,
+			STR_SRC_AC1_8_2_2);
+	define_test("BAP/UCL/STR/BV-100-C [UCL, SRC, AC 4, LC3 8_2_2]",
+			test_setup, test_client, &str_src_ac4_8_2_2,
+			STR_SRC_AC4_8_2_2);
+	define_test("BAP/UCL/STR/BV-101-C [UCL, SRC, AC 1, LC3 16_1_2]",
+			test_setup, test_client, &str_src_ac1_16_1_2,
+			STR_SRC_AC1_16_1_2);
+	define_test("BAP/UCL/STR/BV-102-C [UCL, SRC, AC 4, LC3 16_1_2]",
+			test_setup, test_client, &str_src_ac4_16_1_2,
+			STR_SRC_AC4_16_1_2);
+	define_test("BAP/UCL/STR/BV-103-C [UCL, SRC, AC 1, LC3 16_2_2]",
+			test_setup, test_client, &str_src_ac1_16_2_2,
+			STR_SRC_AC1_16_2_2);
+	define_test("BAP/UCL/STR/BV-104-C [UCL, SRC, AC 4, LC3 16_2_2]",
+			test_setup, test_client, &str_src_ac4_16_2_2,
+			STR_SRC_AC4_16_2_2);
+	define_test("BAP/UCL/STR/BV-105-C [UCL, SRC, AC 1, LC3 24_1_2]",
+			test_setup, test_client, &str_src_ac1_24_1_2,
+			STR_SRC_AC1_24_1_2);
+	define_test("BAP/UCL/STR/BV-106-C [UCL, SRC, AC 4, LC3 24_1_2]",
+			test_setup, test_client, &str_src_ac4_24_1_2,
+			STR_SRC_AC4_24_1_2);
+	define_test("BAP/UCL/STR/BV-107-C [UCL, SRC, AC 1, LC3 24_2_2]",
+			test_setup, test_client, &str_src_ac1_24_2_2,
+			STR_SRC_AC1_24_2_2);
+	define_test("BAP/UCL/STR/BV-108-C [UCL, SRC, AC 4, LC3 24_2_2]",
+			test_setup, test_client, &str_src_ac4_24_2_2,
+			STR_SRC_AC4_24_2_2);
+	define_test("BAP/UCL/STR/BV-109-C [UCL, SRC, AC 1, LC3 32_1_2]",
+			test_setup, test_client, &str_src_ac1_32_1_2,
+			STR_SRC_AC1_32_1_2);
+	define_test("BAP/UCL/STR/BV-110-C [UCL, SRC, AC 4, LC3 32_1_2]",
+			test_setup, test_client, &str_src_ac4_32_1_2,
+			STR_SRC_AC4_32_1_2);
+	define_test("BAP/UCL/STR/BV-111-C [UCL, SRC, AC 1, LC3 32_2_2]",
+			test_setup, test_client, &str_src_ac1_32_2_2,
+			STR_SRC_AC1_32_2_2);
+	define_test("BAP/UCL/STR/BV-112-C [UCL, SRC, AC 4, LC3 32_2_2]",
+			test_setup, test_client, &str_src_ac4_32_2_2,
+			STR_SRC_AC4_32_2_2);
+	define_test("BAP/UCL/STR/BV-113-C [UCL, SRC, AC 1, LC3 44_1_2]",
+			test_setup, test_client, &str_src_ac1_44_1_2,
+			STR_SRC_AC1_44_1_2);
+	define_test("BAP/UCL/STR/BV-114-C [UCL, SRC, AC 4, LC3 44_1_2]",
+			test_setup, test_client, &str_src_ac4_44_1_2,
+			STR_SRC_AC4_44_1_2);
+	define_test("BAP/UCL/STR/BV-115-C [UCL, SRC, AC 1, LC3 44_2_2]",
+			test_setup, test_client, &str_src_ac1_44_2_2,
+			STR_SRC_AC1_44_2_2);
+	define_test("BAP/UCL/STR/BV-116-C [UCL, SRC, AC 4, LC3 44_2_2]",
+			test_setup, test_client, &str_src_ac4_44_2_2,
+			STR_SRC_AC4_44_2_2);
+	define_test("BAP/UCL/STR/BV-117-C [UCL, SRC, AC 1, LC3 48_1_2]",
+			test_setup, test_client, &str_src_ac1_48_1_2,
+			STR_SRC_AC1_48_1_2);
+	define_test("BAP/UCL/STR/BV-118-C [UCL, SRC, AC 4, LC3 48_1_2]",
+			test_setup, test_client, &str_src_ac4_48_1_2,
+			STR_SRC_AC4_48_1_2);
+	define_test("BAP/UCL/STR/BV-119-C [UCL, SRC, AC 1, LC3 48_2_2]",
+			test_setup, test_client, &str_src_ac1_48_2_2,
+			STR_SRC_AC1_48_2_2);
+	define_test("BAP/UCL/STR/BV-120-C [UCL, SRC, AC 4, LC3 48_2_2]",
+			test_setup, test_client, &str_src_ac4_48_2_2,
+			STR_SRC_AC4_48_2_2);
+	define_test("BAP/UCL/STR/BV-121-C [UCL, SRC, AC 1, LC3 48_3_2]",
+			test_setup, test_client, &str_src_ac1_48_3_2,
+			STR_SRC_AC1_48_3_2);
+	define_test("BAP/UCL/STR/BV-122-C [UCL, SRC, AC 4, LC3 48_3_2]",
+			test_setup, test_client, &str_src_ac4_48_3_2,
+			STR_SRC_AC4_48_3_2);
+	define_test("BAP/UCL/STR/BV-123-C [UCL, SRC, AC 1, LC3 48_4_2]",
+			test_setup, test_client, &str_src_ac1_48_4_2,
+			STR_SRC_AC1_48_4_2);
+	define_test("BAP/UCL/STR/BV-124-C [UCL, SRC, AC 4, LC3 48_4_2]",
+			test_setup, test_client, &str_src_ac4_48_4_2,
+			STR_SRC_AC4_48_4_2);
+	define_test("BAP/UCL/STR/BV-121-C [UCL, SRC, AC 1, LC3 48_5_2]",
+			test_setup, test_client, &str_src_ac1_48_5_2,
+			STR_SRC_AC1_48_5_2);
+	define_test("BAP/UCL/STR/BV-122-C [UCL, SRC, AC 4, LC3 48_5_2]",
+			test_setup, test_client, &str_src_ac4_48_5_2,
+			STR_SRC_AC4_48_5_2);
+	define_test("BAP/UCL/STR/BV-123-C [UCL, SRC, AC 1, LC3 48_6_2]",
+			test_setup, test_client, &str_src_ac1_48_6_2,
+			STR_SRC_AC1_48_6_2);
+	define_test("BAP/UCL/STR/BV-124-C [UCL, SRC, AC 4, LC3 48_6_2]",
+			test_setup, test_client, &str_src_ac4_48_6_2,
+			STR_SRC_AC4_48_6_2);
+}
+
+static void test_scc(void)
+{
+	test_scc_cc_lc3();
+	test_scc_cc_vs();
+	test_scc_qos_lc3();
+	test_scc_qos_vs();
+	test_scc_enable();
+	test_scc_disable();
+	test_scc_release();
+	test_scc_metadata();
+	test_str_1_1_1_lc3();
+}
+
+static struct test_config cfg_bsrc_8_1_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_8_1_2 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_8_2_1 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_8_2_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_16_1_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_16_1_2 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_16_2_1 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_16_2_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_24_1_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_24_1_2 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_24_2_1 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_24_2_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_32_1_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_32_1_2 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_32_2_1 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_32_2_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_44_1_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_44_1_2 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_44_2_1 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_44_2_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_1_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_1_2 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_1),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_2_1 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_2_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_2),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_3_1 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_3),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_3_2 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_3),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_4_1 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_4),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_4_2 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_4),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_5_1 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_5),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_5_2 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_5),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_6_1 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_6),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_48_6_2 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_2_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_6),
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+#define VS_CC \
+	0x02, 0x01, 0x08, \
+	0x02, 0x02, 0x00, \
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00, \
+	0x03, 0x04, 0x75, 0x00
+
+#define VS_CFG \
+	0x10, \
+	VS_CC
+
+#define QOS_BCAST \
+{ \
+	.bcast.big = 0x00, \
+	.bcast.bis = 0x00, \
+	.bcast.framing = LC3_QOS_UNFRAMED, \
+	.bcast.delay = 40000, \
+	.bcast.io_qos.interval = 7500, \
+	.bcast.io_qos.latency = 10, \
+	.bcast.io_qos.sdu = 40, \
+	.bcast.io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
+	.bcast.io_qos.rtn = 2, \
+}
+
+static struct test_config cfg_bsrc_vs = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.base = UTIL_IOV_INIT(BASE_VS(VS_CFG)),
+	.vs = true,
+	.src = true,
+	.state_func = bsrc_state_cfg,
+	.streams = 1,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can configure a broadcast
+ * Audio Stream with information defined by the values in its BASE
+ * structure. The verification is performed one Codec Setting and
+ * set of parameters at a time, as enumerated in the test cases in
+ * Table 4.73.
+ *
+ * Pass verdict:
+ * In step 2, the AdvData field of AUX_SYNC_IND and optionally
+ * AUX_CHAIN_IND PDUs contains the configured BASE information.
+ *
+ * In step 3, the IUT transmits the PA synchronization information in
+ * the SyncInfo field of the Extended Header field of AUX_ADV_IND PDUs.
+ * The AUX_ADV_IND PDUs include the Service Data AD Type in the AdvData
+ * field with the Service UUID equal to the Broadcast Audio Announcement
+ * Service UUID. The additional service data includes Broadcast_ID.
+ *
+ * Each value included in the Codec_Specific_Configuration is formatted in
+ * an LTV structure with the length, type, and value specified in Table 4.74.
+ */
+static void test_bsrc_scc_config(void)
+{
+	define_test("BAP/BSRC/SCC/BV-01-C [Config Broadcast, LC3 8_1_1]",
+		NULL, test_bcast, &cfg_bsrc_8_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-02-C [Config Broadcast, LC3 8_2_1]",
+		NULL, test_bcast, &cfg_bsrc_8_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-03-C [Config Broadcast, LC3 16_1_1]",
+		NULL, test_bcast, &cfg_bsrc_16_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-04-C [Config Broadcast, LC3 16_2_1]",
+		NULL, test_bcast, &cfg_bsrc_16_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-05-C [Config Broadcast, LC3 24_1_1]",
+		NULL, test_bcast, &cfg_bsrc_24_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-06-C [Config Broadcast, LC3 24_2_1]",
+		NULL, test_bcast, &cfg_bsrc_24_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-07-C [Config Broadcast, LC3 32_1_1]",
+		NULL, test_bcast, &cfg_bsrc_32_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-08-C [Config Broadcast, LC3 32_2_1]",
+		NULL, test_bcast, &cfg_bsrc_32_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-09-C [Config Broadcast, LC3 44.1_1_1]",
+		NULL, test_bcast, &cfg_bsrc_44_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-10-C [Config Broadcast, LC3 44.1_2_1]",
+		NULL, test_bcast, &cfg_bsrc_44_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-11-C [Config Broadcast, LC3 48_1_1]",
+		NULL, test_bcast, &cfg_bsrc_48_1_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-12-C [Config Broadcast, LC3 48_2_1]",
+		NULL, test_bcast, &cfg_bsrc_48_2_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-13-C [Config Broadcast, LC3 48_3_1]",
+		NULL, test_bcast, &cfg_bsrc_48_3_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-14-C [Config Broadcast, LC3 48_4_1]",
+		NULL, test_bcast, &cfg_bsrc_48_4_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-15-C [Config Broadcast, LC3 48_5_1]",
+		NULL, test_bcast, &cfg_bsrc_48_5_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-16-C [Config Broadcast, LC3 48_6_1]",
+		NULL, test_bcast, &cfg_bsrc_48_6_1, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-17-C [Config Broadcast, LC3 8_1_2]",
+		NULL, test_bcast, &cfg_bsrc_8_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-18-C [Config Broadcast, LC3 8_2_2]",
+		NULL, test_bcast, &cfg_bsrc_8_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-19-C [Config Broadcast, LC3 16_1_2]",
+		NULL, test_bcast, &cfg_bsrc_16_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-20-C [Config Broadcast, LC3 16_2_2]",
+		NULL, test_bcast, &cfg_bsrc_16_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-21-C [Config Broadcast, LC3 24_1_2]",
+		NULL, test_bcast, &cfg_bsrc_24_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-22-C [Config Broadcast, LC3 24_2_2]",
+		NULL, test_bcast, &cfg_bsrc_24_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-23-C [Config Broadcast, LC3 32_1_2]",
+		NULL, test_bcast, &cfg_bsrc_32_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-24-C [Config Broadcast, LC3 32_2_2]",
+		NULL, test_bcast, &cfg_bsrc_32_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-25-C [Config Broadcast, LC3 44.1_1_2]",
+		NULL, test_bcast, &cfg_bsrc_44_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-26-C [Config Broadcast, LC3 44.1_2_2]",
+		NULL, test_bcast, &cfg_bsrc_44_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-27-C [Config Broadcast, LC3 48_1_2]",
+		NULL, test_bcast, &cfg_bsrc_48_1_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-28-C [Config Broadcast, LC3 48_2_2]",
+		NULL, test_bcast, &cfg_bsrc_48_2_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-29-C [Config Broadcast, LC3 48_3_2]",
+		NULL, test_bcast, &cfg_bsrc_48_3_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-30-C [Config Broadcast, LC3 48_4_2]",
+		NULL, test_bcast, &cfg_bsrc_48_4_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-31-C [Config Broadcast, LC3 48_5_2]",
+		NULL, test_bcast, &cfg_bsrc_48_5_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-32-C [Config Broadcast, LC3 48_6_2]",
+		NULL, test_bcast, &cfg_bsrc_48_6_2, IOV_NULL);
+
+	define_test("BAP/BSRC/SCC/BV-33-C [Config Broadcast, VS]",
+		NULL, test_bcast, &cfg_bsrc_vs, IOV_NULL);
+}
+
+static void bsrc_state_estab(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		bt_bap_stream_enable(stream, true, NULL, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		bt_bap_stream_start(stream, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		tester_test_passed();
+		break;
+	}
+}
+
+static struct test_config cfg_bsrc_8_1_1_estab = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.src = true,
+	.state_func = bsrc_state_estab,
+	.streams = 1,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can establish a broadcast
+ * Audio Stream.
+ *
+ * Pass verdict:
+ * The IUT sends AUX_SYNC_IND PDUs with an Extended Header
+ * containing BIGInfo in the ACAD field. The IUT sends BIS Data
+ * PDUs over the broadcast Audio Stream.
+ */
+static void test_bsrc_scc_estab(void)
+{
+	define_test("BAP/BSRC/SCC/BV-35-C [Establishes Broadcast]",
+		NULL, test_bcast, &cfg_bsrc_8_1_1_estab, IOV_NULL);
+}
+
+static void bsrc_state_disable(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		if (old_state == BT_BAP_STREAM_STATE_IDLE)
+			bt_bap_stream_enable(stream, true, NULL, NULL, NULL);
+		else if (old_state == BT_BAP_STREAM_STATE_STREAMING)
+			tester_test_passed();
+		else
+			/* Other transitions to CONFIG state are invalid. */
+			tester_test_failed();
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		bt_bap_stream_start(stream, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		bt_bap_stream_disable(stream, true, NULL, NULL);
+		break;
+	}
+}
+
+static struct test_config cfg_bsrc_8_1_1_disable = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.src = true,
+	.state_func = bsrc_state_disable,
+	.streams = 1,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can disable a broadcast
+ * Audio Stream.
+ *
+ * Pass verdict:
+ * The IUT sends a BIG_TERMINATE_IND PDU in step 1.
+ */
+static void test_bsrc_scc_disable(void)
+{
+	define_test("BAP/BSRC/SCC/BV-36-C [Disables Broadcast]",
+		NULL, test_bcast, &cfg_bsrc_8_1_1_disable, IOV_NULL);
+}
+
+static void bsrc_state_release(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		if (old_state == BT_BAP_STREAM_STATE_IDLE)
+			bt_bap_stream_enable(stream, true, NULL, NULL, NULL);
+		else if (old_state == BT_BAP_STREAM_STATE_STREAMING)
+			bt_bap_stream_release(stream, NULL, NULL);
+		else
+			/* Other transitions to CONFIG state are invalid. */
+			tester_test_failed();
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		bt_bap_stream_start(stream, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		bt_bap_stream_disable(stream, true, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_IDLE:
+		tester_test_passed();
+		break;
+	}
+}
+
+static struct test_config cfg_bsrc_8_1_1_release = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.src = true,
+	.state_func = bsrc_state_release,
+	.streams = 1,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can release a broadcast
+ * Audio Stream and transition from Configured state to Idle
+ * state.
+ *
+ * Pass verdict:
+ * The IUT stops transmitting periodic advertising.
+ */
+static void test_bsrc_scc_release(void)
+{
+	define_test("BAP/BSRC/SCC/BV-37-C [Releases Broadcast]",
+		NULL, test_bcast, &cfg_bsrc_8_1_1_release, IOV_NULL);
+}
+
+static void test_bsrc_scc(void)
+{
+	test_bsrc_scc_config();
+	test_bsrc_scc_estab();
+	test_bsrc_scc_disable();
+	test_bsrc_scc_release();
+}
+
+static struct test_config cfg_bsnk_8_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_8_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_16_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_16_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_24_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_24_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_32_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_32_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_44_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_44_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_3 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_4 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_5 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_48_6 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_vs = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.snk = true,
+	.vs = true,
+	.state_func = bsnk_state,
+	.streams = 1,
+};
+
+static void test_bsnk_scc(void)
+{
+	define_test("BAP/BSNK/SCC/BV-01-C [Sync to PA, LC3 8_1_1]",
+		NULL, test_bcast, &cfg_bsnk_8_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-02-C [Sync to PA, LC3 8_2_1]",
+		NULL, test_bcast, &cfg_bsnk_8_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-03-C [Sync to PA, LC3 16_1_1]",
+		NULL, test_bcast, &cfg_bsnk_16_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-04-C [Sync to PA, LC3 16_2_1]",
+		NULL, test_bcast, &cfg_bsnk_16_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-05-C [Sync to PA, LC3 24_1_1]",
+		NULL, test_bcast, &cfg_bsnk_24_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-06-C [Sync to PA, LC3 24_2_1]",
+		NULL, test_bcast, &cfg_bsnk_24_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-07-C [Sync to PA, LC3 32_1_1]",
+		NULL, test_bcast, &cfg_bsnk_32_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-08-C [Sync to PA, LC3 32_2_1]",
+		NULL, test_bcast, &cfg_bsnk_32_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-09-C [Sync to PA, LC3 44.1_1_1]",
+		NULL, test_bcast, &cfg_bsnk_44_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-10-C [Sync to PA, LC3 44.1_2_1]",
+		NULL, test_bcast, &cfg_bsnk_44_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-11-C [Sync to PA, LC3 48_1_1]",
+		NULL, test_bcast, &cfg_bsnk_48_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-12-C [Sync to PA, LC3 48_2_1]",
+		NULL, test_bcast, &cfg_bsnk_48_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-13-C [Sync to PA, LC3 48_3_1]",
+		NULL, test_bcast, &cfg_bsnk_48_3, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-14-C [Sync to PA, LC3 48_4_1]",
+		NULL, test_bcast, &cfg_bsnk_48_4, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-15-C [Sync to PA, LC3 48_5_1]",
+		NULL, test_bcast, &cfg_bsnk_48_5, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-16-C [Sync to PA, LC3 48_6_1]",
+		NULL, test_bcast, &cfg_bsnk_48_6, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-17-C [Sync to PA, LC3 8_1_2]",
+		NULL, test_bcast, &cfg_bsnk_8_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-18-C [Sync to PA, LC3 8_2_2]",
+		NULL, test_bcast, &cfg_bsnk_8_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-19-C [Sync to PA, LC3 16_1_2]",
+		NULL, test_bcast, &cfg_bsnk_16_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-20-C [Sync to PA, LC3 16_2_2]",
+		NULL, test_bcast, &cfg_bsnk_16_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-21-C [Sync to PA, LC3 24_1_2]",
+		NULL, test_bcast, &cfg_bsnk_24_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-22-C [Sync to PA, LC3 24_2_2]",
+		NULL, test_bcast, &cfg_bsnk_24_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-23-C [Sync to PA, LC3 32_1_2]",
+		NULL, test_bcast, &cfg_bsnk_32_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-24-C [Sync to PA, LC3 32_2_2]",
+		NULL, test_bcast, &cfg_bsnk_32_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-25-C [Sync to PA, LC3 44.1_1_2]",
+		NULL, test_bcast, &cfg_bsnk_44_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-26-C [Sync to PA, LC3 44.1_2_2]",
+		NULL, test_bcast, &cfg_bsnk_44_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-27-C [Sync to PA, LC3 48_1_2]",
+		NULL, test_bcast, &cfg_bsnk_48_1, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-28-C [Sync to PA, LC3 48_2_2]",
+		NULL, test_bcast, &cfg_bsnk_48_2, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-29-C [Sync to PA, LC3 48_3_2]",
+		NULL, test_bcast, &cfg_bsnk_48_3, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-30-C [Sync to PA, LC3 48_4_2]",
+		NULL, test_bcast, &cfg_bsnk_48_4, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-31-C [Sync to PA, LC3 48_5_2]",
+		NULL, test_bcast, &cfg_bsnk_48_5, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-32-C [Sync to PA, LC3 48_6_2]",
+		NULL, test_bcast, &cfg_bsnk_48_6, IOV_NULL);
+
+	define_test("BAP/BSNK/SCC/BV-33-C [Sync to PA, VS]",
+		NULL, test_bcast, &cfg_bsnk_vs, IOV_NULL);
+}
+
+static void stream_count_streaming(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	uint8_t *num = user_data;
+
+	if (bt_bap_stream_get_state(stream) == BT_BAP_STREAM_STATE_STREAMING)
+		(*num)++;
+}
+
+static void bsnk_state_str(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct test_data *data = user_data;
+	struct iovec *cc;
+	uint8_t num = 0;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		if (old_state == BT_BAP_STREAM_STATE_IDLE) {
+			/* Check that stream has been configured as expected */
+			cc = bt_bap_stream_get_config(stream);
+
+			g_assert(cc);
+			g_assert(cc->iov_len == data->cfg->cc.iov_len);
+			g_assert(memcmp(cc->iov_base, data->cfg->cc.iov_base,
+					cc->iov_len) == 0);
+
+			/* Enable stream */
+			bt_bap_stream_enable(stream, true, NULL, NULL, NULL);
+		} else {
+			/* Other state transitions are invalid */
+			tester_test_failed();
+		}
+
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		/* Start stream */
+		bt_bap_stream_start(stream, NULL, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		queue_foreach(data->streams, stream_count_streaming, &num);
+
+		if (num == data->cfg->streams)
+			/* Test is completed after all streams have transitioned
+			 * to STREAMING state.
+			 */
+			tester_test_passed();
+
+		break;
+	}
+}
+
+static struct test_config cfg_bsnk_str_8_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_8_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_16_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_16_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_24_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_24_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_32_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_32_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_44_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_44_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_3 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_4 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_5 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_48_6 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_vs = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.snk = true,
+	.vs = true,
+	.state_func = bsnk_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsnk_str_8_1_mbis = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_8_2_mbis = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_16_1_mbis = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_16_2_mbis = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_24_1_mbis = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_24_2_mbis = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_32_1_mbis = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_32_2_mbis = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_44_1_mbis = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_44_2_mbis = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_1_mbis = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_2_mbis = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_3_mbis = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_4_mbis = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_5_mbis = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_48_6_mbis = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = QOS_BCAST,
+	.snk = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsnk_str_vs_mbis = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.snk = true,
+	.vs = true,
+	.state_func = bsnk_state_str,
+	.streams = 2,
+};
+
+static void test_bsnk_str(void)
+{
+	define_test("BAP/BSNK/STR/BV-01-C [BSNK, LC3 8_1]",
+		NULL, test_bcast, &cfg_bsnk_str_8_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-02-C [BSNK, LC3 8_2]",
+		NULL, test_bcast, &cfg_bsnk_str_8_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-03-C [BSNK, LC3 16_1]",
+		NULL, test_bcast, &cfg_bsnk_str_16_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-04-C [BSNK, LC3 16_2]",
+		NULL, test_bcast, &cfg_bsnk_str_16_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-05-C [BSNK, LC3 24_1]",
+		NULL, test_bcast, &cfg_bsnk_str_24_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-06-C [BSNK, LC3 24_2]",
+		NULL, test_bcast, &cfg_bsnk_str_24_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-07-C [BSNK, LC3 32_1]",
+		NULL, test_bcast, &cfg_bsnk_str_32_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-08-C [BSNK, LC3 32_2]",
+		NULL, test_bcast, &cfg_bsnk_str_32_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-09-C [BSNK, LC3 44.1_1]",
+		NULL, test_bcast, &cfg_bsnk_str_44_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-10-C [BSNK, LC3 44.1_2]",
+		NULL, test_bcast, &cfg_bsnk_str_44_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-11-C [BSNK, LC3 48_1]",
+		NULL, test_bcast, &cfg_bsnk_str_48_1, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-12-C [BSNK, LC3 48_2]",
+		NULL, test_bcast, &cfg_bsnk_str_48_2, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-13-C [BSNK, LC3 48_3]",
+		NULL, test_bcast, &cfg_bsnk_str_48_3, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-14-C [BSNK, LC3 48_4]",
+		NULL, test_bcast, &cfg_bsnk_str_48_4, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-15-C [BSNK, LC3 48_5]",
+		NULL, test_bcast, &cfg_bsnk_str_48_5, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-16-C [BSNK, LC3 48_6]",
+		NULL, test_bcast, &cfg_bsnk_str_48_6, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-17-C [BSNK, VS]",
+		NULL, test_bcast, &cfg_bsnk_str_vs, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-18-C [BSNK, Multiple BISes, LC3 8_1]",
+		NULL, test_bcast, &cfg_bsnk_str_8_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-19-C [BSNK, Multiple BISes, LC3 8_2]",
+		NULL, test_bcast, &cfg_bsnk_str_8_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-20-C [BSNK, Multiple BISes, LC3 16_1]",
+		NULL, test_bcast, &cfg_bsnk_str_16_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-21-C [BSNK, Multiple BISes, LC3 16_2]",
+		NULL, test_bcast, &cfg_bsnk_str_16_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-22-C [BSNK, Multiple BISes, LC3 24_1]",
+		NULL, test_bcast, &cfg_bsnk_str_24_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-23-C [BSNK, Multiple BISes, LC3 24_2]",
+		NULL, test_bcast, &cfg_bsnk_str_24_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-24-C [BSNK, Multiple BISes, LC3 32_1]",
+		NULL, test_bcast, &cfg_bsnk_str_32_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-25-C [BSNK, Multiple BISes, LC3 32_2]",
+		NULL, test_bcast, &cfg_bsnk_str_32_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-26-C [BSNK, Multiple BISes, LC3 44.1_1]",
+		NULL, test_bcast, &cfg_bsnk_str_44_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-27-C [BSNK, Multiple BISes, LC3 44.1_2]",
+		NULL, test_bcast, &cfg_bsnk_str_44_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-28-C [BSNK, Multiple BISes, LC3 48_1]",
+		NULL, test_bcast, &cfg_bsnk_str_48_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-29-C [BSNK, Multiple BISes, LC3 48_2]",
+		NULL, test_bcast, &cfg_bsnk_str_48_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-30-C [BSNK, Multiple BISes, LC3 48_3]",
+		NULL, test_bcast, &cfg_bsnk_str_48_3_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-31-C [BSNK, Multiple BISes, LC3 48_4]",
+		NULL, test_bcast, &cfg_bsnk_str_48_4_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-32-C [BSNK, Multiple BISes, LC3 48_5]",
+		NULL, test_bcast, &cfg_bsnk_str_48_5_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-33-C [BSNK, Multiple BISes, LC3 48_6]",
+		NULL, test_bcast, &cfg_bsnk_str_48_6_mbis, IOV_NULL);
+
+	define_test("BAP/BSNK/STR/BV-34-C [BSNK, Multiple BISes, VS]",
+		NULL, test_bcast, &cfg_bsnk_str_vs_mbis, IOV_NULL);
+}
+
+static void stream_count_config(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	uint8_t *streams = user_data;
+
+	if (bt_bap_stream_get_state(stream) == BT_BAP_STREAM_STATE_CONFIG)
+		(*streams)++;
+}
+
+static void stream_count_enabling(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+	uint8_t *streams = user_data;
+
+	if (bt_bap_stream_get_state(stream) == BT_BAP_STREAM_STATE_ENABLING)
+		(*streams)++;
+}
+
+static void stream_enable(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+
+	bt_bap_stream_enable(stream, true, NULL, NULL, NULL);
+}
+
+static void stream_start(void *data, void *user_data)
+{
+	struct bt_bap_stream *stream = data;
+
+	bt_bap_stream_start(stream, NULL, NULL);
+}
+
+static void bsrc_state_str(struct bt_bap_stream *stream, uint8_t old_state,
+				uint8_t new_state, void *user_data)
+{
+	struct test_data *data = user_data;
+	uint8_t streams = 0;
+
+	switch (new_state) {
+	case BT_BAP_STREAM_STATE_CONFIG:
+		queue_foreach(data->streams, stream_count_config, &streams);
+
+		if (streams == data->cfg->streams)
+			/* After all streams have transitioned to CONFIG
+			 * state, enable each one.
+			 */
+			queue_foreach(data->streams, stream_enable, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_ENABLING:
+		queue_foreach(data->streams, stream_count_enabling, &streams);
+
+		if (streams == 1) {
+			/* After the first stream has transitioned to ENABLING
+			 * state, bt_bap_stream_get_base will generate the
+			 * BASE from all previously configured streams.
+			 */
+			data->base = bt_bap_stream_get_base(stream);
+
+			g_assert(data->base);
+			g_assert(data->base->iov_len ==
+					data->cfg->base.iov_len);
+			g_assert(memcmp(data->base->iov_base,
+					data->cfg->base.iov_base,
+					data->base->iov_len) == 0);
+		}
+
+		if (streams == data->cfg->streams)
+			/* After all streams have transitioned to ENABLING
+			 * state, start each one.
+			 */
+			queue_foreach(data->streams, stream_start, NULL);
+		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		queue_foreach(data->streams, stream_count_streaming, &streams);
+
+		if (streams == data->cfg->streams)
+			/* Test is completed after all streams have transitioned
+			 * to STREAMING state.
+			 */
+			tester_test_passed();
+		break;
+	}
+}
+
+static struct test_config cfg_bsrc_str_8_1 = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_8_2 = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_16_1 = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_16_2 = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_24_1 = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_24_2 = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_32_1 = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_32_2 = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_44_1 = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_44_2 = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_1 = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_1),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_2 = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_2),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_3 = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_3),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_4 = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_4),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_5 = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_5),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_48_6 = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_6),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+};
+
+static struct test_config cfg_bsrc_str_vs = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.base = UTIL_IOV_INIT(BASE_VS(VS_CFG)),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 1,
+	.vs = true,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can stream one BIS to a
+ * Broadcast Sink. The verification is performed for each Config
+ * Settings in turn.
+ *
+ * Pass verdict:
+ * If the Codec ID is LC3, the IUT sends encoded LC3 audio data
+ * in BIS Data PDUs on the broadcast Audio Stream. The audio data
+ * is formatted using the LC3 Media Packet format.
+ *
+ * If the Codec ID is a vendor-specific Codec ID, the IUT sends BIS
+ * Data PDUs on the broadcast Audio Stream. The parameters included
+ * in the Codec_Specific_Configuration data are as defined in
+ * TSPX_VS_Codec_Specific_Configuration.
+ *
+ * If the Codec ID is LC3, each parameter included in
+ * Codec_Specific_Configuration data is formatted in an LTV structure
+ * with the length, type, and value specified in Table 4.79.
+ */
+
+static void test_bsrc_str_1b(void)
+{
+	define_test("BAP/BSRC/STR/BV-01-C [BSRC, LC3 8_1]",
+		NULL, test_bcast, &cfg_bsrc_str_8_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-02-C [BSRC, LC3 8_2]",
+		NULL, test_bcast, &cfg_bsrc_str_8_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-03-C [BSRC, LC3 16_1]",
+		NULL, test_bcast, &cfg_bsrc_str_16_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-04-C [BSRC, LC3 16_2]",
+		NULL, test_bcast, &cfg_bsrc_str_16_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-05-C [BSRC, LC3 24_1]",
+		NULL, test_bcast, &cfg_bsrc_str_24_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-06-C [BSRC, LC3 24_2]",
+		NULL, test_bcast, &cfg_bsrc_str_24_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-07-C [BSRC, LC3 32_1]",
+		NULL, test_bcast, &cfg_bsrc_str_32_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-08-C [BSRC, LC3 32_2]",
+		NULL, test_bcast, &cfg_bsrc_str_32_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-09-C [BSRC, LC3 44.1_1]",
+		NULL, test_bcast, &cfg_bsrc_str_44_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-10-C [BSRC, LC3 44.1_2]",
+		NULL, test_bcast, &cfg_bsrc_str_44_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-11-C [BSRC, LC3 48_1]",
+		NULL, test_bcast, &cfg_bsrc_str_48_1, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-12-C [BSRC, LC3 48_2]",
+		NULL, test_bcast, &cfg_bsrc_str_48_2, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-13-C [BSRC, LC3 48_3]",
+		NULL, test_bcast, &cfg_bsrc_str_48_3, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-14-C [BSRC, LC3 48_4]",
+		NULL, test_bcast, &cfg_bsrc_str_48_4, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-15-C [BSRC, LC3 48_5]",
+		NULL, test_bcast, &cfg_bsrc_str_48_5, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-16-C [BSRC, LC3 48_6]",
+		NULL, test_bcast, &cfg_bsrc_str_48_6, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-17-C [BSRC, VS]",
+		NULL, test_bcast, &cfg_bsrc_str_vs, IOV_NULL);
+}
+
+static struct test_config cfg_bsrc_str_8_1_mbis = {
+	.cc = LC3_CONFIG_8_1,
+	.qos = LC3_QOS_8_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_8_2_mbis = {
+	.cc = LC3_CONFIG_8_2,
+	.qos = LC3_QOS_8_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_8_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_16_1_mbis = {
+	.cc = LC3_CONFIG_16_1,
+	.qos = LC3_QOS_16_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_16_2_mbis = {
+	.cc = LC3_CONFIG_16_2,
+	.qos = LC3_QOS_16_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_16_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_24_1_mbis = {
+	.cc = LC3_CONFIG_24_1,
+	.qos = LC3_QOS_24_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_24_2_mbis = {
+	.cc = LC3_CONFIG_24_2,
+	.qos = LC3_QOS_24_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_24_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_32_1_mbis = {
+	.cc = LC3_CONFIG_32_1,
+	.qos = LC3_QOS_32_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_32_2_mbis = {
+	.cc = LC3_CONFIG_32_2,
+	.qos = LC3_QOS_32_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_32_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_44_1_mbis = {
+	.cc = LC3_CONFIG_44_1,
+	.qos = LC3_QOS_44_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_44_2_mbis = {
+	.cc = LC3_CONFIG_44_2,
+	.qos = LC3_QOS_44_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_44_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_1_mbis = {
+	.cc = LC3_CONFIG_48_1,
+	.qos = LC3_QOS_48_1_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_1_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_2_mbis = {
+	.cc = LC3_CONFIG_48_2,
+	.qos = LC3_QOS_48_2_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_2_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_3_mbis = {
+	.cc = LC3_CONFIG_48_3,
+	.qos = LC3_QOS_48_3_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_3_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_4_mbis = {
+	.cc = LC3_CONFIG_48_4,
+	.qos = LC3_QOS_48_4_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_4_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_5_mbis = {
+	.cc = LC3_CONFIG_48_5,
+	.qos = LC3_QOS_48_5_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_5_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_48_6_mbis = {
+	.cc = LC3_CONFIG_48_6,
+	.qos = LC3_QOS_48_6_1_B,
+	.base = UTIL_IOV_INIT(BASE_LC3_48_6_MBIS),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.streams = 2,
+};
+
+static struct test_config cfg_bsrc_str_vs_mbis = {
+	.cc = UTIL_IOV_INIT(VS_CC),
+	.qos = QOS_BCAST,
+	.base = UTIL_IOV_INIT(BASE_VS_MBIS(VS_CFG)),
+	.src = true,
+	.state_func = bsrc_state_str,
+	.vs = true,
+	.streams = 2,
+};
+
+/* Test Purpose:
+ * Verify that a Broadcast Source IUT can stream multiple BISes to
+ * a Broadcast Sink. The verification is performed for each set of
+ * parameters in turn, as specified in Table 4.82.
+ *
+ * Pass verdict:
+ * If the Codec ID is LC3, the IUT sends encoded LC3 audio data in
+ * BIS Data PDUs on each synchronized BIS.
+ *
+ * If the Codec ID is a vendor-specific Codec ID, the IUT sends BIS
+ * Data PDUs on each synchronized BIS. The parameters included in the
+ * Codec_Specific_Configuration data are as defined in
+ * TSPX_VS_Codec_Specific_Configuration.
+ *
+ * If the Codec ID is LC3, each parameter included in
+ * Codec_Specific_Configuration data is formatted in an LTV structure
+ * with the length, type, and value specified in Table 4.83.
+ */
+static void test_bsrc_str_2b(void)
+{
+	define_test("BAP/BSRC/STR/BV-18-C [BSRC, Multiple BISes, LC3 8_1]",
+		NULL, test_bcast, &cfg_bsrc_str_8_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-19-C [BSRC, Multiple BISes, LC3 8_2]",
+		NULL, test_bcast, &cfg_bsrc_str_8_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-20-C [BSRC, Multiple BISes, LC3 16_1]",
+		NULL, test_bcast, &cfg_bsrc_str_16_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-21-C [BSRC, Multiple BISes, LC3 16_2]",
+		NULL, test_bcast, &cfg_bsrc_str_16_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-22-C [BSRC, Multiple BISes, LC3 24_1]",
+		NULL, test_bcast, &cfg_bsrc_str_24_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-23-C [BSRC, Multiple BISes, LC3 24_2]",
+		NULL, test_bcast, &cfg_bsrc_str_24_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-24-C [BSRC, Multiple BISes, LC3 32_1]",
+		NULL, test_bcast, &cfg_bsrc_str_32_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-25-C [BSRC, Multiple BISes, LC3 32_2]",
+		NULL, test_bcast, &cfg_bsrc_str_32_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-26-C [BSRC, Multiple BISes, LC3 44.1_1]",
+		NULL, test_bcast, &cfg_bsrc_str_44_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-27-C [BSRC, Multiple BISes, LC3 44.1_2]",
+		NULL, test_bcast, &cfg_bsrc_str_44_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-28-C [BSRC, Multiple BISes, LC3 48_1]",
+		NULL, test_bcast, &cfg_bsrc_str_48_1_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-29-C [BSRC, Multiple BISes, LC3 48_2]",
+		NULL, test_bcast, &cfg_bsrc_str_48_2_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-30-C [BSRC, Multiple BISes, LC3 48_3]",
+		NULL, test_bcast, &cfg_bsrc_str_48_3_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-31-C [BSRC, Multiple BISes, LC3 48_4]",
+		NULL, test_bcast, &cfg_bsrc_str_48_4_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-32-C [BSRC, Multiple BISes, LC3 48_5]",
+		NULL, test_bcast, &cfg_bsrc_str_48_5_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-33-C [BSRC, Multiple BISes, LC3 48_6]",
+		NULL, test_bcast, &cfg_bsrc_str_48_6_mbis, IOV_NULL);
+
+	define_test("BAP/BSRC/STR/BV-34-C [BSRC, Multiple BISes, VS]",
+		NULL, test_bcast, &cfg_bsrc_str_vs_mbis, IOV_NULL);
+}
+
+static void test_bsrc_str(void)
+{
+	test_bsrc_str_1b();
+	test_bsrc_str_2b();
+}
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_disc();
+	test_scc();
+	test_bsrc_scc();
+	test_bsnk_scc();
+	test_bsnk_str();
+	test_bsrc_str();
+
+	return tester_run();
+}
diff --git a/unit/test-bass.c b/unit/test-bass.c
new file mode 100644
index 0000000..ace47d9
--- /dev/null
+++ b/unit/test-bass.c
@@ -0,0 +1,823 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright 2023 NXP
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "src/shared/util.h"
+#include "src/shared/io.h"
+#include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/bass.h"
+
+struct test_data {
+	struct gatt_db *db;
+	struct bt_bass *bass;
+	struct bt_gatt_server *server;
+	struct queue *ccc_states;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+struct ccc_state {
+	uint16_t handle;
+	uint16_t value;
+};
+
+/* ATT: Exchange MTU Request (0x02) len 2
+ *   Client RX MTU: 64
+ * ATT: Exchange MTU Response (0x03) len 2
+ *   Server RX MTU: 64
+ */
+#define EXCHANGE_MTU \
+	IOV_DATA(0x02, 0x40, 0x00), \
+	IOV_DATA(0x03, 0x40, 0x00)
+
+/* ATT: Find By Type Value Request (0x06) len 8
+ *   Handle range: 0x0001-0xffff
+ *   Attribute Type(UUID): Primary Service (0x2800)
+ *   Value to find: Broadcast Audio Scan Service (0x184f)
+ * ATT: Find By Type Value Response (0x07) len 4
+ *   Handle range: 0x0001-0x0009
+ * ATT: Find By Type Value Request (0x06) len 8
+ *   Handle range: 0x000a-0xffff
+ *   Attribute Type(UUID): Primary Service (0x2800)
+ *   Value to find: Broadcast Audio Scan Service (0x184f)
+ * ATT: Error Response (0x01) len 4
+ *   Find By Type Value Request (0x06)
+ *   Handle: 0x000a
+ *   Error: Attribute Not Found (0x0a)
+ */
+#define BASS_FIND_BY_TYPE_VALUE \
+	IOV_DATA(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0x4f, 0x18), \
+	IOV_DATA(0x07, 0x01, 0x00, 0x09, 0x00), \
+	IOV_DATA(0x06, 0x0a, 0x00, 0xff, 0xff, 0x00, 0x28, 0x4f, 0x18), \
+	IOV_DATA(0x01, 0x06, 0x0a, 0x00, 0x0a)
+
+/* ATT: Read By Type Request (0x08) len 6
+ *   Handle range: 0x0001-0x0009
+ *   Attribute type: Characteristic (0x2803)
+ * ATT: Read By Type Response (0x09) len 22
+ * Attribute data length: 7
+ * Attribute data list: 3 entries
+ *   Handle: 0x0002
+ *   Value: 120300c82b
+ *   Properties: 0x12
+ *     Read (0x02)
+ *     Notify (0x10)
+ *   Value Handle: 0x0003
+ *   Value UUID: Broadcast Receive State (0x2bc8)
+ *   Handle: 0x0005
+ *   Value: 120600c82b
+ *   Properties: 0x12
+ *     Read (0x02)
+ *     Notify (0x10)
+ *   Value Handle: 0x0006
+ *   Value UUID: Broadcast Receive State (0x2bc8)
+ *   Handle: 0x0008
+ *   Value: 0c0900c72b
+ *   Properties: 0x0c
+ *     Write (0x08)
+ *     Write Without Response (0x04)
+ *   Value Handle: 0x0009
+ *   Value UUID: Broadcast Audio Scan Control Point (0x2bc7)
+ * ATT: Read By Type Request (0x08) len 6
+ *   Handle range: 0x0009-0x0009
+ *   Attribute type: Characteristic (0x2803)
+ * ATT: Error Response (0x01) len 4
+ *   Read By Type Request (0x08)
+ *   Handle: 0x0009
+ *   Error: Attribute Not Found (0x0a)
+ */
+#define DISC_BASS_CHAR \
+	IOV_DATA(0x08, 0x01, 0x00, 0x09, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x09, 0x07, \
+		0x02, 0x00, 0x12, 0x03, 0x00, 0xc8, 0x2b, \
+		0x05, 0x00, 0x12, 0x06, 0x00, 0xc8, 0x2b, \
+		0x08, 0x00, 0x0c, 0x09, 0x00, 0xc7, 0x2b), \
+	IOV_DATA(0x08, 0x09, 0x00, 0x09, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x09, 0x00, 0x0a)
+
+/* ATT: Read By Group Type Request (0x10) len 6
+ *   Handle range: 0x0001-0xffff
+ *   Attribute group type: Primary Service (0x2800)
+ * ATT: Read By Group Type Response (0x11) len 7
+ *   Attribute data length: 6
+ *   Attribute group list: 1 entry
+ *   Handle range: 0x0001-0x0009
+ *   UUID: Broadcast Audio Scan Service (0x184f)
+ * ATT: Read By Group Type Request (0x10) len 6
+ *   Handle range: 0x000a-0xffff
+ *   Attribute group type: Primary Service (0x2800)
+ * ATT: Error Response (0x01) len 4
+ *   Read By Group Type Request (0x10)
+ *   Handle: 0x000a
+ *   Error: Attribute Not Found (0x0a)
+ */
+#define DISC_BASS_SER \
+	EXCHANGE_MTU,\
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x11, 0x06, 0x01, 0x00, 0x09, 0x00, 0x4f, 0x18), \
+	IOV_DATA(0x10, 0x0a, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x0a, 0x00, 0x0a), \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR
+
+/* ATT: Find Information Request (0x04) len 4
+ *   Handle range: 0x0004-0x0004
+ * ATT: Find Information Response (0x05) len 5
+ *   Format: Handle(s) and 16 bit bluetooth UUID(s) (0x01)
+ *   Handle: 0x0004
+ *   Attribute: Client Characteristic Configuration (0x2902)
+ * ATT: Find Information Request (0x04) len 4
+ *   Handle range: 0x0007-0x0007
+ * ATT: Find Information Response (0x05) len 5
+ *   Format: Handle(s) and 16 bit bluetooth UUID(s) (0x01)
+ *   Handle: 0x0007
+ *   Attribute: Client Characteristic Configuration (0x2902)
+ */
+#define BASS_FIND_INFO \
+	IOV_DATA(0x04, 0x04, 0x00, 0x04, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x04, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x07, 0x00, 0x07, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x07, 0x00, 0x02, 0x29)
+
+#define DISC_BCAST_AUDIO_SCAN_CP \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0004 Type: Client Characteristic Configuration (0x2902)
+ * ATT: Read Response (0x0b) len 2
+ *   Value: 0000
+ *   Handle: 0x0004 Type: Client Characteristic Configuration (0x2902)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0007 Type: Client Characteristic Configuration (0x2902)
+ * ATT: Read Response (0x0b) len 2
+ *   Value: 0000
+ *   Handle: 0x0007 Type: Client Characteristic Configuration (0x2902)
+ */
+#define BASS_READ_CHAR_DESC \
+	IOV_DATA(0x0a, 0x04, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x07, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00)
+
+#define DISC_BCAST_RECV_STATE \
+	DISC_BCAST_AUDIO_SCAN_CP, \
+	BASS_READ_CHAR_DESC
+
+/* ATT: Write Request (0x12) len 4
+ *   Handle: 0x0004 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0007 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define BASS_WRITE_CHAR_DESC \
+	IOV_DATA(0x12, 0x04, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x12, 0x07, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0003 Type: Broadcast Receive State (0x2bc8)
+ * ATT: Read Response (0x0b) len 0
+ *   Handle: 0x0003 Broadcast Receive State (0x2bc8)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0006 Type: Broadcast Receive State (0x2bc8)
+ * ATT: Read Response (0x0b) len 0
+ *   Handle: 0x0006 Broadcast Receive State (0x2bc8)
+ */
+#define BASS_READ_BCAST_RECV_STATE_CHARS \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b), \
+	IOV_DATA(0x0a, 0x06, 0x00), \
+	IOV_DATA(0x0b)
+
+#define BASS_CP_WRITE_CMD(_op, _args...) \
+	IOV_DATA(0x52, 0x09, 0x00, _op, _args)
+
+#define BASS_CP_WRITE_REQ(_op, _args...) \
+	IOV_DATA(0x12, 0x09, 0x00, _op, _args)
+
+/* ATT: Write Command (0x52) len 19
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0401693C4572685526613465597073275455
+ *       Opcode: Set Broadcast_Code
+ *       Source_ID: 1
+ *       Broadcast_Code: 0x55542773705965346126556872453c69
+ * ATT: Write Command (0x52) len 2
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0501
+ *       Opcode: Remove Source
+ *       Source_ID: 1
+ */
+#define IGNORE_INVALID_SRC_ID \
+	EXCHANGE_MTU, \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO, \
+	BASS_WRITE_CHAR_DESC, \
+	BASS_READ_BCAST_RECV_STATE_CHARS, \
+	BASS_CP_WRITE_CMD(0x04, 0x01, 0x69, 0x3C, 0x45, 0x72, 0x68, \
+			0x55, 0x26, 0x61, 0x34, 0x65, 0x59, 0x70, \
+			0x73, 0x27, 0x54, 0x55), \
+	IOV_NULL, \
+	BASS_CP_WRITE_CMD(0x05, 0x01)
+
+/* ATT: Write Command (0x52) len 26
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0200F2698BE807C0003412000610270200000000000000000000
+ *       Opcode: Add Source
+ *       Advertiser_Address_Type: Public Device or Public Identity Address
+ *       Advertiser_Address: c0:07:e8:8b:69:f2
+ *       Advertising_SID: 0x00
+ *       Broadcast_ID: 0x001234
+ *       PA_Sync: 0x06 (Reserved for Future Use)
+ *       PA_Interval: 0x2710
+ *       Num_Subgroups: 2
+ *         Subgroup #0:
+ *           BIS_Sync: 00000000000000000000000000000000
+ *           Metadata_Length: 0
+ *         Subgroup #1:
+ *           BIS_Sync: 00000000000000000000000000000000
+ *           Metadata_Length: 0
+ * ATT: Write Command (0x52) len 26
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0205F2698BE807C0003412000210270200000000000000000000
+ *       Opcode: Add Source
+ *       Advertiser_Address_Type: 0x05 (Reserved for Future Use)
+ *       Advertiser_Address: c0:07:e8:8b:69:f2
+ *       Advertising_SID: 0x00
+ *       Broadcast_ID: 0x001234
+ *       PA_Sync: Synchronize to PA (PAST not available)
+ *       PA_Interval: 0x2710
+ *       Num_Subgroups: 2
+ *         Subgroup #0:
+ *           BIS_Sync: 00000000000000000000000000000000
+ *           Metadata_Length: 0
+ *         Subgroup #1:
+ *           BIS_Sync: 00000000000000000000000000000000
+ *           Metadata_Length: 0
+ * ATT: Write Command (0x52) len 26
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0200F2698BE807C0003412000210270201000000000100000000
+ *       Opcode: Add Source
+ *       Advertiser_Address_Type: Public Device or Public Identity Address
+ *       Advertiser_Address: c0:07:e8:8b:69:f2
+ *       Advertising_SID: 0x00
+ *       Broadcast_ID: 0x001234
+ *       PA_Sync: Synchronize to PA (PAST not available)
+ *       PA_Interval: 0x2710
+ *       Num_Subgroups: 2
+ *         Subgroup #0:
+ *           BIS_Sync: 00000000000000000000000000000001
+ *           Metadata_Length: 0
+ *         Subgroup #1:
+ *           BIS_Sync: 00000000000000000000000000000001
+ *           Metadata_Length: 0
+ */
+#define ADD_SRC_INVALID_PARAMS \
+	EXCHANGE_MTU, \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO, \
+	BASS_WRITE_CHAR_DESC,\
+	BASS_READ_BCAST_RECV_STATE_CHARS, \
+	BASS_CP_WRITE_CMD(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+			0x00, 0x34, 0x12, 0x00, 0x06, 0x10, 0x27, 0x02, \
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+			0x00, 0x00), \
+	IOV_NULL, \
+	BASS_CP_WRITE_CMD(0x02, 0x05, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+			0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+			0x00, 0x00), \
+	IOV_NULL, \
+	BASS_CP_WRITE_CMD(0x02, 0x05, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+			0x3F, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+			0x00, 0x00), \
+	IOV_NULL, \
+	BASS_CP_WRITE_CMD(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+			0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+			0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, \
+			0x00, 0x00)
+
+/* ATT: Write Request (0x12) len 3
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: FF
+ *       Opcode: 0xff (Reserved  For Future Use)
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Opcode Not Supported (0x80)
+ */
+#define OPCODE_NOT_SUPPORTED \
+	EXCHANGE_MTU, \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO, \
+	BASS_WRITE_CHAR_DESC,\
+	BASS_READ_BCAST_RECV_STATE_CHARS, \
+	BASS_CP_WRITE_REQ(0xFF), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x80)
+
+/* ATT: Write Request (0x12) len 5
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 006dfe
+ *       Opcode: Remote Scan Stopped
+ *       Extra Data: 0xfe6d
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 5
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 006dfe
+ *       Opcode: Remote Scan Started
+ *       Extra Data: 0xa2c2
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 25
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0200F2698BE807C0003412000210270100000000000000
+ *       Opcode: Add Source
+ *       Advertiser_Address_Type: Public Device or Public Identity Address
+ *       Advertiser_Address: c0:07:e8:8b:69:f2
+ *       Advertising_SID: 0x00
+ *       Broadcast_ID: 0x001234
+ *       PA_Sync: Synchronize to PA (PAST not available)
+ *       PA_Interval: 0x2710
+ *       Num_Subgroups: 1
+ *         Subgroup #0:
+ *           BIS_Sync: 00000000000000000000000000000001
+ *           Metadata_Length: 0
+ *       Extra Data: 0x0000
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 13
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 03000210270100000000001500
+ *       Opcode: Modify Source
+ *       Source_ID: 0x00
+ *       PA_Sync: Synchronize to PA (PAST not available)
+ *       PA_Interval: 0x2710
+ *       Num_Subgroups: 1
+ *         Subgroup #0:
+ *           BIS_Sync: 00000000000000000000000000000001
+ *           Metadata_Length: 0
+ *       Extra Data: 0x0015
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 20
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0400B803EAC6AFBB65A25A41F153056802010000
+ *       Opcode: Set Broadcast_Code
+ *       Source_ID: 0x00
+ *       Broadcast_Code: 0x0102680553f1415aa265bbafc6ea03b8
+ *       Extra Data: 0x0000
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 05008F13
+ *       Opcode: Remove Source
+ *       Source_ID: 0x00
+ *       Extra Data: 0x138f
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Write Request Rejected (0xFC)
+ */
+#define INVALID_LEN \
+	EXCHANGE_MTU, \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO, \
+	BASS_WRITE_CHAR_DESC,\
+	BASS_READ_BCAST_RECV_STATE_CHARS, \
+	BASS_CP_WRITE_REQ(0x00, 0x6D, 0xFE), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+	BASS_CP_WRITE_REQ(0x01, 0xC2, 0xA2), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+	BASS_CP_WRITE_REQ(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+			0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x01, \
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+	BASS_CP_WRITE_REQ(0x03, 0x00, 0x02, 0x10, 0x27, 0x01, 0x00, 0x00, \
+			0x00, 0x00, 0x00, 0x15, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+	BASS_CP_WRITE_REQ(0x04, 0x00, 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, \
+			0x65, 0xA2, 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, \
+			0x02, 0x01, 0x00, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+	BASS_CP_WRITE_REQ(0x05, 0x00, 0x8F, 0x13), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC)
+
+/* ATT: Write Request (0x12) len 20
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 0400B803EAC6AFBB65A25A41F153056802010000
+ *       Opcode: Set Broadcast_Code
+ *       Source_ID: 0x05
+ *       Broadcast_Code: 0x0102680553f1415aa265bbafc6ea03b
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Invalid Source ID (0x81)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ *     Data: 005
+ *       Opcode: Remove Source
+ *       Source_ID: 0x05
+ * ATT: Error Response (0x01) len 4
+ *   Write Request (0x12)
+ *   Handle: 0x0009
+ *   Error: Invalid Source ID (0x81)
+ */
+#define INVALID_SRC_ID \
+	EXCHANGE_MTU, \
+	BASS_FIND_BY_TYPE_VALUE, \
+	DISC_BASS_CHAR, \
+	BASS_FIND_INFO, \
+	BASS_WRITE_CHAR_DESC, \
+	BASS_READ_BCAST_RECV_STATE_CHARS, \
+	BASS_CP_WRITE_REQ(0x04, 0x05, 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, \
+			0x65, 0xA2, 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, \
+			0x02, 0x01), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x81), \
+	BASS_CP_WRITE_REQ(0x05, 0x05), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x81)
+
+#define iov_data(args...) ((const struct iovec[]) { args })
+
+#define define_test(name, function, _cfg, args...)		\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data data;			\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		tester_add(name, &data, NULL, function,	\
+				test_teardown);			\
+	} while (0)
+
+static void test_complete_cb(const void *user_data)
+{
+	tester_test_passed();
+}
+
+static void print_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	if (tester_use_debug())
+		tester_debug("%s%s", prefix, str);
+}
+
+static void test_teardown(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+
+	bt_bass_unref(data->bass);
+	bt_gatt_server_unref(data->server);
+	util_iov_free(data->iov, data->iovcnt);
+
+	gatt_db_unref(data->db);
+
+	queue_destroy(data->ccc_states, free);
+
+	tester_teardown_complete();
+}
+
+static bool ccc_state_match(const void *a, const void *b)
+{
+	const struct ccc_state *ccc = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return ccc->handle == handle;
+}
+
+static struct ccc_state *find_ccc_state(struct test_data *data,
+				uint16_t handle)
+{
+	return queue_find(data->ccc_states, ccc_state_match,
+				UINT_TO_PTR(handle));
+}
+
+static struct ccc_state *get_ccc_state(struct test_data *data, uint16_t handle)
+{
+	struct ccc_state *ccc;
+
+	ccc = find_ccc_state(data, handle);
+	if (ccc)
+		return ccc;
+
+	ccc = new0(struct ccc_state, 1);
+	ccc->handle = handle;
+	queue_push_tail(data->ccc_states, ccc);
+
+	return ccc;
+}
+
+static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	struct ccc_state *ccc;
+	uint16_t handle;
+	uint8_t ecode = 0;
+	const uint8_t *value = NULL;
+	size_t len = 0;
+
+	handle = gatt_db_attribute_get_handle(attrib);
+
+	ccc = get_ccc_state(data, handle);
+	if (!ccc) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	len = sizeof(ccc->value);
+	value = (void *) &ccc->value;
+
+done:
+	gatt_db_attribute_read_result(attrib, id, ecode, value, len);
+}
+
+static void gatt_ccc_write_cb(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 test_data *data = (void *)user_data;
+	struct ccc_state *ccc_state;
+	uint16_t val;
+	uint8_t ecode = 0;
+
+	if (!value || len > 2) {
+		ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto done;
+	}
+
+	if (offset > 2) {
+		ecode = BT_ATT_ERROR_INVALID_OFFSET;
+		goto done;
+	}
+
+	if (len == 1)
+		val = *value;
+	else
+		val = get_le16(value);
+
+	ccc_state = get_ccc_state(data, gatt_db_attribute_get_handle(attrib));
+	if (!ccc_state)
+		return;
+
+	/* If value is identical, then just succeed */
+	if (val == ccc_state->value)
+		goto done;
+
+	ccc_state->value = val;
+
+done:
+	gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
+static void gatt_notify_cb(struct gatt_db_attribute *attrib,
+				struct gatt_db_attribute *ccc,
+				const uint8_t *value, size_t len,
+				struct bt_att *att, void *user_data)
+{
+	struct test_data *data = user_data;
+	struct ccc_state *ccc_state;
+
+	ccc_state = find_ccc_state(data, gatt_db_attribute_get_handle(ccc));
+	if (!ccc_state || !(ccc_state->value & 0x0001))
+		return;
+
+	bt_gatt_server_send_notification(data->server,
+		gatt_db_attribute_get_handle(attrib),
+		value, len, false);
+}
+
+static void test_server(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct bt_att *att;
+	struct io *io;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, gatt_ccc_write_cb,
+					gatt_notify_cb, data);
+
+	data->bass = bt_bass_new(data->db, NULL, BDADDR_ANY);
+	g_assert(data->bass);
+
+	bt_bass_set_att(data->bass, att);
+	bt_bass_attach(data->bass, NULL);
+
+	bt_bass_set_debug(data->bass, print_debug, "bt_bass:", NULL);
+
+	data->server = bt_gatt_server_new(data->db, att, 64, 0);
+	g_assert(data->server);
+
+	bt_gatt_server_set_debug(data->server, print_debug, "bt_gatt_server:",
+						NULL);
+
+	data->ccc_states = queue_new();
+
+	tester_io_send();
+
+	bt_att_unref(att);
+}
+
+static void test_sggit(void)
+{
+	/* BASS/SR/SGGIT/SER/BV-01-C [Service GGIT - Broadcast Scan]
+	 *
+	 * For each ATT_Read_By_Group_Type_Request, the IUT sends a correctly
+	 * formatted ATT_Read_By_Group_Type_Response reporting BASS to the
+	 * Lower Tester, or an ATT_Error_Response if there is no handle/UUID
+	 * pair matching the request.
+	 *
+	 * For each ATT_Find_By_Type_Value_Request, the IUT sends one
+	 * ATT_Find_By_Type_Value_Response reporting BASS to the Lower Tester,
+	 * or an ATT_Error_Response when there are no more services matching
+	 * the request.
+	 *
+	 * The IUT sends one ATT_Read_By_Type_Response to the Lower Tester for
+	 * each received ATT_Read_By_Type_Request, if it has characteristic
+	 * declarations within the handle range, or an ATT_Error_Response if
+	 * there are no further characteristic declarations within the
+	 * handle range of the request. The IUT reports all BASS
+	 * characteristics.
+	 */
+	define_test("BASS/SR/SGGIT/SER/BV-01-C", test_server, NULL,
+							DISC_BASS_SER);
+
+	/* BASS/SR/SGGIT/CHA/BV-01-C [Service GGIT -
+	 * Broadcast Audio Scan Control Point]
+	 *
+	 * The IUT sends one ATT_Read_By_Type_Response to the Lower Tester for
+	 * each received ATT_Read_By_Type_Request, if it has characteristic
+	 * declarations within the handle range, or an ATT_Error_Response if
+	 * there are no further characteristic declarations within the
+	 * handle range of the request. The IUT reports one instance of the
+	 * Broadcast Audio Scan Control Point characteristic.
+	 */
+	define_test("BASS/SR/SGGIT/CHA/BV-01-C", test_server, NULL,
+						DISC_BCAST_AUDIO_SCAN_CP);
+
+	/* BASS/SR/SGGIT/CHA/BV-02-C [Service GGIT -
+	 * Broadcast Receive State]
+	 *
+	 * The IUT sends one ATT_Read_By_Type_Response to the Lower Tester for
+	 * each received ATT_Read_By_Type_Request, if it has characteristic
+	 * declarations within the handle range, or an ATT_Error_Response if
+	 * there are no further characteristic declarations within the
+	 * handle range of the request. The IUT reports two instances of the
+	 * Broadcast Receive State characteristic.
+	 *
+	 * The IUT sends one ATT_Find_Information_Response to the Lower Tester
+	 * for each received ATT_Find_Information_Request, if it has
+	 * characteristic descriptors within the handle range, or an
+	 * ATT_Error_Response if there are no characteristic descriptors within
+	 * the handle range of the request. For each Broadcast Receive State
+	 * characteristic, the IUT reports one Client Characteristic
+	 * Configuration descriptor.
+	 *
+	 * The IUT sends an ATT_Read_Response to the Lower Tester for each
+	 * ATT_Read_Request.
+	 */
+	define_test("BASS/SR/SGGIT/CHA/BV-02-C", test_server, NULL,
+						DISC_BCAST_RECV_STATE);
+}
+
+static void test_spe(void)
+{
+	/* BASS/SR/SPE/BI-01-C [Ignore Invalid Source ID]
+	 *
+	 * Test Purpose:
+	 * Verify that the BASS Server IUT does not respond to a control point
+	 * procedure call that uses an invalid Source_ID parameter.
+	 *
+	 * Pass verdict:
+	 * The IUT does not send a notification of the Broadcast Receive State
+	 * characteristic.
+	 */
+	define_test("BASS/SR/SPE/BI-01-C", test_server, NULL,
+				IGNORE_INVALID_SRC_ID);
+
+	/* BASS/SR/SPE/BI-03-C [Add Source - Ignore Invalid Values]
+	 *
+	 * Test Purpose:
+	 * Verify that the BASS Server IUT ignores Add Source control point
+	 * procedure calls that include an RFU or Invalid parameter.
+	 *
+	 * Pass verdict:
+	 * The IUT does not send a notification of the Broadcast Receive State
+	 * characteristic.
+	 */
+	define_test("BASS/SR/SPE/BI-03-C", test_server, NULL,
+				ADD_SRC_INVALID_PARAMS);
+
+	/* BASS/SR/SPE/BI-04-C [Opcode Not Supported]
+	 *
+	 * Test Purpose:
+	 * Verify that the BASS Server IUT returns an Opcode Not Supported error
+	 * response when the opcode written is not supported by the IUT or is
+	 * within a range that is reserved for future use being written to the
+	 * Broadcast Audio Scan Control Point.
+	 *
+	 * Pass verdict:
+	 * The IUT sends an error response of OPCODE NOT SUPPORTED.
+	 */
+	define_test("BASS/SR/SPE/BI-04-C", test_server, NULL,
+				OPCODE_NOT_SUPPORTED);
+
+	/* BASS/SR/SPE/BI-06-C [Invalid Length]
+	 *
+	 * Test Purpose:
+	 * Verify that the BASS Server IUT rejects writing of an opcode with
+	 * an invalid length.
+	 *
+	 * Pass verdict:
+	 * The IUT rejects the opcode.
+	 */
+	define_test("BASS/SR/SPE/BI-06-C", test_server, NULL,
+				INVALID_LEN);
+
+	/* BASS/SR/SPE/BI-07-C [Invalid Source ID]
+	 *
+	 * Test Purpose:
+	 * Verify that the BASS Server IUT returns an error when a control
+	 * point procedure passing an invalid Source_ID parameter is called.
+	 *
+	 * Pass verdict:
+	 * The IUT sends an ATT Error Response with the Error Code set to
+	 * Invalid Source_ID.
+	 */
+	define_test("BASS/SR/SPE/BI-07-C", test_server, NULL,
+				INVALID_SRC_ID);
+}
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_sggit();
+	test_spe();
+
+	return tester_run();
+}
diff --git a/unit/test-crypto.c b/unit/test-crypto.c
index 3a88b4a..8fd7bec 100644
--- a/unit/test-crypto.c
+++ b/unit/test-crypto.c
@@ -311,6 +311,78 @@ static void test_verify_sign(gconstpointer data)
 	tester_test_passed();
 }
 
+static void test_sef(const void *data)
+{
+	const uint8_t sirk[16] = {
+			0xcd, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
+			0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45 };
+	const uint8_t k[16] = {
+			0xd9, 0xce, 0xe5, 0x3c, 0x22, 0xc6, 0x1e, 0x06,
+			0x6f, 0x69, 0x48, 0xd4, 0x9b, 0x1b, 0x6e, 0x67 };
+	const uint8_t exp[16] = {
+			0x46, 0xd3, 0x5f, 0xf2, 0xd5, 0x62, 0x25, 0x7e,
+			0xa0, 0x24, 0x35, 0xe1, 0x35, 0x38, 0x0a, 0x17 };
+	uint8_t res[16];
+
+	tester_debug("SIRK:");
+	util_hexdump(' ', sirk, 16, print_debug, NULL);
+
+	tester_debug("K:");
+	util_hexdump(' ', k, 16, print_debug, NULL);
+
+	if (!bt_crypto_sef(crypto, k, sirk, res)) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_debug("Expected:");
+	util_hexdump(' ', exp, 16, print_debug, NULL);
+
+	tester_debug("Result:");
+	util_hexdump(' ', res, 16, print_debug, NULL);
+
+	if (memcmp(res, exp, 16)) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_test_passed();
+}
+
+static void test_sih(const void *data)
+{
+	const uint8_t k[16] = {
+			0xcd, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
+			0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45 };
+	const uint8_t r[3] = { 0x63, 0xf5, 0x69 };
+	const uint8_t exp[3] = { 0xda, 0x48, 0x19 };
+	uint8_t hash[3];
+
+	tester_debug("K:");
+	util_hexdump(' ', k, 16, print_debug, NULL);
+
+	tester_debug("R:");
+	util_hexdump(' ', r, 3, print_debug, NULL);
+
+	if (!bt_crypto_sih(crypto, k, r, hash)) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_debug("Expected:");
+	util_hexdump(' ', exp, 3, print_debug, NULL);
+
+	tester_debug("Result:");
+	util_hexdump(' ', hash, 3, print_debug, NULL);
+
+	if (memcmp(hash, exp, 3)) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_test_passed();
+}
+
 int main(int argc, char *argv[])
 {
 	int exit_status;
@@ -337,6 +409,8 @@ int main(int argc, char *argv[])
 						NULL, test_verify_sign, NULL);
 	tester_add("/crypto/verify_sign_too_short", &verify_sign_too_short_data,
 						NULL, test_verify_sign, NULL);
+	tester_add("/crypto/sef", NULL, NULL, test_sef, NULL);
+	tester_add("/crypto/sih", NULL, NULL, test_sih, NULL);
 
 	exit_status = tester_run();
 
diff --git a/unit/test-eir.c b/unit/test-eir.c
index e05a37d..49ce65f 100644
--- a/unit/test-eir.c
+++ b/unit/test-eir.c
@@ -21,6 +21,7 @@
 #include "lib/sdp.h"
 #include "src/shared/tester.h"
 #include "src/shared/util.h"
+#include "src/shared/ad.h"
 #include "src/eir.h"
 
 struct test_data {
@@ -539,6 +540,54 @@ static void print_debug(const char *str, void *user_data)
 	tester_debug("%s%s", prefix, str);
 }
 
+static void test_ad(const struct test_data *test, struct eir_data *eir)
+{
+	struct bt_ad *ad;
+	GSList *list;
+
+	ad = bt_ad_new_with_data(test->eir_size, test->eir_data);
+	g_assert(ad);
+
+	g_assert_cmpint(bt_ad_get_flags(ad), ==, test->flags);
+	g_assert_cmpstr(bt_ad_get_name(ad), ==, test->name);
+	g_assert_cmpint(bt_ad_get_tx_power(ad), ==, test->tx_power);
+
+	if (test->uuid) {
+		int i;
+
+		for (i = 0; test->uuid[i]; i++) {
+			bt_uuid_t uuid;
+
+			bt_string_to_uuid(&uuid, test->uuid[i]);
+			g_assert(bt_ad_has_service_uuid(ad, &uuid));
+		}
+	}
+
+	for (list = eir->msd_list; list; list = list->next) {
+		struct eir_msd *msd = list->data;
+		struct bt_ad_manufacturer_data adm;
+
+		adm.manufacturer_id = msd->company;
+		adm.data = msd->data;
+		adm.len = msd->data_len;
+
+		g_assert(bt_ad_has_manufacturer_data(ad, &adm));
+	}
+
+	for (list = eir->sd_list; list; list = list->next) {
+		struct eir_sd *sd = list->data;
+		struct bt_ad_service_data ads;
+
+		bt_string_to_uuid(&ads.uuid, sd->uuid);
+		ads.data = sd->data;
+		ads.len = sd->data_len;
+
+		g_assert(bt_ad_has_service_data(ad, &ads));
+	}
+
+	bt_ad_unref(ad);
+}
+
 static void test_parsing(gconstpointer data)
 {
 	const struct test_data *test = data;
@@ -599,6 +648,8 @@ static void test_parsing(gconstpointer data)
 							"Service Data:");
 	}
 
+	test_ad(data, &eir);
+
 	eir_data_free(&eir);
 
 	tester_test_passed();
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index f92d860..1613fbc 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -1237,6 +1237,7 @@ add_char_with_value(struct gatt_db_attribute *service_att, uint16_t handle,
 
 	if (handle)
 		attrib = gatt_db_service_insert_characteristic(service_att,
+								handle - 1,
 								handle, uuid,
 								att_permissions,
 								char_properties,
@@ -1908,6 +1909,60 @@ static struct gatt_db *make_test_spec_large_db_1(void)
 	return make_db(specs);
 }
 
+/*
+ * Tiny database which fits into a single minimum sized-pdu with services
+ * added in the following order to check ability to create hash db:
+ * - one secondary service at handle 0x0003,
+ * - one primary service at the max handle,
+ * - one primary service at handle 0x0001.
+ */
+
+static struct gatt_db *make_test_tail_db(void)
+{
+	const struct att_handle_spec specs[] = {
+		SECONDARY_SERVICE(0x0003, DEVICE_INFORMATION_UUID, 16),
+		CHARACTERISTIC_STR(GATT_CHARAC_MANUFACTURER_NAME_STRING,
+						BT_ATT_PERM_READ |
+						BT_ATT_PERM_WRITE,
+						BT_GATT_CHRC_PROP_READ |
+						BT_GATT_CHRC_PROP_NOTIFY |
+						BT_GATT_CHRC_PROP_INDICATE |
+						BT_GATT_CHRC_PROP_EXT_PROP,
+						"BlueZ"),
+		DESCRIPTOR(GATT_CLIENT_CHARAC_CFG_UUID, BT_ATT_PERM_READ |
+						BT_ATT_PERM_WRITE, 0x00, 0x00),
+		DESCRIPTOR_STR(GATT_CHARAC_USER_DESC_UUID, BT_ATT_PERM_READ,
+							"Manufacturer Name"),
+		DESCRIPTOR(GATT_CHARAC_EXT_PROPER_UUID, BT_ATT_PERM_READ, 0x01,
+									0x00),
+		CHARACTERISTIC_STR(GATT_CHARAC_SOFTWARE_REVISION_STRING,
+						BT_ATT_PERM_READ,
+						BT_GATT_CHRC_PROP_READ |
+						BT_GATT_CHRC_PROP_INDICATE,
+						"5.59"),
+		DESCRIPTOR(GATT_CLIENT_CHARAC_CFG_UUID, BT_ATT_PERM_READ
+			| BT_ATT_PERM_WRITE, 0x00, 0x00),
+
+		PRIMARY_SERVICE(0xFFFF - 9 + 1, GAP_UUID, 9),
+		INCLUDE(0x0003),
+		CHARACTERISTIC_STR(GATT_CHARAC_DEVICE_NAME, BT_ATT_PERM_READ,
+							BT_GATT_CHRC_PROP_READ,
+							"BlueZ Unit Tester"),
+		CHARACTERISTIC(0000B009-0000-0000-0123-456789abcdef,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					BT_GATT_CHRC_PROP_READ |
+					BT_GATT_CHRC_PROP_EXT_PROP, 0x09),
+		DESCRIPTOR(GATT_CHARAC_EXT_PROPER_UUID, BT_ATT_PERM_READ, 0x01,
+									0x00),
+		CHARACTERISTIC(GATT_CHARAC_APPEARANCE, BT_ATT_PERM_READ,
+					BT_GATT_CHRC_PROP_READ, 0x00, 0x00),
+		PRIMARY_SERVICE(0x0001, DEVICE_INFORMATION_UUID, 1),
+		{ }
+	};
+
+	return make_db(specs);
+}
+
 static void test_client(gconstpointer data)
 {
 	create_context(512, data);
@@ -2345,10 +2400,22 @@ static const struct test_step test_indication_server_1 = {
 	.length = 0x03,
 };
 
+static void test_hash_db(gconstpointer data)
+{
+	struct context *context = create_context(512, data);
+
+	/* test that gatt_db_get_hash is able to manage services at tail end of
+	 * a db.
+	 */
+	gatt_db_get_hash(context->server_db);
+
+	context_quit(context);
+}
+
 int main(int argc, char *argv[])
 {
 	struct gatt_db *service_db_1, *service_db_2, *service_db_3;
-	struct gatt_db *ts_small_db, *ts_large_db_1;
+	struct gatt_db *ts_small_db, *ts_large_db_1, *ts_tail_db;
 
 	tester_init(&argc, &argv);
 
@@ -2357,6 +2424,7 @@ int main(int argc, char *argv[])
 	service_db_3 = make_service_data_3_db();
 	ts_small_db = make_test_spec_small_db();
 	ts_large_db_1 = make_test_spec_large_db_1();
+	ts_tail_db = make_test_tail_db();
 
 	/*
 	 * Server Configuration
@@ -4487,5 +4555,9 @@ int main(int argc, char *argv[])
 			raw_pdu(0xff, 0x00),
 			raw_pdu());
 
+	define_test_server("/robustness/hash-db",
+			test_hash_db, ts_tail_db, NULL,
+			{});
+
 	return tester_run();
 }
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 067497d..a7cb5f0 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -182,7 +182,7 @@ static struct context *create_context(gconstpointer data)
 	fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
 	g_assert(fd > 0);
 
-	context->hog = bt_hog_new(fd, name, vendor, product, version, NULL);
+	context->hog = bt_hog_new(fd, name, vendor, product, version, 0, NULL);
 	g_assert(context->hog);
 
 	channel = g_io_channel_unix_new(sv[1]);
diff --git a/unit/test-mesh-crypto.c b/unit/test-mesh-crypto.c
index f9b7d81..39632d9 100644
--- a/unit/test-mesh-crypto.c
+++ b/unit/test-mesh-crypto.c
@@ -633,6 +633,36 @@ static const struct mesh_crypto_test s8_4_3 = {
 	.beacon		= "01003ecaff672f673370123456788ea261582f364f6f",
 };
 
+static const struct mesh_crypto_test s8_4_6_1 = {
+	.name		= "8.4.6.1 Private Beacon IVU",
+
+	.net_key	= "f7a2a44f8e8a8029064f173ddc1e2b00",
+	.iv_index	= 0x1010abcd,
+
+	.enc_key	= "6be76842460b2d3a5850d4698409f1bb",
+	.rand		= "435f18f85cf78a3121f58478a5",
+
+	.beacon_type	= 0x02,
+	.beacon_flags	= 0x02,
+	.beacon_cmac	= "f3174f022a514741",
+	.beacon	= "02435f18f85cf78a3121f58478a561e488e7cbf3174f022a514741",
+};
+
+static const struct mesh_crypto_test s8_4_6_2 = {
+	.name		= "8.4.6.2 Private Beacon IVU Complete",
+
+	.net_key	= "3bbb6f1fbd53e157417f308ce7aec58f",
+	.iv_index	= 0x00000000,
+
+	.enc_key	= "ca478cdac626b7a8522d7272dd124f26",
+	.rand		= "1b998f82927535ea6f3076f422",
+
+	.beacon_type	= 0x02,
+	.beacon_flags	= 0x00,
+	.beacon_cmac	= "2f0ffb94cf97f881",
+	.beacon	= "021b998f82927535ea6f3076f422ce827408ab2f0ffb94cf97f881",
+};
+
 static const struct mesh_crypto_test s8_6_2 = {
 	.name		= "8.6.2 Service Data using Node Identity",
 
@@ -683,6 +713,17 @@ static void verify_data(const char *label, unsigned int indent,
 	l_free(str);
 }
 
+static void verify_bool(const char *label, unsigned int indent,
+						bool sample, bool data)
+{
+	l_info("%-20s =%*c%s", label, 1 + (indent * 2), ' ',
+						sample ? "true" : "false");
+	l_info("%-20s  %*c%s => %s", "", 1 + (indent * 2), ' ',
+						data ? "true" : "false",
+						EVALNUM(sample, data));
+	EXITNUM(sample, data);
+}
+
 static void verify_bool_not_both(const char *label, unsigned int indent,
 						bool sample, bool data)
 {
@@ -796,10 +837,11 @@ static void check_encrypt_segment(const struct mesh_crypto_test *keys,
 	uint32_t hdr;
 	uint64_t net_mic64, net_mic32;
 	size_t net_msg_len;
+	bool status;
 	uint8_t key_aid = keys->key_aid | (keys->akf ? KEY_ID_AKF : 0x00);
 
 	if (keys->ctl) {
-		mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
+		status = mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
 				keys->net_seq[0],
 				keys->net_src, keys->net_dst,
 				keys->opcode,
@@ -809,7 +851,7 @@ static void check_encrypt_segment(const struct mesh_crypto_test *keys,
 				enc_msg, len,
 				packet, &packet_len);
 	} else {
-		mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
+		status = mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
 				keys->net_seq[0],
 				keys->net_src, keys->net_dst,
 				keys->opcode,
@@ -822,6 +864,10 @@ static void check_encrypt_segment(const struct mesh_crypto_test *keys,
 
 	l_info(COLOR_YELLOW "Segment-%d" COLOR_OFF, seg);
 
+	verify_bool("Crypto packet build", 0, true, status);
+	if (!status)
+		return;
+
 	hdr = l_get_be32(packet + 9);
 	verify_uint8("SEG", 9, keys->segmented << (SEG_HDR_SHIFT % 8),
 			packet[9] & (1 << (SEG_HDR_SHIFT % 8)));
@@ -870,15 +916,20 @@ static void check_encrypt_segment(const struct mesh_crypto_test *keys,
 	net_msg_len = len + 2;
 	show_data("TransportPayload", 7, packet + 7, net_msg_len);
 
-	mesh_crypto_packet_encrypt(packet, packet_len,
+	status = mesh_crypto_packet_encrypt(packet, packet_len,
 						enc_key,
 						keys->iv_index, false,
 						keys->ctl, keys->net_ttl,
 						keys->net_seq[0],
 						keys->net_src);
 
+	verify_bool("Crypto packet encrypt", 0, true, status);
+	if (!status)
+		return;
+
 	mesh_crypto_privacy_counter(keys->iv_index, packet + 7, priv_rand);
 
+
 	l_info("");
 	show_uint32("IVindex", 0, keys->iv_index);
 	verify_data("NetworkNonce", 0, keys->net_nonce[0], net_nonce, 13);
@@ -907,10 +958,15 @@ static void check_encrypt_segment(const struct mesh_crypto_test *keys,
 	}
 
 	show_data("PreObsPayload", 1, packet + 1, 6 + net_msg_len);
-	mesh_crypto_network_obfuscate(packet, priv_key,
+	status = mesh_crypto_network_obfuscate(packet, priv_key,
 					keys->iv_index,
 					keys->ctl, keys->net_ttl,
 					keys->net_seq[0], keys->net_src);
+
+	verify_bool("Crypto network obfuscate", 0, true, status);
+	if (!status)
+		return;
+
 	show_data("PostObsPayload", 1, packet + 1, 6 + net_msg_len);
 
 	packet[0] = (keys->iv_index & 0x01) << 7 | nid;
@@ -926,7 +982,7 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 	uint8_t *dev_key;
 	uint8_t *app_key;
 	uint8_t *net_key;
-	uint8_t nid;
+	uint8_t nid = 0;
 	uint8_t enc_key[16];
 	uint8_t priv_key[16];
 	uint8_t net_nonce[13];
@@ -949,6 +1005,7 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 	uint8_t packet_len;
 	uint16_t i, seg_max, seg_len = 0;
 	uint32_t seqZero, hdr;
+	bool status;
 
 	l_info(COLOR_BLUE "[Encrypt %s]" COLOR_OFF, keys->name);
 	verify_bool_not_both("CTL && Segmented", 0, keys->ctl, keys->segmented);
@@ -960,8 +1017,7 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 
 	show_data("NetworkKey", 0, net_key, 16);
 
-	if (keys->akf) {
-		mesh_crypto_k4(app_key, &key_aid);
+	if (keys->akf && mesh_crypto_k4(app_key, &key_aid)) {
 		key_aid |= KEY_ID_AKF;
 	} else {
 		key_aid = 0;
@@ -1034,7 +1090,7 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 			seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
 			enc_msg = l_malloc(app_msg_len + 8);
 
-			mesh_crypto_payload_encrypt(aad, app_msg,
+			status = mesh_crypto_payload_encrypt(aad, app_msg,
 					enc_msg, app_msg_len,
 					keys->net_src, keys->net_dst, key_aid,
 					keys->app_seq, keys->iv_index,
@@ -1044,7 +1100,7 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 			seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
 			enc_msg = l_malloc(app_msg_len + 4);
 
-			mesh_crypto_payload_encrypt(aad, app_msg,
+			status = mesh_crypto_payload_encrypt(aad, app_msg,
 					enc_msg, app_msg_len,
 					keys->net_src, keys->net_dst, key_aid,
 					keys->app_seq, keys->iv_index,
@@ -1052,6 +1108,10 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 					keys->akf ? app_key : dev_key);
 		}
 
+		verify_bool("Crypto payload encrypt", 0, true, status);
+		if (!status)
+			return;
+
 		if (keys->dev_key && !keys->akf)
 			show_data("DeviceKey", 0, dev_key, 16);
 
@@ -1097,7 +1157,8 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 		}
 
 		if (keys->ctl) {
-			mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
+			status = mesh_crypto_packet_build(keys->ctl,
+					keys->net_ttl,
 					keys->net_seq[i],
 					keys->net_src, keys->net_dst,
 					keys->opcode,
@@ -1107,7 +1168,8 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 					enc_msg + 1, seg_len,
 					packet, &packet_len);
 		} else {
-			mesh_crypto_packet_build(keys->ctl, keys->net_ttl,
+			status = mesh_crypto_packet_build(keys->ctl,
+					keys->net_ttl,
 					keys->net_seq[i],
 					keys->net_src, keys->net_dst,
 					keys->opcode,
@@ -1120,6 +1182,10 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 
 		if (seg_max) l_info(COLOR_YELLOW "Segment-%d" COLOR_OFF, i);
 
+		verify_bool("Crypto packet build", 0, true, status);
+		if (!status)
+			return;
+
 		hdr = l_get_be32(packet + 9);
 		verify_uint8("SEG", 9, keys->segmented << (SEG_HDR_SHIFT % 8),
 					packet[9] & (1 << (SEG_HDR_SHIFT % 8)));
@@ -1193,12 +1259,16 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 		net_msg_len = seg_len + 2;
 		show_data("TransportPayload", 7, packet + 7, net_msg_len);
 
-		mesh_crypto_packet_encrypt(packet, packet_len, enc_key,
+		status = mesh_crypto_packet_encrypt(packet, packet_len, enc_key,
 						keys->iv_index, false,
 						keys->ctl, keys->net_ttl,
 						keys->net_seq[i],
 						keys->net_src);
 
+		verify_bool("Crypto packet encrypt", 0, true, status);
+		if (!status)
+			return;
+
 		mesh_crypto_privacy_counter(keys->iv_index, packet + 7,
 								priv_rand);
 
@@ -1232,11 +1302,15 @@ static void check_encrypt(const struct mesh_crypto_test *keys)
 		}
 
 		show_data("PreObsPayload", 1, packet + 1, 6 + net_msg_len);
-		mesh_crypto_network_obfuscate(packet, priv_key,
+		status = mesh_crypto_network_obfuscate(packet, priv_key,
 					keys->iv_index,
 					keys->ctl, keys->net_ttl,
 					keys->net_seq[i], keys->net_src);
 
+		verify_bool("Crypto network obfuscate", 0, true, status);
+		if (!status)
+			return;
+
 		show_data("PostObsPayload", 1, packet + 1, 6 + net_msg_len);
 
 		packet[0] = (keys->iv_index & 0x01) << 7 | nid;
@@ -1265,19 +1339,20 @@ static void check_decrypt_segment(const struct mesh_crypto_test *keys,
 	uint8_t net_clr[29];
 	uint64_t net_mic64, calc_net_mic64;
 	uint32_t hdr, net_mic32, calc_net_mic32;
-	bool ctl, segmented, relay, szmic, key_akf;
+	bool ctl, segmented, relay, szmic, key_akf, status;
 	uint8_t ttl, opcode, key_aid, segO, segN;
 	uint32_t seq;
 	uint16_t src, dst, seqZero;
 
 	memcpy(net_clr, pkt, pkt_len);
 	show_data("NetworkMessage", 0, pkt, pkt_len);
-	mesh_crypto_packet_decode(pkt, pkt_len,
+	status = mesh_crypto_packet_decode(pkt, pkt_len,
 				false, net_clr, keys->iv_index,
 				enc_key, priv_key);
 	show_data("Decoded", 0, net_clr, pkt_len);
 
-	mesh_crypto_packet_parse(net_clr, pkt_len,
+	if (status)
+		status = mesh_crypto_packet_parse(net_clr, pkt_len,
 			&ctl, &ttl, &seq,
 			&src, &dst,
 			NULL, &opcode,
@@ -1286,6 +1361,10 @@ static void check_decrypt_segment(const struct mesh_crypto_test *keys,
 			&segO, &segN,
 			&msg, &msg_len);
 
+	verify_bool("Crypto Decode-Parse", 0, true, status);
+	if (!status)
+		return;
+
 	if (ctl) {
 		net_mic64 = l_get_be64(pkt + pkt_len - 8);
 		show_data("EncryptedPayload", 7, pkt + 7, pkt_len - 7 - 8);
@@ -1416,7 +1495,7 @@ static void check_decrypt(const struct mesh_crypto_test *keys)
 	uint16_t app_msg_len = 0;
 	uint32_t calc_net_mic32, net_mic32 = 0;
 	uint64_t calc_net_mic64, net_mic64 = 0;
-	bool net_ctl, net_segmented, net_rly, net_akf;
+	bool net_ctl, net_segmented, net_rly, net_akf, status;
 	uint8_t net_aid, net_ttl, nid, net_segO, net_segN = 0;
 	uint32_t net_seq, hdr, seqZero = 0;
 	uint16_t net_src, net_dst;
@@ -1501,8 +1580,14 @@ static void check_decrypt(const struct mesh_crypto_test *keys)
 		net_msg = packet + 7;
 		net_msg_len = packet_len - 7;
 
-		mesh_crypto_network_clarify(packet, priv_key, keys->iv_index,
-				&net_ctl, &net_ttl, &net_seq, &net_src);
+		status = mesh_crypto_network_clarify(packet, priv_key,
+				keys->iv_index, &net_ctl, &net_ttl, &net_seq,
+				&net_src);
+
+		verify_bool("Crypto Clarify", 0, true, status);
+		if (!status)
+			return;
+
 
 		show_str("Packet", 0, keys->packet[i]);
 
@@ -1731,42 +1816,67 @@ static void check_beacon(const struct mesh_crypto_test *keys)
 {
 	uint8_t *net_key;
 	uint8_t *beacon_cmac;
-	uint8_t beacon[22];
+	uint8_t *random = NULL;
+	uint8_t beacon[29];
 	uint8_t enc_key[16];
 	uint8_t net_id[8];
 	uint8_t cmac[8];
-	uint64_t cmac_tmp;
+	uint64_t cmac_tmp = 0;
+
+	if (keys->beacon_type < 1 || keys->beacon_type > 2)
+		verify_uint8("Unknown Beacon", 0, true,
+			(keys->beacon_type >= 1 || keys->beacon_type <= 2));
 
 	net_key = l_util_from_hexstring(keys->net_key, NULL);
 	beacon_cmac = l_util_from_hexstring(keys->beacon_cmac, NULL);
 
-	mesh_crypto_nkbk(net_key, enc_key);
+	if (keys->beacon_type == 1) {
+		mesh_crypto_nkbk(net_key, enc_key);
+	} else {
+		mesh_crypto_nkpk(net_key, enc_key);
+		random = l_util_from_hexstring(keys->rand, NULL);
+	}
+
 	mesh_crypto_k3(net_key, net_id);
 
 	l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name);
 
 	verify_data("NetworkKey", 0, keys->net_key, net_key, 16);
+	show_uint8("Beacon Flags", 0, keys->beacon_flags);
 	show_uint32("IVindex", 0, keys->iv_index);
 
 	verify_data("BeaconKey", 0, keys->enc_key, enc_key, 16);
-	verify_data("NetworkID", 0, keys->net_id, net_id, 8);
 
 	beacon[0] = keys->beacon_type;
-	beacon[1] = keys->beacon_flags;
-	memcpy(beacon + 2, net_id, 8);
-	l_put_be32(keys->iv_index, beacon + 10);
-	mesh_crypto_beacon_cmac(enc_key, net_id, keys->iv_index,
-					!!(keys->beacon_flags & 0x01),
-					!!(keys->beacon_flags & 0x02),
-					&cmac_tmp);
-
-	l_put_be64(cmac_tmp, cmac);
-	l_put_be64(cmac_tmp, beacon + 14);
-	verify_data("BeaconCMAC", 0, keys->beacon_cmac, cmac, 8);
-	verify_data("Beacon", 0, keys->beacon, beacon, sizeof(beacon));
+	if (keys->beacon_type == 1) {
+		verify_data("NetworkID", 0, keys->net_id, net_id, 8);
+		beacon[1] = keys->beacon_flags;
+		memcpy(beacon + 2, net_id, 8);
+		l_put_be32(keys->iv_index, beacon + 10);
+		mesh_crypto_beacon_cmac(enc_key, net_id, keys->iv_index,
+				!!(keys->beacon_flags & 0x01),
+				!!(keys->beacon_flags & 0x02),
+				&cmac_tmp);
+
+		l_put_be64(cmac_tmp, cmac);
+		l_put_be64(cmac_tmp, beacon + 14);
+		verify_data("BeaconCMAC", 0, keys->beacon_cmac, cmac, 8);
+		verify_data("SNBeacon", 0, keys->beacon, beacon, 22);
+	} else {
+		show_data("Random", 0, random, sizeof(random));
+		memcpy(beacon + 1, random, 13);
+		beacon[14] = keys->beacon_flags;
+		l_put_be32(keys->iv_index, beacon + 15);
+		mesh_crypto_aes_ccm_encrypt(random, enc_key, NULL, 0,
+							beacon + 14, 5,
+							beacon + 14, NULL, 8);
+		verify_data("BeaconMIC", 0, keys->beacon_cmac, beacon + 19, 8);
+		verify_data("PrivBeacon", 0, keys->beacon, beacon, 27);
+	}
 
 	l_info("");
 
+	l_free(random);
 	l_free(beacon_cmac);
 	l_free(net_key);
 }
@@ -2071,6 +2181,8 @@ int main(int argc, char *argv[])
 
 	/* Section 8.4 Beacon Sample Data */
 	check_beacon(&s8_4_3);
+	check_beacon(&s8_4_6_1);
+	check_beacon(&s8_4_6_2);
 
 	/* Section 8.6 Mesh Proxy Service sample data */
 	check_id_beacon(&s8_6_2);
diff --git a/unit/test-micp.c b/unit/test-micp.c
new file mode 100644
index 0000000..a7fc7fb
--- /dev/null
+++ b/unit/test-micp.c
@@ -0,0 +1,838 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  NXP Semiconductors. All rights reserved.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "src/shared/util.h"
+#include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/gatt-helpers.h"
+#include "src/shared/micp.h"
+
+struct test_data_mics {
+	struct gatt_db *db;
+	struct bt_micp *micp;
+	struct bt_gatt_server *server;
+	struct bt_gatt_client *client;
+	struct queue *ccc_states;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+struct test_data_micp {
+	struct gatt_db *db;
+	struct bt_micp *micp;
+	struct bt_gatt_client *client;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+struct ccc_state {
+	uint16_t handle;
+	uint16_t value;
+};
+
+struct notify {
+	uint16_t handle, ccc_handle;
+	uint8_t *value;
+	uint16_t len;
+	bt_gatt_server_conf_func_t conf;
+	void *user_data;
+};
+
+#define MICP_GATT_CLIENT_MTU	64
+
+#define iov_data(args...) ((const struct iovec[]) { args })
+
+#define define_test_mics(name, function, _cfg, args...)		\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data_mics data;			\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		tester_add(name, &data, NULL, function,	\
+				test_teardown_mics);			\
+	} while (0)
+
+#define define_test_micp(name, function, _cfg, args...)		\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data_micp data;			\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		tester_add(name, &data, test_setup, function,	\
+				test_teardown_micp);			\
+	} while (0)
+
+static void print_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	if (tester_use_debug())
+		tester_debug("%s%s", prefix, str);
+}
+
+static void test_teardown_mics(const void *user_data)
+{
+	struct test_data_mics *data = (void *)user_data;
+
+	bt_micp_unref(data->micp);
+	bt_gatt_server_unref(data->server);
+	util_iov_free(data->iov, data->iovcnt);
+	gatt_db_unref(data->db);
+
+	queue_destroy(data->ccc_states, free);
+
+	tester_teardown_complete();
+}
+
+static void test_teardown_micp(const void *user_data)
+{
+	struct test_data_micp *data = (void *)user_data;
+
+	bt_micp_unref(data->micp);
+	bt_gatt_client_unref(data->client);
+	util_iov_free(data->iov, data->iovcnt);
+	gatt_db_unref(data->db);
+
+	tester_teardown_complete();
+}
+
+static void test_complete_cb(const void *user_data)
+{
+	tester_test_passed();
+}
+
+static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
+{
+
+	if (!success)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+static void micp_write_cb(bool success, uint8_t att_ecode, void *user_data)
+{
+	if (success)
+		printf("MICP Write successful\n");
+	else
+		printf("\nWrite failed: 0x%02x\n", att_ecode);
+}
+
+static void micp_write_value(struct bt_micp *micp, void *user_data)
+{
+	struct bt_mics *mics = micp_get_mics(micp);
+	uint16_t	value_handle;
+	int ret;
+	uint16_t value = cpu_to_le16(0x0001);
+
+	gatt_db_attribute_get_char_data(mics->ms, NULL, &value_handle,
+							NULL, NULL, NULL);
+
+	printf("%s handle: %x\n", __func__, value_handle);
+	ret = bt_gatt_client_write_value(micp->client, value_handle,
+		(void *)&value, sizeof(value), micp_write_cb, NULL, NULL);
+
+	if (!ret)
+		printf("bt_gatt_client_write_value() : Write FAILED");
+}
+
+static void micp_ready(struct bt_micp *micp, void *user_data)
+{
+	micp_write_value(micp, user_data);
+}
+
+static void test_client(const void *user_data)
+{
+	struct test_data_micp *data = (void *)user_data;
+	struct io *io;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	data->micp = bt_micp_new(data->db, bt_gatt_client_get_db(data->client));
+	g_assert(data->micp);
+
+	bt_micp_set_debug(data->micp, print_debug, "bt_micp: ", NULL);
+
+	bt_micp_ready_register(data->micp, micp_ready, data, NULL);
+
+	bt_micp_attach(data->micp, data->client);
+}
+
+static bool ccc_state_match(const void *a, const void *b)
+{
+	const struct ccc_state *ccc = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return ccc->handle == handle;
+}
+
+static struct ccc_state *find_ccc_state(struct test_data_mics *data,
+			uint16_t handle)
+{
+	return queue_find(data->ccc_states, ccc_state_match,
+				UINT_TO_PTR(handle));
+}
+
+static struct ccc_state *get_ccc_state(struct test_data_mics *data,
+			uint16_t handle)
+{
+	struct ccc_state *ccc;
+
+	ccc = find_ccc_state(data, handle);
+	if (ccc)
+		return ccc;
+
+	ccc = new0(struct ccc_state, 1);
+	ccc->handle = handle;
+	queue_push_tail(data->ccc_states, ccc);
+
+	return ccc;
+}
+
+static void gatt_notify_cb(struct gatt_db_attribute *attrib,
+					struct gatt_db_attribute *ccc,
+					const uint8_t *value, size_t len,
+					struct bt_att *att, void *user_data)
+{
+	struct test_data_mics *data = user_data;
+	struct notify notify;
+
+	memset(&notify, 0, sizeof(notify));
+
+	notify.handle = gatt_db_attribute_get_handle(attrib);
+	notify.ccc_handle = gatt_db_attribute_get_handle(ccc);
+	notify.value = (void *) value;
+	notify.len = len;
+
+	printf("%s: notify.value:%d notify->len:%d\n", __func__,
+		(int)*(notify.value), notify.len);
+	if (!bt_gatt_server_send_notification(data->server,
+			notify.handle, notify.value,
+			notify.len, false))
+		printf("%s: Failed to send notification\n", __func__);
+}
+
+static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct test_data_mics *data = user_data;
+	struct ccc_state *ccc;
+	uint16_t handle;
+	uint8_t ecode = 0;
+	const uint8_t *value = NULL;
+	size_t len = 0;
+
+	handle = gatt_db_attribute_get_handle(attrib);
+
+	ccc = get_ccc_state(data, handle);
+	if (!ccc) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	len = sizeof(ccc->value);
+	value = (void *) &ccc->value;
+
+done:
+	gatt_db_attribute_read_result(attrib, id, ecode, value, len);
+}
+
+static void test_server(const void *user_data)
+{
+	struct test_data_mics *data = (void *)user_data;
+	struct bt_att *att;
+	struct io *io;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, NULL,
+					gatt_notify_cb, data);
+
+	data->micp = bt_micp_new(data->db, NULL);
+	g_assert(data->micp);
+
+	data->server = bt_gatt_server_new(data->db, att, 64, 0);
+	g_assert(data->server);
+
+	bt_gatt_server_set_debug(data->server, print_debug, "bt_gatt_server:",
+					NULL);
+
+	data->ccc_states = queue_new();
+
+	tester_io_send();
+
+	bt_att_unref(att);
+}
+
+/*
+ *  ATT: Exchange MTU Request (0x02) len 2
+ *       Client RX MTU: 64
+ *
+ *  ATT: Exchange MTU Response (0x03) len 2
+ *        Server RX MTU: 64
+ */
+#define ATT_EXCHANGE_MTU	IOV_DATA(0x02, 0x40, 0x00), \
+	IOV_DATA(0x03, 0x40, 0x00)
+
+/*
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0001-0xffff
+ *       Attribute type: Server Supported Features (0x2b3a)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Type Request (0x08)
+ *       Handle: 0x0001
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICP_READ_SR_FEATURE	IOV_DATA(0x08, 0x01, 0x00, 0Xff, 0xff, \
+	0x3a, 0x2b), \
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a)
+
+/*
+ *  ATT: Read By Group Type Request (0x10) len 6
+ *       Handle range: 0x0001-0xffff
+ *       Attribute group type: Primary Service (0x2800)
+ *
+ *  ATT: Read By Group Type Response (0x11) len 7
+ *       Attribute data length: 6
+ *       Attribute group list: 1 entry
+ *       Handle range: 0x0001-0x0004
+ *       UUID: Microphone Control (0x184d)
+ *
+ *  ATT: Read By Group Type Request (0x10) len 6
+ *       Handle range: 0x0005-0xffff
+ *       Attribute group type: Primary Service (0x2800)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Group Type Request (0x10)
+ *       Handle: 0x0006
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICP_READ_GROUP_TYPE	\
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x11, 0x06, \
+	0x01, 0x00, 0x04, 0x00, 0x4d, 0x18), \
+	IOV_DATA(0x10, 0x05, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x06, 0x00, 0x0a)
+
+/*
+ *  ATT: Read By Group Type Request (0x10) len 6
+ *       Handle range: 0x0001-0xffff
+ *       Attribute group type: Secondary Service (0x2801)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Group Type Request (0x10)
+ *       Handle: 0x0001
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICP_READ_REQ_SECOND_SERVICE	\
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x01, 0x00, 0x0a)
+
+/*
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0001-0x0004
+ *       Attribute type: Include (0x2802)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Type Request (0x08)
+ *       Handle: 0x0001
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICP_READ_REQ_INCLUDE_SERVICE	\
+	IOV_DATA(0x08, 0x01, 0x00, 0x04, 0x00, 0x02, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a)
+
+/*  ATT: Find Information Request (0x04) len 4
+ *      Handle range: 0x0004-0x0004
+ */
+#define	MICP_FIND_INFO_REQ	\
+	IOV_DATA(0x04, 0x04, 0x00, 0x04, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x04, 0x00, 0x02, 0x29)
+
+/*
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0001-0x0004
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Read By Type Response (0x09) len 8
+ *       Attribute data length: 7
+ *       Attribute data list: 1 entry
+ *       Handle: 0x0002
+ *       Value: 1a0300c32b
+ *
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0003-0x0004
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Type Request (0x08)
+ *       Handle: 0x0004
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define	MICP_READ_REQ_CHAR	\
+	IOV_DATA(0x08, 0x01, 0x00, 0x04, 0x00, 0x03, 0x28),\
+	IOV_DATA(0x09, 0x07, \
+	0x02, 0x00, 0x1a, 0x03, 0x00, 0xc3, 0x2b), \
+	IOV_DATA(0x08, 0x03, 0x00, 0x04, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x04, 0x00, 0x0a)
+/*
+ *  ATT: Read Request (0x0a) len 2
+ *       Handle: 0x0003
+ *
+ *  ATT: Read Response (0x0b) len 1
+ */
+#define	MICS_MUTE_READ \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01)
+
+/*
+ *  ATT: Write Request (0x12) len 4
+ *       Handle: 0x0004
+ *       Data: 0100
+ *  ATT: Write Response (0x13) len 0
+ */
+#define	MICS_EN_MUTE_DISCPTR	\
+	IOV_DATA(0x12, 0x04, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+#define	MICS_MUTE_WRITE	\
+	IOV_DATA(0x12, 0x03, 0x00, 0x01),\
+	IOV_DATA(0x13)
+
+#define MICP_CL_CGGIT_SER_BV_01_C \
+	MICS_MUTE_READ, \
+	MICS_EN_MUTE_DISCPTR, \
+	IOV_DATA(0x12, 0x03, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x013)
+
+#define	MICP_CL_CGGIT_CHA_BV_01_C	\
+	MICS_MUTE_READ, \
+	MICS_EN_MUTE_DISCPTR, \
+	IOV_DATA(0x12, 0x03, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x013)
+
+#define MICP_CL_SPE_BI_01_C	\
+	MICS_MUTE_READ, \
+	MICS_EN_MUTE_DISCPTR, \
+	IOV_DATA(0x12, 0x03, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x80)
+
+/* GATT Discover All procedure */
+static const struct iovec setup_data[] = {
+				ATT_EXCHANGE_MTU,
+				MICP_READ_SR_FEATURE,
+				MICP_READ_GROUP_TYPE,
+				MICP_READ_REQ_SECOND_SERVICE,
+				MICP_READ_REQ_INCLUDE_SERVICE,
+				MICP_READ_REQ_CHAR,
+				MICP_FIND_INFO_REQ
+};
+
+static void test_setup(const void *user_data)
+{
+	struct test_data_micp *data = (void *)user_data;
+	struct bt_att *att;
+	struct gatt_db *db;
+	struct io *io;
+
+	io = tester_setup_io(setup_data, ARRAY_SIZE(setup_data));
+	g_assert(io);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	db = gatt_db_new();
+	g_assert(db);
+
+	data->client = bt_gatt_client_new(db, att, MICP_GATT_CLIENT_MTU, 0);
+	g_assert(data->client);
+
+	bt_gatt_client_set_debug(data->client, print_debug, "bt_gatt_client:",
+						NULL);
+
+	bt_gatt_client_ready_register(data->client, client_ready_cb, data,
+						NULL);
+
+	bt_att_unref(att);
+	gatt_db_unref(db);
+}
+
+/*
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 00
+ *
+ *  ATT: Write Response (0x13) len 0
+ */
+#define	MICS_MUTE_WRITE_VAL_00 \
+	IOV_DATA(0x12, 0x03, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 01
+ *
+ *  ATT: Write Response (0x13) len 0
+ */
+#define	MICS_MUTE_WRITE_VAL_01 \
+	IOV_DATA(0x12, 0x03, 0x00, 0x01), \
+	IOV_DATA(0x13)
+/*
+ *  ATT: Read Request (0x0a) len 2
+ *       Handle: 0x0003
+ *
+ *  ATT: Read Response (0x0b) len 1
+ */
+#define	MICS_MUTE_READ \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01)
+
+/*
+ *  ATT: Read By Group Type Request (0x10) len 6
+ *       Handle range: 0x0001-0xffff
+ *       Attribute group type: Primary Service (0x2800)
+ *
+ *  ATT: Read By Group Type Response (0x11) len 7
+ *       Attribute data length: 6
+ *       Attribute group list: 1 entry
+ *       Handle range: 0x0001-0x0004
+ *       UUID: Microphone Control (0x184d)
+ *
+ *  ATT: Read By Group Type Request (0x10) len 6
+ *      Handle range: 0x0005-0xffff
+ *      Attribute group type: Primary Service (0x2800)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *      Read By Group Type Request (0x10)
+ *      Handle: 0x0005
+ *      Error: Attribute Not Found (0x0a)
+ */
+#define DISCOVER_PRIM_SERV_NOTIF \
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x11, 0x06, 0x01, 0x00, 0x04, 0x00, 0x4d, 0x18), \
+	IOV_DATA(0x10, 0x05, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x05, 0x00, 0x0a)
+
+/*
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0001-0x0005
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Read By Type Response (0x09) len 8
+ *       Attribute data length: 7
+ *       Attribute data list: 1 entry
+ *       Handle: 0x0002
+ *       Value: 1a0300c32b
+ *
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0005-0x0005
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Type Request (0x08)
+ *       Handle: 0x0005
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define DISC_MICS_CHAR_1 \
+	IOV_DATA(0x08, 0x01, 0x00, 0x05, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x09, 0x07, \
+		0x02, 0x00, 0x1a, 0x03, 0x00, 0xc3, 0x2b), \
+	IOV_DATA(0x08, 0x05, 0x00, 0x05, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x05, 0x00, 0x0a)
+
+/*
+ *  ATT: Find By Type Value Request (0x06) len 8
+ *       Handle range: 0x0001-0xffff
+ *       Attribute type: Primary Service (0x2800)
+ *       UUID: Microphone Control (0x184d)
+ *
+ *  ATT: Find By Type Value Response (0x07) len 4
+ *       Handle range: 0x0001-0x0004
+ *
+ *  ATT: Find By Type Value Request (0x06) len 8
+ *       Handle range: 0x0005-0xffff
+ *       Attribute type: Primary Service (0x2800)
+ *       UUID: Microphone Control (0x184d)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Find By Type Value Request (0x06)
+ *       Handle: 0x0005
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICS_FIND_BY_TYPE_VALUE \
+	IOV_DATA(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0x4d, 0x18), \
+	IOV_DATA(0x07, 0x01, 0x00, 0x04, 0x00), \
+	IOV_DATA(0x06, 0x05, 0x00, 0xff, 0xff, 0x00, 0x28, 0x4d, 0x18), \
+	IOV_DATA(0x01, 0x06, 0x05, 0x00, 0x0a)
+
+/*
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0001-0x0005
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Read By Type Response (0x09) len 8
+ *       Attribute data length: 7
+ *       Attribute data list: 1 entry
+ *       Handle: 0x0002
+ *       Value: 1a0300c32b
+ *
+ *  ATT: Read By Type Request (0x08) len 6
+ *       Handle range: 0x0003-0x0005
+ *       Attribute type: Characteristic (0x2803)
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Read By Type Request (0x08)
+ *       Handle: 0x0003
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define DISC_MICS_CHAR_AFTER_TYPE \
+	IOV_DATA(0x08, 0x01, 0x00, 0x05, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x09, 0x07, \
+		0x02, 0x00, 0x1a, 0x03, 0x00, 0xc3, 0x2b), \
+	IOV_DATA(0x08, 0x03, 0x00, 0x05, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x03, 0x00, 0x0a)
+
+/*
+ *  ATT: Write Request (0x12) len 4
+ *       Handle: 0x0004
+ *       Data: 0000
+ *
+ *  ATT: Write Response (0x13) len 0
+ *
+ *  ATT: Write Request (0x12) len 4
+ *       Handle: 0x0004
+ *       Data: 0100
+ *
+ *  ATT: Write Response (0x13) len 0
+ */
+#define MICS_WRITE_CCD \
+	IOV_DATA(0x12, 0x04, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x12, 0x04, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ *  ATT: Find Information Request (0x04) len 4
+ *       Handle range: 0x0004-0x0005
+ *
+ *  ATT: Find Information Response (0x05) len 5
+ *       Format: UUID-16 (0x01)
+ *       Handle: 0x0004
+ *       UUID: Client Characteristic Configuration (0x2902)
+ *
+ *  ATT: Find Information Request (0x04) len 4
+ *       Handle range: 0x0005-0x0005
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Find Information Request (0x04)
+ *       Handle: 0x0005
+ *       Error: Attribute Not Found (0x0a)
+ */
+#define MICS_FIND_INFO \
+	IOV_DATA(0x04, 0x04, 0x00, 0x05, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x04, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x05, 0x00, 0x05, 0x00), \
+	IOV_DATA(0x01, 0x04, 0x05, 0x00, 0x0a)
+
+/*
+ * 1.reads the characteristic value for the
+ *  Mute characteristic
+ * 2.update the Mute characteristic to 0 or 1
+ * 3.sends a notification containing the updated value
+ *  of the Mute characteristic
+ * 4.update the Mute characteristic to 0 or 1 which ever
+ *  different than step 2
+ * 5.sends a notification containing the updated value of
+ *  the Mute characteristic
+ */
+#define MICS_SR_SPN_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	DISC_MICS_CHAR_1, \
+	MICS_FIND_BY_TYPE_VALUE, \
+	DISC_MICS_CHAR_AFTER_TYPE, \
+	MICS_FIND_INFO, \
+	MICS_WRITE_CCD, \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01), \
+	MICS_MUTE_WRITE_VAL_00, \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x00), \
+	MICS_MUTE_WRITE_VAL_01, \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x01), \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01)
+
+#define MICS_SR_SGGIT_SER_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	MICS_FIND_BY_TYPE_VALUE
+
+#define MICS_SR_SGGIT_CHA_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	MICS_FIND_BY_TYPE_VALUE, \
+	DISC_MICS_CHAR_AFTER_TYPE
+
+/*
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 02
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Write Request (0x12)
+ *       Handle: 0x0003
+ *       Error: Value Not Allowed (0x13)
+ *
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 05
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Write Request (0x12)
+ *       Handle: 0x0003
+ *       Error: Value Not Allowed (0x13)
+ */
+#define MICS_WRITE_MUTE_CHAR_INVALID \
+	IOV_DATA(0x12, 0x03, 0x00, 0x02), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x13), \
+	IOV_DATA(0x12, 0x03, 0x00, 0x05), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x13)
+
+#define MICS_SR_SPE_BI_1_C	\
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	MICS_FIND_BY_TYPE_VALUE, \
+	MICS_WRITE_MUTE_CHAR_INVALID
+
+/*
+ *  ATT: Read Request (0x0a) len 2
+ *       Handle: 0x0003
+ *
+ *  ATT: Read Response (0x0b) len 1
+ */
+#define	MICS_MUTE_READ_INVALID \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x02)
+
+/*
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 01
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Write Request (0x12)
+ *       Handle: 0x0003
+ *       Error: Reserved (0x80)
+ */
+#define	MICS_MUTE_WRITE_1 \
+	IOV_DATA(0x12, 0x03, 0x00, 0x01), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x80)
+
+/*
+ *  ATT: Write Request (0x12) len 3
+ *       Handle: 0x0003
+ *       Data: 00
+ *
+ *  ATT: Error Response (0x01) len 4
+ *       Write Request (0x12)
+ *       Handle: 0x0003
+ *       Error: Reserved (0x80)
+ */
+#define	MICS_MUTE_WRITE_0 \
+	IOV_DATA(0x12, 0x03, 0x00, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x03, 0x00, 0x80)
+
+#define MICS_SR_SPE_BI_02_C	\
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	MICS_FIND_BY_TYPE_VALUE, \
+	MICS_MUTE_READ_INVALID, \
+	MICS_MUTE_WRITE_0, \
+	MICS_MUTE_WRITE_1
+
+int main(int argc, char *argv[])
+{
+
+	tester_init(&argc, &argv);
+
+    /* MICS Testcases */
+	define_test_mics("MICS/SR/SGGIT/SER/BV-01-C", test_server, NULL,
+					MICS_SR_SGGIT_SER_BV_01_C);
+	define_test_mics("MICS/SR/SGGIT/CHA/BV-01-C", test_server, NULL,
+					MICS_SR_SGGIT_CHA_BV_01_C);
+	define_test_mics("MICS/SR/SPE/BI-01-C", test_server, NULL,
+					MICS_SR_SPE_BI_1_C);
+
+	/* MICS/SR/SPE/BI-02-C:
+	 * In function *mics_new(struct gatt_db *db)[src/shared/micp.c]
+	 * by default the mics->mute_stat is set to MICS_MUTED[0x01].
+	 * As per test specs, Testcase MICS/SR/SPE/BI-02-C, Initial
+	 * condition of mute state should be MICS_DISABLED[0x02].
+	 * To verify this Unit test case we have to modify the initial
+	 * state of mics->mute_stat to MICS_DISABLED in code
+	 * [in func mics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test_mics("MICS/SR/SPE/BI-02-C", test_server, NULL,
+	 *				MICS_SR_SPE_BI_02_C);
+	 */
+	define_test_mics("MICS/SR/SPN/BV-01-C", test_server, NULL,
+					MICS_SR_SPN_BV_01_C);
+
+    /* MICP Testcases */
+	define_test_micp("MICP/CL/CGGIT/SER/BV-01-C", test_client, NULL,
+					MICP_CL_CGGIT_SER_BV_01_C);
+	define_test_micp("MICP/CL/CGGIT/CHA/BV-01-C", test_client, NULL,
+					MICP_CL_CGGIT_CHA_BV_01_C);
+	define_test_micp("MICP/CL/SPE/BI-01-C", test_client, NULL,
+					MICP_CL_SPE_BI_01_C);
+
+	return tester_run();
+}
diff --git a/unit/test-midi.c b/unit/test-midi.c
index 644fcdc..702133e 100644
--- a/unit/test-midi.c
+++ b/unit/test-midi.c
@@ -525,50 +525,54 @@ static const snd_seq_event_t event5_expect[] = {
 
 static const struct midi_write_test midi5 = BLE_WRITE_TEST_INIT(event5, event5_expect);
 
-static void test_midi_writer(gconstpointer data)
+struct midi_data {
+	size_t events_tested;
+	const struct midi_write_test *midi_test;
+	struct midi_read_parser *midi_in;
+} midi_data;
+
+static void compare_events_cb(const struct midi_write_parser *parser,
+						void *user_data)
 {
-	const struct midi_write_test *midi_test = data;
-	struct midi_write_parser midi_out;
-	struct midi_read_parser midi_in;
-	size_t i; /* event counter */
-	size_t j; /* test counter */
-	struct midi_data {
-		size_t events_tested;
-		const struct midi_write_test *midi_test;
-		struct midi_read_parser *midi_in;
-	} midi_data;
+	struct midi_data *midi_data = user_data;
+	const struct midi_write_test *midi_test = midi_data->midi_test;
+	struct midi_read_parser *midi_in = midi_data->midi_in;
+	size_t i = 0;
 
-	void compare_events_cb(const struct midi_write_parser *parser, void *user_data) {
-		struct midi_data *midi_data = user_data;
-		const struct midi_write_test *midi_test = midi_data->midi_test;
-		struct midi_read_parser *midi_in = midi_data->midi_in;
-		size_t i = 0;
+	midi_read_reset(midi_in);
 
-		midi_read_reset(midi_in);
+	while (i < midi_write_data_size(parser)) {
+		snd_seq_event_t ev;
+		size_t count;
 
-		while (i < midi_write_data_size(parser)) {
-			snd_seq_event_t ev;
-			size_t count;
+		snd_seq_ev_clear(&ev);
 
-			snd_seq_ev_clear(&ev);
+		count = midi_read_raw(midi_in, midi_write_data(parser) + i,
+					midi_write_data_size(parser) - i, &ev);
 
-			count = midi_read_raw(midi_in, midi_write_data(parser) + i,
-			                      midi_write_data_size(parser) - i, &ev);
+		g_assert_cmpuint(count, >, 0);
 
-			g_assert_cmpuint(count, >, 0);
+		if (ev.type != SND_SEQ_EVENT_NONE){
+			g_assert_cmpint(midi_data->events_tested, <,
+						midi_test->event_expect_size);
+			compare_events(&midi_test->event_expect
+				       [midi_data->events_tested],
+				       &ev);
+			midi_data->events_tested++;
+		}
 
-			if (ev.type != SND_SEQ_EVENT_NONE){
-				g_assert_cmpint(midi_data->events_tested,
-				                <,
-				                midi_test->event_expect_size);
-				compare_events(&midi_test->event_expect[midi_data->events_tested],
-				               &ev);
-				midi_data->events_tested++;
-			}
+		i += count;
+	}
+};
 
-			i += count;
-		}
-	};
+static void test_midi_writer(gconstpointer data)
+{
+	const struct midi_write_test *midi_test = data;
+	struct midi_write_parser midi_out;
+	struct midi_read_parser midi_in;
+	size_t i; /* event counter */
+	size_t j; /* test counter */
+	struct midi_data midi_data;
 
 	midi_read_init(&midi_in);
 
diff --git a/unit/test-uhid.c b/unit/test-uhid.c
index 8a8eef8..c5848be 100644
--- a/unit/test-uhid.c
+++ b/unit/test-uhid.c
@@ -33,8 +33,19 @@ struct test_pdu {
 	size_t size;
 };
 
+struct test_device {
+	const char *name;
+	uint32_t vendor;
+	uint32_t product;
+	uint32_t version;
+	uint32_t country;
+	uint8_t type;
+	struct iovec map;
+};
+
 struct test_data {
 	char *test_name;
+	struct test_device *test_device;
 	struct test_pdu *pdu_list;
 };
 
@@ -54,17 +65,21 @@ struct context {
 		.size = sizeof(*args),				\
 	}
 
-#define define_test(name, function, args...)				\
+#define define_test_device(name, function, device, args...)		\
 	do {								\
 		const struct test_pdu pdus[] = {			\
 			args, { }					\
 		};							\
 		static struct test_data data;				\
 		data.test_name = g_strdup(name);			\
+		data.test_device = device;				\
 		data.pdu_list = util_memdup(pdus, sizeof(pdus));	\
 		tester_add(name, &data, NULL, function, NULL);		\
 	} while (0)
 
+#define define_test(name, function, args...)			\
+	define_test_device(name, function, NULL, args)
+
 static void test_debug(const char *str, void *user_data)
 {
 	const char *prefix = user_data;
@@ -85,6 +100,7 @@ static void destroy_context(struct context *context)
 	if (context->source > 0)
 		g_source_remove(context->source);
 
+	bt_uhid_unregister_all(context->uhid);
 	bt_uhid_unref(context->uhid);
 
 	test_free(context->data);
@@ -117,8 +133,8 @@ static gboolean send_pdu(gpointer user_data)
 
 	len = write(context->fd, pdu->data, pdu->size);
 
-
-	util_hexdump('<', pdu->data, len, test_debug, "uHID: ");
+	if (tester_use_debug())
+		util_hexdump('<', pdu->data, len, test_debug, "uHID: ");
 
 	g_assert_cmpint(len, ==, pdu->size);
 
@@ -159,7 +175,8 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 
 	g_assert(len > 0);
 
-	util_hexdump('>', buf, len, test_debug, "uHID: ");
+	if (tester_use_debug())
+		util_hexdump('>', buf, len, test_debug, "uHID: ");
 
 	g_assert_cmpint(len, ==, pdu->size);
 
@@ -173,8 +190,25 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 static struct context *create_context(gconstpointer data)
 {
 	struct context *context = g_new0(struct context, 1);
+	const struct test_data *test_data = data;
 	GIOChannel *channel;
 	int err, sv[2];
+	uid_t uid = getuid();
+
+	context->data = data;
+
+	/* Device testings requires extra permissions in order to be able to
+	 * create devices.
+	 */
+	if (test_data->test_device && !uid) {
+		context->uhid = bt_uhid_new_default();
+		if (!context->uhid) {
+			tester_test_abort();
+			context_quit(context);
+			return NULL;
+		}
+		return context;
+	}
 
 	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
 	g_assert(err == 0);
@@ -196,7 +230,6 @@ static struct context *create_context(gconstpointer data)
 	g_io_channel_unref(channel);
 
 	context->fd = sv[1];
-	context->data = data;
 
 	return context;
 }
@@ -228,19 +261,47 @@ static const struct uhid_event ev_feature = {
 static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(data);
+	struct test_device *device;
+	int err;
 
-	if (g_str_equal(context->data->test_name, "/uhid/command/create"))
-		bt_uhid_send(context->uhid, &ev_create);
+	if (!context)
+		return;
 
-	if (g_str_equal(context->data->test_name, "/uhid/command/destroy"))
-		bt_uhid_send(context->uhid, &ev_destroy);
+	device = context->data->test_device;
+	if (device)
+		err = bt_uhid_create(context->uhid, device->name,
+					BDADDR_ANY, BDADDR_ANY,
+					device->vendor, device->product,
+					device->version, device->country,
+					device->type, device->map.iov_base,
+					device->map.iov_len);
+	else
+		err = bt_uhid_create(context->uhid, "", NULL, NULL, 0, 0, 0, 0,
+					BT_UHID_NONE, NULL, 0);
+
+	if (err < 0) {
+		tester_debug("create failed: %s\n", strerror(-err));
+		tester_test_failed();
+	}
+
+	if (g_str_equal(context->data->test_name, "/uhid/command/destroy")) {
+		err = bt_uhid_destroy(context->uhid, true);
+		if (err < 0)
+			tester_test_failed();
+	}
 
 	if (g_str_equal(context->data->test_name,
-						"/uhid/command/feature_answer"))
-		bt_uhid_send(context->uhid, &ev_feature_answer);
+				"/uhid/command/feature_answer")) {
+		err = bt_uhid_send(context->uhid, &ev_feature_answer);
+		if (err < 0)
+			tester_test_failed();
+	}
 
-	if (g_str_equal(context->data->test_name, "/uhid/command/input"))
-		bt_uhid_send(context->uhid, &ev_input);
+	if (g_str_equal(context->data->test_name, "/uhid/command/input")) {
+		err = bt_uhid_input(context->uhid, 0, NULL, 0);
+		if (err < 0)
+			tester_test_failed();
+	}
 
 	context_quit(context);
 }
@@ -269,6 +330,29 @@ static void test_server(gconstpointer data)
 	g_idle_add(send_pdu, context);
 }
 
+
+static struct test_device mx_anywhere_3 = {
+	.name = "MX Anywhere 3",
+	.vendor = 0x46D,
+	.product = 0xB025,
+	.version = 0x14,
+	.country = 0x00,
+	.type = BT_UHID_MOUSE,
+	.map = UTIL_IOV_INIT(0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x02,
+				0x09, 0x01, 0xA1, 0x00, 0x95, 0x10, 0x75, 0x01,
+				0x15, 0x00, 0x25, 0x01, 0x05, 0x09, 0x19, 0x01,
+				0x29, 0x10, 0x81, 0x02, 0x05, 0x01, 0x16, 0x01,
+				0xF8, 0x26, 0xFF, 0x07, 0x75, 0x0C, 0x95, 0x02,
+				0x09, 0x30, 0x09, 0x31, 0x81, 0x06, 0x15, 0x81,
+				0x25, 0x7F, 0x75, 0x08, 0x95, 0x01, 0x09, 0x38,
+				0x81, 0x06, 0x95, 0x01, 0x05, 0x0C, 0x0A, 0x38,
+				0x02, 0x81, 0x06, 0xC0, 0xC0, 0x06, 0x43, 0xFF,
+				0x0A, 0x02, 0x02, 0xA1, 0x01, 0x85, 0x11, 0x75,
+				0x08, 0x95, 0x13, 0x15, 0x00, 0x26, 0xFF, 0x00,
+				0x09, 0x02, 0x81, 0x00, 0x09, 0x02, 0x91, 0x00,
+				0xC0),
+};
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -282,5 +366,8 @@ int main(int argc, char *argv[])
 	define_test("/uhid/event/output", test_server, event(&ev_output));
 	define_test("/uhid/event/feature", test_server, event(&ev_feature));
 
+	define_test_device("/uhid/device/mx_anywhere_3", test_client,
+					&mx_anywhere_3, event(&ev_create));
+
 	return tester_run();
 }
diff --git a/unit/test-vcp.c b/unit/test-vcp.c
new file mode 100644
index 0000000..6a61ea2
--- /dev/null
+++ b/unit/test-vcp.c
@@ -0,0 +1,2761 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2023  NXP Semiconductors. All rights reserved.
+ *
+ *  This file contains only VOCS related Unit Test cases.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "src/shared/util.h"
+#include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/vcp.h"
+
+struct test_data {
+	struct gatt_db *db;
+	struct bt_vcp *vcp;
+	struct bt_gatt_server *server;
+	struct queue *ccc_states;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+struct notify {
+	uint16_t handle, ccc_handle;
+	uint8_t *value;
+	uint16_t len;
+	bt_gatt_server_conf_func_t conf;
+	void *user_data;
+};
+
+struct ccc_state {
+	uint16_t handle;
+	uint16_t value;
+};
+
+#define iov_data(args...) ((const struct iovec[]) { args })
+
+#define define_test(name, function, _cfg, args...)		\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data data;			\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		tester_add(name, &data, NULL, function,	\
+				test_teardown);			\
+	} while (0)
+
+static void test_complete_cb(const void *user_data)
+{
+	tester_test_passed();
+}
+
+static void print_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	if (tester_use_debug())
+		tester_debug("%s%s", prefix, str);
+}
+
+static void test_teardown(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+
+	bt_vcp_unref(data->vcp);
+	bt_gatt_server_unref(data->server);
+	util_iov_free(data->iov, data->iovcnt);
+
+	gatt_db_unref(data->db);
+
+	queue_destroy(data->ccc_states, free);
+
+	tester_teardown_complete();
+}
+
+static bool ccc_state_match(const void *a, const void *b)
+{
+	const struct ccc_state *ccc = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return ccc->handle == handle;
+}
+
+static struct ccc_state *find_ccc_state(struct test_data *data,
+				uint16_t handle)
+{
+	return queue_find(data->ccc_states, ccc_state_match,
+				UINT_TO_PTR(handle));
+}
+
+static struct ccc_state *get_ccc_state(struct test_data *data,
+					uint16_t handle)
+{
+	struct ccc_state *ccc;
+
+	ccc = find_ccc_state(data, handle);
+	if (ccc)
+		return ccc;
+
+	ccc = new0(struct ccc_state, 1);
+	ccc->handle = handle;
+	queue_push_tail(data->ccc_states, ccc);
+
+	return ccc;
+}
+
+static void gatt_notify_cb(struct gatt_db_attribute *attrib,
+					struct gatt_db_attribute *ccc,
+					const uint8_t *value, size_t len,
+					struct bt_att *att, void *user_data)
+{
+	struct test_data *data = user_data;
+	uint16_t handle = gatt_db_attribute_get_handle(attrib);
+
+	if (!bt_gatt_server_send_notification(data->server,
+			handle, value, len, false))
+		printf("%s: Failed to send notification\n", __func__);
+}
+
+static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offest,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct test_data *data = user_data;
+	struct ccc_state *ccc;
+	uint16_t handle;
+	uint8_t ecode = 0;
+	uint16_t value = 0;
+
+	handle = gatt_db_attribute_get_handle(attrib);
+
+	ccc = get_ccc_state(data, handle);
+	if (!ccc) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	value = cpu_to_le16(ccc->value);
+
+done:
+	gatt_db_attribute_read_result(attrib, id, ecode, (void *)&value,
+							sizeof(value));
+}
+
+static void test_server(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct bt_att *att;
+	struct io *io;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	data->db = gatt_db_new();
+	g_assert(data->db);
+
+	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, NULL,
+					gatt_notify_cb, data);
+
+	data->vcp = bt_vcp_new(data->db, NULL);
+	g_assert(data->vcp);
+
+	data->server = bt_gatt_server_new(data->db, att, 64, 0);
+	g_assert(data->server);
+
+	bt_gatt_server_set_debug(data->server, print_debug, "bt_gatt_server",
+						NULL);
+
+	data->ccc_states = queue_new();
+
+	tester_io_send();
+
+	bt_att_unref(att);
+}
+
+ /* ATT: Exchange MTU Request (0x02) len 2
+  *     Client RX MTU: 64
+  * ATT: Exchange MTU Response (0x03) len 2
+  *     Server RX MTU: 64
+  */
+#define VCS_EXCHANGE_MTU \
+	IOV_DATA(0x02, 0x40, 0x00), \
+	IOV_DATA(0x03, 0x40, 0x00)
+
+ /*  ATT: Read By Group Type Request (0x10) len 6
+  *      Handle range: 0x0001-0xffff
+  *      Attribute group type: Primary Service (0x2800)
+  *
+  *  ATT: Read By Group Type Response (0x11) len 7
+  *      Attribute data length: 6
+  *      Attribute group list: 1 entry
+  *      Handle range: 0x001d-0x0027
+  *      UUID: Volume Control (0x1844)
+  *
+  *  ATT: Read By Group Type Request (0x10) len 6
+  *      Handle range: 0x0027-0xffff
+  *      Attribute group type: Primary Service (0x2800)
+  *
+  *  ATT: Error Response (0x01) len 4
+  *      Read By Group Type Request (0x10)
+  *      Handle: 0x0027
+  *      Error: Attribute Not Found (0x0a)
+  */
+#define VOCS_AICS_PRIMARY_SERVICE_VCS \
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x11, 0x06, 0x1d, 0x00, 0x27, 0x00, 0x44, 0x18), \
+	IOV_DATA(0x10, 0x27, 0x00, 0xff, 0xff, 0x00, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x27, 0x00, 0x0a)
+
+ /* ATT: Read By Group Type Request (0x10) len 6
+  *      Handle range: 0x0001-0xffff
+  *      Attribute group type: Secondary Service (0x2801)
+  *
+  * ATT: Read By Group Type Response (0x11) len 7
+  *     Attribute data length: 6
+  *     Attribute group list: 2 entry
+  *     Handle range: 0x0001-0x000c
+  *     UUID: Volume Offset Control (0x1845)
+  *     Handle range: 0x000d-0x001c
+  *     UUID: Audio Input Control (0x1843)
+  *
+  * ATT: Read By Group Type Request (0x10) len 6
+  *     Handle range: 0x001d-0xffff
+  *     Attribute group type: Secondary Service (0x2801)
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Read By Group Type Request (0x10)
+  *     Handle: 0x001d
+  *     Error: Attribute Not Found (0x0a)
+  */
+#define VOCS_AICS_SECONDARY_SERVICE \
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28), \
+	IOV_DATA(0x11, 0x06, \
+		0x01, 0x00, 0x0c, 0x00, 0x45, 0x18, \
+		0x0d, 0x00, 0x1c, 0x00, 0x43, 0x18), \
+	IOV_DATA(0x10, 0x1d, 0x00, 0xff, 0xff, 0x01, 0x28), \
+	IOV_DATA(0x01, 0x10, 0x1d, 0x00, 0x0a)
+
+ /* ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x0001-0xffff
+  *     Attribute type: Include (0x2802)
+  *
+  * ATT: Read By Type Response (0x09) len 9
+  *     Attribute data length: 8
+  *     Attribute data list: 2 entries
+  *     Handle: 0x001e
+  *     Value: 01000c004518
+  *     Handle: 0x001f
+  *     Value: 0d001c004318
+  *
+  * ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x0020-0xffff
+  *     Attribute type: Include (0x2802)
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Read By Type Request (0x08)
+  *     Handle: 0x0020
+  *     Error: Attribute Not Found (0x0a)
+  */
+#define VOCS_AICS_INCLUDED_SERVICE \
+	IOV_DATA(0x08, 0x01, 0x00, 0xff, 0xff, 0x02, 0x28), \
+	IOV_DATA(0x09, 0x08, \
+		0x1e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x45, 0x18, \
+		0x1f, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x43, 0x18), \
+	IOV_DATA(0x08, 0x20, 0x00, 0xff, 0xff, 0x02, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x20, 0x00, 0x0a)
+
+ /* ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x0001-0x000c
+  *     Attribute type: Characteristic (0x2803)
+  *
+  * ATT: Read By Type Response (0x09) len 29
+  *     Attribute data length: 7
+  *     Attribute data list: 4 entries
+  *     Handle: 0x0002
+  *     Value: 120300802b
+  *     Handle: 0x0005
+  *     Value: 120600812b
+  *     Handle: 0x0008
+  *     Value: 080900822b
+  *     Handle: 0x000a
+  *     Value: 120b00832b
+  *
+  * ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x000b-0x000c
+  *     Attribute type: Characteristic (0x2803)
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Read By Type Request (0x08)
+  *     Handle: 0x000b
+  *     Error: Attribute Not Found (0x0a)
+  */
+#define VOCS_DISC_CHAR \
+	IOV_DATA(0x08, 0x01, 0x00, 0x0c, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x09, 0x07, \
+		0x02, 0x00, 0x12, 0x03, 0x00, 0x80, 0x2b, \
+		0x05, 0x00, 0x12, 0x06, 0x00, 0x81, 0x2b, \
+		0x08, 0x00, 0x08, 0x09, 0x00, 0x82, 0x2b, \
+		0x0a, 0x00, 0x12, 0x0b, 0x00, 0x83, 0x2b), \
+	IOV_DATA(0x08, 0x0b, 0x00, 0x0c, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x0b, 0x00, 0x0a)
+
+ /*
+  *   ATT: Read By Type Request (0x08) len 6
+  *   Handle range: 0x000d-0x001c
+  *   Attribute type: Characteristic (0x2803)
+  *
+  *   ATT: Read By Type Response (0x09) len 43
+  *    Attribute data length: 7
+  *    Attribute data list: 6 entries
+  *    Handle: 0x000e
+  *    Value: 120f00772b
+  *    Handle: 0x0011
+  *    Value: 021200782b
+  *    Handle: 0x0013
+  *    Value: 021400792b
+  *    Handle: 0x0015
+  *    Value: 1216007a2b
+  *    Handle: 0x0018
+  *    Value: 0819007b2b
+  *    Handle: 0x001a
+  *    Value: 161b007c2b
+  *
+  *  ATT: Read By Type Request (0x08) len 6
+  *    Handle range: 0x001b-0x001c
+  *    Attribute type: Characteristic (0x2803)
+  *
+  *  ATT: Error Response (0x01) len 4
+  *    Read By Type Request (0x08)
+  *    Handle: 0x001b
+  *    Error: Attribute Not Found (0x0a)
+  */
+ #define AICS_DISC_CHAR \
+	IOV_DATA(0x08, 0x0d, 0x00, 0x1c, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x09, 0x07, \
+		0x0e, 0x00, 0x12, 0x0f, 0x00, 0x77, 0x2b, \
+		0x11, 0x00, 0x02, 0x12, 0x00, 0x78, 0x2b, \
+		0x13, 0x00, 0x02, 0x14, 0x00, 0x79, 0x2b, \
+		0x15, 0x00, 0x12, 0x16, 0x00, 0x7a, 0x2b, \
+		0x18, 0x00, 0x08, 0x19, 0x00, 0x7b, 0x2b, \
+		0x1a, 0x00, 0x16, 0x1b, 0x00, 0x7c, 0x2b), \
+	IOV_DATA(0x08, 0x1b, 0x00, 0x1c, 0x00, 0x03, 0x28), \
+	IOV_DATA(0x01, 0x08, 0x1b, 0x00, 0x0a)
+
+ /* ATT: Find Information Request (0x04) len 4
+  *    Handle range: 0x0004-0x0004
+  *
+  * ATT: Find Information Response (0x05) len 5
+  *    Format: UUID-16 (0x01)
+  *    Handle: 0x0004
+  *    UUID: Client Characteristic Configuration (0x2902)
+  *
+  * ATT: Find Information Request (0x04) len 4
+  *    Handle range: 0x0007-0x0007
+  *
+  * ATT: Find Information Response (0x05) len 5
+  *    Format: UUID-16 (0x01)
+  *    Handle: 0x0007
+  *    UUID: Client Characteristic Configuration (0x2902)
+  *
+  * ATT: Find Information Request (0x04) len 4
+  *    Handle range: 0x000c-0x000c
+  *
+  * ATT: Find Information Response (0x05) len 5
+  *    Format: UUID-16 (0x01)
+  *    Handle: 0x000c
+  *    UUID: Client Characteristic Configuration (0x2902)
+  */
+#define VOCS_DISC_CHAR_DESC \
+	IOV_DATA(0x04, 0x04, 0x00, 0x04, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x04, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x07, 0x00, 0x07, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x07, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x0c, 0x00, 0x0c, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x0c, 0x00, 0x02, 0x29)
+
+ /*
+  *  ATT: Find Information Request (0x04) len 4
+  *     Handle range: 0x0010-0x0010
+  *
+  *  ATT: Find Information Response (0x05) len 5
+  *     Format: UUID-16 (0x01)
+  *     Handle: 0x0010
+  *     UUID: Client Characteristic Configuration (0x2902)
+  *
+  *  ATT: Find Information Request (0x04) len 4
+  *     Handle range: 0x0017-0x0017
+  *
+  *  ATT: Find Information Response (0x05) len 5
+  *     Format: UUID-16 (0x01)
+  *     Handle: 0x0017
+  *     UUID: Client Characteristic Configuration (0x2902)
+  *
+  *  ATT: Find Information Request (0x04) len 4
+  *      Handle range: 0x001c-0x001c
+  *
+  *  ATT: Find Information Response (0x05) len 5
+  *     Format: UUID-16 (0x01)
+  *     Handle: 0x001c
+  *     UUID: Client Characteristic Configuration (0x2902)
+  */
+ #define AICS_DISC_CHAR_DESC \
+	IOV_DATA(0x04, 0x10, 0x00, 0x10, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x10, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x17, 0x00, 0x17, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x17, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x04, 0x1c, 0x00, 0x1c, 0x00), \
+	IOV_DATA(0x05, 0x01, 0x1c, 0x00, 0x02, 0x29)
+
+ /* ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0004
+  *
+  * ATT: Read Response (0x0b) len 2
+  *
+  *  ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0007
+  *
+  * ATT: Read Response (0x0b) len 2
+  *
+  * ATT: Read Request (0x0a) len 2
+  *     Handle: 0x000c
+  *
+  * ATT: Read Request (0x0a) len 2
+  *     Handle: 0x000c
+  */
+#define VOCS_READ_CHAR_DESC \
+	IOV_DATA(0x0a, 0x04, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x07, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x0c, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00)
+
+ /*
+  *  ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0010
+  *  ATT: Read Response (0x0b) len 2
+  *
+  *  ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0017
+  *  ATT: Read Response (0x0b) len 2
+  *
+  *  ATT: Read Request (0x0a) len 2
+  *      Handle: 0x001c
+  *  ATT: Read Response (0x0b) len 2
+  */
+#define AICS_READ_CHAR_DESC \
+	IOV_DATA(0x0a, 0x10, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x17, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x1c, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x0012
+  *
+  * ATT: Read Response (0x0b) len 3
+  */
+#define AICS_READ_CHAR_GAIN_SETTNG_PROP \
+	IOV_DATA(0x0a, 0x12, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x80, 0x7f)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x00, 0x02, 00)
+
+ /*
+  *  ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  *  ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE_MUT_DIS \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x02, 0x02, 00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE_MUTED \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x01, 0x02, 00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE_UNMUTED \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x00, 0x02, 00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE_AUTOMATIC \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x00, 0x03, 00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x000f
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define AICS_READ_CHAR_AUD_IP_STATE_MANUAL \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0x58, 0x00, 0x02, 00)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x0012
+  *
+  * ATT: Read Response (0x0b) len 3
+  */
+#define AICS_READ_CHAR_GAIN_SETTING_PROP \
+	IOV_DATA(0x0a, 0x12, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x80, 0x7f)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x0014
+  *
+  * ATT: Read Response (0x0b) len 1
+  */
+#define AICS_READ_CHAR_AUD_IP_TYPE \
+	IOV_DATA(0x0a, 0x14, 0x00), \
+	IOV_DATA(0x0b, 0x01)
+
+ /*
+  * ATT: Read Request (0x0a) len 2
+  *		Handle: 0x0014
+  *
+  * ATT: Read Response (0x0b) len 1
+  */
+#define AICS_READ_CHAR_AUD_IP_STATUS \
+	IOV_DATA(0x0a, 0x16, 0x00), \
+	IOV_DATA(0x0b, 0x01)
+
+ /*
+  * ATT: Write Request (0x12) len 5
+  *		Handle: 0x0019
+  *			Data: 016401
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0019
+  *      Error: Reserved (0x80)
+  *
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *        Data: 0265/0366/0467/0568
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0019
+  *     Error: Reserved (0x80)
+  */
+#define AICS_CP_WR_INVLD_CHG_COUNTER \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x64, 0x01), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x80), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x02, 0x65), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x80), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x03, 0x66), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x80), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x04, 0x67), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x80), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x05, 0x68), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x80)
+
+ /*
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *			Data: 0600/ff00
+  *
+  * ATT: Error Response (0x01) len 4
+  *		Write Request (0x12)
+  *		Handle: 0x0019
+  *		Error: Reserved (0x81)
+  */
+#define AICS_CP_WR_INVLD_OP_CODE \
+	IOV_DATA(0x12, 0x19, 0x00, 0x06, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x81), \
+	IOV_DATA(0x12, 0x19, 0x00, 0xff, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x81)
+
+ /*
+  *  ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *        Data: 0200
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0019
+  *     Error: Reserved (0x82)
+  */
+#define AICS_CP_WR_UNMUTE \
+	IOV_DATA(0x12, 0x19, 0x00, 0x02, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x82)
+
+ /*
+  *  ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *			Data: 0300
+  *
+  *  ATT: Error Response (0x01) len 4
+  *		Write Request (0x12)
+  *     Handle: 0x0019
+  *     Error: Reserved (0x82)
+  */
+#define AICS_CP_WR_MUTE \
+	IOV_DATA(0x12, 0x19, 0x00, 0x03, 0x00), \
+	IOV_DATA(0x01, 0x12, 0x19, 0x00, 0x82)
+
+ /*
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *			Data: 0200
+  *
+  *  ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_UNMUTE_SUCCESS \
+	IOV_DATA(0x12, 0x19, 0x00, 0x02, 0x00), \
+	IOV_DATA(0x13)
+
+ /*
+  *  ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *       Data: 0300
+  *
+  *   ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_MUTE_SUCCESS \
+	IOV_DATA(0x12, 0x19, 0x00, 0x03, 0x00), \
+	IOV_DATA(0x13)
+
+ /*
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *			Data: 0400
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_MANUAL_GAIN \
+	IOV_DATA(0x12, 0x19, 0x00, 0x04, 0x00), \
+	IOV_DATA(0x13)
+
+ /*
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0019
+  *			Data: 0500
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_AUTOMATIC_GAIN \
+	IOV_DATA(0x12, 0x19, 0x00, 0x05, 0x00), \
+	IOV_DATA(0x13)
+
+ /*
+  * ATT: Write Request (0x12) len 5
+  *		Handle: 0x0019
+  *		Data: 01007f
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_GAIN_SETTING_MAX \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x00, 0x7f), \
+	IOV_DATA(0x13)
+
+ /*
+  * ATT: Write Request (0x12) len 5
+  *		Handle: 0x0019
+  *		Data: 010080
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define AICS_CP_WR_GAIN_SETTING_MIN \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x01, 0x80), \
+	IOV_DATA(0x13)
+
+ /*
+  * ATT: Write Request (0x12) len 4
+  *		Handle: 0x0010
+  *			Data: 0100
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define AICS_ENABLE_AUD_IP_STATE_CC \
+	IOV_DATA(0x12, 0x10, 0x00, 0x01, 0x00), \
+	IOV_DATA(0X13)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 58000201
+  */
+#define AICS_AUD_IP_STATE_UNMUTED_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x00, 0x02, 0x01)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 58010201
+  */
+#define AICS_AUD_IP_STATE_MUTED_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x01, 0x02, 0x01)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 58000201
+  *
+  */
+#define AICS_AUD_IP_STATE_MANUAL_GAIN_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x00, 0x02, 0x01)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 58000301
+  */
+#define AICS_AUD_IP_STATE_AUTOMATIC_GAIN_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x00, 0x03, 0x01)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 7f000201
+  */
+#define AICS_AUD_IP_STATE_GAIN_SETTING_MAX_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7f, 0x00, 0x02, 0x01)
+
+ /*
+  * ATT: Handle Value Notification (0x1b) len 6
+  *		Handle: 0x000f
+  *			Data: 80000202
+  */
+#define AICS_AUD_IP_STATE_GAIN_SETTING_MIN_NOTIF \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x80, 0x00, 0x02, 0x02)
+
+ /*
+  * AICS/SR/CP/BV-01-C
+  * Test Procedure:
+  * 1. The Lower Tester executes the GATT Read Characteristic Value
+  *     sub-procedure for the Audio Input State characteristic.
+  * 2. The Lower Tester executes the GATT Read Characteristic Value
+  *     sub-procedure for the Gain Setting Properties characteristic.
+  * Repeat steps 3–5 for (255 – Change_Counter value) + 1 times.
+  *		[AICS_CP_WR_GAIN_SETTING_255_LOOP does the above point]
+  * 3. The Lower Tester executes the GATT Write Characteristic Value
+  *    sub-procedure for the Audio Input Control Point characteristic with
+  *    the Set Gain Setting Opcode, Gain Setting parameter set to a random
+  *    value between the Gain_Setting_Minimum field and Gain_Setting_Maximum
+  *    field values and different than the last iteration, and the
+  *     Change_Counter parameter.
+  * 4. The Lower Tester receives a Write Response indicating that the IUT
+  *    has accepted the Opcode.
+  * 5. The Lower Tester receives a GATT Characteristic Value Notification
+  *    for the Audio Input State characteristic.
+  *
+  */
+#define AICS_CP_WR_GAIN_SETTING_255_LOOP \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x00, 0xc4), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc4, 0x00, 0x02, 0x01), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x01, 0xaf), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xaf, 0x00, 0x02, 0x02), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x02, 0xcd), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xcd, 0x00, 0x02, 0x03), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x03, 0xd4), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xd4, 0x00, 0x02, 0x04), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x04, 0x08), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x08, 0x00, 0x02, 0x05), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x05, 0x88), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x88, 0x00, 0x02, 0x06), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x06, 0xde), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xde, 0x00, 0x02, 0x07), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x07, 0x21), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x21, 0x00, 0x02, 0x08), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x08, 0x41), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x41, 0x00, 0x02, 0x09), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x09, 0x08), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x08, 0x00, 0x02, 0x0a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0a, 0x05), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x05, 0x00, 0x02, 0x0b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0b, 0x18), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x18, 0x00, 0x02, 0x0c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0c, 0x28), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x28, 0x00, 0x02, 0x0d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0d, 0xca), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xca, 0x00, 0x02, 0x0e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0e, 0xa0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa0, 0x00, 0x02, 0x0f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x0f, 0xd0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xd0, 0x00, 0x02, 0x10), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x10, 0xec), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xec, 0x00, 0x02, 0x11), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x11, 0x3c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3c, 0x00, 0x02, 0x12), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x12, 0x09), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x09, 0x00, 0x02, 0x13), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x13, 0x05), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x05, 0x00, 0x02, 0x14), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x14, 0x29), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x29, 0x00, 0x02, 0x15), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x15, 0x28), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x28, 0x00, 0x02, 0x16), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x16, 0x25), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x25, 0x00, 0x02, 0x17), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x17, 0x31), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x31, 0x00, 0x02, 0x18), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x18, 0x49), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x49, 0x00, 0x02, 0x19), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x19, 0x12), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x12, 0x00, 0x02, 0x1a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1a, 0x09), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x09, 0x00, 0x02, 0x1b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1b, 0x29), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x29, 0x00, 0x02, 0x1c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1c, 0x55), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x55, 0x00, 0x02, 0x1d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1d, 0x35), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x35, 0x00, 0x02, 0x1e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1e, 0x59), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x59, 0x00, 0x02, 0x1f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x1f, 0x69), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x69, 0x00, 0x02, 0x20), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x20, 0x22), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x22, 0x00, 0x02, 0x21), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x21, 0x79), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x79, 0x00, 0x02, 0x22), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x22, 0x11), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x11, 0x00, 0x02, 0x23), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x23, 0x21), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x21, 0x00, 0x02, 0x24), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x24, 0x0a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0a, 0x00, 0x02, 0x25), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x25, 0x0b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0b, 0x00, 0x02, 0x26), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x26, 0x0c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0c, 0x00, 0x02, 0x27), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x27, 0x0d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0d, 0x00, 0x02, 0x28), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x28, 0x0e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0e, 0x00, 0x02, 0x29), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x29, 0x0f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0f, 0x00, 0x02, 0x2a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2a, 0x61), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x61, 0x00, 0x02, 0x2b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2b, 0x63), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x63, 0x00, 0x02, 0x2c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2c, 0x64), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x64, 0x00, 0x02, 0x2d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2d, 0x68), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x68, 0x00, 0x02, 0x2e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2e, 0x14), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x14, 0x00, 0x02, 0x2f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x2f, 0x33), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x33, 0x00, 0x02, 0x30), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x30, 0x31), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x31, 0x00, 0x02, 0x31), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x31, 0x3e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3e, 0x00, 0x02, 0x32), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x32, 0x79), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x79, 0x00, 0x02, 0x33), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x33, 0x99), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x99, 0x00, 0x02, 0x34), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x34, 0x81), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x81, 0x00, 0x02, 0x35), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x35, 0x73), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x73, 0x00, 0x02, 0x36), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x36, 0x75), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x75, 0x00, 0x02, 0x37), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x37, 0x6f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6f, 0x00, 0x02, 0x38), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x38, 0x4e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4e, 0x00, 0x02, 0x39), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x39, 0x1a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1a, 0x00, 0x02, 0x3a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3a, 0x1c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1c, 0x00, 0x02, 0x3b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3b, 0x2c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2c, 0x00, 0x02, 0x3c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3c, 0x5a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5a, 0x00, 0x02, 0x3d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3d, 0x3d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3d, 0x00, 0x02, 0x3e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3e, 0x5f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5f, 0x00, 0x02, 0x3f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x3f, 0x6e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6e, 0x00, 0x02, 0x40), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x40, 0x2c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2c, 0x00, 0x02, 0x41), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x41, 0x7c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7c, 0x00, 0x02, 0x42), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x42, 0x01), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x01, 0x00, 0x02, 0x43), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x43, 0x2b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2b, 0x00, 0x02, 0x44), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x44, 0xbc), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xbc, 0x00, 0x02, 0x45), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x45, 0x3b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3b, 0x00, 0x02, 0x46), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x46, 0x4c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4c, 0x00, 0x02, 0x47), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x47, 0x3d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3d, 0x00, 0x02, 0x48), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x48, 0x7e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7e, 0x00, 0x02, 0x49), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x49, 0x2f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2f, 0x00, 0x02, 0x4a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4a, 0x71), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x71, 0x00, 0x02, 0x4b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4b, 0x93), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x93, 0x00, 0x02, 0x4c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4c, 0x6c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6c, 0x00, 0x02, 0x4d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4d, 0x78), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x78, 0x00, 0x02, 0x4e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4e, 0x44), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x44, 0x00, 0x02, 0x4f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x4f, 0x83), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x83, 0x00, 0x02, 0x50), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x50, 0x2c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2c, 0x00, 0x02, 0x51), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x51, 0x7e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7e, 0x00, 0x02, 0x52), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x52, 0x61), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x61, 0x00, 0x02, 0x53), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x53, 0xbb), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xbb, 0x00, 0x02, 0x54), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x54, 0xb1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb1, 0x00, 0x02, 0x55), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x55, 0x3e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3e, 0x00, 0x02, 0x56), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x56, 0xca), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xca, 0x00, 0x02, 0x57), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x57, 0x3f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3f, 0x00, 0x02, 0x58), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x58, 0x3e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3e, 0x00, 0x02, 0x59), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x59, 0xdf), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xdf, 0x00, 0x02, 0x5a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5a, 0xe1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe1, 0x00, 0x02, 0x5b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5b, 0xd3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xd3, 0x00, 0x02, 0x5c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5c, 0x9c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9c, 0x00, 0x02, 0x5d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5d, 0x70), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x70, 0x00, 0x02, 0x5e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5e, 0xa4), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa4, 0x00, 0x02, 0x5f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x5f, 0x8a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x8a, 0x00, 0x02, 0x60), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x60, 0x7c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7c, 0x00, 0x02, 0x61), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x61, 0x5f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5f, 0x00, 0x02, 0x62), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x62, 0x6a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6a, 0x00, 0x02, 0x63), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x63, 0xb3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb3, 0x00, 0x02, 0x64), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x64, 0xb7), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb7, 0x00, 0x02, 0x65), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x65, 0x3b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3b, 0x00, 0x02, 0x66), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x66, 0x4a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4a, 0x00, 0x02, 0x67), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x67, 0x3b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3b, 0x00, 0x02, 0x68), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x68, 0x8e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x8e, 0x00, 0x02, 0x69), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x69, 0xef), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xef, 0x00, 0x02, 0x6a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6a, 0xe5), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe5, 0x00, 0x02, 0x6b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6b, 0xe3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe3, 0x00, 0x02, 0x6c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6c, 0x5c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5c, 0x00, 0x02, 0x6d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6d, 0x79), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x79, 0x00, 0x02, 0x6e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6e, 0xa1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa1, 0x00, 0x02, 0x6f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x6f, 0x8b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x8b, 0x00, 0x02, 0x70), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x70, 0x5e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5e, 0x00, 0x02, 0x71), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x71, 0x0f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x0f, 0x00, 0x02, 0x72), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x72, 0x6c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6c, 0x00, 0x02, 0x73), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x73, 0xb9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb9, 0x00, 0x02, 0x74), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x74, 0xb0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb0, 0x00, 0x02, 0x75), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x75, 0x31), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x31, 0x00, 0x02, 0x76), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x76, 0x4d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4d, 0x00, 0x02, 0x77), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x77, 0x39), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x39, 0x00, 0x02, 0x78), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x78, 0xde), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xde, 0x00, 0x02, 0x79), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x79, 0xe9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe9, 0x00, 0x02, 0x7a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7a, 0xe8), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe8, 0x00, 0x02, 0x7b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7b, 0xa3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa3, 0x00, 0x02, 0x7c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7c, 0xcc), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xcc, 0x00, 0x02, 0x7d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7d, 0x89), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x89, 0x00, 0x02, 0x7e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7e, 0xa9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa9, 0x00, 0x02, 0x7f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x7f, 0x83), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x83, 0x00, 0x02, 0x80), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x80, 0x4e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4e, 0x00, 0x02, 0x81), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x81, 0x9f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9f, 0x00, 0x02, 0x82), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x82, 0x6f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6f, 0x00, 0x02, 0x83), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x83, 0xb5), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb5, 0x00, 0x02, 0x84), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x84, 0xb4), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb4, 0x00, 0x02, 0x85), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x85, 0x21), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x21, 0x00, 0x02, 0x86), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x86, 0x7d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7d, 0x00, 0x02, 0x87), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x87, 0x29), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x29, 0x00, 0x02, 0x88), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x88, 0x9d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9d, 0x00, 0x02, 0x89), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x89, 0xe1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe1, 0x00, 0x02, 0x8a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8a, 0xa8), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa8, 0x00, 0x02, 0x8b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8b, 0xaa), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xaa, 0x00, 0x02, 0x8c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8c, 0x1c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1c, 0x00, 0x02, 0x8d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8d, 0x59), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x59, 0x00, 0x02, 0x8e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8e, 0xc9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc9, 0x00, 0x02, 0x8f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x8f, 0x33), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x33, 0x00, 0x02, 0x90), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x90, 0xe0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xe0, 0x00, 0x02, 0x91), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x91, 0xf1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf1, 0x00, 0x02, 0x92), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x92, 0x6e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6e, 0x00, 0x02, 0x93), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x93, 0xb3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb3, 0x00, 0x02, 0x94), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x94, 0xb8), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb8, 0x00, 0x02, 0x95), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x95, 0x2f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2f, 0x00, 0x02, 0x96), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x96, 0x7c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7c, 0x00, 0x02, 0x97), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x97, 0x25), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x25, 0x00, 0x02, 0x98), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x98, 0x9e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9e, 0x00, 0x02, 0x99), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x99, 0xed), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xed, 0x00, 0x02, 0x9a), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9a, 0xa5), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa5, 0x00, 0x02, 0x9b), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9b, 0xab), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xab, 0x00, 0x02, 0x9c), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9c, 0x5c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5c, 0x00, 0x02, 0x9d), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9d, 0x5c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5c, 0x00, 0x02, 0x9e), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9e, 0xc8), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc8, 0x00, 0x02, 0x9f), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0x9f, 0x3b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3b, 0x00, 0x02, 0xa0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa0, 0xed), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xed, 0x00, 0x02, 0xa1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa1, 0x9a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9a, 0x00, 0x02, 0xa2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa2, 0x6b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6b, 0x00, 0x02, 0xa3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa3, 0xb9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xb9, 0x00, 0x02, 0xa4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa4, 0xbe), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xbe, 0x00, 0x02, 0xa5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa5, 0x2e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x2e, 0x00, 0x02, 0xa6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa6, 0x7c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7c, 0x00, 0x02, 0xa7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa7, 0x24), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x24, 0x00, 0x02, 0xa8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa8, 0x9b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9b, 0x00, 0x02, 0xa9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xa9, 0xee), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xee, 0x00, 0x02, 0xaa), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xaa, 0xc2), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc2, 0x00, 0x02, 0xab), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xab, 0xc0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc0, 0x00, 0x02, 0xac), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xac, 0x10), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x10, 0x00, 0x02, 0xad), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xad, 0x58), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x00, 0x02, 0xae), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xae, 0xa9), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xa9, 0x00, 0x02, 0xaf), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xaf, 0x30), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x30, 0x00, 0x02, 0xb0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb0, 0x49), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x49, 0x00, 0x02, 0xb1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb1, 0x90), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x90, 0x00, 0x02, 0xb2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb2, 0x60), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x60, 0x00, 0x02, 0xb3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb3, 0xbf), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xbf, 0x00, 0x02, 0xb4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb4, 0xbd), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xbd, 0x00, 0x02, 0xb5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb5, 0x33), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x33, 0x00, 0x02, 0xb6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb6, 0x77), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x77, 0x00, 0x02, 0xb7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb7, 0x89), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x89, 0x00, 0x02, 0xb8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb8, 0x9f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9f, 0x00, 0x02, 0xb9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xb9, 0xf1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf1, 0x00, 0x02, 0xba), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xba, 0xaa), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xaa, 0x00, 0x02, 0xbb), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xbb, 0xac), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xac, 0x00, 0x02, 0xbc), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xbc, 0x1e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1e, 0x00, 0x02, 0xbd), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xbd, 0x58), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x58, 0x00, 0x02, 0xbe), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xbe, 0xcd), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xcd, 0x00, 0x02, 0xbf), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xbf, 0x3a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x3a, 0x00, 0x02, 0xc0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc0, 0x48), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x48, 0x00, 0x02, 0xc1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc1, 0x9a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x9a, 0x00, 0x02, 0xc2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc2, 0x6c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6c, 0x00, 0x02, 0xc3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc3, 0x7a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7a, 0x00, 0x02, 0xc4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc4, 0x7d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7d, 0x00, 0x02, 0xc5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc5, 0x7c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7c, 0x00, 0x02, 0xc6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc6, 0x7d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7d, 0x00, 0x02, 0xc7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc7, 0x7e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7e, 0x00, 0x02, 0xc8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc8, 0x7f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x7f, 0x00, 0x02, 0xc9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xc9, 0xf0), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf0, 0x00, 0x02, 0xca), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xca, 0xf1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf1, 0x00, 0x02, 0xcb), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xcb, 0xf2), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf2, 0x00, 0x02, 0xcc), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xcc, 0xf3), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf3, 0x00, 0x02, 0xcd), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xcd, 0xf4), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xf4, 0x00, 0x02, 0xce), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xce, 0xc1), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc1, 0x00, 0x02, 0xcf), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xcf, 0xc2), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0xc2, 0x00, 0x02, 0xd0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd0, 0x4f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4f, 0x00, 0x02, 0xd1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd1, 0x60), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x60, 0x00, 0x02, 0xd2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd2, 0x6a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6a, 0x00, 0x02, 0xd3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd3, 0x6b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6b, 0x00, 0x02, 0xd4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd4, 0x6c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6c, 0x00, 0x02, 0xd5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd5, 0x6d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6d, 0x00, 0x02, 0xd6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd6, 0x6e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6e, 0x00, 0x02, 0xd7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd7, 0x6f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x6f, 0x00, 0x02, 0xd8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd8, 0x91), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x91, 0x00, 0x02, 0xd9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xd9, 0x92), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x92, 0x00, 0x02, 0xda), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xda, 0x93), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x93, 0x00, 0x02, 0xdb), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xdb, 0x94), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x94, 0x00, 0x02, 0xdc), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xdc, 0x95), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x95, 0x00, 0x02, 0xdd), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xdd, 0x96), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x96, 0x00, 0x02, 0xde), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xde, 0x97), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x97, 0x00, 0x02, 0xdf), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xdf, 0x98), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x98, 0x00, 0x02, 0xe0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe0, 0x59), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x59, 0x00, 0x02, 0xe1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe1, 0x5a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5a, 0x00, 0x02, 0xe2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe2, 0x5b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5b, 0x00, 0x02, 0xe3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe3, 0x5c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5c, 0x00, 0x02, 0xe4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe4, 0x5d), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5d, 0x00, 0x02, 0xe5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe5, 0x5e), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5e, 0x00, 0x02, 0xe6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe6, 0x5f), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x5f, 0x00, 0x02, 0xe7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe7, 0x70), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x70, 0x00, 0x02, 0xe8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe8, 0x71), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x71, 0x00, 0x02, 0xe9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xe9, 0x72), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x72, 0x00, 0x02, 0xea), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xea, 0x73), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x73, 0x00, 0x02, 0xeb), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xeb, 0x74), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x74, 0x00, 0x02, 0xec), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xec, 0x4a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4a, 0x00, 0x02, 0xed), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xed, 0x4b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4b, 0x00, 0x02, 0xee), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xee, 0x4c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x4c, 0x00, 0x02, 0xef), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xef, 0x50), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x50, 0x00, 0x02, 0xf0), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf0, 0x40), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x40, 0x00, 0x02, 0xf1), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf1, 0x30), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x30, 0x00, 0x02, 0xf2), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf2, 0x50), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x50, 0x00, 0x02, 0xf3), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf3, 0x60), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x60, 0x00, 0x02, 0xf4), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf4, 0x10), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x10, 0x00, 0x02, 0xf5), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf5, 0x11), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x11, 0x00, 0x02, 0xf6), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf6, 0x12), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x12, 0x00, 0x02, 0xf7), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf7, 0x13), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x13, 0x00, 0x02, 0xf8), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf8, 0x14), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x14, 0x00, 0x02, 0xf9), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xf9, 0x15), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x15, 0x00, 0x02, 0xfa), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xfa, 0x16), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x16, 0x00, 0x02, 0xfb), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xfb, 0x18), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x18, 0x00, 0x02, 0xfc), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xfc, 0x19), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x19, 0x00, 0x02, 0xfd), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xfd, 0x1a), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1a, 0x00, 0x02, 0xfe), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xfe, 0x1b), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1b, 0x00, 0x02, 0xff), \
+	IOV_DATA(0x12, 0x19, 0x00, 0x01, 0xff, 0x1c), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x0f, 0x00, 0x1c, 0x00, 0x02, 0x00)
+
+ /* ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0003
+  *
+  * ATT: Read Response (0x0b) len 3
+  */
+#define VOCS_READ_CHAR_VOL_OFFSET \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x00, 0x00, 0x00)
+
+ /* ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x0002-0x0003
+  *     Attribute type: Offset State (0x2b80)
+  *
+  * ATT: Read By Type Response (0x09) len 6
+  *     Attribute data length: 5
+  *     Attribute data list: 1 entry
+  *     Handle: 0x0003
+  *     Value: 000000
+  */
+#define VOCS_READ_CHAR_VOL_OFFSET_UUID \
+	IOV_DATA(0x08, 0x02, 0x00, 0x03, 0x00, 0x80, 0x2b), \
+	IOV_DATA(0x09, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00)
+
+ /* ATT: Read Request (0x0a) len 2
+  *     Handle: 0x0006
+  *
+  * ATT: Read Response (0x0b) len 4
+  */
+#define VOCS_READ_CHAR_AUD_LOC \
+	IOV_DATA(0x0a, 0x06, 0x00), \
+	IOV_DATA(0x0b, 0x02, 0x00, 0x00, 0x00)
+
+ /* ATT: Read By Type Request (0x08) len 6
+  *     Handle range: 0x0005-0x0006
+  *     Attribute type: Audio Location (0x2b81)
+  *
+  * ATT: Read By Type Response (0x09) len 7
+  *     Attribute data length: 6
+  *     Attribute data list: 1 entry
+  *     Handle: 0x0006
+  *     Value: 02000000
+  */
+#define VOCS_READ_CHAR_AUD_LOC_UUID \
+	IOV_DATA(0x08, 0x05, 0x00, 0x06, 0x00, 0x81, 0x2b), \
+	IOV_DATA(0x09, 0x06, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00)
+
+ /* ATT: Write Request (0x12) len 6
+  *     Handle: 0x0009
+  *          Data: 01280a00
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0009
+  *     Error: Reserved (0x80)
+  */
+#define VOCS_CP_INVALID_CHNG_COUNTER \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x28, 0x0a, 0x00),\
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x80)
+
+ /* ATT: Write Request (0x12) len 6
+  *     Handle: 0x0009
+  *         Data: 00007800
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0009
+  *     Error: Reserved (0x81)
+  */
+#define VOCS_CP_INVALID_OPCODE \
+	IOV_DATA(0x12, 0x09, 0x00, 0x00, 0x00, 0x78, 0x00),\
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x81)
+
+ /* ATT: Write Request (0x12) len 6
+  *     Handle: 0x0009
+  *         Data: 01000e01
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0009
+  *     Error: Reserved (0x82)
+  *
+  * ATT: Write Request (0x12) len 6
+  *     Handle: 0x0009
+  *         Data: 0100f2fe
+  *
+  * ATT: Error Response (0x01) len 4
+  *     Write Request (0x12)
+  *     Handle: 0x0009
+  *     Error: Reserved (0x82)
+  */
+#define VOCS_CP_OUT_OF_RANGE_VALUE \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x00, 0x0e, 0x01), \
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x82), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x00, 0xf2, 0xfe),\
+	IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x82)
+
+ /* ATT: Write Request (0x12) len 4
+  *     Handle: 0x0004
+  *         Data: 0100
+  *
+  * ATT: Write Response (0x13) len 0
+  */
+#define VOCS_ENNABLE_VOL_OFFSET_CCD \
+	IOV_DATA(0x12, 0x04, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+#define VOCS_SR_SGGIT_CHA_TST_CMDS \
+	VCS_EXCHANGE_MTU, \
+	VOCS_AICS_PRIMARY_SERVICE_VCS, \
+	VOCS_AICS_SECONDARY_SERVICE, \
+	VOCS_AICS_INCLUDED_SERVICE, \
+	VOCS_DISC_CHAR, \
+	VOCS_DISC_CHAR_DESC, \
+	VOCS_READ_CHAR_DESC
+
+#define AICS_SR_SGGIT_CHA_TST_CMDS \
+	VCS_EXCHANGE_MTU, \
+	VOCS_AICS_PRIMARY_SERVICE_VCS, \
+	VOCS_AICS_SECONDARY_SERVICE, \
+	VOCS_AICS_INCLUDED_SERVICE, \
+	AICS_DISC_CHAR, \
+	AICS_DISC_CHAR_DESC, \
+	AICS_READ_CHAR_DESC
+
+#define AICS_SR_SGGIT_CHA_BV_01_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_AUD_IP_STATE
+
+#define AICS_SR_SGGIT_CHA_BV_02_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_GAIN_SETTING_PROP
+
+#define AICS_SR_SGGIT_CHA_BV_03_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_AUD_IP_TYPE
+
+#define AICS_SR_SGGIT_CHA_BV_04_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_AUD_IP_STATUS
+
+#define AICS_SR_SGGIT_CHA_BV_05_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS
+
+#define AICS_SR_SGGIT_CHA_BV_06_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS
+
+#define AICS_SR_SGGIT_CP_BI_01_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_AUD_IP_STATE, \
+	AICS_CP_WR_INVLD_CHG_COUNTER
+
+#define AICS_SR_SGGIT_CP_BI_02_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_CP_WR_INVLD_OP_CODE
+
+#define AICS_SR_SGGIT_CP_BI_03_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_READ_CHAR_AUD_IP_STATE_MUT_DIS, \
+	AICS_CP_WR_UNMUTE, \
+	AICS_CP_WR_MUTE
+
+#define AICS_SR_CP_BV_01_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE, \
+	AICS_READ_CHAR_GAIN_SETTNG_PROP, \
+	AICS_CP_WR_GAIN_SETTING_255_LOOP
+
+#define AICS_SR_CP_BV_02_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE_MUTED, \
+	AICS_CP_WR_UNMUTE_SUCCESS, \
+	AICS_AUD_IP_STATE_UNMUTED_NOTIF
+
+#define AICS_SR_CP_BV_03_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE_UNMUTED, \
+	AICS_CP_WR_MUTE_SUCCESS, \
+	AICS_AUD_IP_STATE_MUTED_NOTIF
+
+#define AICS_SR_CP_BV_04_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE_AUTOMATIC, \
+	AICS_CP_WR_MANUAL_GAIN, \
+	AICS_AUD_IP_STATE_MANUAL_GAIN_NOTIF
+
+#define AICS_SR_CP_BV_05_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE_MANUAL, \
+	AICS_CP_WR_AUTOMATIC_GAIN, \
+	AICS_AUD_IP_STATE_AUTOMATIC_GAIN_NOTIF
+
+#define AICS_SR_SPE_BI_01_C \
+	AICS_SR_SGGIT_CHA_TST_CMDS, \
+	AICS_ENABLE_AUD_IP_STATE_CC, \
+	AICS_READ_CHAR_AUD_IP_STATE, \
+	AICS_READ_CHAR_GAIN_SETTNG_PROP, \
+	AICS_CP_WR_GAIN_SETTING_MAX, \
+	AICS_AUD_IP_STATE_GAIN_SETTING_MAX_NOTIF, \
+	AICS_CP_WR_GAIN_SETTING_MIN, \
+	AICS_AUD_IP_STATE_GAIN_SETTING_MIN_NOTIF
+
+#define VOCS_SR_SGGIT_SER_BV_01_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS
+
+#define VOCS_SR_SGGIT_CHA_BV_01_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_READ_CHAR_VOL_OFFSET, \
+	VOCS_READ_CHAR_VOL_OFFSET_UUID
+
+#define VOCS_SR_SGGIT_CHA_BV_02_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_READ_CHAR_AUD_LOC, \
+	VOCS_READ_CHAR_AUD_LOC_UUID
+
+#define VOCS_SR_SGGIT_CHA_BV_03_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS
+
+#define VOCS_SR_SGGIT_CHA_BV_04_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS
+
+#define VOCS_SR_SGGIT_CP_BI_01_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_CP_INVALID_CHNG_COUNTER
+
+#define VOCS_SR_SGGIT_CP_BI_02_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_CP_INVALID_OPCODE
+
+#define VOCS_SR_SGGIT_CP_BI_03_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_CP_OUT_OF_RANGE_VALUE
+
+#define VOCS_SR_SPE_BI_01_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_READ_CHAR_AUD_LOC
+ /*
+  * VOCS/SR/CP/BV-01-C [Set Volume Offset]
+  * Do Initial Condition Proedures
+  * 1. The Lower Tester executes the GATT Read Characteristic
+  *    Value sub-procedure for the Volume Offset State characteristic.
+  * Repeat steps 2-4 for (255 - Change_Counter value) + 1 times.
+  * 2. The Lower Tester executes the GATT Write Characteristic Value
+  *    sub-procedure for the Volume
+  *    Offset Control Point characteristic with the Set Volume Offset
+  *    Opcode, with the Volume Offset parameters set to a random value
+  *    different from the last one, and the Change_Counter parameter.
+  * 3. The Lower Tester receives a Write Response indicating that the IUT
+  *     has accepted the Opcode.
+  * 4. The Lower Tester receives a GATT Characteristic Value Notification
+  *    for the Volume Offset State characteristic.
+  */
+#define VOCS_SR_CP_BV_01_C \
+	VOCS_SR_SGGIT_CHA_TST_CMDS, \
+	VOCS_ENNABLE_VOL_OFFSET_CCD, \
+	VOCS_READ_CHAR_VOL_OFFSET, \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x00, 0xde, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xde, 0x00, 0x01), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x01, 0xda, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xda, 0xff, 0x02), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x02, 0x1a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1a, 0x00, 0x03), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x03, 0x49, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x49, 0xff, 0x04), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x04, 0x05, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x05, 0xff, 0x05), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x05, 0xf1, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xf1, 0xff, 0x06), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x06, 0xca, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xca, 0xff, 0x07), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x07, 0x5c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5c, 0x00, 0x08), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x08, 0xaf, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xaf, 0x00, 0x09), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x09, 0x5f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5f, 0x00, 0x0a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0a, 0x69, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x69, 0xff, 0x0b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0b, 0x3d, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3d, 0xff, 0x0c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0c, 0xb6, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb6, 0xff, 0x0d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0d, 0xa4, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa4, 0x00, 0x0e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0e, 0x14, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x14, 0xff, 0x0f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x0f, 0x2a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x2a, 0xff, 0x10), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x10, 0x51, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x51, 0x00, 0x11), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x011, 0xc4, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xc4, 0xff, 0x12), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x12, 0xe8, 00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xe8, 0x00, 0x13), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x13, 0xca, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xca, 0xff, 0x14), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x14, 0xe6, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xe6, 0xff, 0x15), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x15, 0x62, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x62, 0x00, 0x16), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x16, 0x22, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x22, 0x00, 0x17), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x17, 0xa1, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa1, 0xff, 0x18), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x18, 0xaa, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xaa, 0x00, 0x19), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x19, 0x65, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x65, 0x00, 0x1a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1a, 0x11, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x11, 0xff, 0x1b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1b, 0x69, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x69, 0xff, 0x1c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1c, 0xee, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xee, 0x00, 0x1d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1d, 0xaa, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xaa, 0xff, 0x1e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1e, 0x1f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1f, 0xff, 0x1f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x1f, 0xbe, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbe, 0x00, 0x20), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x20, 0x93, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x93, 0xff, 0x21), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x21, 0x11, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x11, 0xff, 0x22), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x22, 0x83, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x83, 0xff, 0x23), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x23, 0xf8, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xf8, 0x00, 0x24), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x24, 0x90, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x90, 0xff, 0x25), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x25, 0x0c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0c, 0x00, 0x26), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x26, 0xc8, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xc8, 0x00, 0x27), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x27, 0x59, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x59, 0xff, 0x28), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x28, 0x80, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x80, 0xff, 0x29), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x29, 0x0d, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0d, 0xff, 0x2a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2a, 0x0c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0c, 0x00, 0x2b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2b, 0x0a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0a, 0x00, 0x2c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2c, 0x12, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x12, 0x00, 0x2d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2d, 0x0b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0b, 0xff, 0x2e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2e, 0x83, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x83, 0xff, 0x2f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x2f, 0x91, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x91, 0xff, 0x30), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x30, 0x71, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x71, 0xff, 0x31), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x31, 0x72, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x72, 0xff, 0x32), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x32, 0x75, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x75, 0xff, 0x33), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x33, 0x78, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x78, 0xff, 0x34), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x34, 0x61, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x61, 0xff, 0x35), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x35, 0x63, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x63, 0xff, 0x36), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x36, 0x38, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x38, 0xff, 0x37), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x37, 0x21, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x21, 0xff, 0x38), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x38, 0xa4, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa4, 0x00, 0x39), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x39, 0xb4, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb4, 0x00, 0x3a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3a, 0xb5, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb5, 0xff, 0x3b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3b, 0xac, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xac, 0x00, 0x3c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3c, 0xab, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xab, 0x00, 0x3d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3d, 0xad, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xad, 0x00, 0x3e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3e, 0x83, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x83, 0xff, 0x3f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x3f, 0x84, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x84, 0xff, 0x40), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x40, 0x85, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x85, 0xff, 0x41), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x41, 0x86, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x86, 0xff, 0x42), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x42, 0x87, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x87, 0xff, 0x43), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x43, 0x87, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x87, 0xff, 0x44), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x44, 0x05, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x05, 0x000, 0x45), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x45, 0xce, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xce, 0x00, 0x46), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x46, 0x96, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x96, 0x00, 0x47), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x47, 0x07, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x07, 0x00, 0x48), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x48, 0x08, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x08, 0x00, 0x49), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x49, 0x09, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x09, 0xff, 0x4a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4a, 0x0a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0a, 0xff, 0x4b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4b, 0x11, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x11, 0xff, 0x4c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4c, 0x22, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x22, 0xff, 0x4d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4d, 0x33, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x33, 0xff, 0x4e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4e, 0x09, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x09, 0xff, 0x4f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x4f, 0x19, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x19, 0xff, 0x50), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x50, 0x1a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1a, 0xff, 0x51), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x51, 0x1b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1b, 0xff, 0x52), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x52, 0xa1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa1, 0x00, 0x53), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x53, 0xa2, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa2, 0x00, 0x54), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x54, 0xb2, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb2, 0x00, 0x55), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x55, 0xb3, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb3, 0x00, 0x56), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x56, 0x68, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x68, 0x00, 0x57), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x57, 0x69, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x69, 0x00, 0x58), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x58, 0x6a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6a, 0x00, 0x59), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x59, 0x7a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7a, 0x00, 0x5a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5a, 0x7b, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7b, 0x00, 0x5b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5b, 0x8c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x8c, 0x00, 0x5c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5c, 0x9c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9c, 0x00, 0x5d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5d, 0x9b, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9b, 0x00, 0x5e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5e, 0x9c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9c, 0x00, 0x5f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x5f, 0x9d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9d, 0x00, 0x60), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x60, 0x9e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9e, 0x00, 0x61), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x61, 0x21, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x21, 0x00, 0x62), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x62, 0x23, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x23, 0x00, 0x63), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x63, 0x24, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x24, 0x00, 0x64), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x64, 0x34, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x34, 0x00, 0x65), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x65, 0x44, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x44, 0x00, 0x66), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x66, 0x45, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x45, 0x00, 0x67), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x67, 0x9d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9d, 0x00, 0x68), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x68, 0x9d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9d, 0x00, 0x69), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x69, 0x9d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9d, 0x00, 0x6a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6a, 0x49, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x49, 0x00, 0x6b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6b, 0x39, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x39, 0x00, 0x6c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6c, 0x9d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9d, 0x00, 0x6d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6d, 0x9e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9e, 0x00, 0x6e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6e, 0x9f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9f, 0x00, 0x6f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x6f, 0x91, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x91, 0x00, 0x70), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x70, 0x18, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x18, 0x00, 0x71), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x71, 0x34, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x34, 0xff, 0x72), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x72, 0x44, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x44, 0xff, 0x73), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x73, 0x05, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x05, 0xff, 0x74), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x74, 0x06, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x06, 0xff, 0x75), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x75, 0x38, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x38, 0x00, 0x76), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x76, 0x48, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x48, 0x00, 0x77), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x77, 0x58, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x58, 0x00, 0x78), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x78, 0x88, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x88, 0x00, 0x79), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x79, 0x98, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x98, 0x00, 0x7a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7a, 0x91, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x91, 0x00, 0x7b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7b, 0x95, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x95, 0x00, 0x7c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7c, 0x89, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x89, 0x00, 0x7d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7d, 0x82, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x82, 0x00, 0x7e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7e, 0x88, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x88, 0x00, 0x7f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x7f, 0x66, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x66, 0x00, 0x80), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x80, 0x55, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x55, 0x00, 0x81), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x81, 0x44, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x44, 0x00, 0x82), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x82, 0x33, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x33, 0x00, 0x83), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x83, 0x22, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x22, 0x00, 0x84), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x84, 0x11, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x11, 0x00, 0x85), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x85, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x01, 0x00, 0x86), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x86, 0x3a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3a, 0x00, 0x87), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x87, 0x3b, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3b, 0x00, 0x88), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x88, 0x3c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3c, 0x00, 0x89), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x89, 0x4c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x4c, 0x00, 0x8a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8a, 0x5c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5c, 0x00, 0x8b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8b, 0x6c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6c, 0x00, 0x8c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8c, 0xab, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xab, 0xff, 0x8d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8d, 0xac, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xac, 0xff, 0x8e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8e, 0xbc, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbc, 0x00, 0x8f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x8f, 0xbb, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbb, 0x00, 0x90), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x90, 0x11, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x11, 0x00, 0x91), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x91, 0x21, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x21, 0x00, 0x92), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x92, 0x31, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x31, 0x00, 0x93), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x93, 0x21, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x21, 0x00, 0x94), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x94, 0x31, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x31, 0x00, 0x95), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x95, 0x41, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x41, 0x00, 0x96), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x96, 0x51, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x51, 0x00, 0x97), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x97, 0x61, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x61, 0x00, 0x98), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x98, 0x81, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x81, 0x00, 0x99), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x99, 0x55, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x55, 0x00, 0x9a), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9a, 0x59, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x59, 0x00, 0x9b), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9b, 0x56, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x56, 0x00, 0x9c), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9c, 0x57, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x57, 0x00, 0x9d), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9d, 0x58, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x58, 0x00, 0x9e), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9e, 0x59, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x59, 0x00, 0x9f), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0x9f, 0x60, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x60, 0x00, 0xa0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa0, 0x0b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0b, 0xff, 0xa1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa1, 0x0c, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0c, 0xff, 0xa2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa2, 0x0c, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0c, 0xff, 0xa3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa3, 0x0d, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0d, 0xff, 0xa4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa4, 0x53, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x53, 0xff, 0xa5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa5, 0x54, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x54, 0xff, 0xa6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa6, 0x75, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x75, 0xff, 0xa7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa7, 0x76, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x76, 0xff, 0xa8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa8, 0x77, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x77, 0xff, 0xa9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xa9, 0x78, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x78, 0xff, 0xaa), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xaa, 0x76, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x76, 0xff, 0xab), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xab, 0xa1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa1, 0x00, 0xac), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xac, 0xc1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xc1, 0x00, 0xad), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xad, 0xd1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd1, 0x00, 0xae), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xae, 0xe1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xe1, 0x00, 0xaf), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xaf, 0xf1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xf1, 0x00, 0xb0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb0, 0xae, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xae, 0x00, 0xb1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb1, 0xbe, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbe, 0x00, 0xb2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb2, 0xdd, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xdd, 0x00, 0xb3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb3, 0xee, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xee, 0x00, 0xb4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb4, 0x1d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1d, 0x00, 0xb5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb5, 0x3a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3a, 0x00, 0xb6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb6, 0x4a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x4a, 0x00, 0xb7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb7, 0x5a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5a, 0x00, 0xb8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb8, 0x7e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7e, 0x00, 0xb9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xb9, 0x3f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3f, 0x00, 0xba), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xba, 0x3f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3f, 0x00, 0xbb), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xbb, 0xa1, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa1, 0x00, 0xbc), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xbc, 0xa2, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa2, 0x00, 0xbd), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xbd, 0xa3, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa3, 0x00, 0xbe), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xbe, 0xa4, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa4, 0x00, 0xbf), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xbf, 0xa5, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa5, 0x00, 0xc0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc0, 0xa6, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xa6, 0x00, 0xc1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc1, 0x1f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1f, 0x00, 0xc2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc2, 0x2f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x2f, 0x00, 0xc3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc3, 0x3f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3f, 0x00, 0xc4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc4, 0x4f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x4f, 0x00, 0xc5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc5, 0x5f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5f, 0x00, 0xc6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc6, 0x6f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6f, 0x00, 0xc7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc7, 0x7f, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7f, 0x00, 0xc8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc8, 0x1d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1d, 0x00, 0xc9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xc9, 0xaa, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xaa, 0x00, 0xca), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xca, 0xbb, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbb, 0x00, 0xcb), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xcb, 0xcd, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xcd, 0x00, 0xcc), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xcc, 0xce, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xce, 0x00, 0xcd), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xcd, 0xde, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xde, 0x00, 0xce), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xce, 0xdf, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xdf, 0x00, 0xcf), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xcf, 0xdb, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xdb, 0x00, 0xd0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd0, 0x6e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6e, 0x00, 0xd1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd1, 0x5e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5e, 0x00, 0xd2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd2, 0x8e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x8e, 0x00, 0xd3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd3, 0x9e, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x9e, 0x00, 0xd4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd4, 0xae, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xae, 0x00, 0xd5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd5, 0xbe, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xbe, 0x00, 0xd6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd6, 0xee, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xee, 0x00, 0xd7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd7, 0x1c, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1c, 0x00, 0xd8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd8, 0x33, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x33, 0x00, 0xd9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xd9, 0x88, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x88, 0x00, 0xda), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xda, 0x0d, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0d, 0x00, 0xdb), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xdb, 0x88, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x88, 0x00, 0xdc), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xdc, 0x99, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x99, 0x00, 0xdd), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xdd, 0x66, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x66, 0x00, 0xde), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xde, 0x49, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x49, 0x00, 0xdf), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xdf, 0x86, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x86, 0x00, 0xe0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe0, 0x3a, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3a, 0x00, 0xe1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe1, 0xd0, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd0, 0x00, 0xe2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe2, 0xd2, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd2, 0x00, 0xe3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe3, 0xd3, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd3, 0x00, 0xe4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe4, 0xd4, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd4, 0x00, 0xe5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe5, 0xdf, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xdf, 0x00, 0xe6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe6, 0xef, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xef, 0x00, 0xe7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe7, 0xed, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xed, 0x00, 0xe8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe8, 0xcc, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xcc, 0x00, 0xe9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xe9, 0x1f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x1f, 0xff, 0xea), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xea, 0x2f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x2f, 0xff, 0xeb), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xeb, 0x3f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x3f, 0xff, 0xec), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xec, 0x4f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x4f, 0xff, 0xed), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xed, 0x5f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x5f, 0xff, 0xee), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xee, 0x6f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6f, 0xff, 0xef), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xef, 0x7f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7f, 0xff, 0xf0), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf0, 0xc9, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xc9, 0xff, 0xf1), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf1, 0xb9, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xb9, 0xff, 0xf2), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf2, 0xd9, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xd9, 0xff, 0xf3), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf3, 0xe1, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0xe1, 0xff, 0xf4), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf4, 0x8f, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x8f, 0xff, 0xf5), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf5, 0x7a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7a, 0xff, 0xf6), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf6, 0x7b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7b, 0xff, 0xf7), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf7, 0x7c, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7c, 0xff, 0xf8), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf8, 0x7d, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7d, 0xff, 0xf9), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xf9, 0x7e, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7e, 0xff, 0xfa), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xfa, 0x6a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6a, 0xff, 0xfb), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xfb, 0x6b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x6b, 0xff, 0xfc), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xfc, 0x7e, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x7e, 0xff, 0xfd), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xfd, 0x0a, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0a, 0xff, 0xfe), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xfe, 0x0b, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0b, 0xff, 0xff), \
+	IOV_DATA(0x12, 0x09, 0x00, 0x01, 0xff, 0x0c, 0xff), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x1b, 0x03, 0x00, 0x0c, 0xff, 0x00)
+
+static void test_vocs_unit_testcases(void)
+{
+	/*
+	 * VOCS Unit Testcases
+	 */
+	define_test("VOCS/SR/SGGIT/SER/BV-01-C", test_server, NULL,
+					VOCS_SR_SGGIT_SER_BV_01_C);
+
+	define_test("VOCS/SR/SGGIT/CHA/BV-01-C", test_server, NULL,
+					VOCS_SR_SGGIT_CHA_BV_01_C);
+	define_test("VOCS/SR/SGGIT/CHA/BV-02-C", test_server, NULL,
+					VOCS_SR_SGGIT_CHA_BV_02_C);
+	define_test("VOCS/SR/SGGIT/CHA/BV-03-C", test_server, NULL,
+					VOCS_SR_SGGIT_CHA_BV_03_C);
+	define_test("VOCS/SR/SGGIT/CHA/BV-04-C", test_server, NULL,
+					VOCS_SR_SGGIT_CHA_BV_04_C);
+
+	define_test("VOCS/SR/SGGIT/CP/BI-01-C", test_server, NULL,
+					VOCS_SR_SGGIT_CP_BI_01_C);
+	define_test("VOCS/SR/SGGIT/CP/BI-02-C", test_server, NULL,
+					VOCS_SR_SGGIT_CP_BI_02_C);
+	define_test("VOCS/SR/SGGIT/CP/BI-03-C", test_server, NULL,
+					VOCS_SR_SGGIT_CP_BI_03_C);
+
+	define_test("VOCS/SR/SPE/BI-01-C", test_server, NULL,
+					VOCS_SR_SPE_BI_01_C);
+
+	define_test("VOCS/SR/CP/BV-01-C", test_server, NULL,
+					VOCS_SR_CP_BV_01_C);
+}
+
+static void test_aics_unit_testcases(void)
+{
+	/*
+	 * AICS Unit Testcases
+	 */
+	define_test("AICS/SR/SGGIT/CHA/BV-01-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_01_C);
+
+	define_test("AICS/SR/SGGIT/CHA/BV-02-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_02_C);
+
+	define_test("AICS/SR/SGGIT/CHA/BV-03-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_03_C);
+
+	define_test("AICS/SR/SGGIT/CHA/BV-04-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_04_C);
+
+	define_test("AICS/SR/SGGIT/CHA/BV-05-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_05_C);
+
+	define_test("AICS/SR/SGGIT/CHA/BV-06-C", test_server, NULL,
+					AICS_SR_SGGIT_CHA_BV_06_C);
+
+	define_test("AICS/SR/SGGIT/CP/BI-01-C", test_server, NULL,
+					AICS_SR_SGGIT_CP_BI_01_C);
+
+	define_test("AICS/SR/SGGIT/CP/BI-02-C", test_server, NULL,
+					AICS_SR_SGGIT_CP_BI_02_C);
+
+	/* AICS/SR/SGGIT/CP/BI-03-C:
+	 * In function *aics_new(struct gatt_db *db)[src/shared/vcp.c]
+	 * by default state of the 'aics_aud_ip_st->mute' is set to
+	 * AICS_NOT_MUTED[0x00];.
+	 * As per test specs, Testcase AICS/SR/SGGIT/CP/BI-03-C, Initial
+	 * condition of mute state should be AICS_DISABLED[0x02].
+	 * To verify this Unit test case we have to modify the initial
+	 * state of 'aics_aud_ip_st->mute' to AICS_DISABLED in code
+	 * [in func aics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test("AICS/SR/SGGIT/CP/BI-03-C", test_server, NULL,
+	 *				AICS_SR_SGGIT_CP_BI_03_C);
+	 */
+
+	/* AICS/SR/SGGIT/CP/BI-04-C - TO-DO Need to give two times input
+	 *  from user during test case run
+	 */
+
+	define_test("AICS/SR/CP/BV-01-C", test_server, NULL,
+					AICS_SR_CP_BV_01_C);
+
+	/* AICS/SR/CP/BV-02-C:
+	 * In function *aics_new(struct gatt_db *db)[src/shared/vcp.c]
+	 * by default state of the 'aics_aud_ip_st->mute' is set to
+	 * AICS_NOT_MUTED[0x00];.
+	 * As per test specs, Testcase AICS/SR/CP/BV-02-C, Initial
+	 * condition of mute state should be AICS_MUTED[0x01].
+	 * To verify this Unit test case we have to modify the initial
+	 * state of 'aics_aud_ip_st->mute' to AICS_MUTED in code
+	 * [in func aics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test("AICS/SR/CP/BV-02-C", test_server, NULL,
+	 *				AICS_SR_CP_BV_02_C);
+	 */
+
+	/* AICS/SR/CP/BV-03-C:
+	 * In function *aics_new(struct gatt_db *db)[src/shared/vcp.c]
+	 * by default state of the 'aics_aud_ip_st->mute' is set to
+	 * AICS_NOT_MUTED[0x00];.
+	 * As per test specs, Testcase AICS/SR/CP/BV-03-C, Initial
+	 * condition of mute state should be AICS_NOT_MUTED[0x00].
+	 * If you have changed this value to some other value, then
+	 * To verify this Unit test case you have to modify the initial
+	 * state of 'aics_aud_ip_st->mute' to AICS_NOT_MUTED in code
+	 * [in func aics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test("AICS/SR/CP/BV-03-C", test_server, NULL,
+	 *               AICS_SR_CP_BV_03_C);
+	 */
+
+	/* AICS/SR/CP/BV-04-C:
+	 * In function *aics_new(struct gatt_db *db)[src/shared/vcp.c]
+	 * by default state of the 'aics_aud_ip_st->gain_mode' is set to
+	 * AICS_GAIN_MODE_MANUAL[0x02];.
+	 * As per test specs, Testcase AICS/SR/CP/BV-04-C, Initial
+	 * value of gain mode field, should be AICS_GAIN_MODE_AUTO[0x03].
+	 * To verify this Unit test case you have to modify the initial
+	 * state of 'aics_aud_ip_st->gain_mode' to AICS_GAIN_MODE_AUTO in code
+	 * [in func aics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test("AICS/SR/CP/BV-04-C", test_server, NULL,
+	 *				AICS_SR_CP_BV_04_C);
+	 */
+
+	/* AICS/SR/CP/BV-05-C:
+	 * In function *aics_new(struct gatt_db *db)[src/shared/vcp.c]
+	 * by default state of the 'aics_aud_ip_st->gain_mode' is set to
+	 * AICS_GAIN_MODE_MANUAL[0x02];.
+	 * As per test specs, Testcase AICS/SR/CP/BV-05-C, Initial
+	 * value of gain mode field, should be AICS_GAIN_MODE_MANUAL[0x02].
+	 * If you have changed this value to some other value, then
+	 * To verify this Unit test case you have to modify the initial
+	 * state of 'aics_aud_ip_st->gain_mode' to AICS_GAIN_MODE_MANUAL in code
+	 * [in func aics_new()], build it and run bluetoothd. Then run
+	 * this unit test case and this test case will Pass.
+	 */
+	/* define_test("AICS/SR/CP/BV-05-C", test_server, NULL,
+	 *			AICS_SR_CP_BV_05_C);
+	 */
+	define_test("AICS/SR/SPE/BI-01-C", test_server, NULL,
+					AICS_SR_SPE_BI_01_C);
+
+
+}
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_vocs_unit_testcases();
+	test_aics_unit_testcases();
+
+	return tester_run();
+}
+
-- 
GitLab


From 4c19b966f9b9ded0f9b3392aabd9f971a410ded9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <dylan.aissi@collabora.com>
Date: Mon, 7 Apr 2025 16:18:53 +0200
Subject: [PATCH 2/4] Add patch to make bluez compatible with libeditrealine
 instead of readline
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 .../compatibility-with-libeditrealine.patch   | 38 +++++++++++++++++++
 debian/patches/series                         |  1 +
 2 files changed, 39 insertions(+)
 create mode 100644 debian/patches/apertis/compatibility-with-libeditrealine.patch

diff --git a/debian/patches/apertis/compatibility-with-libeditrealine.patch b/debian/patches/apertis/compatibility-with-libeditrealine.patch
new file mode 100644
index 0000000..9e8c874
--- /dev/null
+++ b/debian/patches/apertis/compatibility-with-libeditrealine.patch
@@ -0,0 +1,38 @@
+Description: In Apertis, we use libeditrealine instead of readline for licensing
+ concerns.
+ .
+ However, some symbols (like rl_reset_line_state) are not yet implemented
+ in libeditrealine. This patch revert the use of rl_reset_line_state to the
+ previous behavior from:
+ https://github.com/bluez/bluez/commit/40621e269287d6c5de8fd653df0c49b7907c2c17
+ This is only a temporary workaround until rl_reset_line_state is properly
+ implemented in libeditrealine.
+ .
+ It also includes a missing header which is included in readline.h
+ (readline.h -> keymaps.h -> chardefs.h -> string.h) from readline but not
+ in readline.h from libeditrealine.
+
+Forwarded: not-needed
+
+--- a/src/shared/shell.c
++++ b/src/shared/shell.c
+@@ -719,7 +719,8 @@
+ 		saved_line = rl_copy_text(0, rl_end);
+ 		if (!data.saved_prompt)
+ 			rl_save_prompt();
+-		rl_reset_line_state();
++		rl_replace_line("", 0);
++ 		rl_redisplay();
+ 	}
+ 
+ 	va_start(args, fmt);
+--- a/client/display.c
++++ b/client/display.c
+@@ -21,6 +21,7 @@
+ #include <readline/readline.h>
+ 
+ #include "display.h"
++#include <string.h>
+ 
+ static char *saved_prompt = NULL;
+ static int saved_point = 0;
diff --git a/debian/patches/series b/debian/patches/series
index 88ef9c0..325a548 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -16,3 +16,4 @@ raspi-bcm43xx-3wire.patch
 ubuntu_error_restart.patch
 
 apertis/set_car_device_class.patch
+apertis/compatibility-with-libeditrealine.patch
-- 
GitLab


From a063b96bfb2b0fbd192e4c16b434e0654d000ae0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <dylan.aissi@collabora.com>
Date: Mon, 10 Mar 2025 16:57:53 +0100
Subject: [PATCH 3/4] Release bluez version 5.79-1+apertis1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 debian/changelog | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index aa1b499..db49557 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+bluez (5.79-1+apertis1) apertis; urgency=medium
+
+  * Sync from debian/trixie.
+  * Remaining Apertis specific changes:
+    - Replace libreadline-dev by libeditreadline-dev in Build-Deps
+    - Add patch to make bluez compatible with libeditreadline
+    - Install AppArmor rules
+    - Create tmpfile for bluez data storage
+    - Set car class of device
+
+ -- Dylan Aïssi <dylan.aissi@collabora.com>  Mon, 10 Mar 2025 16:56:55 +0100
+
 bluez (5.79-1) unstable; urgency=medium
 
   [ Jeremy Bícha ]
-- 
GitLab


From 0546f7ec716c8415b17c654ddcbce3e17b3ff4d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <dylan.aissi@collabora.com>
Date: Mon, 10 Mar 2025 15:58:37 +0000
Subject: [PATCH 4/4] Refresh the automatically detected licensing information
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 debian/apertis/copyright | 615 +++++++++++++++++++++++++--------------
 1 file changed, 396 insertions(+), 219 deletions(-)

diff --git a/debian/apertis/copyright b/debian/apertis/copyright
index d6d7a5e..5e2907c 100644
--- a/debian/apertis/copyright
+++ b/debian/apertis/copyright
@@ -1,6 +1,6 @@
 Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 
-Files: * doc/* mesh/* tools/mesh-gatt/* tools/mesh/*
+Files: * client/*
 Copyright: 2008-2015, Intel Corporation.
 License: GPL-2+
 
@@ -13,8 +13,54 @@ Files: Makefile.am
 Copyright: no-info-found
 License: GPL-2
 
-Files: android/*
-Copyright: 2011-2022, Intel Corporation.
+Files: Makefile.in
+Copyright: 1987-2021, Free Software Foundation, Inc.
+License: GPL-2
+
+Files: aclocal.m4
+Copyright: 1996-2021, Free Software Foundation, Inc.
+License: (FSFULLR or GPL-2) with Libtool exception
+
+Files: android/a2dp-sink.c
+ android/a2dp-sink.h
+ android/a2dp.c
+ android/a2dp.h
+ android/audio-msg.h
+ android/avrcp-lib.c
+ android/avrcp-lib.h
+ android/avrcp.c
+ android/avrcp.h
+ android/bluetooth.c
+ android/bluetooth.h
+ android/bluetoothd-snoop.c
+ android/gatt.c
+ android/gatt.h
+ android/hal-msg.h
+ android/handsfree-client.c
+ android/handsfree-client.h
+ android/handsfree.c
+ android/handsfree.h
+ android/health.h
+ android/hidhost.c
+ android/hidhost.h
+ android/ipc-common.h
+ android/ipc-tester.c
+ android/ipc.c
+ android/ipc.h
+ android/main.c
+ android/map-client.c
+ android/map-client.h
+ android/pan.c
+ android/pan.h
+ android/sco-msg.h
+ android/sco.h
+ android/socket.c
+ android/socket.h
+ android/system-emulator.c
+ android/test-ipc.c
+ android/tester-main.h
+ android/utils.h
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: android/audio_utils/*
@@ -35,7 +81,7 @@ Copyright: 2006-2011, Nokia Corporation
 License: GPL-2
 
 Files: android/avdtptest.c
-Copyright: 2011-2015, Intel Corporation
+Copyright: 2011-2015, 2023, Intel Corporation
 License: GPL-2
 
 Files: android/bluetoothd-wrapper.c
@@ -80,13 +126,17 @@ Copyright: 2013, 2014, Intel Corporation
 License: Apache-2.0
 
 Files: android/compat/*
-Copyright: 1987-2011, Free Software Foundation, Inc.
+Copyright: 1987-2021, Free Software Foundation, Inc.
 License: GPL-2
 
 Files: android/compat/wordexp.h
 Copyright: 1991-2013, Free Software Foundation, Inc.
 License: LGPL-2.1
 
+Files: android/cutils/*
+Copyright: 2011-2023, Intel Corporation.
+License: LGPL-2.1
+
 Files: android/hal-audio-aptx.c
 Copyright: 2014, Tieto Poland
 License: Apache-2.0
@@ -102,7 +152,7 @@ License: LGPL-2.1
 
 Files: android/log.c
  android/sco.c
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: android/system/*
@@ -118,59 +168,107 @@ Files: attrib/att-database.h
 Copyright: 2012, Texas Instruments Corporation
 License: GPL-2
 
-Files: attrib/gatttool.h
- attrib/interactive.c
- attrib/utils.c
-Copyright: 2007-2011, Nokia Corporation
-License: GPL-2
-
 Files: btio/*
-Copyright: 2006-2011, Nokia Corporation
+Copyright: 2023, 2024, NXP
+ 2006-2011, Nokia Corporation
  2004-2011, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
-Files: client/*
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
-License: GPL-2
-
 Files: client/admin.c
  client/admin.h
 Copyright: 2021, Google LLC
 License: GPL-2+
 
 Files: client/adv_monitor.c
- client/adv_monitor.h
+Copyright: 2024, NXP
+ 2020, Google LLC
+License: GPL-2
+
+Files: client/adv_monitor.h
 Copyright: 2020, Google LLC
 License: GPL-2
 
+Files: client/advertising.c
+ client/advertising.h
+ client/agent.c
+ client/agent.h
+ client/display.c
+ client/display.h
+ client/gatt.h
+ client/mgmt.c
+ client/mgmt.h
+ client/player.h
+ client/print.c
+ client/print.h
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
+License: GPL-2
+
+Files: client/assistant.c
+ client/assistant.h
+Copyright: 2023, 2024, NXP
+License: GPL-2
+
+Files: client/bluetoothctl.1
+ client/bluetoothctl.rst
+Copyright: Free use of this software is granted under the terms of the GNU
+License: LGPL
+
+Files: client/gatt.c
+ client/main.c
+ client/player.c
+Copyright: 2023, 2024, NXP
+ 2012, 2014, 2020, 2022, Intel Corporation.
+License: GPL-2
+
+Files: compile
+ depcomp
+ missing
+ test-driver
+Copyright: 1996-2021, Free Software Foundation, Inc.
+License: GPL-2+ with Autoconf-data exception
+
+Files: configure
+Copyright: 1992-1996, 1998-2017, 2020-2023, Free Software Foundation
+License: FSFUL
+
 Files: debian/*
-Copyright: Edd Dumbill <edd@usefulinc.com>
-   Andrea Veri <andrea.veri89@gmail.com>
-   Filippo Giunchedi <filippo@debian.org>
-   Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
-   Mario Limonciello <mario_limonciello@dell.com>
-   Scott James Remnant <scott@ubuntu.com>
-   Nobuhiro Iwamatsu <iwamatsu@debian.org>
+Copyright: Scott James Remnant <scott@ubuntu.com>
+ Nobuhiro Iwamatsu <iwamatsu@debian.org>
+ Mario Limonciello <mario_limonciello@dell.com>
+ Filippo Giunchedi <filippo@debian.org>
+ Edd Dumbill <edd@usefulinc.com>
+ Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
+ Andrea Veri <andrea.veri89@gmail.com>
 License: GPL-2+
 
 Files: debian/control
-Copyright: Edd Dumbill <edd@usefulinc.com>
-   Andrea Veri <andrea.veri89@gmail.com>
-   Filippo Giunchedi <filippo@debian.org>
-   Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
-   Mario Limonciello <mario_limonciello@dell.com>
-   Scott James Remnant <scott@ubuntu.com>
-   Nobuhiro Iwamatsu <iwamatsu@debian.org>
+Copyright: Scott James Remnant <scott@ubuntu.com>
+ Nobuhiro Iwamatsu <iwamatsu@debian.org>
+ Mario Limonciello <mario_limonciello@dell.com>
+ Filippo Giunchedi <filippo@debian.org>
+ Edd Dumbill <edd@usefulinc.com>
+ Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
+ Andrea Veri <andrea.veri89@gmail.com>
 License: GPL
 
-Files: debian/patches/Change-shebang-from-usr-bin-python-to-usr-bin-python.patch
-Copyright: Edd Dumbill <edd@usefulinc.com>
-   Andrea Veri <andrea.veri89@gmail.com>
-   Filippo Giunchedi <filippo@debian.org>
-   Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
-   Mario Limonciello <mario_limonciello@dell.com>
-   Scott James Remnant <scott@ubuntu.com>
-   Nobuhiro Iwamatsu <iwamatsu@debian.org>
+Files: ell/*
+Copyright: 2011-2021, Intel Corporation
+License: LGPL-2.1
+
+Files: ell/dbus-client.c
+ ell/dbus-client.h
+Copyright: 2017, Codecoup
+ 2011-2014, Intel Corporation
+License: LGPL-2.1
+
+Files: ell/ecc-external.c
+Copyright: 2013, Kenneth MacKay
+License: BSD-2-clause
+
+Files: ell/utf8.c
+ ell/utf8.h
+Copyright: 2024, Cruise, LLC
+ 2011-2014, Intel Corporation
 License: LGPL-2.1
 
 Files: emulator/*
@@ -180,27 +278,45 @@ License: LGPL-2.1
 
 Files: emulator/b1ee.c
  emulator/hfp.c
-Copyright: 2009-2012, Intel Corporation
+Copyright: 2007-2012, Intel Corporation
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
+Files: emulator/btdev.c
+ emulator/bthost.c
+ emulator/bthost.h
+Copyright: 2023, 2024, NXP
+ 2011-2014, Intel Corporation
+ 2002-2010, Marcel Holtmann <marcel@holtmann.org>
+License: LGPL-2.1
+
 Files: emulator/hciemu.c
  emulator/hciemu.h
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: emulator/smp.c
-Copyright: 2013, 2014, 2016, 2018, 2019, Intel Corporation
+Copyright: 2011-2021, Intel Corporation
 License: LGPL-2.1
 
 Files: gdbus/*
 Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
+Files: gdbus/client.c
+ gdbus/gdbus.h
+Copyright: 2024, NXP
+ 2004-2011, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
 Files: gobex/*
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
+Files: install-sh
+Copyright: 1994, X Consortium
+License: X11
+
 Files: lib/*
 Copyright: 2002-2010, Marcel Holtmann <marcel@holtmann.org>
  2002, 2003, Maxim Krasnyansky <maxk@qualcomm.com>
@@ -213,6 +329,13 @@ Copyright: 2012, Intel Corporation.
  2010-2012, Code Aurora Forum.
 License: GPL-2
 
+Files: lib/bluetooth.h
+Copyright: 2023, NXP
+ 2002-2010, Marcel Holtmann <marcel@holtmann.org>
+ 2002, 2003, Maxim Krasnyansky <maxk@qualcomm.com>
+ 2000, 2001, Qualcomm Incorporated
+License: GPL-2
+
 Files: lib/bnep.h
  lib/rfcomm.h
  lib/sco.h
@@ -226,7 +349,7 @@ Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
 Files: lib/iso.h
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: lib/l2cap.h
@@ -238,7 +361,6 @@ License: GPL-2
 
 Files: lib/mgmt.h
  lib/uuid.c
- lib/uuid.h
 Copyright: 2006-2011, Nokia Corporation
  2004-2011, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
@@ -252,57 +374,18 @@ Copyright: 2002-2010, Marcel Holtmann <marcel@holtmann.org>
  2001, 2002, Nokia Corporation
 License: GPL-2
 
-Files: mesh/agent.c
- mesh/agent.h
- mesh/appkey.c
- mesh/appkey.h
- mesh/cfgmod-server.c
- mesh/cfgmod.h
- mesh/crypto.c
- mesh/crypto.h
- mesh/dbus.c
- mesh/dbus.h
- mesh/error.h
- mesh/friend.c
- mesh/friend.h
- mesh/keyring.c
- mesh/keyring.h
- mesh/main.c
- mesh/manager.c
- mesh/manager.h
- mesh/mesh-config-json.c
- mesh/mesh-config.h
- mesh/mesh-defs.h
- mesh/mesh-io-api.h
- mesh/mesh-io-generic.c
- mesh/mesh-io-generic.h
- mesh/mesh-io-mgmt.c
- mesh/mesh-io-mgmt.h
- mesh/mesh-io-unit.c
- mesh/mesh-io-unit.h
- mesh/mesh-io.c
- mesh/mesh-io.h
- mesh/mesh.c
- mesh/mesh.h
- mesh/model.c
- mesh/model.h
- mesh/net-keys.c
- mesh/net-keys.h
- mesh/net.c
- mesh/net.h
- mesh/node.c
- mesh/node.h
- mesh/pb-adv.c
- mesh/pb-adv.h
- mesh/prov-acceptor.c
- mesh/prov-initiator.c
- mesh/prov.h
- mesh/provision.h
- mesh/rpl.c
- mesh/rpl.h
- mesh/util.c
- mesh/util.h
-Copyright: 2011-2022, Intel Corporation.
+Files: lib/uuid.h
+Copyright: 2023, 2024, NXP
+ 2006-2011, Nokia Corporation
+ 2004-2011, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
+Files: ltmain.sh
+Copyright: 1996-2019, 2021, 2022, Free Software Foundation, Inc.
+License: (Expat or GPL-2+) with Libtool exception
+
+Files: mesh/*
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: mesh/mesh-mgmt.c
@@ -310,6 +393,13 @@ Files: mesh/mesh-mgmt.c
 Copyright: 2019, SILVAIR sp. z o.o.
 License: LGPL-2.1
 
+Files: mesh/prv-beacon.h
+ mesh/prvbeac-server.c
+ mesh/remprv-server.c
+ mesh/remprv.h
+Copyright: 2023, Intel Corporation.
+License: LGPL-2.1+
+
 Files: monitor/*
 Copyright: 2011-2014, Intel Corporation
  2002-2010, Marcel Holtmann <marcel@holtmann.org>
@@ -326,6 +416,14 @@ Files: monitor/a2dp.h
 Copyright: 2015, Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
 License: LGPL-2.1
 
+Files: monitor/att.c
+ monitor/bt.h
+ monitor/packet.c
+Copyright: 2023, 2024, NXP
+ 2011-2014, Intel Corporation
+ 2002-2010, Marcel Holtmann <marcel@holtmann.org>
+License: LGPL-2.1
+
 Files: monitor/jlink.c
  monitor/jlink.h
 Copyright: 2018, Codecoup
@@ -338,11 +436,22 @@ Copyright: 2011-2014, Intel Corporation
 License: LGPL-2.1+
 
 Files: monitor/tty.h
-Copyright: 2013, 2014, 2016, 2018, 2019, Intel Corporation
+Copyright: 2011-2021, Intel Corporation
 License: LGPL-2.1
 
 Files: obexd/*
-Copyright: 2011-2015, Intel Corporation
+Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
+Files: obexd/client/*
+Copyright: 2011-2015, 2023, Intel Corporation
+License: GPL-2
+
+Files: obexd/client/bip-common.c
+ obexd/client/bip-common.h
+ obexd/client/bip.c
+ obexd/client/bip.h
+Copyright: 2024, Collabora Ltd.
 License: GPL-2
 
 Files: obexd/client/driver.c
@@ -369,8 +478,8 @@ Files: obexd/client/pbap.c
  obexd/client/pbap.h
  obexd/client/sync.c
  obexd/client/sync.h
-Copyright: 2007-2010, Marcel Holtmann <marcel@holtmann.org>
- 2007-2010, Intel Corporation
+Copyright: 2007-2012, Intel Corporation
+ 2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
 Files: obexd/client/session.c
@@ -382,13 +491,6 @@ Copyright: 2011, 2012, BMW Car IT GmbH.
 License: GPL-2
 
 Files: obexd/plugins/*
-Copyright: 2007-2011, Nokia Corporation
-License: GPL-2
-
-Files: obexd/plugins/bluetooth.c
- obexd/plugins/ftp.c
- obexd/plugins/opp.c
- obexd/plugins/pcsuite.c
 Copyright: 2006-2011, Nokia Corporation
  2004-2011, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
@@ -396,7 +498,7 @@ License: GPL-2
 Files: obexd/plugins/filesystem.c
  obexd/plugins/pbap.c
  obexd/plugins/phonebook-dummy.c
-Copyright: 2009-2012, Intel Corporation
+Copyright: 2007-2012, Intel Corporation
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
@@ -416,25 +518,19 @@ Copyright: 2021, Dylan Van Assche <me@dylanvanassche.be>
  2007-2021, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
-Files: obexd/plugins/syncevolution.c
-Copyright: 2007-2010, Marcel Holtmann <marcel@holtmann.org>
- 2007-2010, Intel Corporation
-License: GPL-2
-
 Files: obexd/plugins/vcard.c
  obexd/plugins/vcard.h
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
-License: GPL-2
-
-Files: obexd/src/*
-Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: obexd/src/manager.h
- obexd/src/map_ap.h
 Copyright: 2007-2011, Nokia Corporation
 License: GPL-2
 
+Files: obexd/src/map_ap.h
+Copyright: 2010, 2011, Nokia Corporation
+License: GPL-2
+
 Files: obexd/src/obex-priv.h
  obexd/src/obex.c
  obexd/src/obex.h
@@ -445,11 +541,11 @@ Copyright: 2006-2011, Nokia Corporation
 License: GPL-2
 
 Files: peripheral/*
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: plugins/*
-Copyright: 2011, 2012, David Herrmann <dh.herrmann@googlemail.com>
+Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
 Files: plugins/admin.c
@@ -460,20 +556,12 @@ Files: plugins/autopair.c
 Copyright: 2012, 2014, 2015, Google Inc.
 License: GPL-2
 
-Files: plugins/external-dummy.c
-Copyright: no-info-found
-License: GPL-2
-
-Files: plugins/hostname.c
-Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
-License: GPL-2
-
 Files: plugins/neard.c
 Copyright: 2012, 2013, Tieto Poland
 License: GPL-2
 
 Files: plugins/policy.c
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: plugins/sixaxis.c
@@ -482,6 +570,10 @@ Copyright: 2013, Szymon Janc <szymon.janc@gmail.com>
  2009, 2017, Bastien Nocera <hadess@hadess.net>
 License: GPL-2
 
+Files: plugins/wiimote.c
+Copyright: 2011, 2012, David Herrmann <dh.herrmann@googlemail.com>
+License: GPL-2
+
 Files: profiles/*
 Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
@@ -499,12 +591,16 @@ License: LGPL-2.1
 
 Files: profiles/audio/a2dp.c
  profiles/audio/a2dp.h
- profiles/audio/media.c
 Copyright: 2011, BMW Car IT GmbH.
  2006-2010, Nokia Corporation
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
+Files: profiles/audio/asha.c
+ profiles/audio/asha.h
+Copyright: 2024, Asymptotic Inc.
+License: GPL-2
+
 Files: profiles/audio/avctp.c
  profiles/audio/avrcp.c
  profiles/audio/control.c
@@ -514,9 +610,35 @@ Copyright: 2011, Texas Instruments, Inc.
 License: GPL-2
 
 Files: profiles/audio/bap.c
+Copyright: 2023, 2024, NXP
+ 2012, 2014, 2020, 2022, Intel Corporation.
+License: GPL-2
+
+Files: profiles/audio/bap.h
+ profiles/audio/bass.h
+Copyright: 2023, 2024, NXP
+License: GPL-2
+
+Files: profiles/audio/bass.c
+Copyright: 2023, 2024, NXP
+License: LGPL-2.1
+
+Files: profiles/audio/ccp.c
+ profiles/audio/csip.c
  profiles/audio/mcp.c
  profiles/audio/vcp.c
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
+License: GPL-2
+
+Files: profiles/audio/media.c
+Copyright: 2023, NXP
+ 2011, BMW Car IT GmbH.
+ 2006, 2007, Nokia Corporation
+ 2004-2009, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
+Files: profiles/audio/micp.c
+Copyright: 2023, NXP Semiconductors.
 License: GPL-2
 
 Files: profiles/audio/player.c
@@ -533,8 +655,14 @@ Copyright: 2009, Joao Paulo Rechi Vita
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
+Files: profiles/audio/transport.c
+Copyright: 2023, 2024, NXP
+ 2006-2011, Nokia Corporation
+ 2004-2011, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
 Files: profiles/battery/*
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: profiles/battery/battery.c
@@ -544,6 +672,10 @@ Copyright: 2017, Red Hat Inc.
 License: GPL-2
 
 Files: profiles/deviceinfo/*
+Copyright: 2011-2023, Intel Corporation.
+License: LGPL-2.1
+
+Files: profiles/deviceinfo/deviceinfo.c
 Copyright: 2015, Google Inc.
  2012, Texas Instruments, Inc.
 License: GPL-2
@@ -552,10 +684,6 @@ Files: profiles/deviceinfo/dis.c
 Copyright: 2012, Texas Instruments, Inc.
 License: GPL-2
 
-Files: profiles/deviceinfo/dis.h
-Copyright: 2011-2022, Intel Corporation.
-License: LGPL-2.1
-
 Files: profiles/gap/*
 Copyright: 2014, Google Inc.
  2012, Instituto Nokia de Tecnologia - INdT
@@ -586,7 +714,7 @@ Copyright: 2014, Intel Corporation.
 License: GPL-2
 
 Files: profiles/input/hog-lib.h
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: profiles/input/hog.c
@@ -601,8 +729,7 @@ Copyright: 2013, Szymon Janc <szymon.janc@gmail.com>
  2009, 2017, Bastien Nocera <hadess@hadess.net>
 License: GPL-2
 
-Files: profiles/input/suspend-dummy.c
- profiles/input/suspend-none.c
+Files: profiles/input/suspend-none.c
  profiles/input/suspend.h
 Copyright: 2012, Nordic Semiconductor Inc.
  2012, Instituto Nokia de Tecnologia - INdT
@@ -643,20 +770,18 @@ Copyright: 2012, Nordic Semiconductor Inc.
 License: GPL-2
 
 Files: profiles/scanparam/scpp.h
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
 License: LGPL-2.1
 
 Files: src/*
-Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
-License: GPL-2
+Copyright: 2011-2023, Intel Corporation.
+License: LGPL-2.1
 
 Files: src/adapter.c
  src/adapter.h
  src/agent.c
  src/agent.h
  src/dbus-common.h
- src/device.c
- src/device.h
  src/eir.c
  src/eir.h
  src/storage.c
@@ -678,6 +803,27 @@ Files: src/advertising.c
 Copyright: 2012, 2014, 2015, Google Inc.
 License: GPL-2
 
+Files: src/backtrace.c
+ src/backtrace.h
+ src/log.c
+ src/log.h
+ src/oui.c
+ src/oui.h
+ src/plugin.c
+ src/plugin.h
+ src/rfkill.c
+ src/sdp-client.c
+ src/sdp-client.h
+ src/sdp-xml.c
+ src/sdp-xml.h
+ src/storage.h
+ src/textfile.c
+ src/textfile.h
+ src/uuid-helper.c
+ src/uuid-helper.h
+Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
 Files: src/battery.c
  src/battery.h
 Copyright: 2020, Google LLC
@@ -696,6 +842,13 @@ Copyright: 2006-2010, Nokia Corporation
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
+Files: src/device.c
+ src/device.h
+Copyright: 2023, 2024, NXP
+ 2006-2011, Nokia Corporation
+ 2004-2011, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
 Files: src/error.c
  src/error.h
 Copyright: 2007, 2008, Fabien Chevalier <fabchevalier@free.fr>
@@ -705,7 +858,7 @@ License: GPL-2
 
 Files: src/profile.c
  src/profile.h
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: src/sdpd-database.c
@@ -724,29 +877,50 @@ Files: src/service.c
 Copyright: 2012, 2013, BMW Car IT GmbH.
 License: GPL-2
 
-Files: src/settings.c
- src/settings.h
-Copyright: 2011-2022, Intel Corporation.
-License: LGPL-2.1
-
-Files: src/shared/*
-Copyright: 2011-2022, Intel Corporation.
-License: LGPL-2.1
+Files: src/set.c
+ src/set.h
+Copyright: 2011-2015, 2023, Intel Corporation
+License: GPL-2
 
 Files: src/shared/ad.c
  src/shared/ad.h
- src/shared/att-types.h
  src/shared/att.c
  src/shared/att.h
  src/shared/gatt-client.c
  src/shared/gatt-client.h
  src/shared/gatt-helpers.c
  src/shared/gatt-helpers.h
- src/shared/gatt-server.c
  src/shared/gatt-server.h
 Copyright: 2014, 2015, Google Inc.
 License: LGPL-2.1
 
+Files: src/shared/asha.c
+ src/shared/asha.h
+Copyright: 2024, Asymptotic Inc.
+License: LGPL-2.1
+
+Files: src/shared/att-types.h
+ src/shared/gatt-server.c
+Copyright: 2023, NXP
+ 2014, Google Inc.
+License: LGPL-2.1
+
+Files: src/shared/bap-defs.h
+ src/shared/bap.c
+ src/shared/bap.h
+ src/shared/lc3.h
+ src/shared/shell.c
+ src/shared/util.c
+ src/shared/util.h
+Copyright: 2023, 2024, NXP
+ 2012-2014, 2017, 2022, Intel Corporation.
+License: LGPL-2.1
+
+Files: src/shared/bass.c
+ src/shared/bass.h
+Copyright: 2023, 2024, NXP
+License: LGPL-2.1
+
 Files: src/shared/ecc.c
  src/shared/ecc.h
 Copyright: 2013, Kenneth MacKay
@@ -756,7 +930,7 @@ Files: src/shared/hci-crypto.c
  src/shared/hci-crypto.h
  src/shared/mainloop-ell.c
  src/shared/mainloop-glib.c
-Copyright: 2013, 2014, 2016, 2018, 2019, Intel Corporation
+Copyright: 2011-2021, Intel Corporation
 License: LGPL-2.1
 
 Files: src/shared/mainloop.c
@@ -765,6 +939,11 @@ Copyright: 2011-2014, Intel Corporation
  2002-2010, Marcel Holtmann <marcel@holtmann.org>
 License: LGPL-2.1
 
+Files: src/shared/micp.c
+ src/shared/micp.h
+Copyright: 2023, NXP Semiconductors.
+License: LGPL-2.1
+
 Files: test/*
 Copyright: no-info-found
 License: LGPL-2.1
@@ -774,7 +953,32 @@ Copyright: 2010, 2011, ST-Ericsson SA """
 License: LGPL-2.1
 
 Files: tools/*
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
+License: LGPL-2.1
+
+Files: tools/3dsp.c
+ tools/bluemoon.c
+ tools/bluetooth-player.c
+ tools/bnep-tester.c
+ tools/btmgmt.c
+ tools/btpclientctl.c
+ tools/check-selftest.c
+ tools/create-image.c
+ tools/gap-tester.c
+ tools/hci-tester.c
+ tools/hciattach_bcm43xx.c
+ tools/hciattach_intel.c
+ tools/l2cap-tester.c
+ tools/mesh-tester.c
+ tools/mgmt-tester.c
+ tools/obex-client-tool.c
+ tools/obex-server-tool.c
+ tools/obexctl.c
+ tools/rfcomm-tester.c
+ tools/sco-tester.c
+ tools/smp-tester.c
+ tools/userchan-tester.c
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: tools/advtest.c
@@ -788,7 +992,7 @@ Files: tools/advtest.c
  tools/eddystone.c
  tools/ibeacon.c
  tools/oobtest.c
-Copyright: 2009-2012, Intel Corporation
+Copyright: 2007-2012, Intel Corporation
  2004-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
@@ -799,7 +1003,6 @@ Copyright: 2018, Pali Rohár <pali.rohar@gmail.com>
 License: GPL-2
 
 Files: tools/avtest.c
- tools/btiotest.c
 Copyright: 2006-2011, Nokia Corporation
  2004-2011, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
@@ -811,7 +1014,7 @@ Files: tools/bcmfw.c
  tools/nokfw.c
  tools/rtlfw.c
  tools/seq2bseq.c
-Copyright: 2011-2015, Intel Corporation
+Copyright: 2011-2015, 2023, Intel Corporation
 License: GPL-2
 
 Files: tools/bdaddr.c
@@ -831,23 +1034,18 @@ Files: tools/btgatt-client.c
 Copyright: 2012, 2014, 2015, Google Inc.
 License: GPL-2
 
+Files: tools/btiotest.c
+Copyright: 2023, 2024, NXP
+ 2006-2011, Nokia Corporation
+ 2004-2011, Marcel Holtmann <marcel@holtmann.org>
+License: GPL-2
+
 Files: tools/btmon-logger.c
 Copyright: 2017, 2018, Codecoup
  2011-2014, Intel Corporation
  2002-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
-Files: tools/btpclient.c
- tools/ioctl-tester.c
- tools/iso-tester.c
- tools/isotest.c
- tools/mesh-cfgclient.c
- tools/mesh-cfgtest.c
- tools/meshctl.c
- tools/test-runner.c
-Copyright: 2011-2022, Intel Corporation.
-License: LGPL-2.1
-
 Files: tools/gatt-service.c
 Copyright: 2010, 2014, Instituto Nokia de Tecnologia - INdT
 License: GPL-2
@@ -890,51 +1088,16 @@ Copyright: 2009-2011, Kay Sievers <kay.sievers@vrfy.org>
  2003-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
-Files: tools/mesh-gatt/config-client.c
- tools/mesh-gatt/config-server.c
- tools/mesh-gatt/crypto.c
- tools/mesh-gatt/crypto.h
- tools/mesh-gatt/gatt.c
- tools/mesh-gatt/gatt.h
- tools/mesh-gatt/keys.h
- tools/mesh-gatt/mesh-net.h
- tools/mesh-gatt/net.c
- tools/mesh-gatt/net.h
- tools/mesh-gatt/node.c
- tools/mesh-gatt/node.h
- tools/mesh-gatt/onoff-model.c
- tools/mesh-gatt/onoff-model.h
- tools/mesh-gatt/prov-db.c
- tools/mesh-gatt/prov-db.h
- tools/mesh-gatt/prov.c
- tools/mesh-gatt/prov.h
- tools/mesh-gatt/util.c
- tools/mesh-gatt/util.h
-Copyright: 2011-2022, Intel Corporation.
+Files: tools/iso-tester.c
+ tools/isotest.c
+Copyright: 2023, 2024, NXP
+ 2012-2014, 2017, 2022, Intel Corporation.
 License: LGPL-2.1
 
-Files: tools/mesh/agent.c
- tools/mesh/agent.h
- tools/mesh/cfgcli.c
- tools/mesh/cfgcli.h
- tools/mesh/config-model.h
- tools/mesh/keys.c
- tools/mesh/keys.h
- tools/mesh/mesh-db.c
- tools/mesh/mesh-db.h
- tools/mesh/model.h
- tools/mesh/remote.c
- tools/mesh/remote.h
- tools/mesh/util.c
- tools/mesh/util.h
-Copyright: 2011-2022, Intel Corporation.
+Files: tools/missing.h
+Copyright: 2024, Khem Raj <raj.khem@gmail.com>
 License: LGPL-2.1
 
-Files: tools/parse_companies.pl
- tools/update_compids.sh
-Copyright: no-info-found
-License: GPL-2
-
 Files: tools/parser/*
 Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
@@ -942,7 +1105,7 @@ License: GPL-2
 Files: tools/parser/amp.c
  tools/parser/avrcp.c
  tools/parser/smp.c
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
 License: GPL-2
 
 Files: tools/parser/att.c
@@ -988,7 +1151,16 @@ Copyright: 2002-2010, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
 Files: unit/*
-Copyright: 2008-2016, 2020, 2022, Intel Corporation.
+Copyright: 2008-2016, 2020, 2022-2024, Intel Corporation.
+License: GPL-2
+
+Files: unit/test-bap.c
+Copyright: 2023, 2024, NXP
+ 2012, 2014, 2020, 2022, Intel Corporation.
+License: GPL-2
+
+Files: unit/test-bass.c
+Copyright: 2023, 2024, NXP
 License: GPL-2
 
 Files: unit/test-crc.c
@@ -996,7 +1168,7 @@ Files: unit/test-crc.c
  unit/test-eir.c
  unit/test-gdbus-client.c
  unit/test-uuid.c
-Copyright: 2011-2015, Intel Corporation
+Copyright: 2011-2015, 2023, Intel Corporation
 License: GPL-2
 
 Files: unit/test-ecc.c
@@ -1013,7 +1185,12 @@ Copyright: 2013, Intel Corporation.
 License: GPL-2
 
 Files: unit/test-mesh-crypto.c
-Copyright: 2011-2022, Intel Corporation.
+Copyright: 2011-2023, Intel Corporation.
+License: LGPL-2.1
+
+Files: unit/test-micp.c
+ unit/test-vcp.c
+Copyright: 2023, NXP Semiconductors.
 License: LGPL-2.1
 
 Files: unit/test-midi.c
@@ -1025,6 +1202,6 @@ Files: unit/test-textfile.c
 Copyright: 2002-2012, Marcel Holtmann <marcel@holtmann.org>
 License: GPL-2
 
-Files: INSTALL README doc/mgmt-api.txt mesh/bluetooth-meshd.rst.in monitor/btmon.rst src/bluetoothd.rst.in tools/bdaddr.rst tools/btattach.rst tools/ciptool.rst tools/hciattach.rst tools/hciconfig.rst tools/hcidump.rst tools/hcitool.rst tools/hid2hci.rst tools/isotest.rst tools/l2ping.rst tools/rctest.rst tools/rfcomm.rst tools/sdptool.rst
+Files: INSTALL doc/hci.7 doc/hci.rst doc/l2cap.7 doc/l2cap.rst doc/rfcomm.7 doc/rfcomm.rst mesh/bluetooth-meshd.rst.in monitor/btmon.1 monitor/btmon.rst src/bluetoothd.8 src/bluetoothd.rst src/bluetoothd.rst.in tools/bdaddr.1 tools/bdaddr.rst tools/btattach.1 tools/btattach.rst tools/btmgmt.1 tools/btmgmt.rst tools/ciptool.1 tools/ciptool.rst tools/hciattach.1 tools/hciattach.rst tools/hciconfig.1 tools/hciconfig.rst tools/hcidump.1 tools/hcidump.rst tools/hcitool.1 tools/hcitool.rst tools/hid2hci.1 tools/hid2hci.rst tools/isotest.1 tools/isotest.rst tools/l2ping.1 tools/l2ping.rst tools/rctest.1 tools/rctest.rst tools/rfcomm.1 tools/rfcomm.rst tools/sdptool.1 tools/sdptool.rst
 Copyright: 2008-2015, Intel Corporation.
 License: GPL-2+
-- 
GitLab